From f109c36bbd7db2a36e480d126cd2bc1e306283fc Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 14 Oct 2018 20:00:41 +0200 Subject: [PATCH 01/54] Add Reset 4 command to reset defaults but keep wifi config --- sonoff/sonoff.ino | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ca42c2bbf..518b588ad 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1152,6 +1152,10 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) restart_flag = 210 + payload; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; + case 4: + restart_flag = 214; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); + break; default: snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESET); } @@ -2103,6 +2107,20 @@ void Every250mSeconds() SettingsDefault(); restart_flag = 2; } + if (214 == restart_flag) { + char tmp_sta_ssid[2][33]; + char tmp_sta_pwd[2][65]; + strlcpy(tmp_sta_ssid[0],Settings.sta_ssid[0],sizeof(Settings.sta_ssid[0])); + strlcpy(tmp_sta_pwd[0],Settings.sta_pwd[0],sizeof(Settings.sta_pwd[0])); + strlcpy(tmp_sta_ssid[1],Settings.sta_ssid[1],sizeof(Settings.sta_ssid[1])); + strlcpy(tmp_sta_pwd[1],Settings.sta_pwd[1],sizeof(Settings.sta_pwd[1])); + SettingsDefault(); + strlcpy(Settings.sta_ssid[0],tmp_sta_ssid[0],sizeof(Settings.sta_ssid[0])); + strlcpy(Settings.sta_pwd[0],tmp_sta_pwd[0],sizeof(Settings.sta_pwd[0])); + strlcpy(Settings.sta_ssid[1],tmp_sta_ssid[1],sizeof(Settings.sta_ssid[1])); + strlcpy(Settings.sta_pwd[1],tmp_sta_pwd[1],sizeof(Settings.sta_pwd[1])); + restart_flag = 2; + } SettingsSaveAll(); restart_flag--; if (restart_flag <= 0) { From 5f9867a22f1cddc393b7a13107510803cc4382d2 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 15 Oct 2018 00:10:02 +0200 Subject: [PATCH 02/54] Add command Reset 5 --- sonoff/sonoff.ino | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 518b588ad..9e3263be4 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1156,6 +1156,10 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) restart_flag = 214; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; + case 5: + restart_flag = 215; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); + break; default: snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESET); } @@ -2107,13 +2111,16 @@ void Every250mSeconds() SettingsDefault(); restart_flag = 2; } - if (214 == restart_flag) { + if ((214 == restart_flag) || (215 == restart_flag)) { char tmp_sta_ssid[2][33]; char tmp_sta_pwd[2][65]; strlcpy(tmp_sta_ssid[0],Settings.sta_ssid[0],sizeof(Settings.sta_ssid[0])); strlcpy(tmp_sta_pwd[0],Settings.sta_pwd[0],sizeof(Settings.sta_pwd[0])); strlcpy(tmp_sta_ssid[1],Settings.sta_ssid[1],sizeof(Settings.sta_ssid[1])); strlcpy(tmp_sta_pwd[1],Settings.sta_pwd[1],sizeof(Settings.sta_pwd[1])); + if (215 == restart_flag) { + SettingsErase(0); // Erase all flash from program end to end of physical flash + } SettingsDefault(); strlcpy(Settings.sta_ssid[0],tmp_sta_ssid[0],sizeof(Settings.sta_ssid[0])); strlcpy(Settings.sta_pwd[0],tmp_sta_pwd[0],sizeof(Settings.sta_pwd[0])); From 6b660026cd19f74d69ca68e3afc36531f7d55eb3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Oct 2018 14:43:47 +0200 Subject: [PATCH 03/54] Add cmnds Reset 4 and Reset 5 Add commands Reset 4 (reset to defaults but keep wifi params) and Reset 5 (as reset 4 and also erase flash) (#4061) --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 4 ++-- sonoff/sonoff.ino | 40 ++++++++++++++-------------------------- sonoff/sonoff_post.h | 4 ++++ 4 files changed, 21 insertions(+), 28 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 9a81d11bd..e3ff0857c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Fix Color Temperature slider functionality regression from 6.2.1.5 (#4037) * Add auto reload of main web page to some web restarts * Add whitespace removal from RfRaw and SerialSend5 (#4020) + * Add commands Reset 4 (reset to defaults but keep wifi params) and Reset 5 (as reset 4 and also erase flash) (#4061) * * 6.2.1.14 20181010 * Rewrite Webserver page handler for easier extension (thx to Adrian Scillato) diff --git a/sonoff/settings.h b/sonoff/settings.h index e9e1fd110..a4df43eb5 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -188,8 +188,8 @@ struct SYSCFG { byte seriallog_level; // 09E uint8_t sta_config; // 09F byte sta_active; // 0A0 - char sta_ssid[2][33]; // 0A1 - char sta_pwd[2][65]; // 0E3 + char sta_ssid[2][33]; // 0A1 - Keep together with sta_pwd as being copied as one chunck with reset 4/5 + char sta_pwd[2][65]; // 0E3 - Keep together with sta_ssid as being copied as one chunck with reset 4/5 char hostname[33]; // 165 char syslog_host[33]; // 186 uint8_t rule_stop; // 1A7 diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 9e3263be4..f03b9973b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1149,15 +1149,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) break; case 2: case 3: - restart_flag = 210 + payload; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); - break; case 4: - restart_flag = 214; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); - break; case 5: - restart_flag = 215; + restart_flag = 210 + payload; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; default: @@ -2100,10 +2094,21 @@ void Every250mSeconds() } } if (restart_flag && (backlog_pointer == backlog_index)) { - if (213 == restart_flag) { + if ((214 == restart_flag) || (215 == restart_flag)) { + char storage[sizeof(Settings.sta_ssid) + sizeof(Settings.sta_pwd)]; + memcpy(storage, Settings.sta_ssid, sizeof(storage)); // Backup current SSIDs and Passwords + if (215 == restart_flag) { + SettingsErase(0); // Erase all flash from program end to end of physical flash + } + SettingsDefault(); + memcpy(Settings.sta_ssid, storage, sizeof(storage)); // Restore current SSIDs and Passwords + restart_flag = 2; + } + else if (213 == restart_flag) { SettingsSdkErase(); // Erase flash SDK parameters restart_flag = 2; - } else if (212 == restart_flag) { + } + else if (212 == restart_flag) { SettingsErase(0); // Erase all flash from program end to end of physical flash restart_flag = 211; } @@ -2111,23 +2116,6 @@ void Every250mSeconds() SettingsDefault(); restart_flag = 2; } - if ((214 == restart_flag) || (215 == restart_flag)) { - char tmp_sta_ssid[2][33]; - char tmp_sta_pwd[2][65]; - strlcpy(tmp_sta_ssid[0],Settings.sta_ssid[0],sizeof(Settings.sta_ssid[0])); - strlcpy(tmp_sta_pwd[0],Settings.sta_pwd[0],sizeof(Settings.sta_pwd[0])); - strlcpy(tmp_sta_ssid[1],Settings.sta_ssid[1],sizeof(Settings.sta_ssid[1])); - strlcpy(tmp_sta_pwd[1],Settings.sta_pwd[1],sizeof(Settings.sta_pwd[1])); - if (215 == restart_flag) { - SettingsErase(0); // Erase all flash from program end to end of physical flash - } - SettingsDefault(); - strlcpy(Settings.sta_ssid[0],tmp_sta_ssid[0],sizeof(Settings.sta_ssid[0])); - strlcpy(Settings.sta_pwd[0],tmp_sta_pwd[0],sizeof(Settings.sta_pwd[0])); - strlcpy(Settings.sta_ssid[1],tmp_sta_ssid[1],sizeof(Settings.sta_ssid[1])); - strlcpy(Settings.sta_pwd[1],tmp_sta_pwd[1],sizeof(Settings.sta_pwd[1])); - restart_flag = 2; - } SettingsSaveAll(); restart_flag--; if (restart_flag <= 0) { diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index bc747155e..627110ca3 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -124,6 +124,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library #undef USE_ARDUINO_OTA // Disable support for Arduino OTA #undef USE_KNX // Disable KNX IP Protocol Support +#undef USE_CUSTOM // Disable Custom features #undef USE_TIMERS // Disable support for up to 16 timers #undef USE_TIMERS_WEB // Disable support for timer webpage #undef USE_SUNRISE // Disable support for Sunrise and sunset tools @@ -144,6 +145,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 +#undef USE_HX711 // Disable support for HX711 load cell #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code @@ -211,6 +213,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #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_CUSTOM // Disable Custom features #undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server #undef USE_EMULATION // Disable Wemo or Hue emulation #undef USE_TIMERS // Disable support for up to 16 timers @@ -237,6 +240,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 +#undef USE_HX711 // Disable support for HX711 load cell #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code From fb6cc194a909d971ed119853c761eb30318c53d1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Oct 2018 17:18:30 +0200 Subject: [PATCH 04/54] 6.2.1.16 Add TasmotaModbus lib 6.2.1.16 20181015 * Add TasmotaModbus library for very basic modbus wrapper for TasmotaSerial * Change xsns_17_senseair.ino to use TasmotaModbus library * Fix xnrg_05_pzem2.ino for PZEM-014/016 support using TasmotaModbus library (#3694) --- lib/TasmotaModbus-1.0.0/README.md | 7 + .../examples/modbustest/modbustest.ino | 31 ++++ lib/TasmotaModbus-1.0.0/keywords.txt | 26 ++++ lib/TasmotaModbus-1.0.0/library.json | 15 ++ lib/TasmotaModbus-1.0.0/library.properties | 9 ++ lib/TasmotaModbus-1.0.0/src/TasmotaModbus.cpp | 141 ++++++++++++++++++ lib/TasmotaModbus-1.0.0/src/TasmotaModbus.h | 54 +++++++ sonoff/_changelog.ino | 7 +- sonoff/sonoff_version.h | 2 +- sonoff/xnrg_05_pzem2.ino | 136 +++++------------ sonoff/xsns_17_senseair.ino | 82 ++-------- 11 files changed, 336 insertions(+), 174 deletions(-) create mode 100644 lib/TasmotaModbus-1.0.0/README.md create mode 100644 lib/TasmotaModbus-1.0.0/examples/modbustest/modbustest.ino create mode 100644 lib/TasmotaModbus-1.0.0/keywords.txt create mode 100644 lib/TasmotaModbus-1.0.0/library.json create mode 100644 lib/TasmotaModbus-1.0.0/library.properties create mode 100644 lib/TasmotaModbus-1.0.0/src/TasmotaModbus.cpp create mode 100644 lib/TasmotaModbus-1.0.0/src/TasmotaModbus.h diff --git a/lib/TasmotaModbus-1.0.0/README.md b/lib/TasmotaModbus-1.0.0/README.md new file mode 100644 index 000000000..019aafc07 --- /dev/null +++ b/lib/TasmotaModbus-1.0.0/README.md @@ -0,0 +1,7 @@ +# TasmotaSerial + +Implementation of software serial with hardware serial fallback library for the ESP8266 + +Allows for several instances to be active at the same time. + +Please note that due to the fact that the ESP always have other activities ongoing, there will be some inexactness in interrupt timings. This may lead to bit errors when having heavy data traffic. diff --git a/lib/TasmotaModbus-1.0.0/examples/modbustest/modbustest.ino b/lib/TasmotaModbus-1.0.0/examples/modbustest/modbustest.ino new file mode 100644 index 000000000..6fb4720c0 --- /dev/null +++ b/lib/TasmotaModbus-1.0.0/examples/modbustest/modbustest.ino @@ -0,0 +1,31 @@ + +#include + +TasmotaModbus Modbus(14, 12); + +void setup() { + Serial.begin(115200); + Modbus.Begin(9600); + + Serial.println("\nTasmotaModbus test started"); + + Modbus.Send(0x01, 0x04, 0, 8); +} + +void loop() { + if (Modbus.ReceiveReady()) { + uint8_t buffer[26]; + + uint8_t error = Modbus.ReceiveBuffer(buffer, 8); + if (error) { + Serial.print("Modbus response error "); + Serial.println(error); + } else { + Serial.print("Modbus received:"); + for (int i = 0; i < (buffer[2]) ? buffer[2] +5 : sizeof(buffer); i++) { + Serial.print(" "); + Serial.print(buffer[i], HEX); + } + } + } +} diff --git a/lib/TasmotaModbus-1.0.0/keywords.txt b/lib/TasmotaModbus-1.0.0/keywords.txt new file mode 100644 index 000000000..e019564cf --- /dev/null +++ b/lib/TasmotaModbus-1.0.0/keywords.txt @@ -0,0 +1,26 @@ +####################################### +# Syntax Coloring Map for TasmotaModbus +# (esp8266) +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +TasmotaModbus KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +Begin KEYWORD2 +Send KEYWORD2 +ReceiveReady KEYWORD2 +ReceiveBuffer KEYWORD2 +Receive16BitRegister KEYWORD2 +Receive32BitRegister KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/lib/TasmotaModbus-1.0.0/library.json b/lib/TasmotaModbus-1.0.0/library.json new file mode 100644 index 000000000..06028d38b --- /dev/null +++ b/lib/TasmotaModbus-1.0.0/library.json @@ -0,0 +1,15 @@ +{ + "name": "TasmotaModbus", + "version": "1.0.0", + "keywords": [ + "serial", "io", "TasmotaModbus" + ], + "description": "Basic modbus wrapper for TasmotaSerial for ESP8266.", + "repository": + { + "type": "git", + "url": "https://github.com/arendst/Sonoff-Tasmota/lib/TasmotaModbus" + }, + "frameworks": "arduino", + "platforms": "espressif8266" +} diff --git a/lib/TasmotaModbus-1.0.0/library.properties b/lib/TasmotaModbus-1.0.0/library.properties new file mode 100644 index 000000000..f7bcfcd1a --- /dev/null +++ b/lib/TasmotaModbus-1.0.0/library.properties @@ -0,0 +1,9 @@ +name=TasmotaModbus +version=1.0.0 +author=Theo Arends +maintainer=Theo Arends +sentence=Basic modbus wrapper for TasmotaSerial for ESP8266. +paragraph= +category=Signal Input/Output +url= +architectures=esp8266 diff --git a/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.cpp b/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.cpp new file mode 100644 index 000000000..d242d83a7 --- /dev/null +++ b/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.cpp @@ -0,0 +1,141 @@ +/* + TasmotaModbus.cpp - Basic modbus wrapper for TasmotaSerial for Tasmota + + Copyright (C) 2018 Theo Arends + + This library 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 . +*/ + +#include "TasmotaModbus.h" + +TasmotaModbus::TasmotaModbus(int receive_pin, int transmit_pin) : TasmotaSerial(receive_pin, transmit_pin, 1) +{ +} + +TasmotaModbus::~TasmotaModbus() +{ +} + +uint16_t CalculateCRC(uint8_t *frame, uint8_t num) +{ + uint16_t crc = 0xFFFF; + uint16_t flag; + + for (uint8_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint8_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 + crc ^= 0xA001; + } else { // Else LSB is not set + crc >>= 1; // Just shift right + } + } + } + return crc; +} + +int TasmotaModbus::Begin(long speed) +{ + int result = 0; + + if (begin(speed)) { + result = 1; + if (hardwareSerial()) { result = 2; } + } + return result; +} + +void TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t register_count) +{ + uint8_t frame[8]; + + frame[0] = device_address; // 0xFE default device address or dedicated like 0x01 + frame[1] = function_code; + frame[2] = (uint8_t)(start_address >> 8); + frame[3] = (uint8_t)(start_address); + frame[4] = (uint8_t)(register_count >> 8); + frame[5] = (uint8_t)(register_count); + uint16_t crc = CalculateCRC(frame, 6); + frame[6] = (uint8_t)(crc); + frame[7] = (uint8_t)(crc >> 8); + + flush(); + write(frame, sizeof(frame)); +} + +bool TasmotaModbus::ReceiveReady() +{ + return (available() > 4); +} + +uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t register_count) +{ + uint8_t len = 0; + uint32_t last = millis(); + while ((available() > 0) && (len < (register_count *2) + 5) && (millis() - last < 10)) { + buffer[len++] = (uint8_t)read(); + if (3 == len) { + if (buffer[1] & 0x80) { // fe 84 02 f2 f1 + return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error + } + } + last = millis(); + } + + if (len < 7) { return 7; } // 7 = Not enough data + if (len != buffer[2] + 5) { return 8; } // 8 = Unexpected result + + uint16_t crc = (buffer[len -1] << 8) | buffer[len -2]; + if (CalculateCRC(buffer, len -2) != crc) { return 9; } // 9 = crc error + + return 0; // 0 = No error +} + +uint8_t TasmotaModbus::Receive16BitRegister(uint16_t *value) +{ + // 0 1 2 3 4 5 6 + // 01 04 02 43 21 HH LL + // Id Cc Sz Regis Crc-- + + uint8_t buffer[7]; + + uint8_t error = ReceiveBuffer(buffer, 1); // 1 x 16bit register + if (!error) { + *value = (buffer[3] << 8) | buffer[4]; + } + + return error; +} + +uint8_t TasmotaModbus::Receive32BitRegister(float *value) +{ + // 0 1 2 3 4 5 6 7 8 + // 01 04 04 87 65 43 21 HH LL + // Id Cc Sz Register--- Crc-- + + uint8_t buffer[9]; + + *value = NAN; + + uint8_t error = ReceiveBuffer(buffer, 2); // 1 x 32bit register + if (!error) { + ((uint8_t*)value)[3] = buffer[3]; + ((uint8_t*)value)[2] = buffer[4]; + ((uint8_t*)value)[1] = buffer[5]; + ((uint8_t*)value)[0] = buffer[6]; + } + + return error; +} diff --git a/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.h b/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.h new file mode 100644 index 000000000..664a66b42 --- /dev/null +++ b/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.h @@ -0,0 +1,54 @@ +/* + TasmotaModbus.h - Basic modbus wrapper for TasmotaSerial for Tasmota + + Copyright (C) 2018 Theo Arends + + This library 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 TasmotaModbus_h +#define TasmotaModbus_h + +#include +#include + +#define TM_MODBUS_BAUDRATE 9600 // Default baudrate + +class TasmotaModbus : public TasmotaSerial { + public: + TasmotaModbus(int receive_pin, int transmit_pin); + ~TasmotaModbus(); + + int Begin(long speed = TM_MODBUS_BAUDRATE); + + void Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t register_count); + + bool ReceiveReady(); + + /* Return codes: + * 0 - No error + * 1 - Illegal function + * 2 - Illegal address + * 3 - Illegal data + * 4 - Slave error + * 7 - Not enough minimal data received + * 8 - Not enough data receieved + * 9 - Crc error + */ + uint8_t ReceiveBuffer(uint8_t *buffer, uint8_t register_count); + uint8_t Receive16BitRegister(uint16_t *value); + uint8_t Receive32BitRegister(float *value); +}; + +#endif // TasmotaModbus_h diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e3ff0857c..d924329f9 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ -/* 6.2.1.15 20181012 +/* 6.2.1.16 20181015 + * Add TasmotaModbus library for very basic modbus wrapper for TasmotaSerial + * Change xsns_17_senseair.ino to use TasmotaModbus library + * Fix xnrg_05_pzem2.ino for PZEM-014/016 support using TasmotaModbus library (#3694) + * + * 6.2.1.15 20181012 * Fix Color Temperature slider functionality regression from 6.2.1.5 (#4037) * Add auto reload of main web page to some web restarts * Add whitespace removal from RfRaw and SerialSend5 (#4020) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index d283e0476..5c81a8b16 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0602010F +#define VERSION 0x06020110 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino index bb0f4864d..2c9b35b50 100644 --- a/sonoff/xnrg_05_pzem2.ino +++ b/sonoff/xnrg_05_pzem2.ino @@ -34,108 +34,40 @@ #define XNRG_05 5 -#define PZEM2_TYPES_003_017 8 // Result 16 bit register count -#define PZEM2_TYPES_014_016 10 // Result 16 bit register count +#define PZEM2_MODBUS_SPEED 9600 +#define PZEM2_DEVICE_ADDRESS 0x01 // PZEM default address +#define PZEM2_READ_RESULT 0x04 // Command Read result -#define PZEM2_READ_RESULT 0x04 +#define PZEM2_TYPES_003_017 8 // Result 8 x 16 bit register count +#define PZEM2_TYPES_014_016 10 // Result 10 x 16 bit register count -#include - -TasmotaSerial *Pzem2Serial; +#include +TasmotaModbus *Pzem2Modbus; uint8_t pzem2_type = PZEM2_TYPES_014_016; - -/*********************************************************************************************/ - -uint16_t Pzem2ModbusCalculateCRC(uint8_t *frame, uint8_t num) -{ - uint16_t crc = 0xFFFF; - uint16_t flag; - - for (uint8_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint8_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { // If the LSB is set - crc >>= 1; // Shift right and XOR 0xA001 - crc ^= 0xA001; - } else { // Else LSB is not set - crc >>= 1; // Just shift right - } - } - } - return crc; -} - -void Pzem2ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) -{ - uint8_t frame[8]; - - frame[0] = 0xFE; // Any Address - frame[1] = function_code; - frame[2] = (uint8_t)(start_address >> 8); - frame[3] = (uint8_t)(start_address); - frame[4] = (uint8_t)(register_count >> 8); - frame[5] = (uint8_t)(register_count); - uint16_t crc = Pzem2ModbusCalculateCRC(frame, 6); - frame[6] = (uint8_t)((crc >> 8) & 0xFF); - frame[7] = (uint8_t)(crc & 0xFF); - - Pzem2Serial->flush(); - Pzem2Serial->write(frame, sizeof(frame)); -} - -bool Pzem2ModbusReceiveReady() -{ - return (Pzem2Serial->available() >= 5); // 5 - Error frame, 21 or 25 - Ok frame -} - -uint8_t Pzem2ModbusReceive(uint8_t *buffer, uint8_t register_count) -{ - // 0 1 2 3 4 5 6 - // FE 04 02 08 98 HH LL - // Id Cc Sz Regis Crc-- - - uint8_t len = 0; - while ((Pzem2Serial->available() > 0) && (len < (register_count *2) + 5)) { - buffer[len++] = (uint8_t)Pzem2Serial->read(); - if (3 == len) { - if (buffer[1] & 0x80) { // fe 84 02 f2 f1 - return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error - } - } - } - - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); - - if (len < 7) { return 7; } // 7 = Not enough data - if (len != buffer[2] + 5) { return 8; } // 8 = Unexpected result - - uint16_t crc = (buffer[len -2] << 8) | buffer[len -1]; - if (Pzem2ModbusCalculateCRC(buffer, len -3) != crc) { return 9; } // 9 = crc error - - return 0; // 0 = No error -} - -/*********************************************************************************************/ - uint8_t pzem2_sendRetry = 0; -void Pzem2Every200ms() +void Pzem2EverySecond() { - bool data_ready = Pzem2ModbusReceiveReady(); + bool data_ready = Pzem2Modbus->ReceiveReady(); if (data_ready) { uint8_t buffer[26]; - uint8_t error = Pzem2ModbusReceive(buffer, pzem2_type); + + uint8_t error = Pzem2Modbus->ReceiveBuffer(buffer, pzem2_type); + AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + if (error) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PZEM2 response error %d"), error); AddLog(LOG_LEVEL_DEBUG); // if (9 == error) { +/* if (PZEM2_TYPES_014_016 == pzem2_type) { pzem2_type = PZEM2_TYPES_003_017; } else { pzem2_type = PZEM2_TYPES_014_016; } +*/ // } } else { float energy = 0; @@ -143,12 +75,12 @@ void Pzem2Every200ms() if (PZEM2_TYPES_003_017 == pzem2_type) { energy_type_dc = true; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - // FE 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017 + // 01 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017 // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- - energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V - energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A - energy_active_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]) / 10.0; // 429496729.0 W - energy = (float)((uint32_t)buffer[13] << 24 + (uint32_t)buffer[14] << 16 + (uint32_t)buffer[11] << 8 + buffer[12]); // 4294967295 Wh + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V + energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A + energy_active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W + energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any energy_kWhtoday += (energy - energy_start) * 100; energy_start = energy; @@ -157,14 +89,14 @@ void Pzem2Every200ms() else if (PZEM2_TYPES_014_016 == pzem2_type) { // PZEM-014,016 energy_type_dc = false; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - // FE 04 14 08 98 03 E8 00 00 08 98 00 00 00 00 00 00 01 F4 00 64 00 00 HH LL = PZEM-014 + // 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34 = PZEM-014 // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- - energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V - energy_current = (float)((uint32_t)buffer[7] << 24 + (uint32_t)buffer[8] << 16 + (uint32_t)buffer[5] << 8 + buffer[6]) / 1000.0; // 4294967.000 A - energy_active_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]) / 10.0; // 429496729.0 W - energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz - energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 - energy = (float)((uint32_t)buffer[15] << 24 + (uint32_t)buffer[16] << 16 + (uint32_t)buffer[13] << 8 + buffer[14]); // 4294967295 Wh + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V + energy_current = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A + energy_active_power = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W + energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz + energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 + energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any energy_kWhtoday += (energy - energy_start) * 100; energy_start = energy; @@ -175,7 +107,7 @@ void Pzem2Every200ms() if (0 == pzem2_sendRetry || data_ready) { pzem2_sendRetry = 5; - Pzem2ModbusSend(PZEM2_READ_RESULT, 0, pzem2_type); + Pzem2Modbus->Send(PZEM2_DEVICE_ADDRESS, PZEM2_READ_RESULT, 0, pzem2_type); } else { pzem2_sendRetry--; @@ -184,10 +116,10 @@ void Pzem2Every200ms() void Pzem2SnsInit() { - // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions - Pzem2Serial = new TasmotaSerial(pin[GPIO_PZEM2_RX], pin[GPIO_PZEM2_TX], 1); - if (Pzem2Serial->begin(9600)) { - if (Pzem2Serial->hardwareSerial()) { ClaimSerial(); } + Pzem2Modbus = new TasmotaModbus(pin[GPIO_PZEM2_RX], pin[GPIO_PZEM2_TX]); + uint8_t result = Pzem2Modbus->Begin(PZEM2_MODBUS_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } } else { energy_flg = ENERGY_NONE; } @@ -218,8 +150,8 @@ int Xnrg05(byte function) case FUNC_INIT: Pzem2SnsInit(); break; - case FUNC_EVERY_200_MSECOND: - Pzem2Every200ms(); + case FUNC_EVERY_SECOND: + Pzem2EverySecond(); break; } } diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 6ebd00014..a810a0e27 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -26,7 +26,9 @@ * Hardware Serial will be selected if GPIO1 = [SAir Rx] and GPIO3 = [SAir Tx] \*********************************************************************************************/ -#include +#define SENSEAIR_MODBUS_SPEED 9600 +#define SENSEAIR_DEVICE_ADDRESS 0xFE // Any address +#define SENSEAIR_READ_REGISTER 0x04 // Command Read #ifndef CO2_LOW #define CO2_LOW 800 // Below this CO2 value show green light @@ -35,7 +37,8 @@ #define CO2_HIGH 1200 // Above this CO2 value show red light #endif -TasmotaSerial *SensairSerial; +#include +TasmotaModbus *SenseairModbus; const char kSenseairTypes[] PROGMEM = "Kx0|S8"; @@ -48,68 +51,6 @@ float senseair_humidity = 0; //uint8_t senseair_state = 0; -/*********************************************************************************************/ - -void ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) -{ - uint8_t frame[8]; - - frame[0] = 0xFE; // Any Address - frame[1] = function_code; - frame[2] = (uint8_t)(start_address >> 8); - frame[3] = (uint8_t)(start_address); - frame[4] = (uint8_t)(register_count >> 8); - frame[5] = (uint8_t)(register_count); - uint16_t crc = 0xFFFF; - for (uint8_t pos = 0; pos < sizeof(frame) -2; pos++) { - crc ^= (uint16_t)frame[pos]; // XOR byte into least sig. byte of crc - for (uint8_t i = 8; i != 0; i--) { // Loop over each bit - if ((crc & 0x0001) != 0) { // If the LSB is set - crc >>= 1; // Shift right and XOR 0xA001 - crc ^= 0xA001; - } - else { // Else LSB is not set - crc >>= 1; // Just shift right - } - } - } - frame[7] = (uint8_t)((crc >> 8) & 0xFF); - frame[6] = (uint8_t)(crc & 0xFF); - - SensairSerial->flush(); - SensairSerial->write(frame, sizeof(frame)); -} - -bool ModbusReceiveReady() -{ - return (SensairSerial->available() >= 5); // 5 - Error frame, 7 - Ok frame -} - -uint8_t ModbusReceive(uint16_t *value) -{ - uint8_t buffer[7]; - - uint8_t len = 0; - while (SensairSerial->available() > 0) { - buffer[len++] = (uint8_t)SensairSerial->read(); - if (3 == len) { - if (buffer[1] & 0x80) { // fe 84 02 f2 f1 - return buffer[2]; // 1 = Illegal Function, 2 = Illegal Data Address, 3 = Illegal Data Value - } - } - } - - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); - - if (len != sizeof(buffer)) { - return 9; // 9 = Unexpected result - } - *value = (buffer[3] << 8) | buffer[4]; - return 0; // 0 = No error -} - -/*********************************************************************************************/ - const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; uint8_t senseair_read_state = 0; @@ -122,10 +63,10 @@ void Senseair250ms() // Every 250 mSec // senseair_state = 0; uint16_t value = 0; - bool data_ready = ModbusReceiveReady(); + bool data_ready = SenseairModbus->ReceiveReady(); if (data_ready) { - uint8_t error = ModbusReceive(&value); + uint8_t error = SenseairModbus->Receive16BitRegister(&value); if (error) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); AddLog(LOG_LEVEL_DEBUG); @@ -179,7 +120,7 @@ void Senseair250ms() // Every 250 mSec if (0 == senseair_send_retry || data_ready) { senseair_send_retry = 5; - ModbusSend(0x04, (uint16_t)start_addresses[senseair_read_state], 1); + SenseairModbus->Send(SENSEAIR_DEVICE_ADDRESS, SENSEAIR_READ_REGISTER, (uint16_t)start_addresses[senseair_read_state], 1); } else { senseair_send_retry--; } @@ -193,9 +134,10 @@ void SenseairInit() { senseair_type = 0; if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { - SensairSerial = new TasmotaSerial(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX], 1); - if (SensairSerial->begin(9600)) { - if (SensairSerial->hardwareSerial()) { ClaimSerial(); } + 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; } } From 8345f3f87297f4fe3c5e78e53c854ac9377e824b Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 15 Oct 2018 22:30:26 +0200 Subject: [PATCH 05/54] Fix SerialSendRaw() to adjust for whitespace Fix SerialSendRaw() to adjust for whitespace removal --- sonoff/support.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/support.ino b/sonoff/support.ino index a81699a8c..6dd6776f0 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -755,6 +755,8 @@ void SerialSendRaw(char *codes, int size) char *p; char stemp[3]; uint8_t code; + + size = strlen(codes); // Force size to be strlen of codes, if whitespace was removed it will overrun into unwanted buffer space while (size > 0) { snprintf(stemp, sizeof(stemp), codes); From 5894cd97fcc1bdbf9efdbb187c4f503df268638f Mon Sep 17 00:00:00 2001 From: digiblur <3240875+digiblur@users.noreply.github.com> Date: Mon, 15 Oct 2018 18:32:14 -0500 Subject: [PATCH 06/54] Initial TuyaDimmer Support --- sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 172 +++++++++++++++++++++++++++++++-------- sonoff/sonoff_template.h | 13 ++- sonoff/xdrv_04_light.ino | 39 ++++++++- 4 files changed, 187 insertions(+), 39 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index a573849d3..eb99cc2a1 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -208,7 +208,7 @@ enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, D enum Ws2812ClockIndex { WS_SECOND, WS_MINUTE, WS_HOUR, WS_MARKER }; enum Ws2812Color { WS_RED, WS_GREEN, WS_BLUE }; -enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; +enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_SERIAL, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f03b9973b..898aef66c 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -200,6 +200,8 @@ char mqtt_data[MESSZ]; // MQTT publish buffer and web page char log_data[LOGSZ]; // Logging char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer String backlog[MAX_BACKLOG]; // Command backlog +uint8_t tuya_new_dim = 0; // Tuya dimmer value temp +boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction /********************************************************************************************/ @@ -350,6 +352,23 @@ void SetDevicePower(power_t rpower, int source) Serial.write('\n'); Serial.flush(); } + else if (TUYA_DIMMER == Settings.module && source != SRC_SWITCH ) { // ignore to prevent loop from pushing state from faceplate interaction + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: SetDevicePower.rpower=%d"), rpower); + AddLog(LOG_LEVEL_DEBUG); + Serial.write(0x55); // Tuya header 55AA + Serial.write(0xAA); + Serial.write(0x00); // version 00 + Serial.write(0x06); // Tuya command 06 + Serial.write(0x00); + Serial.write(0x05); // following data length 0x05 + Serial.write(0x01); // relay number 1,2,3 + Serial.write(0x01); + Serial.write(0x00); + Serial.write(0x01); + Serial.write(rpower); // status + Serial.write(0x0D + rpower); // checksum sum of all bytes in packet mod 256 + Serial.flush(); + } else if (EXS_RELAY == Settings.module) { SetLatchingRelay(rpower, 1); } @@ -2214,6 +2233,48 @@ void ArduinoOTAInit() /********************************************************************************************/ +void TuyaPacketProcess() +{ + char scmnd[20]; + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Packet Size=%d"), serial_in_byte_counter); + AddLog(LOG_LEVEL_DEBUG); + if (serial_in_byte_counter == 7 && serial_in_buffer[3] == 14 ) { // heartbeat packet + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); + } + if (serial_in_byte_counter == 12 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 5) { // on/off packet + if (serial_in_buffer[10] == 0) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd - Off State")); + ExecuteCommandPower(1, 0, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } else + { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd - On State")); + ExecuteCommandPower(1, 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } + serial_in_byte_counter = 0; + serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + } + if (serial_in_byte_counter == 15 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 8) { // dim packet + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Dim State=%d"), serial_in_buffer[13]); + AddLog(LOG_LEVEL_DEBUG); + tuya_new_dim = round(serial_in_buffer[13] * (100. / 255.)); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER=%d"), tuya_new_dim ); + AddLog(LOG_LEVEL_DEBUG); + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER_STR=%s"), scmnd ); + AddLog(LOG_LEVEL_DEBUG); + tuya_ignore_dim = true; + ExecuteCommand(scmnd, SRC_SWITCH); + serial_in_byte_counter = 0; + serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + } + if (serial_in_byte_counter == 8 && serial_in_buffer[3] == 5 && serial_in_buffer[5] == 1 && serial_in_buffer[7] == 5 ) { // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd")); + serial_in_byte_counter = 0; + serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " 2"); + ExecuteCommand(scmnd, SRC_BUTTON); + } +} void SerialInput() { while (Serial.available()) { @@ -2242,6 +2303,29 @@ void SerialInput() } } +/*-------------------------------------------------------------------------------------------*\ + * Tuya based Dimmer with Serial Communications to MCU dimmer +\*-------------------------------------------------------------------------------------------*/ + if (TUYA_DIMMER == Settings.module) { + if (serial_in_byte == '\x55') { // Start TUYA Packet + if (serial_in_byte_counter > 0 && serial_in_byte_counter < 11) { + TuyaPacketProcess(); + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: 0x55 Packet Start")); + serial_in_byte_counter = 0; + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; +// return; // test to see if we need this + } else { // read additional packets from TUYA + if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + serial_polling_window = millis(); +// return; // test to see if we need this + } else { + serial_in_byte_counter = 0; + } + } + } + /*-------------------------------------------------------------------------------------------*/ if (XdrvCall(FUNC_SERIAL)) { @@ -2251,33 +2335,33 @@ void SerialInput() } /*-------------------------------------------------------------------------------------------*/ - - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data... - 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) { // add char to string if it still fits - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } else { - serial_in_byte_counter = 0; - } + if (TUYA_DIMMER != Settings.module) { + if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data... + serial_in_byte_counter = 0; + Serial.flush(); + return; } - } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && - ((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - serial_polling_window = millis(); - } else { - serial_polling_window = 0; - break; + if (!Settings.flag.mqtt_serial) { + if (isprint(serial_in_byte)) { + if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits + 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) && + ((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + serial_polling_window = millis(); + } else { + serial_polling_window = 0; + break; + } } } } - /*-------------------------------------------------------------------------------------------*\ * Sonoff SC 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ @@ -2306,23 +2390,34 @@ void SerialInput() } } - if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { - serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - if (!Settings.flag.mqtt_serial_raw) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); - for (int i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + if (TUYA_DIMMER == Settings.module && serial_in_byte_counter > 6 && (millis() > (serial_polling_window + SERIAL_POLLING))) { + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: 0x55 Packet End: \"")); + for (int i = 0; i < serial_in_byte_counter; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, serial_in_buffer[i]); } - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); -// XdrvRulesProcess(); + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG); + TuyaPacketProcess(); + serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed serial_in_byte_counter = 0; + } else { + if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { + serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + if (!Settings.flag.mqtt_serial_raw) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); + for (int i = 0; i < serial_in_byte_counter; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + } + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); +// XdrvRulesProcess(); + serial_in_byte_counter = 0; + } } } - /********************************************************************************************/ void GpioSwitchPinMode(uint8_t index) @@ -2464,6 +2559,11 @@ void GpioInit() devices_present = 0; baudrate = 19200; } + else if (TUYA_DIMMER == Settings.module) { + Settings.flag.mqtt_serial = 0; + baudrate = 9600; + light_type = LT_SERIAL; + } else if (SONOFF_BN == Settings.module) { // PWM Single color led (White) light_type = LT_PWM1; } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index bac97a65c..134778d2c 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -241,6 +241,7 @@ enum SupportedModules { OBI, TECKIN, APLIC_WDP303075, + TUYA_DIMMER, MAXMODULE }; /********************************************************************************************/ @@ -418,7 +419,8 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { AILIGHT, // Light Bulbs PHILIPS, WITTY, // Development Devices - WEMOS + WEMOS, + TUYA_DIMMER }; // Default module settings @@ -1133,6 +1135,15 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO13 LED (0 = On, 1 = Off) GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) 0, 0, 0 + }, + { "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer) + 0, + GPIO_TXD, // TX to dimmer MCU + 0, + GPIO_RXD, // RX from dimmer MCU + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 } }; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 6c8aa938d..a4f58ae67 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -343,6 +343,37 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut os_delay_us(12); // TStop > 12us. } +// *************** Tuya Dimmer Serial Comms +void LightSerialDuty(uint8_t duty) +{ + if (duty > 0 && !tuya_ignore_dim ) { + if (duty < 25) { + duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself + } + Serial.write(0x55); // Tuya header 55AA + Serial.write(0xAA); + Serial.write(0x00); // version 00 + Serial.write(0x06); // Tuya command 06 - send order + Serial.write(0x00); + Serial.write(0x08); // following data length 0x08 + Serial.write(0x03); // dimmer id + Serial.write(0x02); // type=value + Serial.write(0x00); // length hi + Serial.write(0x04); // length low + Serial.write(0x00); // + Serial.write(0x00); // + Serial.write(0x00); // + Serial.write( duty ); // dim value (0-255) + Serial.write( byte(22 + duty) ); // checksum:sum of all bytes in packet mod 256 + Serial.flush(); + snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d"), duty); + AddLog(LOG_LEVEL_DEBUG); + } else { + tuya_ignore_dim = false; // reset flag + snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); + AddLog(LOG_LEVEL_DEBUG); + } +} /********************************************************************************************/ void LightInit() @@ -359,7 +390,7 @@ void LightInit() pinMode(pin[GPIO_PWM1 +i], OUTPUT); } } - if (LT_PWM1 == light_type) { + if (LT_PWM1 == light_type || LT_SERIAL == light_type) { Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color } if (SONOFF_LED == Settings.module) { // Fix Sonoff Led instabilities @@ -391,6 +422,9 @@ void LightInit() max_scheme = LS_MAX + WS2812_SCHEMES; } #endif // USE_WS2812 ************************************************************************ + else if (LT_SERIAL == light_type) { + light_subtype = LST_SINGLE; + } else { light_pdi_pin = pin[GPIO_DI]; light_pdcki_pin = pin[GPIO_DCKI]; @@ -821,6 +855,9 @@ void LightAnimate() if (light_type > LT_WS2812) { LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } + if (light_type == LT_SERIAL) { + LightSerialDuty(cur_col[0]); + } } } } From adf3ed56bfe6e5541b870d626eafd448ba376400 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 15 Oct 2018 23:27:43 -0300 Subject: [PATCH 07/54] Fix Bug for OTA URL if using core STAGE (2.5.0) --- sonoff/sonoff.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f03b9973b..bc354dbb1 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2043,7 +2043,8 @@ void Every250mSeconds() ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); #else // If using core stage or 2.5.0+ the syntax has changed - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(EspClient, mqtt_data)); + WiFiClient OTAclient; + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); #endif if (!ota_result) { #ifndef BE_MINIMAL From dbe7cf3bbc334cf8a74a8c47eeeb5e653e5f798f Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 16 Oct 2018 03:54:55 -0300 Subject: [PATCH 08/54] Fix Some Wifi Connection Issues https://github.com/arendst/Sonoff-Tasmota/issues/4044 --- sonoff/support.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 6dd6776f0..92068504f 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1349,7 +1349,7 @@ void WifiBegin(uint8_t flag) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186)); WiFi.mode(WIFI_OFF); // See https://github.com/esp8266/Arduino/issues/2186 #endif - + WiFi.persistent(false); // Solve possible wifi init errors WiFi.disconnect(true); // Delete SDK wifi config delay(200); WiFi.mode(WIFI_STA); // Disable AP mode From b88aabfd8de62fb4d52bcd616917055b14b151b7 Mon Sep 17 00:00:00 2001 From: Portisch Date: Tue, 16 Oct 2018 09:53:48 +0200 Subject: [PATCH 09/54] fix RF bridge raw receive --- sonoff/xdrv_06_snfbridge.ino | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 0533e2d4a..cacf9a1a0 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -301,7 +301,7 @@ void SonoffBridgeReceived() boolean SonoffBridgeSerialInput() { // iTead Rf Universal Transceiver Module Serial Protocol Version 1.0 (20170420) - int8_t receive_len = 0; + static int8_t receive_len = 0; if (sonoff_bridge_receive_flag) { if (sonoff_bridge_receive_raw_flag) { @@ -309,12 +309,12 @@ boolean SonoffBridgeSerialInput() serial_in_buffer[serial_in_byte_counter++] = 0xAA; } serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter > 2) { - if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { // AA A6 06 023908010155 55 - 06 is receive_len - receive_len = serial_in_buffer[2] + 3 - serial_in_byte_counter; // Get at least receive_len bytes + if (serial_in_byte_counter == 3) { + if ((0xA6 == serial_in_buffer[serial_in_byte_counter - 2]) || (0xAB == serial_in_buffer[serial_in_byte_counter - 2])) { // AA A6 06 023908010155 55 - 06 is receive_len + receive_len = serial_in_buffer[serial_in_byte_counter - 1]; // Get at least receive_len bytes } } - if ((0 == receive_len) && (0x55 == serial_in_byte)) { // 0x55 - End of text + if (((0 == receive_len) && (0x55 == serial_in_byte)) || (serial_in_byte_counter == receive_len + 4)) { // 0x55 - End of text SonoffBridgeReceivedRaw(); sonoff_bridge_receive_flag = 0; return 1; @@ -345,6 +345,7 @@ boolean SonoffBridgeSerialInput() serial_in_byte_counter = 0; serial_in_byte = 0; sonoff_bridge_receive_flag = 1; + receive_len = 0; } return 0; } From d47ab92862a2220ed25ecd90d67818b7a690abe9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Oct 2018 11:21:44 +0200 Subject: [PATCH 10/54] Fixxes and Add Tuya Dimmer * Fix RfRaw and SerialSend5 regression from 6.2.1.15 (#4072) * Fix Sonoff Bridge RfRaw receive (#4080) * Add support for Tuya Dimmer (#469, #4075) --- sonoff/_changelog.ino | 3 +++ sonoff/sonoff.ino | 26 +++++++++++++------------- sonoff/sonoff_template.h | 13 +++++++------ sonoff/support.ino | 6 +++--- sonoff/xdrv_06_snfbridge.ino | 12 ++++++------ 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d924329f9..93fdce4da 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,9 @@ * Add TasmotaModbus library for very basic modbus wrapper for TasmotaSerial * Change xsns_17_senseair.ino to use TasmotaModbus library * Fix xnrg_05_pzem2.ino for PZEM-014/016 support using TasmotaModbus library (#3694) + * Fix RfRaw and SerialSend5 regression from 6.2.1.15 (#4072) + * Fix Sonoff Bridge RfRaw receive (#4080) + * Add support for Tuya Dimmer (#469, #4075) * * 6.2.1.15 20181012 * Fix Color Temperature slider functionality regression from 6.2.1.5 (#4037) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index cfc91eab7..a5dbcef4e 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -201,7 +201,7 @@ char log_data[LOGSZ]; // Logging char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer String backlog[MAX_BACKLOG]; // Command backlog uint8_t tuya_new_dim = 0; // Tuya dimmer value temp -boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction +boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction /********************************************************************************************/ @@ -358,16 +358,16 @@ void SetDevicePower(power_t rpower, int source) Serial.write(0x55); // Tuya header 55AA Serial.write(0xAA); Serial.write(0x00); // version 00 - Serial.write(0x06); // Tuya command 06 + Serial.write(0x06); // Tuya command 06 Serial.write(0x00); Serial.write(0x05); // following data length 0x05 Serial.write(0x01); // relay number 1,2,3 - Serial.write(0x01); - Serial.write(0x00); - Serial.write(0x01); + Serial.write(0x01); + Serial.write(0x00); + Serial.write(0x01); Serial.write(rpower); // status Serial.write(0x0D + rpower); // checksum sum of all bytes in packet mod 256 - Serial.flush(); + Serial.flush(); } else if (EXS_RELAY == Settings.module) { SetLatchingRelay(rpower, 1); @@ -1021,7 +1021,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) Serial.printf("%s", Unescape(dataBuf, &dat_len)); // "Hello\f" } else if (5 == index) { - SerialSendRaw(RemoveSpace(dataBuf), strlen(dataBuf)); // "AA004566" + SerialSendRaw(RemoveSpace(dataBuf)); // "AA004566" } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } @@ -2062,7 +2062,7 @@ void Every250mSeconds() ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); #else // If using core stage or 2.5.0+ the syntax has changed - WiFiClient OTAclient; + WiFiClient OTAclient; ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); #endif if (!ota_result) { @@ -2241,7 +2241,7 @@ void TuyaPacketProcess() AddLog(LOG_LEVEL_DEBUG); if (serial_in_byte_counter == 7 && serial_in_buffer[3] == 14 ) { // heartbeat packet AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); - } + } if (serial_in_byte_counter == 12 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 5) { // on/off packet if (serial_in_buffer[10] == 0) { AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd - Off State")); @@ -2267,14 +2267,14 @@ void TuyaPacketProcess() ExecuteCommand(scmnd, SRC_SWITCH); serial_in_byte_counter = 0; serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - } + } if (serial_in_byte_counter == 8 && serial_in_buffer[3] == 5 && serial_in_buffer[5] == 1 && serial_in_buffer[7] == 5 ) { // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd")); serial_in_byte_counter = 0; serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " 2"); ExecuteCommand(scmnd, SRC_BUTTON); - } + } } void SerialInput() { @@ -2305,7 +2305,7 @@ void SerialInput() } /*-------------------------------------------------------------------------------------------*\ - * Tuya based Dimmer with Serial Communications to MCU dimmer + * Tuya based Dimmer with Serial Communications to MCU dimmer at 9600 baud \*-------------------------------------------------------------------------------------------*/ if (TUYA_DIMMER == Settings.module) { if (serial_in_byte == '\x55') { // Start TUYA Packet @@ -2391,7 +2391,7 @@ void SerialInput() } } - if (TUYA_DIMMER == Settings.module && serial_in_byte_counter > 6 && (millis() > (serial_polling_window + SERIAL_POLLING))) { + if (TUYA_DIMMER == Settings.module && serial_in_byte_counter > 6 && (millis() > (serial_polling_window + SERIAL_POLLING))) { snprintf_P(log_data, sizeof(log_data), PSTR("TYA: 0x55 Packet End: \"")); for (int i = 0; i < serial_in_byte_counter; i++) { snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, serial_in_buffer[i]); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 134778d2c..359466884 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -241,7 +241,7 @@ enum SupportedModules { OBI, TECKIN, APLIC_WDP303075, - TUYA_DIMMER, + TUYA_DIMMER, MAXMODULE }; /********************************************************************************************/ @@ -408,6 +408,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { NEO_COOLCAM, // Socket Relay Devices OBI, ESP_SWITCH, // Switch Devices + TUYA_DIMMER, // Dimmer Devices H801, // Light Devices MAGICHOME, ARILUX_LC01, @@ -419,8 +420,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { AILIGHT, // Light Bulbs PHILIPS, WITTY, // Development Devices - WEMOS, - TUYA_DIMMER + WEMOS }; // Default module settings @@ -1137,13 +1137,14 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0 }, { "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer) + // https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1 0, GPIO_TXD, // TX to dimmer MCU 0, GPIO_RXD, // RX from dimmer MCU - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0 + 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection + 0, 0, 0, 0, 0, 0 } }; diff --git a/sonoff/support.ino b/sonoff/support.ino index 6dd6776f0..1f8f4b912 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -750,13 +750,13 @@ void ClaimSerial() Settings.baudrate = baudrate / 1200; } -void SerialSendRaw(char *codes, int size) +void SerialSendRaw(char *codes) { char *p; char stemp[3]; uint8_t code; - - size = strlen(codes); // Force size to be strlen of codes, if whitespace was removed it will overrun into unwanted buffer space + + int size = strlen(codes); while (size > 0) { snprintf(stemp, sizeof(stemp), codes); diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index cacf9a1a0..7f983fee1 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -310,8 +310,8 @@ boolean SonoffBridgeSerialInput() } serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; if (serial_in_byte_counter == 3) { - if ((0xA6 == serial_in_buffer[serial_in_byte_counter - 2]) || (0xAB == serial_in_buffer[serial_in_byte_counter - 2])) { // AA A6 06 023908010155 55 - 06 is receive_len - receive_len = serial_in_buffer[serial_in_byte_counter - 1]; // Get at least receive_len bytes + if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { // AA A6 06 023908010155 55 - 06 is receive_len + receive_len = serial_in_buffer[2]; // Get at least receive_len bytes } } if (((0 == receive_len) && (0x55 == serial_in_byte)) || (serial_in_byte_counter == receive_len + 4)) { // 0x55 - End of text @@ -345,7 +345,7 @@ boolean SonoffBridgeSerialInput() serial_in_byte_counter = 0; serial_in_byte = 0; sonoff_bridge_receive_flag = 1; - receive_len = 0; + receive_len = 0; } return 0; } @@ -537,12 +537,12 @@ boolean SonoffBridgeCommand() sonoff_bridge_receive_raw_flag = 1; break; case 192: // 0xC0 - Beep - char beep[] = "AAC000C055"; - SerialSendRaw(beep, sizeof(beep)); + char beep[] = "AAC000C055\0"; + SerialSendRaw(beep); break; } } else { - SerialSendRaw(RemoveSpace(XdrvMailbox.data), strlen(XdrvMailbox.data)); + SerialSendRaw(RemoveSpace(XdrvMailbox.data)); sonoff_bridge_receive_raw_flag = 1; } } From ae28a50dc7b77042d841a3c20f04ea368e70899d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Oct 2018 14:00:14 +0200 Subject: [PATCH 11/54] Fix possible wifi connection error Fix possible wifi connection error (#4044, #4083) --- sonoff/_changelog.ino | 1 + sonoff/support.ino | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 93fdce4da..e383c041d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,6 +5,7 @@ * Fix RfRaw and SerialSend5 regression from 6.2.1.15 (#4072) * Fix Sonoff Bridge RfRaw receive (#4080) * Add support for Tuya Dimmer (#469, #4075) + * Fix possible wifi connection error (#4044, #4083) * * 6.2.1.15 20181012 * Fix Color Temperature slider functionality regression from 6.2.1.5 (#4037) diff --git a/sonoff/support.ino b/sonoff/support.ino index 5cf3f03b1..aa50e9cf2 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1349,7 +1349,8 @@ void WifiBegin(uint8_t flag) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186)); WiFi.mode(WIFI_OFF); // See https://github.com/esp8266/Arduino/issues/2186 #endif - WiFi.persistent(false); // Solve possible wifi init errors + + WiFi.persistent(false); // Solve possible wifi init errors (re-add at 6.2.1.16 #4044, #4083) WiFi.disconnect(true); // Delete SDK wifi config delay(200); WiFi.mode(WIFI_STA); // Disable AP mode From 04493965e4c14b43c53c5baef5798a8cdabb2272 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Oct 2018 14:15:20 +0200 Subject: [PATCH 12/54] Update PubSubClient lib Replaced PubSubClient library by EspEasy patched non-blocking version saving some 3k5 code space over arduino-mqtt library --- .../tests/testcases/mqtt_basic.py | 39 ---- .../testcases/mqtt_publish_in_callback.py | 59 ------ lib/PubSubClient-2.6.09/tests/testsuite.py | 181 ------------------ .../.gitignore | 0 .../.travis.yml | 0 .../CHANGES.txt | 0 .../LICENSE.txt | 0 .../README.md | 0 .../examples/mqtt_auth/mqtt_auth.ino | 0 .../examples/mqtt_basic/mqtt_basic.ino | 0 .../examples/mqtt_esp8266/mqtt_esp8266.ino | 24 +-- .../mqtt_publish_in_callback.ino | 0 .../mqtt_reconnect_nonblocking.ino | 0 .../examples/mqtt_stream/mqtt_stream.ino | 0 .../keywords.txt | 0 .../library.json | 0 .../library.properties | 0 .../src/PubSubClient.cpp | 24 ++- .../src/PubSubClient.h | 9 +- .../tests/.gitignore | 0 .../tests/Makefile | 0 .../tests/README.md | 0 .../tests/src/connect_spec.cpp | 17 -- .../tests/src/keepalive_spec.cpp | 0 .../tests/src/lib/Arduino.h | 0 .../tests/src/lib/BDDTest.cpp | 0 .../tests/src/lib/BDDTest.h | 0 .../tests/src/lib/Buffer.cpp | 4 - .../tests/src/lib/Buffer.h | 0 .../tests/src/lib/Client.h | 0 .../tests/src/lib/IPAddress.cpp | 0 .../tests/src/lib/IPAddress.h | 0 .../tests/src/lib/ShimClient.cpp | 0 .../tests/src/lib/ShimClient.h | 0 .../tests/src/lib/Stream.cpp | 0 .../tests/src/lib/Stream.h | 0 .../tests/src/lib/trace.h | 0 .../tests/src/publish_spec.cpp | 0 .../tests/src/receive_spec.cpp | 0 .../tests/src/subscribe_spec.cpp | 0 .../tests/testcases/__init__.py | 0 .../tests/testcases/mqtt_basic.py | 43 +++++ .../testcases/mqtt_publish_in_callback.py | 64 +++++++ .../tests/testcases/settings.py | 0 .../tests/testsuite.py | 179 +++++++++++++++++ 45 files changed, 316 insertions(+), 327 deletions(-) delete mode 100644 lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py delete mode 100644 lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py delete mode 100644 lib/PubSubClient-2.6.09/tests/testsuite.py rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/.gitignore (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/.travis.yml (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/CHANGES.txt (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/LICENSE.txt (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/README.md (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/examples/mqtt_auth/mqtt_auth.ino (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/examples/mqtt_basic/mqtt_basic.ino (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/examples/mqtt_esp8266/mqtt_esp8266.ino (94%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/examples/mqtt_stream/mqtt_stream.ino (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/keywords.txt (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/library.json (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/library.properties (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/src/PubSubClient.cpp (96%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/src/PubSubClient.h (97%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/.gitignore (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/Makefile (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/README.md (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/connect_spec.cpp (92%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/keepalive_spec.cpp (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/Arduino.h (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/BDDTest.cpp (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/BDDTest.h (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/Buffer.cpp (86%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/Buffer.h (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/Client.h (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/IPAddress.cpp (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/IPAddress.h (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/ShimClient.cpp (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/ShimClient.h (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/Stream.cpp (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/Stream.h (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/lib/trace.h (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/publish_spec.cpp (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/receive_spec.cpp (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/src/subscribe_spec.cpp (100%) rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/testcases/__init__.py (100%) create mode 100644 lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py create mode 100644 lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py rename lib/{PubSubClient-2.6.09 => PubSubClient-EspEasy-2.6.09}/tests/testcases/settings.py (100%) create mode 100644 lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py diff --git a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py b/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py deleted file mode 100644 index f23ef71c1..000000000 --- a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py +++ /dev/null @@ -1,39 +0,0 @@ -import unittest -import settings -import time -import mosquitto - - -def on_message(mosq, obj, msg): - obj.message_queue.append(msg) - - -class mqtt_basic(unittest.TestCase): - - message_queue = [] - - @classmethod - def setUpClass(self): - self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) - self.client.connect(settings.server_ip) - self.client.on_message = on_message - self.client.subscribe("outTopic", 0) - - @classmethod - def tearDownClass(self): - self.client.disconnect() - - def test_one(self): - i = 30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - self.assertTrue(i > 0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue[0] - self.assertEqual(msg.mid, 0, "message id not 0") - self.assertEqual(msg.topic, "outTopic", "message topic incorrect") - self.assertEqual(msg.payload, "hello world") - self.assertEqual(msg.qos, 0, "message qos not 0") - self.assertEqual(msg.retain, False, "message retain flag incorrect") diff --git a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py b/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py deleted file mode 100644 index 45b0a8515..000000000 --- a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py +++ /dev/null @@ -1,59 +0,0 @@ -import unittest -import settings -import time -import mosquitto - - -def on_message(mosq, obj, msg): - obj.message_queue.append(msg) - - -class mqtt_publish_in_callback(unittest.TestCase): - - message_queue = [] - - @classmethod - def setUpClass(self): - self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) - self.client.connect(settings.server_ip) - self.client.on_message = on_message - self.client.subscribe("outTopic", 0) - - @classmethod - def tearDownClass(self): - self.client.disconnect() - - def test_connect(self): - i = 30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - self.assertTrue(i > 0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue.pop(0) - self.assertEqual(msg.mid, 0, "message id not 0") - self.assertEqual(msg.topic, "outTopic", "message topic incorrect") - self.assertEqual(msg.payload, "hello world") - self.assertEqual(msg.qos, 0, "message qos not 0") - self.assertEqual(msg.retain, False, "message retain flag incorrect") - - def test_publish(self): - self.assertEqual(len(self.message_queue), 0, "message queue not empty") - payload = "abcdefghij" - self.client.publish("inTopic", payload) - - i = 30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - - self.assertTrue(i > 0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue.pop(0) - self.assertEqual(msg.mid, 0, "message id not 0") - self.assertEqual(msg.topic, "outTopic", "message topic incorrect") - self.assertEqual(msg.payload, payload) - self.assertEqual(msg.qos, 0, "message qos not 0") - self.assertEqual(msg.retain, False, "message retain flag incorrect") diff --git a/lib/PubSubClient-2.6.09/tests/testsuite.py b/lib/PubSubClient-2.6.09/tests/testsuite.py deleted file mode 100644 index 788fc5d97..000000000 --- a/lib/PubSubClient-2.6.09/tests/testsuite.py +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/env python -import os -import os.path -import sys -import shutil -from subprocess import call -import importlib -import unittest -import re - -from testcases import settings - - -class Workspace(object): - - def __init__(self): - self.root_dir = os.getcwd() - self.build_dir = os.path.join(self.root_dir, "tmpbin") - self.log_dir = os.path.join(self.root_dir, "logs") - self.tests_dir = os.path.join(self.root_dir, "testcases") - self.examples_dir = os.path.join(self.root_dir, "../PubSubClient/examples") - self.examples = [] - self.tests = [] - if not os.path.isdir("../PubSubClient"): - raise Exception("Cannot find PubSubClient library") - try: - return __import__('ino') - except ImportError: - raise Exception("ino tool not installed") - - def init(self): - if os.path.isdir(self.build_dir): - shutil.rmtree(self.build_dir) - os.mkdir(self.build_dir) - if os.path.isdir(self.log_dir): - shutil.rmtree(self.log_dir) - os.mkdir(self.log_dir) - - os.chdir(self.build_dir) - call(["ino", "init"]) - - shutil.copytree("../../PubSubClient", "lib/PubSubClient") - - filenames = [] - for root, dirs, files in os.walk(self.examples_dir): - filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] - filenames.sort() - for e in filenames: - self.examples.append(Sketch(self, e)) - - filenames = [] - for root, dirs, files in os.walk(self.tests_dir): - filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] - filenames.sort() - for e in filenames: - self.tests.append(Sketch(self, e)) - - def clean(self): - shutil.rmtree(self.build_dir) - - -class Sketch(object): - def __init__(self, wksp, fn): - self.w = wksp - self.filename = fn - self.basename = os.path.basename(self.filename) - self.build_log = os.path.join(self.w.log_dir, "%s.log" % (os.path.basename(self.filename),)) - self.build_err_log = os.path.join(self.w.log_dir, "%s.err.log" % (os.path.basename(self.filename),)) - self.build_upload_log = os.path.join(self.w.log_dir, "%s.upload.log" % (os.path.basename(self.filename),)) - - def build(self): - sys.stdout.write(" Build: ") - sys.stdout.flush() - - # Copy sketch over, replacing IP addresses as necessary - fin = open(self.filename, "r") - lines = fin.readlines() - fin.close() - fout = open(os.path.join(self.w.build_dir, "src", "sketch.ino"), "w") - for l in lines: - if re.match(r"^byte server\[\] = {", l): - fout.write("byte server[] = { %s };\n" % (settings.server_ip.replace(".", ", "),)) - elif re.match(r"^byte ip\[\] = {", l): - fout.write("byte ip[] = { %s };\n" % (settings.arduino_ip.replace(".", ", "),)) - else: - fout.write(l) - fout.flush() - fout.close() - - # Run build - fout = open(self.build_log, "w") - ferr = open(self.build_err_log, "w") - rc = call(["ino", "build"], stdout=fout, stderr=ferr) - fout.close() - ferr.close() - if rc == 0: - sys.stdout.write("pass") - sys.stdout.write("\n") - return True - else: - sys.stdout.write("fail") - sys.stdout.write("\n") - with open(self.build_err_log) as f: - for line in f: - print(" " + line) - return False - - def upload(self): - sys.stdout.write(" Upload: ") - sys.stdout.flush() - fout = open(self.build_upload_log, "w") - rc = call(["ino", "upload"], stdout=fout, stderr=fout) - fout.close() - if rc == 0: - sys.stdout.write("pass") - sys.stdout.write("\n") - return True - else: - sys.stdout.write("fail") - sys.stdout.write("\n") - with open(self.build_upload_log) as f: - for line in f: - print(" " + line) - return False - - def test(self): - # import the matching test case, if it exists - try: - basename = os.path.basename(self.filename)[:-4] - i = importlib.import_module("testcases." + basename) - except: - sys.stdout.write(" Test: no tests found") - sys.stdout.write("\n") - return - c = getattr(i, basename) - - testmethods = [m for m in dir(c) if m.startswith("test_")] - testmethods.sort() - tests = [] - for m in testmethods: - tests.append(c(m)) - - result = unittest.TestResult() - c.setUpClass() - if self.upload(): - sys.stdout.write(" Test: ") - sys.stdout.flush() - for t in tests: - t.run(result) - print(str(result.testsRun - len(result.failures) - len(result.errors)) + "/" + str(result.testsRun)) - if not result.wasSuccessful(): - if len(result.failures) > 0: - for f in result.failures: - print("-- " + str(f[0])) - print(f[1]) - if len(result.errors) > 0: - print(" Errors:") - for f in result.errors: - print("-- " + str(f[0])) - print(f[1]) - c.tearDownClass() - - -if __name__ == '__main__': - run_tests = True - - w = Workspace() - w.init() - - for e in w.examples: - print("--------------------------------------") - print("[" + e.basename + "]") - if e.build() and run_tests: - e.test() - for e in w.tests: - print("--------------------------------------") - print("[" + e.basename + "]") - if e.build() and run_tests: - e.test() - - w.clean() diff --git a/lib/PubSubClient-2.6.09/.gitignore b/lib/PubSubClient-EspEasy-2.6.09/.gitignore similarity index 100% rename from lib/PubSubClient-2.6.09/.gitignore rename to lib/PubSubClient-EspEasy-2.6.09/.gitignore diff --git a/lib/PubSubClient-2.6.09/.travis.yml b/lib/PubSubClient-EspEasy-2.6.09/.travis.yml similarity index 100% rename from lib/PubSubClient-2.6.09/.travis.yml rename to lib/PubSubClient-EspEasy-2.6.09/.travis.yml diff --git a/lib/PubSubClient-2.6.09/CHANGES.txt b/lib/PubSubClient-EspEasy-2.6.09/CHANGES.txt similarity index 100% rename from lib/PubSubClient-2.6.09/CHANGES.txt rename to lib/PubSubClient-EspEasy-2.6.09/CHANGES.txt diff --git a/lib/PubSubClient-2.6.09/LICENSE.txt b/lib/PubSubClient-EspEasy-2.6.09/LICENSE.txt similarity index 100% rename from lib/PubSubClient-2.6.09/LICENSE.txt rename to lib/PubSubClient-EspEasy-2.6.09/LICENSE.txt diff --git a/lib/PubSubClient-2.6.09/README.md b/lib/PubSubClient-EspEasy-2.6.09/README.md similarity index 100% rename from lib/PubSubClient-2.6.09/README.md rename to lib/PubSubClient-EspEasy-2.6.09/README.md diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_auth/mqtt_auth.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_auth/mqtt_auth.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_auth/mqtt_auth.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_auth/mqtt_auth.ino diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_basic/mqtt_basic.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_basic/mqtt_basic.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_basic/mqtt_basic.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_basic/mqtt_basic.ino diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino similarity index 94% rename from lib/PubSubClient-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino index 34333c9c1..e46f85f3e 100644 --- a/lib/PubSubClient-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino +++ b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino @@ -38,6 +38,14 @@ long lastMsg = 0; char msg[50]; int value = 0; +void setup() { + pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output + Serial.begin(115200); + setup_wifi(); + client.setServer(mqtt_server, 1883); + client.setCallback(callback); +} + void setup_wifi() { delay(10); @@ -53,8 +61,6 @@ void setup_wifi() { Serial.print("."); } - randomSeed(micros()); - Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); @@ -85,11 +91,8 @@ void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); - // Create a random client ID - String clientId = "ESP8266Client-"; - clientId += String(random(0xffff), HEX); // Attempt to connect - if (client.connect(clientId.c_str())) { + if (client.connect("ESP8266Client")) { Serial.println("connected"); // Once connected, publish an announcement... client.publish("outTopic", "hello world"); @@ -104,15 +107,6 @@ void reconnect() { } } } - -void setup() { - pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output - Serial.begin(115200); - setup_wifi(); - client.setServer(mqtt_server, 1883); - client.setCallback(callback); -} - void loop() { if (!client.connected()) { diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_stream/mqtt_stream.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_stream/mqtt_stream.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_stream/mqtt_stream.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_stream/mqtt_stream.ino diff --git a/lib/PubSubClient-2.6.09/keywords.txt b/lib/PubSubClient-EspEasy-2.6.09/keywords.txt similarity index 100% rename from lib/PubSubClient-2.6.09/keywords.txt rename to lib/PubSubClient-EspEasy-2.6.09/keywords.txt diff --git a/lib/PubSubClient-2.6.09/library.json b/lib/PubSubClient-EspEasy-2.6.09/library.json similarity index 100% rename from lib/PubSubClient-2.6.09/library.json rename to lib/PubSubClient-EspEasy-2.6.09/library.json diff --git a/lib/PubSubClient-2.6.09/library.properties b/lib/PubSubClient-EspEasy-2.6.09/library.properties similarity index 100% rename from lib/PubSubClient-2.6.09/library.properties rename to lib/PubSubClient-EspEasy-2.6.09/library.properties diff --git a/lib/PubSubClient-2.6.09/src/PubSubClient.cpp b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp similarity index 96% rename from lib/PubSubClient-2.6.09/src/PubSubClient.cpp rename to lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp index 11e1c874a..7d1d3e102 100644 --- a/lib/PubSubClient-2.6.09/src/PubSubClient.cpp +++ b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp @@ -117,8 +117,8 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass if (!connected()) { int result = 0; - if (domain != NULL) { - result = _client->connect(this->domain, this->port); + if (domain.length() != 0) { + result = _client->connect(this->domain.c_str(), this->port); } else { result = _client->connect(this->ip, this->port); } @@ -209,7 +209,6 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass boolean PubSubClient::readByte(uint8_t * result) { uint32_t previousMillis = millis(); while(!_client->available()) { - delay(1); // Add esp8266 de-blocking (Tasmota #790) uint32_t currentMillis = millis(); if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){ return false; @@ -241,11 +240,17 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { uint8_t start = 0; do { + if (len == 6) { + // Invalid remaining length encoding - kill the connection + _state = MQTT_DISCONNECTED; + _client->stop(); + return 0; + } if(!readByte(&digit)) return 0; buffer[len++] = digit; length += (digit & 127) * multiplier; multiplier *= 128; - } while ((digit & 128) != 0); + } while ((digit & 128) != 0 && len < (MQTT_MAX_PACKET_SIZE -2)); *lengthLength = len-1; if (isPublish) { @@ -336,6 +341,9 @@ boolean PubSubClient::loop() { } else if (type == MQTTPINGRESP) { pingOutstanding = false; } + } else if (!connected()) { + // readPacket has closed the connection + return false; } } return true; @@ -419,7 +427,7 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig lastOutActivity = millis(); - return rc == tlen + 4 + plength; + return rc == tlen + 3 + llen + plength; } boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { @@ -469,7 +477,7 @@ boolean PubSubClient::subscribe(const char* topic) { } boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { - if (qos < 0 || qos > 1) { + if (qos > 1) { return false; } if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { @@ -524,7 +532,7 @@ uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t po const char* idp = string; uint16_t i = 0; pos += 2; - while (*idp) { + while (*idp && pos < (MQTT_MAX_PACKET_SIZE - 2)) { buf[pos++] = *idp++; i++; } @@ -559,7 +567,7 @@ PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) { PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) { this->ip = ip; this->port = port; - this->domain = NULL; + this->domain = ""; return *this; } diff --git a/lib/PubSubClient-2.6.09/src/PubSubClient.h b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h similarity index 97% rename from lib/PubSubClient-2.6.09/src/PubSubClient.h rename to lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h index 7e37a472d..003df770e 100644 --- a/lib/PubSubClient-2.6.09/src/PubSubClient.h +++ b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h @@ -24,13 +24,13 @@ // MQTT_MAX_PACKET_SIZE : Maximum packet size #ifndef MQTT_MAX_PACKET_SIZE //#define MQTT_MAX_PACKET_SIZE 128 -//#define MQTT_MAX_PACKET_SIZE 512 // Tasmota #define MQTT_MAX_PACKET_SIZE 1000 // Tasmota v5.11.1c #endif // MQTT_KEEPALIVE : keepAlive interval in Seconds +// Keepalive timeout for default MQTT Broker is 10s #ifndef MQTT_KEEPALIVE -#define MQTT_KEEPALIVE 15 +#define MQTT_KEEPALIVE 10 #endif // MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds @@ -75,7 +75,7 @@ #define MQTTQOS1 (1 << 1) #define MQTTQOS2 (2 << 1) -#ifdef ESP8266 +#if defined(ESP8266) || defined(ESP32) #include #define MQTT_CALLBACK_SIGNATURE std::function callback #else @@ -97,7 +97,7 @@ private: boolean write(uint8_t header, uint8_t* buf, uint16_t length); uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); IPAddress ip; - const char* domain; + String domain; uint16_t port; Stream* stream; int _state; @@ -116,6 +116,7 @@ public: PubSubClient(const char*, uint16_t, Client& client, Stream&); PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + virtual ~PubSubClient() {} PubSubClient& setServer(IPAddress ip, uint16_t port); PubSubClient& setServer(uint8_t * ip, uint16_t port); diff --git a/lib/PubSubClient-2.6.09/tests/.gitignore b/lib/PubSubClient-EspEasy-2.6.09/tests/.gitignore similarity index 100% rename from lib/PubSubClient-2.6.09/tests/.gitignore rename to lib/PubSubClient-EspEasy-2.6.09/tests/.gitignore diff --git a/lib/PubSubClient-2.6.09/tests/Makefile b/lib/PubSubClient-EspEasy-2.6.09/tests/Makefile similarity index 100% rename from lib/PubSubClient-2.6.09/tests/Makefile rename to lib/PubSubClient-EspEasy-2.6.09/tests/Makefile diff --git a/lib/PubSubClient-2.6.09/tests/README.md b/lib/PubSubClient-EspEasy-2.6.09/tests/README.md similarity index 100% rename from lib/PubSubClient-2.6.09/tests/README.md rename to lib/PubSubClient-EspEasy-2.6.09/tests/README.md diff --git a/lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp similarity index 92% rename from lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp index 3c46e0cc4..69f18646f 100644 --- a/lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp @@ -133,23 +133,6 @@ int test_connect_accepts_username_no_password() { END_IT } -int test_connect_accepts_username_blank_password() { - IT("accepts a username and blank password"); - ShimClient shimClient; - shimClient.setAllowConnect(true); - - byte connect[] = { 0x10,0x20,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x0}; - byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; - shimClient.expect(connect,0x26); - shimClient.respond(connack,4); - - PubSubClient client(server, 1883, callback, shimClient); - int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); - IS_TRUE(rc); - IS_FALSE(shimClient.error()); - - END_IT -} int test_connect_ignores_password_no_username() { IT("ignores a password but no username"); diff --git a/lib/PubSubClient-2.6.09/tests/src/keepalive_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/keepalive_spec.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/keepalive_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/keepalive_spec.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Arduino.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Arduino.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Arduino.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Arduino.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp similarity index 86% rename from lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp index f07759a3a..59a2fbbbd 100644 --- a/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp @@ -2,13 +2,9 @@ #include "Arduino.h" Buffer::Buffer() { - this->pos = 0; - this->length = 0; } Buffer::Buffer(uint8_t* buf, size_t size) { - this->pos = 0; - this->length = 0; this->add(buf,size); } bool Buffer::available() { diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Buffer.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Client.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Client.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Client.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Client.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Stream.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Stream.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Stream.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Stream.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/trace.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/trace.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/trace.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/trace.h diff --git a/lib/PubSubClient-2.6.09/tests/src/publish_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/publish_spec.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/publish_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/publish_spec.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/receive_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/receive_spec.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/receive_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/receive_spec.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/subscribe_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/subscribe_spec.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/subscribe_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/subscribe_spec.cpp diff --git a/lib/PubSubClient-2.6.09/tests/testcases/__init__.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/__init__.py similarity index 100% rename from lib/PubSubClient-2.6.09/tests/testcases/__init__.py rename to lib/PubSubClient-EspEasy-2.6.09/tests/testcases/__init__.py diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py new file mode 100644 index 000000000..1b0cc65bb --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py @@ -0,0 +1,43 @@ +import unittest +import settings + +import time +import mosquitto + +import serial + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + +class mqtt_basic(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic",0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_one(self): + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue[0] + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,"hello world") + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py new file mode 100644 index 000000000..7989f7f17 --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py @@ -0,0 +1,64 @@ +import unittest +import settings + +import time +import mosquitto + +import serial + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + +class mqtt_publish_in_callback(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic",0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_connect(self): + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,"hello world") + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + def test_publish(self): + self.assertEqual(len(self.message_queue), 0, "message queue not empty") + payload = "abcdefghij" + self.client.publish("inTopic",payload) + + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,payload) + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + diff --git a/lib/PubSubClient-2.6.09/tests/testcases/settings.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/settings.py similarity index 100% rename from lib/PubSubClient-2.6.09/tests/testcases/settings.py rename to lib/PubSubClient-EspEasy-2.6.09/tests/testcases/settings.py diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py new file mode 100644 index 000000000..0a8e70dfd --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +import os +import os.path +import sys +import shutil +from subprocess import call +import importlib +import unittest +import re + +from testcases import settings + +class Workspace(object): + + def __init__(self): + self.root_dir = os.getcwd() + self.build_dir = os.path.join(self.root_dir,"tmpbin"); + self.log_dir = os.path.join(self.root_dir,"logs"); + self.tests_dir = os.path.join(self.root_dir,"testcases"); + self.examples_dir = os.path.join(self.root_dir,"../PubSubClient/examples") + self.examples = [] + self.tests = [] + if not os.path.isdir("../PubSubClient"): + raise Exception("Cannot find PubSubClient library") + try: + import ino + except: + raise Exception("ino tool not installed") + + def init(self): + if os.path.isdir(self.build_dir): + shutil.rmtree(self.build_dir) + os.mkdir(self.build_dir) + if os.path.isdir(self.log_dir): + shutil.rmtree(self.log_dir) + os.mkdir(self.log_dir) + + os.chdir(self.build_dir) + call(["ino","init"]) + + shutil.copytree("../../PubSubClient","lib/PubSubClient") + + filenames = [] + for root, dirs, files in os.walk(self.examples_dir): + filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.examples.append(Sketch(self,e)) + + filenames = [] + for root, dirs, files in os.walk(self.tests_dir): + filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.tests.append(Sketch(self,e)) + + def clean(self): + shutil.rmtree(self.build_dir) + +class Sketch(object): + def __init__(self,wksp,fn): + self.w = wksp + self.filename = fn + self.basename = os.path.basename(self.filename) + self.build_log = os.path.join(self.w.log_dir,"%s.log"%(os.path.basename(self.filename),)) + self.build_err_log = os.path.join(self.w.log_dir,"%s.err.log"%(os.path.basename(self.filename),)) + self.build_upload_log = os.path.join(self.w.log_dir,"%s.upload.log"%(os.path.basename(self.filename),)) + + def build(self): + sys.stdout.write(" Build: ") + sys.stdout.flush() + + # Copy sketch over, replacing IP addresses as necessary + fin = open(self.filename,"r") + lines = fin.readlines() + fin.close() + fout = open(os.path.join(self.w.build_dir,"src","sketch.ino"),"w") + for l in lines: + if re.match(r"^byte server\[\] = {",l): + fout.write("byte server[] = { %s };\n"%(settings.server_ip.replace(".",", "),)) + elif re.match(r"^byte ip\[\] = {",l): + fout.write("byte ip[] = { %s };\n"%(settings.arduino_ip.replace(".",", "),)) + else: + fout.write(l) + fout.flush() + fout.close() + + # Run build + fout = open(self.build_log, "w") + ferr = open(self.build_err_log, "w") + rc = call(["ino","build"],stdout=fout,stderr=ferr) + fout.close() + ferr.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_err_log) as f: + for line in f: + print " ",line, + return False + + def upload(self): + sys.stdout.write(" Upload: ") + sys.stdout.flush() + fout = open(self.build_upload_log, "w") + rc = call(["ino","upload"],stdout=fout,stderr=fout) + fout.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_upload_log) as f: + for line in f: + print " ",line, + return False + + + def test(self): + # import the matching test case, if it exists + try: + basename = os.path.basename(self.filename)[:-4] + i = importlib.import_module("testcases."+basename) + except: + sys.stdout.write(" Test: no tests found") + sys.stdout.write("\n") + return + c = getattr(i,basename) + + testmethods = [m for m in dir(c) if m.startswith("test_")] + testmethods.sort() + tests = [] + for m in testmethods: + tests.append(c(m)) + + result = unittest.TestResult() + c.setUpClass() + if self.upload(): + sys.stdout.write(" Test: ") + sys.stdout.flush() + for t in tests: + t.run(result) + print "%d/%d"%(result.testsRun-len(result.failures)-len(result.errors),result.testsRun) + if not result.wasSuccessful(): + if len(result.failures) > 0: + for f in result.failures: + print "-- %s"%(str(f[0]),) + print f[1] + if len(result.errors) > 0: + print " Errors:" + for f in result.errors: + print "-- %s"%(str(f[0]),) + print f[1] + c.tearDownClass() + +if __name__ == '__main__': + run_tests = True + + w = Workspace() + w.init() + + for e in w.examples: + print "--------------------------------------" + print "[%s]"%(e.basename,) + if e.build() and run_tests: + e.test() + for e in w.tests: + print "--------------------------------------" + print "[%s]"%(e.basename,) + if e.build() and run_tests: + e.test() + + w.clean() From 2085f24675f440cc56bc5afbc0e16d679ffd1972 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Oct 2018 14:33:31 +0200 Subject: [PATCH 13/54] Update changelog Update PubSubClient Mqtt library to non-blocking EspEasy version --- sonoff/_changelog.ino | 1 + sonoff/user_config.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e383c041d..0feb0a38d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -6,6 +6,7 @@ * Fix Sonoff Bridge RfRaw receive (#4080) * Add support for Tuya Dimmer (#469, #4075) * Fix possible wifi connection error (#4044, #4083) + * Update PubSubClient Mqtt library to non-blocking EspEasy version * * 6.2.1.15 20181012 * Fix Color Temperature slider functionality regression from 6.2.1.5 (#4037) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 740027277..1cd393017 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -219,7 +219,7 @@ /*-------------------------------------------------------------------------------------------*\ * Select ONE of possible MQTT library types below \*-------------------------------------------------------------------------------------------*/ - // Default MQTT driver for both non-TLS and TLS connections. Blocks network if MQTT server is unavailable. + // Default MQTT driver for both non-TLS and TLS connections. Latest library version (20181016) does not block network if MQTT server is unavailable. //#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library // Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support //#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only From d33af3bb8d6a09592d58114b6aee2d735bee8020 Mon Sep 17 00:00:00 2001 From: Ben Lebherz Date: Tue, 16 Oct 2018 14:38:09 +0200 Subject: [PATCH 14/54] introduce some common python coding styles, remove mixed tabs/spaces and unused imports --- tools/fw_server/fw-server.py | 73 +++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/tools/fw_server/fw-server.py b/tools/fw_server/fw-server.py index 867d89709..8d20b9793 100644 --- a/tools/fw_server/fw-server.py +++ b/tools/fw_server/fw-server.py @@ -1,22 +1,24 @@ #!/usr/bin/env python3 +# coding=utf-8 """ - fw-server.py - firmware server for Sonoff-Tasmota OTA upgrade +fw-server.py - firmware server for Sonoff-Tasmota OTA upgrade - Copyright (C) 2018 Gennaro Tortone +Copyright (C) 2018 Gennaro Tortone - 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 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. +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 . - You should have received a copy of the GNU General Public License - along with this program. If not, see . Requirements: - Python3 @@ -31,26 +33,28 @@ Instructions: Firmware Upgrade -> Upgrade by web server http://:5000/sonoff-minimal.bin + Usage: - ./fw-server.py -d (default: eth0) - or - ./fw-server.py -i + ./fw-server.py -d (default: eth0) + or + ./fw-server.py -i Example: - ./fw-server.py -d wlan0 - or - ./fw-server.py -i 192.168.1.10 + ./fw-server.py -d wlan0 + or + ./fw-server.py -i 192.168.1.10 """ -import io import os.path -from sys import exit -from flask import Flask, send_file from optparse import OptionParser +from sys import exit + +from flask import Flask, send_file import netifaces as ni usage = "usage: fw-server {-d | -i} arg" + parser = OptionParser(usage) parser.add_option("-d", "--dev", action="store", type="string", dest="netdev", default="eth0", help="network interface (default: eth0)") @@ -58,23 +62,30 @@ parser.add_option("-i", "--ip", action="store", type="string", dest="ip", help="IP address to bind") (options, args) = parser.parse_args() +netip = None + if options.ip is None: - try: - netip = ni.ifaddresses(options.netdev)[ni.AF_INET][0]['addr'] - except Exception as e: - print("E: network interface error - {}".format(e)) - exit(1) + try: + netip = ni.ifaddresses(options.netdev)[ni.AF_INET][0]['addr'] + except Exception as e: + print("E: network interface error - {}".format(e)) + exit(1) else: - netip = options.ip + netip = options.ip + app = Flask(__name__) + @app.route('/') def fw(filename): - if(os.path.exists("fw/" + str(filename))): - return send_file("fw/" + str(filename), attachment_filename=filename, mimetype='application/octet-stream') - else: - return("ERROR: file not found") + if os.path.exists("fw/" + str(filename)): + return send_file("fw/" + str(filename), + attachment_filename=filename, + mimetype='application/octet-stream') + + return "ERROR: file not found" + if __name__ == "__main__": try: From c8a04e88b0949fde40a1d8cd4e0fc9231c202c36 Mon Sep 17 00:00:00 2001 From: Ben Lebherz Date: Tue, 16 Oct 2018 15:03:18 +0200 Subject: [PATCH 15/54] remove empty line to trigger travis (staled) once again --- tools/fw_server/fw-server.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/fw_server/fw-server.py b/tools/fw_server/fw-server.py index 8d20b9793..536c76785 100644 --- a/tools/fw_server/fw-server.py +++ b/tools/fw_server/fw-server.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 # coding=utf-8 - """ fw-server.py - firmware server for Sonoff-Tasmota OTA upgrade From b2ca987195407e26ac917fcae49ac9e08e090d4d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Oct 2018 17:27:01 +0200 Subject: [PATCH 16/54] Fix Sonoff Bridge RfRaw Fix Sonoff Bridge RfRaw receive (#4080, #4085) --- sonoff/_changelog.ino | 2 +- sonoff/xdrv_06_snfbridge.ino | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0feb0a38d..e7ce596bf 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,7 +3,7 @@ * Change xsns_17_senseair.ino to use TasmotaModbus library * Fix xnrg_05_pzem2.ino for PZEM-014/016 support using TasmotaModbus library (#3694) * Fix RfRaw and SerialSend5 regression from 6.2.1.15 (#4072) - * Fix Sonoff Bridge RfRaw receive (#4080) + * Fix Sonoff Bridge RfRaw receive (#4080, #4085) * Add support for Tuya Dimmer (#469, #4075) * Fix possible wifi connection error (#4044, #4083) * Update PubSubClient Mqtt library to non-blocking EspEasy version diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 7f983fee1..8e9201b43 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -311,10 +311,10 @@ boolean SonoffBridgeSerialInput() 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])) { // AA A6 06 023908010155 55 - 06 is receive_len - receive_len = serial_in_buffer[2]; // Get at least receive_len bytes + receive_len = serial_in_buffer[2] + 4; // Get at least receive_len bytes } } - if (((0 == receive_len) && (0x55 == serial_in_byte)) || (serial_in_byte_counter == receive_len + 4)) { // 0x55 - End of text + if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { // 0x55 - End of text SonoffBridgeReceivedRaw(); sonoff_bridge_receive_flag = 0; return 1; From 0ab43909c3f851a70fd99cd58e8c357a61db330f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 17 Oct 2018 12:27:05 +0200 Subject: [PATCH 17/54] 6.2.1.17 Changes and Adds 6.2.1.17 20181017 * Enable updated non-blocking PubSubClient as default MQTT client * Update TasmotaModbus and TasmotaSerial libraries for support of serial 8N2 communication * Add support for Pzem-003/017 DC Energy monitoring module (#3694) * Change support for Pzem-014/016 AC Energy monitoring module (#3694) --- .../README.md | 0 .../examples/modbustest/modbustest.ino | 0 .../keywords.txt | 0 .../library.json | 2 +- .../library.properties | 2 +- .../src/TasmotaModbus.cpp | 28 +-- .../src/TasmotaModbus.h | 7 +- .../README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 0 .../library.json | 2 +- .../library.properties | 2 +- .../src/TasmotaSerial.cpp | 37 +++- .../src/TasmotaSerial.h | 6 +- sonoff/_changelog.ino | 8 +- sonoff/language/bg-BG.h | 6 +- sonoff/language/cs-CZ.h | 6 +- sonoff/language/de-DE.h | 6 +- sonoff/language/el-GR.h | 6 +- sonoff/language/en-GB.h | 6 +- sonoff/language/es-AR.h | 6 +- sonoff/language/fr-FR.h | 6 +- sonoff/language/he-HE.h | 6 +- sonoff/language/hu-HU.h | 6 +- sonoff/language/it-IT.h | 6 +- sonoff/language/nl-NL.h | 6 +- sonoff/language/pl-PL.h | 6 +- sonoff/language/pt-BR.h | 6 +- sonoff/language/pt-PT.h | 6 +- sonoff/language/ru-RU.h | 6 +- sonoff/language/tr-TR.h | 6 +- sonoff/language/uk-UK.h | 6 +- sonoff/language/zh-CN.h | 6 +- sonoff/language/zh-TW.h | 6 +- sonoff/sonoff_post.h | 3 +- sonoff/sonoff_template.h | 20 +-- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 27 ++- sonoff/user_config.h | 7 +- sonoff/xnrg_03_pzem004t.ino | 6 +- sonoff/xnrg_05_pzem2.ino | 162 ------------------ sonoff/xnrg_05_pzem_ac.ino | 126 ++++++++++++++ sonoff/xnrg_06_pzem_dc.ino | 125 ++++++++++++++ sonoff/xnrg_interface.ino | 10 +- tools/decode-status.py | 4 +- 45 files changed, 446 insertions(+), 254 deletions(-) rename lib/{TasmotaModbus-1.0.0 => TasmotaModbus-1.1.0}/README.md (100%) rename lib/{TasmotaModbus-1.0.0 => TasmotaModbus-1.1.0}/examples/modbustest/modbustest.ino (100%) rename lib/{TasmotaModbus-1.0.0 => TasmotaModbus-1.1.0}/keywords.txt (100%) rename lib/{TasmotaModbus-1.0.0 => TasmotaModbus-1.1.0}/library.json (93%) rename lib/{TasmotaModbus-1.0.0 => TasmotaModbus-1.1.0}/library.properties (93%) rename lib/{TasmotaModbus-1.0.0 => TasmotaModbus-1.1.0}/src/TasmotaModbus.cpp (83%) rename lib/{TasmotaModbus-1.0.0 => TasmotaModbus-1.1.0}/src/TasmotaModbus.h (92%) rename lib/{TasmotaSerial-2.0.0 => TasmotaSerial-2.1.0}/README.md (100%) rename lib/{TasmotaSerial-2.0.0 => TasmotaSerial-2.1.0}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-2.0.0 => TasmotaSerial-2.1.0}/keywords.txt (100%) rename lib/{TasmotaSerial-2.0.0 => TasmotaSerial-2.1.0}/library.json (94%) rename lib/{TasmotaSerial-2.0.0 => TasmotaSerial-2.1.0}/library.properties (94%) rename lib/{TasmotaSerial-2.0.0 => TasmotaSerial-2.1.0}/src/TasmotaSerial.cpp (91%) rename lib/{TasmotaSerial-2.0.0 => TasmotaSerial-2.1.0}/src/TasmotaSerial.h (95%) delete mode 100644 sonoff/xnrg_05_pzem2.ino create mode 100644 sonoff/xnrg_05_pzem_ac.ino create mode 100644 sonoff/xnrg_06_pzem_dc.ino diff --git a/lib/TasmotaModbus-1.0.0/README.md b/lib/TasmotaModbus-1.1.0/README.md similarity index 100% rename from lib/TasmotaModbus-1.0.0/README.md rename to lib/TasmotaModbus-1.1.0/README.md diff --git a/lib/TasmotaModbus-1.0.0/examples/modbustest/modbustest.ino b/lib/TasmotaModbus-1.1.0/examples/modbustest/modbustest.ino similarity index 100% rename from lib/TasmotaModbus-1.0.0/examples/modbustest/modbustest.ino rename to lib/TasmotaModbus-1.1.0/examples/modbustest/modbustest.ino diff --git a/lib/TasmotaModbus-1.0.0/keywords.txt b/lib/TasmotaModbus-1.1.0/keywords.txt similarity index 100% rename from lib/TasmotaModbus-1.0.0/keywords.txt rename to lib/TasmotaModbus-1.1.0/keywords.txt diff --git a/lib/TasmotaModbus-1.0.0/library.json b/lib/TasmotaModbus-1.1.0/library.json similarity index 93% rename from lib/TasmotaModbus-1.0.0/library.json rename to lib/TasmotaModbus-1.1.0/library.json index 06028d38b..d983bec32 100644 --- a/lib/TasmotaModbus-1.0.0/library.json +++ b/lib/TasmotaModbus-1.1.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaModbus", - "version": "1.0.0", + "version": "1.1.0", "keywords": [ "serial", "io", "TasmotaModbus" ], diff --git a/lib/TasmotaModbus-1.0.0/library.properties b/lib/TasmotaModbus-1.1.0/library.properties similarity index 93% rename from lib/TasmotaModbus-1.0.0/library.properties rename to lib/TasmotaModbus-1.1.0/library.properties index f7bcfcd1a..bb42fb372 100644 --- a/lib/TasmotaModbus-1.0.0/library.properties +++ b/lib/TasmotaModbus-1.1.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaModbus -version=1.0.0 +version=1.1.0 author=Theo Arends maintainer=Theo Arends sentence=Basic modbus wrapper for TasmotaSerial for ESP8266. diff --git a/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.cpp b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp similarity index 83% rename from lib/TasmotaModbus-1.0.0/src/TasmotaModbus.cpp rename to lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp index d242d83a7..0be2c9de3 100644 --- a/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.cpp +++ b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp @@ -21,10 +21,7 @@ TasmotaModbus::TasmotaModbus(int receive_pin, int transmit_pin) : TasmotaSerial(receive_pin, transmit_pin, 1) { -} - -TasmotaModbus::~TasmotaModbus() -{ + mb_address = 0; } uint16_t CalculateCRC(uint8_t *frame, uint8_t num) @@ -46,11 +43,11 @@ uint16_t CalculateCRC(uint8_t *frame, uint8_t num) return crc; } -int TasmotaModbus::Begin(long speed) +int TasmotaModbus::Begin(long speed, int stop_bits) { int result = 0; - if (begin(speed)) { + if (begin(speed, stop_bits)) { result = 1; if (hardwareSerial()) { result = 2; } } @@ -61,7 +58,9 @@ void TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint16_t { uint8_t frame[8]; - frame[0] = device_address; // 0xFE default device address or dedicated like 0x01 + mb_address = device_address; // Save address for receipt check + + frame[0] = mb_address; // 0xFE default device address or dedicated like 0x01 frame[1] = function_code; frame[2] = (uint8_t)(start_address >> 8); frame[3] = (uint8_t)(start_address); @@ -85,10 +84,17 @@ uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t register_count) uint8_t len = 0; uint32_t last = millis(); while ((available() > 0) && (len < (register_count *2) + 5) && (millis() - last < 10)) { - buffer[len++] = (uint8_t)read(); - if (3 == len) { - if (buffer[1] & 0x80) { // fe 84 02 f2 f1 - return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error + uint8_t data = (uint8_t)read(); + if (!len) { // Skip leading data as provided by hardware serial + if (mb_address == data) { + buffer[len++] = data; + } + } else { + buffer[len++] = data; + if (3 == len) { + if (buffer[1] & 0x80) { // 01 84 02 f2 f1 + return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error + } } } last = millis(); diff --git a/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.h b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.h similarity index 92% rename from lib/TasmotaModbus-1.0.0/src/TasmotaModbus.h rename to lib/TasmotaModbus-1.1.0/src/TasmotaModbus.h index 664a66b42..5176aa89e 100644 --- a/lib/TasmotaModbus-1.0.0/src/TasmotaModbus.h +++ b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.h @@ -28,9 +28,9 @@ class TasmotaModbus : public TasmotaSerial { public: TasmotaModbus(int receive_pin, int transmit_pin); - ~TasmotaModbus(); + virtual ~TasmotaModbus() {} - int Begin(long speed = TM_MODBUS_BAUDRATE); + int Begin(long speed = TM_MODBUS_BAUDRATE, int stop_bits = 1); void Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t register_count); @@ -49,6 +49,9 @@ class TasmotaModbus : public TasmotaSerial { uint8_t ReceiveBuffer(uint8_t *buffer, uint8_t register_count); uint8_t Receive16BitRegister(uint16_t *value); uint8_t Receive32BitRegister(float *value); + + private: + uint8_t mb_address; }; #endif // TasmotaModbus_h diff --git a/lib/TasmotaSerial-2.0.0/README.md b/lib/TasmotaSerial-2.1.0/README.md similarity index 100% rename from lib/TasmotaSerial-2.0.0/README.md rename to lib/TasmotaSerial-2.1.0/README.md diff --git a/lib/TasmotaSerial-2.0.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-2.1.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-2.0.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-2.1.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-2.0.0/keywords.txt b/lib/TasmotaSerial-2.1.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-2.0.0/keywords.txt rename to lib/TasmotaSerial-2.1.0/keywords.txt diff --git a/lib/TasmotaSerial-2.0.0/library.json b/lib/TasmotaSerial-2.1.0/library.json similarity index 94% rename from lib/TasmotaSerial-2.0.0/library.json rename to lib/TasmotaSerial-2.1.0/library.json index 00a2a9e0f..59d06ad5f 100644 --- a/lib/TasmotaSerial-2.0.0/library.json +++ b/lib/TasmotaSerial-2.1.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaSerial", - "version": "2.0.0", + "version": "2.1.0", "keywords": [ "serial", "io", "TasmotaSerial" ], diff --git a/lib/TasmotaSerial-2.0.0/library.properties b/lib/TasmotaSerial-2.1.0/library.properties similarity index 94% rename from lib/TasmotaSerial-2.0.0/library.properties rename to lib/TasmotaSerial-2.1.0/library.properties index b250399b9..93f4a1d39 100644 --- a/lib/TasmotaSerial-2.0.0/library.properties +++ b/lib/TasmotaSerial-2.1.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaSerial -version=2.0.0 +version=2.1.0 author=Theo Arends maintainer=Theo Arends sentence=Implementation of software serial with hardware serial fallback for ESP8266. diff --git a/lib/TasmotaSerial-2.0.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp similarity index 91% rename from lib/TasmotaSerial-2.0.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp index cbd2a3523..d9fc29e6f 100644 --- a/lib/TasmotaSerial-2.0.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp @@ -80,6 +80,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa { m_valid = false; m_hardserial = 0; + m_stop_bits = 1; if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { return; } @@ -106,15 +107,33 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa m_valid = true; } +TasmotaSerial::~TasmotaSerial() +{ + if (!m_hardserial) { + if (m_rx_pin > -1) { + detachInterrupt(m_rx_pin); + tms_obj_list[m_rx_pin] = NULL; + if (m_buffer) { + free(m_buffer); + } + } + } +} + bool TasmotaSerial::isValidGPIOpin(int pin) { return (pin >= -1 && pin <= 5) || (pin >= 12 && pin <= 15); } -bool TasmotaSerial::begin(long speed) { +bool TasmotaSerial::begin(long speed, int stop_bits) { + m_stop_bits = ((stop_bits -1) &1) +1; if (m_hardserial) { Serial.flush(); - Serial.begin(speed, SERIAL_8N1); + if (2 == m_stop_bits) { + Serial.begin(speed, SERIAL_8N2); + } else { + Serial.begin(speed, SERIAL_8N1); + } } else { // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed; @@ -195,9 +214,11 @@ size_t TasmotaSerial::write(uint8_t b) TM_SERIAL_WAIT; b >>= 1; } - // Stop bit - digitalWrite(m_tx_pin, HIGH); - TM_SERIAL_WAIT; + // Stop bit(s) + for (int i = 0; i < m_stop_bits; i++) { + digitalWrite(m_tx_pin, HIGH); + TM_SERIAL_WAIT; + } if (m_high_speed) sei(); return 1; } @@ -220,8 +241,12 @@ void TasmotaSerial::rxRead() rec >>= 1; if (digitalRead(m_rx_pin)) rec |= 0x80; } - // Stop bit + // Stop bit(s) TM_SERIAL_WAIT; + if (2 == m_stop_bits) { + digitalRead(m_rx_pin); + TM_SERIAL_WAIT; + } // Store the received value in the buffer unless we have an overflow int next = (m_in_pos+1) % TM_SERIAL_BUFFER_SIZE; if (next != (int)m_out_pos) { diff --git a/lib/TasmotaSerial-2.0.0/src/TasmotaSerial.h b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h similarity index 95% rename from lib/TasmotaSerial-2.0.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h index d4c993368..e40c34ee8 100644 --- a/lib/TasmotaSerial-2.0.0/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h @@ -33,12 +33,15 @@ #define TM_SERIAL_USE_IRAM // Enable to use iram (+368 bytes) #endif +#include #include class TasmotaSerial : public Stream { public: TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback = false); - bool begin(long speed); + virtual ~TasmotaSerial(); + + bool begin(long speed, int stop_bits = 1); bool begin(); bool hardwareSerial(); int peek(); @@ -62,6 +65,7 @@ class TasmotaSerial : public Stream { bool m_high_speed; int m_rx_pin; int m_tx_pin; + int m_stop_bits; unsigned long m_bit_time; unsigned int m_in_pos; unsigned int m_out_pos; diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e7ce596bf..36de9f29c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,10 @@ -/* 6.2.1.16 20181015 +/* 6.2.1.17 20181017 + * Enable updated non-blocking PubSubClient as default MQTT client + * Update TasmotaModbus and TasmotaSerial libraries for support of serial 8N2 communication + * Add support for Pzem-003/017 DC Energy monitoring module (#3694) + * Change support for Pzem-014/016 AC Energy monitoring module (#3694) + * + * 6.2.1.16 20181015 * Add TasmotaModbus library for very basic modbus wrapper for TasmotaSerial * Change xsns_17_senseair.ino to use TasmotaModbus library * Fix xnrg_05_pzem2.ino for PZEM-014/016 support using TasmotaModbus library (#3694) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index a7d3fca7d..c485b79ff 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 2886b130f..ab548ad70 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 299e8207a..19cbff44b 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRRecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 2f320211d..c0873dd07 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index ad3762f8d..eed796889 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index b57985803..cf34dbce9 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IR RX" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 7e1098bed..b70cbbb8b 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "RécptIR" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index c6aec9681..736ea89aa 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 857cfec12..b33e4cc41 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRvevő" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 6b922cb4d..e819c8558 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index eb938970d..eef55f90a 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 0b6a07e7d..a99b9e972 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index f4c556ed9..fa8caec36 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHz Rx" #define D_SENSOR_MHZ_TX "MHz Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index f79f7a14c..ae2ee4316 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 4cea913e6..61c2c2f08 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index b24a355d8..1f542af3b 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 93b5f32cd..1b075a4b6 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 42a381f18..63f687f3e 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 92193f483..89222d077 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -482,8 +482,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM 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" diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 627110ca3..3db21b48f 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -136,7 +136,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor #undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor #undef USE_PZEM004T // Disable PZEM004T energy sensor -#undef USE_PZEM2 // Disable PZEM003,014,016,017 Energy monitor +#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor +#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 359466884..b7d591801 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -86,8 +86,8 @@ enum UserSelectablePins { GPIO_LED4_INV, GPIO_MHZ_TXD, // MH-Z19 Serial interface GPIO_MHZ_RXD, // MH-Z19 Serial interface - GPIO_PZEM_TX, // PZEM004T Serial interface - GPIO_PZEM_RX, // PZEM004T Serial interface + GPIO_PZEM0XX_TX, // PZEM0XX Serial interface + GPIO_PZEM004_RX, // PZEM004T Serial interface GPIO_SAIR_TX, // SenseAir Serial interface GPIO_SAIR_RX, // SenseAir Serial interface GPIO_SPI_CS, // SPI Chip Select @@ -122,8 +122,8 @@ enum UserSelectablePins { GPIO_CNTR2_NP, GPIO_CNTR3_NP, GPIO_CNTR4_NP, - GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface - GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface + GPIO_PZEM016_RX, // PZEM-014,016 Serial Modbus interface + GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface GPIO_HX711_SCK, // HX711 Load Cell clock @@ -168,7 +168,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_LED "1|" D_SENSOR_LED "2|" D_SENSOR_LED "3|" D_SENSOR_LED "4|" D_SENSOR_LED "1i|" D_SENSOR_LED "2i|" D_SENSOR_LED "3i|" D_SENSOR_LED "4i|" D_SENSOR_MHZ_TX "|" D_SENSOR_MHZ_RX "|" - D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" + D_SENSOR_PZEM0XX_TX "|" D_SENSOR_PZEM004_RX "|" D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|" D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|" D_SENSOR_BACKLIGHT "|" D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1_RX "|" @@ -180,7 +180,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SWITCH "1n|" D_SENSOR_SWITCH "2n|" D_SENSOR_SWITCH "3n|" D_SENSOR_SWITCH "4n|" D_SENSOR_SWITCH "5n|" D_SENSOR_SWITCH "6n|" D_SENSOR_SWITCH "7n|" D_SENSOR_SWITCH "8n|" D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|" D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|" - D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" + D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|" D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|" D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT; @@ -354,10 +354,10 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { GPIO_SAIR_RX, // SenseAir Serial interface GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface - GPIO_PZEM_TX, // PZEM004T Serial interface - GPIO_PZEM_RX, // PZEM004T Serial interface - GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface - GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface + GPIO_PZEM0XX_TX, // PZEM0XX Serial interface + GPIO_PZEM004_RX, // PZEM004T Serial interface + GPIO_PZEM016_RX, // PZEM-014,016 Serial Modbus interface + GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface GPIO_SDM120_TX, // SDM120 Serial interface GPIO_SDM120_RX, // SDM120 Serial interface GPIO_SDM630_TX, // SDM630 Serial interface diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 5c81a8b16..1ee95769f 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020110 +#define VERSION 0x06020111 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index aa50e9cf2..a18de8667 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -647,14 +647,22 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_MHZ_TXD == val) { return true; } if (GPIO_MHZ_RXD == val) { return true; } #endif + + int pzem = 3; #ifndef USE_PZEM004T - if (GPIO_PZEM_TX == val) { return true; } - if (GPIO_PZEM_RX == val) { return true; } + pzem--; + if (GPIO_PZEM004_RX == val) { return true; } #endif -#ifndef USE_PZEM2 - if (GPIO_PZEM2_TX == val) { return true; } - if (GPIO_PZEM2_RX == val) { return true; } +#ifndef USE_PZEM_AC + pzem--; + if (GPIO_PZEM016_RX == val) { return true; } #endif +#ifndef USE_PZEM_DC + pzem--; + if (GPIO_PZEM017_RX == val) { return true; } +#endif + if (!pzem && (GPIO_PZEM0XX_TX == val)) { return true; } + #ifndef USE_SENSEAIR if (GPIO_SAIR_TX == val) { return true; } if (GPIO_SAIR_RX == val) { return true; } @@ -1166,14 +1174,17 @@ void GetFeatures() #ifdef USE_MCP39F501 feature_sns2 |= 0x00000100; // xnrg_04_mcp39f501.ino #endif -#ifdef USE_PZEM2 - feature_sns2 |= 0x00000200; // xnrg_05_pzem2.ino +#ifdef USE_PZEM_AC + feature_sns2 |= 0x00000200; // xnrg_05_pzem_ac.ino #endif #ifdef USE_DS3231 feature_sns2 |= 0x00000400; // xsns_33_ds3231.ino #endif #ifdef USE_HX711 - feature_sns2 |= 0x00000400; // xsns_34_hx711.ino + feature_sns2 |= 0x00000800; // xsns_34_hx711.ino +#endif +#ifdef USE_PZEM_DC + feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino #endif } diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 1cd393017..1d66a92c4 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -220,11 +220,11 @@ * Select ONE of possible MQTT library types below \*-------------------------------------------------------------------------------------------*/ // Default MQTT driver for both non-TLS and TLS connections. Latest library version (20181016) does not block network if MQTT server is unavailable. -//#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library +#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library // Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support //#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only // Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested. -#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) +//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) // -- MQTT ---------------------------------------- #define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on) @@ -356,7 +356,8 @@ // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) -#define USE_PZEM2 // Add support for PZEM003,014,016,017 Energy monitor (+1k1 code) +#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) +#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) #define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) // -- Low level interface devices ----------------- diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 3dfbc3879..dae285b01 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -25,7 +25,7 @@ * Source: Victor Ferrer https://github.com/vicfergar/Sonoff-MQTT-OTA-Arduino * Based on: PZEM004T library https://github.com/olehs/PZEM004T * - * Hardware Serial will be selected if GPIO1 = [PZEM Rx] and [GPIO3 = PZEM Tx] + * Hardware Serial will be selected if GPIO1 = [63 PZEM004 Rx] and GPIO3 = [62 PZEM0XX Tx] \*********************************************************************************************/ #define XNRG_03 3 @@ -203,7 +203,7 @@ void PzemEvery200ms() void PzemSnsInit() { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions - PzemSerial = new TasmotaSerial(pin[GPIO_PZEM_RX], pin[GPIO_PZEM_TX], 1); + PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); if (PzemSerial->begin(9600)) { if (PzemSerial->hardwareSerial()) { ClaimSerial(); } } else { @@ -214,7 +214,7 @@ void PzemSnsInit() void PzemDrvInit() { if (!energy_flg) { - if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T + if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { // Any device with a Pzem004T energy_flg = XNRG_03; } } diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino deleted file mode 100644 index 2c9b35b50..000000000 --- a/sonoff/xnrg_05_pzem2.ino +++ /dev/null @@ -1,162 +0,0 @@ -/* - xnrg_06_pzem2.ino - PZEM-003,017 and PZEM-014,016 Modbus energy sensor support for Sonoff-Tasmota - - Copyright (C) 2018 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_ENERGY_SENSOR -#ifdef USE_PZEM2 -/*********************************************************************************************\ - * PZEM-003 - DC 300V 10A Energy - * PZEM-014 - AC 220V 10A Energy - * PZEM-016 - AC 220V 100A Energy - * PZEM-017 - DC 300V 50A - 300A Energy - * - * Based on: - * PZEM-003,017 docs Https://pan.baidu.com/s/1V9bDWj3RK2u6_fbBJ3GtqQ password rq37 - * PZEM-014,016 docs https://pan.baidu.com/s/1B0MdMgURyjtO1oQa2lavKw password ytkv - * - * Hardware Serial will be selected if GPIO1 = [99 PZEM Rx] and GPIO3 = [98 PZEM Tx] -\*********************************************************************************************/ - -#define XNRG_05 5 - -#define PZEM2_MODBUS_SPEED 9600 -#define PZEM2_DEVICE_ADDRESS 0x01 // PZEM default address -#define PZEM2_READ_RESULT 0x04 // Command Read result - -#define PZEM2_TYPES_003_017 8 // Result 8 x 16 bit register count -#define PZEM2_TYPES_014_016 10 // Result 10 x 16 bit register count - -#include -TasmotaModbus *Pzem2Modbus; - -uint8_t pzem2_type = PZEM2_TYPES_014_016; -uint8_t pzem2_sendRetry = 0; - -void Pzem2EverySecond() -{ - bool data_ready = Pzem2Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[26]; - - uint8_t error = Pzem2Modbus->ReceiveBuffer(buffer, pzem2_type); - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); - - if (error) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PZEM2 response error %d"), error); - AddLog(LOG_LEVEL_DEBUG); -// if (9 == error) { -/* - if (PZEM2_TYPES_014_016 == pzem2_type) { - pzem2_type = PZEM2_TYPES_003_017; - } else { - pzem2_type = PZEM2_TYPES_014_016; - } -*/ -// } - } else { - float energy = 0; - - if (PZEM2_TYPES_003_017 == pzem2_type) { - energy_type_dc = true; - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - // 01 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017 - // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- - energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V - energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A - energy_active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W - energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh - if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any - energy_kWhtoday += (energy - energy_start) * 100; - energy_start = energy; - EnergyUpdateToday(); - } - else if (PZEM2_TYPES_014_016 == pzem2_type) { // PZEM-014,016 - energy_type_dc = false; - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - // 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34 = PZEM-014 - // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- - energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V - energy_current = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A - energy_active_power = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W - energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz - energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 - energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh - if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any - energy_kWhtoday += (energy - energy_start) * 100; - energy_start = energy; - EnergyUpdateToday(); - } - } - } - - if (0 == pzem2_sendRetry || data_ready) { - pzem2_sendRetry = 5; - Pzem2Modbus->Send(PZEM2_DEVICE_ADDRESS, PZEM2_READ_RESULT, 0, pzem2_type); - } - else { - pzem2_sendRetry--; - } -} - -void Pzem2SnsInit() -{ - Pzem2Modbus = new TasmotaModbus(pin[GPIO_PZEM2_RX], pin[GPIO_PZEM2_TX]); - uint8_t result = Pzem2Modbus->Begin(PZEM2_MODBUS_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Pzem2DrvInit() -{ - if (!energy_flg) { - if ((pin[GPIO_PZEM2_RX] < 99) && (pin[GPIO_PZEM2_TX] < 99)) { // Any device with a Pzem-003,014,016,017 - energy_flg = XNRG_05; - } - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -int Xnrg05(byte function) -{ - int result = 0; - - if (FUNC_PRE_INIT == function) { - Pzem2DrvInit(); - } - else if (XNRG_05 == energy_flg) { - switch (function) { - case FUNC_INIT: - Pzem2SnsInit(); - break; - case FUNC_EVERY_SECOND: - Pzem2EverySecond(); - break; - } - } - return result; -} - -#endif // USE_PZEM2 -#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino new file mode 100644 index 000000000..ca2262bb5 --- /dev/null +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -0,0 +1,126 @@ +/* + xnrg_05_pzem_ac.ino - PZEM-014,016 Modbus AC energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 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_ENERGY_SENSOR +#ifdef USE_PZEM_AC +/*********************************************************************************************\ + * PZEM-014 - AC 220V 10A Energy + * PZEM-016 - AC 220V 100A Energy + * + * Based on: + * PZEM-014,016 docs https://pan.baidu.com/s/1B0MdMgURyjtO1oQa2lavKw password ytkv + * + * Hardware Serial will be selected if GPIO1 = [98 PZEM016 Rx] and GPIO3 = [62 PZEM0XX Tx] +\*********************************************************************************************/ + +#define XNRG_05 5 + +#define PZEM_AC_DEVICE_ADDRESS 0x01 // PZEM default address + +#include +TasmotaModbus *PzemAcModbus; + +void PzemAcEverySecond() +{ + static uint8_t send_retry = 0; + + bool data_ready = PzemAcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[26]; + + uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, 10); + AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + + if (error) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemAc response error %d"), error); + AddLog(LOG_LEVEL_DEBUG); + } else { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + // 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34 + // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V + energy_current = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A + energy_active_power = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W + energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz + energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 + float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh + + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any + energy_kWhtoday += (energy - energy_start) * 100; + energy_start = energy; + EnergyUpdateToday(); + } + } + + if (0 == send_retry || data_ready) { + send_retry = 5; + PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS, 0x04, 0, 10); + } + else { + send_retry--; + } +} + +void PzemAcSnsInit() +{ + PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemAcModbus->Begin(9600); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemAcDrvInit() +{ + if (!energy_flg) { + if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_05; + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg05(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + PzemAcDrvInit(); + } + else if (XNRG_05 == energy_flg) { + switch (function) { + case FUNC_INIT: + PzemAcSnsInit(); + break; + case FUNC_EVERY_SECOND: + PzemAcEverySecond(); + break; + } + } + return result; +} + +#endif // USE_PZEM_AC +#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino new file mode 100644 index 000000000..b7a693bef --- /dev/null +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -0,0 +1,125 @@ +/* + xnrg_06_pzem_dc.ino - PZEM-003,017 Modbus DC energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 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_ENERGY_SENSOR +#ifdef USE_PZEM_DC +/*********************************************************************************************\ + * PZEM-003 - DC 300V 10A Energy + * PZEM-017 - DC 300V 50A - 300A Energy + * + * Based on: + * PZEM-003,017 docs Https://pan.baidu.com/s/1V9bDWj3RK2u6_fbBJ3GtqQ password rq37 + * + * Hardware Serial will be selected if GPIO1 = [99 PZEM017 Rx] and GPIO3 = [62 PZEM0XX Tx] +\*********************************************************************************************/ + +#define XNRG_06 6 + +#define PZEM_DC_DEVICE_ADDRESS 0x01 // PZEM default address + +#include +TasmotaModbus *PzemDcModbus; + +void PzemDcEverySecond() +{ + static uint8_t send_retry = 0; + + bool data_ready = PzemDcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[22]; + + uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, 8); + AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + + if (error) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemDc response error %d"), error); + AddLog(LOG_LEVEL_DEBUG); + } else { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + // 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29 + // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V + energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A + energy_active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W + float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh + + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any + energy_kWhtoday += (energy - energy_start) * 100; + energy_start = energy; + EnergyUpdateToday(); + } + } + + if (0 == send_retry || data_ready) { + send_retry = 5; + PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS, 0x04, 0, 8); + } + else { + send_retry--; + } +} + +void PzemDcSnsInit() +{ + PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemDcModbus->Begin(9600, 2); // Uses two stop bits!! + if (result) { + if (2 == result) { ClaimSerial(); } + energy_type_dc = true; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDcDrvInit() +{ + if (!energy_flg) { + if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_06; + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg06(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + PzemDcDrvInit(); + } + else if (XNRG_06 == energy_flg) { + switch (function) { + case FUNC_INIT: + PzemDcSnsInit(); + break; + case FUNC_EVERY_SECOND: + PzemDcEverySecond(); + break; + } + } + return result; +} + +#endif // USE_PZEM_DC +#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino index d9726ac05..9af865f26 100644 --- a/sonoff/xnrg_interface.ino +++ b/sonoff/xnrg_interface.ino @@ -39,7 +39,15 @@ int (* const xnrg_func_ptr[])(byte) PROGMEM = { // Energy driver Function Poin #endif #ifdef XNRG_06 - &Xnrg06 + &Xnrg06, +#endif + +#ifdef XNRG_07 + &Xnrg07, +#endif + +#ifdef XNRG_08 + &Xnrg08 #endif }; diff --git a/tools/decode-status.py b/tools/decode-status.py index 4fe1c285b..e9da483b3 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -127,8 +127,8 @@ a_features = [[ ],[ "USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050", "USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766", - "USE_MCP39F501","USE_PZEM2","USE_DS3231","USE_HX711", - "","","","", + "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", + "USE_PZEM_DC","","","", "","","","", "","","","", "","","","", From f8ab8ef552b662bac231efed0199261dfa64f409 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 17 Oct 2018 15:29:43 +0200 Subject: [PATCH 18/54] Clean settings.h Removed custom fields from settings.h --- sonoff/settings.h | 4 +--- tools/decode-config.py | 7 ------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index a4df43eb5..bef70acc5 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -322,10 +322,8 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A - byte free_71F[93]; // 71F + byte free_71F[157]; // 71F - char custom1[32]; // 77C Custom - char custom2[32]; // 79C Custom uint16_t weight_item; // 7BC Weight of one item in gram * 10 uint16_t weight_max; // 7BE Total max weight in kilogram unsigned long weight_reference; // 7C0 Reference weight in gram diff --git a/tools/decode-config.py b/tools/decode-config.py index c3d4af9b3..ffa78c031 100644 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -781,14 +781,7 @@ Setting_6_2_1_14.update({ 'web_refresh': (' Date: Thu, 18 Oct 2018 13:01:31 +0200 Subject: [PATCH 19/54] Rewrite Tuya Dimmer code Rewrite Tuya Dimmer code --- sonoff/_changelog.ino | 1 + sonoff/sonoff.h | 4 +- sonoff/sonoff.ino | 192 ++++++------------------- sonoff/sonoff_template.h | 18 ++- sonoff/user_config.h | 3 + sonoff/xdrv_04_light.ino | 35 +---- sonoff/xdrv_16_tuyadimmer.ino | 263 ++++++++++++++++++++++++++++++++++ 7 files changed, 330 insertions(+), 186 deletions(-) create mode 100644 sonoff/xdrv_16_tuyadimmer.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 36de9f29c..c54e2199d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Update TasmotaModbus and TasmotaSerial libraries for support of serial 8N2 communication * Add support for Pzem-003/017 DC Energy monitoring module (#3694) * Change support for Pzem-014/016 AC Energy monitoring module (#3694) + * Rewrite Tuya Dimmer code * * 6.2.1.16 20181015 * Add TasmotaModbus library for very basic modbus wrapper for TasmotaSerial diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index eb99cc2a1..8acbc8db5 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -202,7 +202,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MAX_PARAM8}; enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; @@ -212,7 +212,7 @@ enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; -enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, +enum XsnsFunctions {FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index a5dbcef4e..edb9253fb 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -200,8 +200,6 @@ char mqtt_data[MESSZ]; // MQTT publish buffer and web page char log_data[LOGSZ]; // Logging char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer String backlog[MAX_BACKLOG]; // Command backlog -uint8_t tuya_new_dim = 0; // Tuya dimmer value temp -boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction /********************************************************************************************/ @@ -342,9 +340,11 @@ void SetDevicePower(power_t rpower, int source) } XdrvMailbox.index = rpower; - XdrvCall(FUNC_SET_POWER); + XdrvMailbox.payload = source; + if (XdrvCall(FUNC_SET_POWER)) { - if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { + } + else if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { Serial.write(0xA0); Serial.write(0x04); Serial.write(rpower &0xFF); @@ -352,23 +352,6 @@ void SetDevicePower(power_t rpower, int source) Serial.write('\n'); Serial.flush(); } - else if (TUYA_DIMMER == Settings.module && source != SRC_SWITCH ) { // ignore to prevent loop from pushing state from faceplate interaction - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: SetDevicePower.rpower=%d"), rpower); - AddLog(LOG_LEVEL_DEBUG); - Serial.write(0x55); // Tuya header 55AA - Serial.write(0xAA); - Serial.write(0x00); // version 00 - Serial.write(0x06); // Tuya command 06 - Serial.write(0x00); - Serial.write(0x05); // following data length 0x05 - Serial.write(0x01); // relay number 1,2,3 - Serial.write(0x01); - Serial.write(0x00); - Serial.write(0x01); - Serial.write(rpower); // status - Serial.write(0x0D + rpower); // checksum sum of all bytes in packet mod 256 - Serial.flush(); - } else if (EXS_RELAY == Settings.module) { SetLatchingRelay(rpower, 1); } @@ -770,19 +753,16 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } } else { // SetOption32 .. 49 -/* + uint8_t param_low = 0; + uint8_t param_high = 255; switch (pindex) { case P_HOLD_TIME: case P_MAX_POWER_RETRY: - if ((payload >= 1) && (payload <= 250)) { - Settings.param[pindex] = payload; - } + param_low = 1; + param_high = 250; break; - default: - ptype = 99; // Command Error } -*/ - if ((payload >= 1) && (payload <= 250)) { + if ((payload >= param_low) && (payload <= param_high)) { Settings.param[pindex] = payload; } } @@ -2234,48 +2214,6 @@ void ArduinoOTAInit() /********************************************************************************************/ -void TuyaPacketProcess() -{ - char scmnd[20]; - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Packet Size=%d"), serial_in_byte_counter); - AddLog(LOG_LEVEL_DEBUG); - if (serial_in_byte_counter == 7 && serial_in_buffer[3] == 14 ) { // heartbeat packet - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); - } - if (serial_in_byte_counter == 12 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 5) { // on/off packet - if (serial_in_buffer[10] == 0) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd - Off State")); - ExecuteCommandPower(1, 0, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - } else - { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd - On State")); - ExecuteCommandPower(1, 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - } - serial_in_byte_counter = 0; - serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - } - if (serial_in_byte_counter == 15 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 8) { // dim packet - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Dim State=%d"), serial_in_buffer[13]); - AddLog(LOG_LEVEL_DEBUG); - tuya_new_dim = round(serial_in_buffer[13] * (100. / 255.)); - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER=%d"), tuya_new_dim ); - AddLog(LOG_LEVEL_DEBUG); - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER_STR=%s"), scmnd ); - AddLog(LOG_LEVEL_DEBUG); - tuya_ignore_dim = true; - ExecuteCommand(scmnd, SRC_SWITCH); - serial_in_byte_counter = 0; - serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - } - if (serial_in_byte_counter == 8 && serial_in_buffer[3] == 5 && serial_in_buffer[5] == 1 && serial_in_buffer[7] == 5 ) { // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd")); - serial_in_byte_counter = 0; - serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " 2"); - ExecuteCommand(scmnd, SRC_BUTTON); - } -} void SerialInput() { while (Serial.available()) { @@ -2304,29 +2242,6 @@ void SerialInput() } } -/*-------------------------------------------------------------------------------------------*\ - * Tuya based Dimmer with Serial Communications to MCU dimmer at 9600 baud -\*-------------------------------------------------------------------------------------------*/ - if (TUYA_DIMMER == Settings.module) { - if (serial_in_byte == '\x55') { // Start TUYA Packet - if (serial_in_byte_counter > 0 && serial_in_byte_counter < 11) { - TuyaPacketProcess(); - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: 0x55 Packet Start")); - serial_in_byte_counter = 0; - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; -// return; // test to see if we need this - } else { // read additional packets from TUYA - if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - serial_polling_window = millis(); -// return; // test to see if we need this - } else { - serial_in_byte_counter = 0; - } - } - } - /*-------------------------------------------------------------------------------------------*/ if (XdrvCall(FUNC_SERIAL)) { @@ -2336,33 +2251,33 @@ void SerialInput() } /*-------------------------------------------------------------------------------------------*/ - if (TUYA_DIMMER != Settings.module) { - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data... - 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) { // add char to string if it still fits - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } else { - serial_in_byte_counter = 0; - } + + if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data... + 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) { // add char to string if it still fits + 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) && - ((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - serial_polling_window = millis(); - } else { - serial_polling_window = 0; - break; - } + } + } else { + if (serial_in_byte || Settings.flag.mqtt_serial_raw) { + if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && + ((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + serial_polling_window = millis(); + } else { + serial_polling_window = 0; + break; } } } + /*-------------------------------------------------------------------------------------------*\ * Sonoff SC 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ @@ -2391,32 +2306,20 @@ void SerialInput() } } - if (TUYA_DIMMER == Settings.module && serial_in_byte_counter > 6 && (millis() > (serial_polling_window + SERIAL_POLLING))) { - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: 0x55 Packet End: \"")); - for (int i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, serial_in_buffer[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); - AddLog(LOG_LEVEL_DEBUG); - TuyaPacketProcess(); + if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - serial_in_byte_counter = 0; - } else { - if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { - serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - if (!Settings.flag.mqtt_serial_raw) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); - for (int i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + if (!Settings.flag.mqtt_serial_raw) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); + for (int i = 0; i < serial_in_byte_counter; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]); } - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); -// XdrvRulesProcess(); - serial_in_byte_counter = 0; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); } + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); +// XdrvRulesProcess(); + serial_in_byte_counter = 0; } } /********************************************************************************************/ @@ -2545,7 +2448,9 @@ void GpioInit() baudrate = 19200; } - if (SONOFF_DUAL == Settings.module) { + if (XdrvCall(FUNC_MODULE_INIT)) { + } + else if (SONOFF_DUAL == Settings.module) { Settings.flag.mqtt_serial = 0; devices_present = 2; baudrate = 19200; @@ -2560,11 +2465,6 @@ void GpioInit() devices_present = 0; baudrate = 19200; } - else if (TUYA_DIMMER == Settings.module) { - Settings.flag.mqtt_serial = 0; - baudrate = 9600; - light_type = LT_SERIAL; - } else if (SONOFF_BN == Settings.module) { // PWM Single color led (White) light_type = LT_PWM1; } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index b7d591801..ad2a44e6b 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1138,13 +1138,19 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer) // https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1 - 0, - GPIO_TXD, // TX to dimmer MCU - 0, - GPIO_RXD, // RX from dimmer MCU - 0, 0, + GPIO_KEY1, // Virtual Button (controlled by MCU) + GPIO_TXD, // GPIO01 MCU serial control + GPIO_USER, + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, 0, 0, 0, 0, 0, 0, // Flash connection - 0, 0, 0, 0, 0, 0 + GPIO_USER, + GPIO_USER, + GPIO_LED1, // GPIO14 Green Led + GPIO_USER, + GPIO_USER, + 0 } }; diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 1d66a92c4..32fbaa8ca 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -378,6 +378,9 @@ #define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code) +#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer + #define TUYA_DIMMER_ID 3 // Default dimmer Id + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index a4f58ae67..c5ba2acc7 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -343,37 +343,6 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut os_delay_us(12); // TStop > 12us. } -// *************** Tuya Dimmer Serial Comms -void LightSerialDuty(uint8_t duty) -{ - if (duty > 0 && !tuya_ignore_dim ) { - if (duty < 25) { - duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself - } - Serial.write(0x55); // Tuya header 55AA - Serial.write(0xAA); - Serial.write(0x00); // version 00 - Serial.write(0x06); // Tuya command 06 - send order - Serial.write(0x00); - Serial.write(0x08); // following data length 0x08 - Serial.write(0x03); // dimmer id - Serial.write(0x02); // type=value - Serial.write(0x00); // length hi - Serial.write(0x04); // length low - Serial.write(0x00); // - Serial.write(0x00); // - Serial.write(0x00); // - Serial.write( duty ); // dim value (0-255) - Serial.write( byte(22 + duty) ); // checksum:sum of all bytes in packet mod 256 - Serial.flush(); - snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d"), duty); - AddLog(LOG_LEVEL_DEBUG); - } else { - tuya_ignore_dim = false; // reset flag - snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); - AddLog(LOG_LEVEL_DEBUG); - } -} /********************************************************************************************/ void LightInit() @@ -424,7 +393,7 @@ void LightInit() #endif // USE_WS2812 ************************************************************************ else if (LT_SERIAL == light_type) { light_subtype = LST_SINGLE; - } + } else { light_pdi_pin = pin[GPIO_DI]; light_pdcki_pin = pin[GPIO_DCKI]; @@ -855,9 +824,11 @@ void LightAnimate() if (light_type > LT_WS2812) { LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } +#ifdef USE_TUYA_DIMMER if (light_type == LT_SERIAL) { LightSerialDuty(cur_col[0]); } +#endif // USE_TUYA_DIMMER } } } diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino new file mode 100644 index 000000000..cb5c31038 --- /dev/null +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -0,0 +1,263 @@ +/* + xdrv_16_tuyadimmer.ino - Tuya dimmer support for Sonoff-Tasmota + + Copyright (C) 2018 digiblur, Joel Stein 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_TUYA_DIMMER + +#ifndef TUYA_DIMMER_ID +#define TUYA_DIMMER_ID 3 +#endif + +uint8_t tuya_new_dim = 0; // Tuya dimmer value temp +boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction +uint8_t tuya_cmd_status = 0; // Current status of serial-read +uint8_t tuya_cmd_checksum = 0; // Checksum of tuya command +uint8_t tuya_data_len = 0; // Data lenght of command + +boolean TuyaSetPower() +{ + boolean status = false; + + uint8_t rpower = XdrvMailbox.index; + int16_t source = XdrvMailbox.payload; + + if (source != SRC_SWITCH ) { // ignore to prevent loop from pushing state from faceplate interaction + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: SetDevicePower.rpower=%d"), rpower); + AddLog(LOG_LEVEL_DEBUG); + + Serial.write(0x55); // Tuya header 55AA + Serial.write(0xAA); + Serial.write(0x00); // version 00 + Serial.write(0x06); // Tuya command 06 + Serial.write(0x00); + Serial.write(0x05); // following data length 0x05 + Serial.write(0x01); // relay number 1,2,3 + Serial.write(0x01); + Serial.write(0x00); + Serial.write(0x01); + Serial.write(rpower); // status + Serial.write(0x0D + rpower); // checksum sum of all bytes in packet mod 256 + Serial.flush(); + + status = true; + } + return status; +} + +void LightSerialDuty(uint8_t duty) +{ + if (duty > 0 && !tuya_ignore_dim ) { + if (duty < 25) { + duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself + } + Serial.write(0x55); // Tuya header 55AA + Serial.write(0xAA); + Serial.write(0x00); // version 00 + Serial.write(0x06); // Tuya command 06 - send order + Serial.write(0x00); + Serial.write(0x08); // following data length 0x08 + Serial.write(Settings.param[P_TUYA_DIMMER_ID]); // dimmer id + Serial.write(0x02); // type=value + Serial.write(0x00); // length hi + Serial.write(0x04); // length low + Serial.write(0x00); // + Serial.write(0x00); // + Serial.write(0x00); // + Serial.write( duty ); // dim value (0-255) + Serial.write( byte(Settings.param[P_TUYA_DIMMER_ID] + 19 + duty) ); // checksum:sum of all bytes in packet mod 256 + Serial.flush(); + + snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]); + AddLog(LOG_LEVEL_DEBUG); + + } else { + tuya_ignore_dim = false; // reset flag + + snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); + AddLog(LOG_LEVEL_DEBUG); + + } +} + +void TuyaPacketProcess() +{ + char scmnd[20]; + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Packet Size=%d"), serial_in_byte_counter); + AddLog(LOG_LEVEL_DEBUG); + + if (serial_in_byte_counter == 7 && serial_in_buffer[3] == 14 ) { // heartbeat packet + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); + } + else if (serial_in_byte_counter == 12 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 5) { // on/off packet + + snprintf_P(log_data, sizeof(log_data),PSTR("TYA: Rcvd - %s State"),serial_in_buffer[10]?"On":"Off"); + AddLog(LOG_LEVEL_DEBUG); + + if((power || Settings.light_dimmer > 0) && (power != serial_in_buffer[10])) { + ExecuteCommandPower(1, serial_in_buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } + } + else if (serial_in_byte_counter == 15 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 8) { // dim packet + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Dim State=%d"), serial_in_buffer[13]); + AddLog(LOG_LEVEL_DEBUG); + + tuya_new_dim = round(serial_in_buffer[13] * (100. / 255.)); + if((power || !Settings.light_dimmer ) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 2)) { + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER=%d"), tuya_new_dim ); + AddLog(LOG_LEVEL_DEBUG); + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER_STR=%s"), scmnd ); + AddLog(LOG_LEVEL_DEBUG); + + tuya_ignore_dim = true; + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + else if (serial_in_byte_counter == 8 && serial_in_buffer[3] == 5 && serial_in_buffer[5] == 1 && serial_in_buffer[7] == 5 ) { // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd")); + + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " 2"); + ExecuteCommand(scmnd, SRC_BUTTON); + } +} + +void TuyaSerialInput() +{ + while (Serial.available()) { + yield(); + serial_in_byte = Serial.read(); + + //snprintf_P(log_data, sizeof(log_data), PSTR("TYA: serial_in_byte %d, tuya_cmd_status %d, tuya_cmd_checksum %d, tuya_data_len %d, serial_in_byte_counter %d"), serial_in_byte, tuya_cmd_status, tuya_cmd_checksum, tuya_data_len, serial_in_byte_counter); + //AddLog(LOG_LEVEL_DEBUG); + + if (serial_in_byte == 0x55) { // Start TUYA Packet + tuya_cmd_status = 1; + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + tuya_cmd_checksum += serial_in_byte; + } + else if (tuya_cmd_status == 1 && serial_in_byte == 0xAA){ // Only packtes with header 0x55AA are valid + tuya_cmd_status = 2; + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: 0x55AA Packet Start")); + + serial_in_byte_counter = 0; + serial_in_buffer[serial_in_byte_counter++] = 0x55; + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + tuya_cmd_checksum = 0xFF; + } + else if (tuya_cmd_status == 2){ + if(serial_in_byte_counter == 5){ // Get length of data + tuya_cmd_status = 3; + tuya_data_len = serial_in_byte; + } + tuya_cmd_checksum += serial_in_byte; + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + else if ((tuya_cmd_status == 3) && (serial_in_byte_counter == (6 + tuya_data_len)) && (tuya_cmd_checksum == serial_in_byte)){ // Compare checksum and process packet + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: 0x55 Packet End: \"")); + for (int i = 0; i < serial_in_byte_counter; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, serial_in_buffer[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG); + + TuyaPacketProcess(); + serial_in_byte_counter = 0; + tuya_cmd_status = 0; + tuya_cmd_checksum = 0; + tuya_data_len = 0; + } // read additional packets from TUYA + else if(serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + tuya_cmd_checksum += serial_in_byte; + } else { + serial_in_byte_counter = 0; + tuya_cmd_status = 0; + tuya_cmd_checksum = 0; + tuya_data_len = 0; + } + } +} + +boolean TuyaModuleSelected() +{ + baudrate = 9600; + light_type = LT_SERIAL; + return true; +} + +void TuyaInit() +{ + if (!Settings.param[P_TUYA_DIMMER_ID]) { + Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; + } + Serial.setDebugOutput(false); + ClaimSerial(); + + // Get current status of MCU + snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU state"); + AddLog(LOG_LEVEL_DEBUG); + Serial.write(0x55); // header 55AA + Serial.write(0xAA); + Serial.write(0x00); // version 00 + Serial.write(0x08); // command 08 - get status + Serial.write(0x00); + Serial.write(0x00); // following data length 0x00 + Serial.write(0x07); // checksum:sum of all bytes in packet mod 256 + Serial.flush(); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XDRV_16 + +boolean Xdrv16(byte function) +{ + boolean result = false; + + if (TUYA_DIMMER == Settings.module) { + switch (function) { + case FUNC_MODULE_INIT: + result = TuyaModuleSelected(); + break; + case FUNC_INIT: + TuyaInit(); + break; + case FUNC_LOOP: + TuyaSerialInput(); + break; + case FUNC_SET_POWER: + result = TuyaSetPower(); + break; + } + } + return result; +} + +#endif // USE_TUYA_DIMMER \ No newline at end of file From cfdec25bcbf05d1969f811a9f7bb9a4f32762e11 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Thu, 18 Oct 2018 16:02:40 +0200 Subject: [PATCH 20/54] Add reset-button-handler vor tuya-dimmer --- sonoff/sonoff.ino | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index edb9253fb..bedf49421 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1723,7 +1723,20 @@ void ButtonHandler() ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally } } - } else { + } +#ifdef USE_TUYA_DIMMER + else if (TUYA_DIMMER == Settings.module) { + if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); + AddLog(LOG_LEVEL_DEBUG); + if (!Settings.flag.button_restrict) { + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + } +#endif + else { if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { if (Settings.flag.button_single) { // Allow only single button press for immediate action snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); From 824603b3020afd9036764c1841b1d0b12dfcf983 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 18 Oct 2018 11:44:58 -0300 Subject: [PATCH 21/54] Fix typo for sonoff_sensors.bin file ADC is set to use analog input in pin A0 for sonoff_sensors.bin --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8cf1a0022..212e3a7da 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -55,7 +55,7 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_SUNRISE | - | - | x | x | x | | USE_RULES | - | - | x | x | x | | | | | | | | -| USE_ADC_VCC | x | x | x | x | x | +| USE_ADC_VCC | x | x | x | x | | | USE_DS18B20 | - | - | - | - | - | Single sensor | USE_DS18x20 | - | x | x | x | x | Multiple sensors | USE_DS18x20_LEGACY | - | - | - | - | - | Multiple sensors From 613ffde5c0a6bd043a1f19b5473fe3efbda23eec Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 19 Oct 2018 12:53:22 +0200 Subject: [PATCH 22/54] 6.2.1.18 Add API.md 6.2.1.18 20181019 * Add more API callbacks and document API.md --- sonoff/API.md | 64 +++++++++++++++++++++++++++++++++++ sonoff/_changelog.ino | 5 ++- sonoff/sonoff.h | 7 ++-- sonoff/sonoff.ino | 27 +++++++-------- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_16_tuyadimmer.ino | 21 +++++++++++- 6 files changed, 105 insertions(+), 21 deletions(-) create mode 100644 sonoff/API.md diff --git a/sonoff/API.md b/sonoff/API.md new file mode 100644 index 000000000..68442970f --- /dev/null +++ b/sonoff/API.md @@ -0,0 +1,64 @@ +## Sonoff-Tasmota basic API information +Sonoff-Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. See the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Sensor-API) for more information. + +Callback availability can be checked by searching for either XdrvCall, XsnsCall, XdspCall and XnrgCall. + +## Driver, Sensor and Energy Callback Ids +The following table lists Callback Ids and their availability for a Driver, Sensor or Energy service. + +Callback Id | Bool | Version | xdrv | xsns | xnrg | Description +----------------------------|------|----------|------|------|------|---------------------------------- +FUNC_MODULE_INIT | x | 6.2.1.17 | x | | | Init module specific parameters +FUNC_PRE_INIT | | | x | | x | Once GPIO have been established +FUNC_INIT | | | x | x | x | At end of initialisation +FUNC_LOOP | | | x | | | In main loop +FUNC_EVERY_50_MSECOND | | | x | x | | +FUNC_EVERY_100_MSECOND | | | x | x | | +FUNC_EVERY_200_MSECOND | | | | x | x | +FUNC_EVERY_250_MSECOND | | | x | | | +FUNC_EVERY_SECOND | | | x | x | x | +FUNC_PREP_BEFORE_TELEPERIOD | | | | x | | Deprecated. Use a FUNC_EVERY_ +FUNC_JSON_APPEND | | | | x | | Extend teleperiod JSON text +FUNC_WEB_APPEND | | | | x | | Extend webgui ajax info +FUNC_SAVE_BEFORE_RESTART | | | | x | | Just before a planned restart +FUNC_COMMAND | x | | x | x | | When a command is not recognized +FUNC_MQTT_SUBSCRIBE | | 5.12.0k | x | | | At end of MQTT subscriptions +FUNC_MQTT_INIT | | 5.12.0k | x | | | Once at end of MQTT connection +FUNC_MQTT_DATA | x | 5.12.0k | x | | | Before decoding command +FUNC_SET_POWER | | | x | | | Before setting relays +FUNC_SET_DEVICE_POWER | x | 6.2.1.18 | x | | | Set relay +FUNC_SHOW_SENSOR | | | x | | | When FUNC_JSON_APPEND completes +FUNC_RULES_PROCESS | x | 6.0.0 | x | | | Process specific rule +FUNC_SERIAL | x | | x | | x | Process serial data +FUNC_FREE_MEM | | | x | | | Show free memory for debugging +FUNC_BUTTON_PRESSED | x | 6.2.1.18 | x | | | When a button is pressed +FUNC_WEB_ADD_BUTTON | | 6.2.1.14 | x | | | Add a Configuration Button to GUI +FUNC_WEB_ADD_MAIN_BUTTON | | 6.2.1.14 | x | | | Add a main button to GUI +FUNC_WEB_ADD_HANDLER | | 6.2.1.14 | x | | | Add a webserver handler + +## Display Call back Ids +The following table lists all Callback Ids for a Display service. + +Callback Id | Bool | Version | Description +------------------------------|------|----------|--------------------- +FUNC_DISPLAY_INIT_DRIVER | | 6.1.1.7 | +FUNC_DISPLAY_INIT | | 6.1.1.7 | +FUNC_DISPLAY_EVERY_50_MSECOND | | 6.1.1.7 | +FUNC_DISPLAY_EVERY_SECOND | | 6.1.1.7 | +FUNC_DISPLAY_MODEL | x | 6.1.1.7 | +FUNC_DISPLAY_MODE | | 6.1.1.7 | +FUNC_DISPLAY_POWER | | 6.1.1.7 | +FUNC_DISPLAY_CLEAR | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_FRAME | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_HLINE | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_VLINE | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_LINE | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_CIRCLE | | 6.1.1.7 | +FUNC_DISPLAY_FILL_CIRCLE | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_RECTANGLE | | 6.1.1.7 | +FUNC_DISPLAY_FILL_RECTANGLE | | 6.1.1.7 | +FUNC_DISPLAY_TEXT_SIZE | | 6.1.1.7 | +FUNC_DISPLAY_FONT_SIZE | | 6.1.1.7 | +FUNC_DISPLAY_ROTATION | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_STRING | | 6.1.1.7 | +FUNC_DISPLAY_ONOFF | | 6.1.1.7 | diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c54e2199d..b02834394 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.17 20181017 +/* 6.2.1.18 20181019 + * Add more API callbacks and document API.md + * + * 6.2.1.17 20181017 * Enable updated non-blocking PubSubClient as default MQTT client * Update TasmotaModbus and TasmotaSerial libraries for support of serial 8N2 communication * Add support for Pzem-003/017 DC Energy monitoring module (#3694) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 8acbc8db5..beacb9f93 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -212,9 +212,10 @@ enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; -enum XsnsFunctions {FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, - FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, - FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER}; +enum XsnsFunctions {FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, + FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, + FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index bedf49421..3972d4f40 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -340,9 +340,12 @@ void SetDevicePower(power_t rpower, int source) } XdrvMailbox.index = rpower; - XdrvMailbox.payload = source; - if (XdrvCall(FUNC_SET_POWER)) { + XdrvCall(FUNC_SET_POWER); // Signal power state + XdrvMailbox.index = rpower; + XdrvMailbox.payload = source; + if (XdrvCall(FUNC_SET_DEVICE_POWER)) { // Set power state and stop if serviced + // Serviced } else if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { Serial.write(0xA0); @@ -1703,7 +1706,12 @@ void ButtonHandler() } if (button_present) { - if (SONOFF_4CHPRO == Settings.module) { + XdrvMailbox.index = button_index; + XdrvMailbox.payload = button; + if (XdrvCall(FUNC_BUTTON_PRESSED)) { + // Serviced + } + else if (SONOFF_4CHPRO == Settings.module) { if (holdbutton[button_index]) { holdbutton[button_index]--; } boolean button_pressed = false; @@ -1724,18 +1732,6 @@ void ButtonHandler() } } } -#ifdef USE_TUYA_DIMMER - else if (TUYA_DIMMER == Settings.module) { - if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); - AddLog(LOG_LEVEL_DEBUG); - if (!Settings.flag.button_restrict) { - snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } -#endif else { if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { if (Settings.flag.button_single) { // Allow only single button press for immediate action @@ -2462,6 +2458,7 @@ void GpioInit() } if (XdrvCall(FUNC_MODULE_INIT)) { + // Serviced } else if (SONOFF_DUAL == Settings.module) { Settings.flag.mqtt_serial = 0; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 1ee95769f..2c70d6928 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020111 +#define VERSION 0x06020112 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index cb5c31038..add97fd98 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -231,6 +231,22 @@ void TuyaInit() Serial.flush(); } +boolean TuyaButtonPressed() +{ + if ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == lastbutton[XdrvMailbox.index])) { + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), XdrvMailbox.index +1); + AddLog(LOG_LEVEL_DEBUG); + + if (!Settings.flag.button_restrict) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + return true; // Serviced here +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -252,9 +268,12 @@ boolean Xdrv16(byte function) case FUNC_LOOP: TuyaSerialInput(); break; - case FUNC_SET_POWER: + case FUNC_SET_DEVICE_POWER: result = TuyaSetPower(); break; + case FUNC_BUTTON_PRESSED: + result = TuyaButtonPressed(); + break; } } return result; From 802969b263899e76973d3d08c637a2ade98bcfa5 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 19 Oct 2018 10:39:19 -0300 Subject: [PATCH 23/54] Added build flags for next esp8266 core --- platformio.ini | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 5dfd0a442..852db9128 100644 --- a/platformio.ini +++ b/platformio.ini @@ -62,7 +62,10 @@ board_build.f_cpu = 80000000L build_unflags = -Wall build_flags = - -Wl,-Tesp8266.flash.1m0.ld +; if using esp8266 core 2.5.0 (stage) or up +; -Wl,-Tesp8266.flash.1m.ld -Wl,-Map,firmware.map +; if using esp8266 core < 2.5.0 + -Wl,-Tesp8266.flash.1m0.ld -Wl,-Map,firmware.map -mtarget-align ; -DUSE_CONFIG_OVERRIDE ; lwIP 1.4 (Default) From 42aa66e02fdf4d8fb5fbe81ee3e3deb47e517773 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Fri, 19 Oct 2018 17:11:30 +0200 Subject: [PATCH 24/54] obi-socket: allow user-configuration of free GPIOs --- sonoff/sonoff_template.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index ad2a44e6b..0faf0c5f4 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1102,14 +1102,17 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1_INV, // GPIO16 Green Led 1 (0 = On, 1 = Off) }, { "OBI Socket", // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 - 0, 0, 0, 0, - GPIO_LED1, // GPIO04 LED on top and in switch button - GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) + GPIO_USER, // GPIO00 + 0,0,0, + GPIO_LED1, // GPIO04 Blue LED + GPIO_REL1, // GPIO05 (Relay OFF, but used as Relay Switch) 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_LED2, // GPIO12 - 0, // GPIO13 - GPIO_KEY1, // GPIO14 switch button - 0, 0, 0 + GPIO_LED4, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) + GPIO_USER, // GPIO13 + GPIO_KEY1, // GPIO14 Button + 0, + GPIO_USER, // GPIO16 + GPIO_ADC0 // Analog input }, { "Teckin", // https://www.amazon.de/gp/product/B07D5V139R 0, From 2e150b5ca45560162512faf09cbd16a1264fdc2d Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Fri, 19 Oct 2018 18:04:30 +0200 Subject: [PATCH 25/54] tuya-dimmer: ignore dim-values when powered off --- sonoff/xdrv_16_tuyadimmer.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index add97fd98..1a5776d4a 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -120,7 +120,7 @@ void TuyaPacketProcess() AddLog(LOG_LEVEL_DEBUG); tuya_new_dim = round(serial_in_buffer[13] * (100. / 255.)); - if((power || !Settings.light_dimmer ) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 2)) { + if((power) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 2)) { snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER=%d"), tuya_new_dim ); AddLog(LOG_LEVEL_DEBUG); @@ -279,4 +279,4 @@ boolean Xdrv16(byte function) return result; } -#endif // USE_TUYA_DIMMER \ No newline at end of file +#endif // USE_TUYA_DIMMER From 0078b9f650987e01849aa6df6ebb78cb3cb24519 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Fri, 19 Oct 2018 18:12:09 +0200 Subject: [PATCH 26/54] remove ADC0 --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 0faf0c5f4..8de1a301e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1112,7 +1112,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO14 Button 0, GPIO_USER, // GPIO16 - GPIO_ADC0 // Analog input + GPIO_USER // Analog input }, { "Teckin", // https://www.amazon.de/gp/product/B07D5V139R 0, From 22ecc8f61847737e9fffe1468d16437834d99fdb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 19 Oct 2018 18:16:53 +0200 Subject: [PATCH 27/54] Fix JSON error Fix JSON error (#4108) --- sonoff/xsns_30_mpr121.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index cc4fba3ab..d08b8c2db 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -365,7 +365,7 @@ void Mpr121Show(struct mpr121 *pS, byte function) // Append JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"Button%i\":%i,"), mqtt_data, j, BITC(i, j)); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"Button%i\":%i"), mqtt_data, (i > 0 ? "," : ""), j, BITC(i, j)); } } // for-loop j From df5a7ec05414344bad9e6fedc8128fa7b00e0ac4 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Fri, 19 Oct 2018 19:10:55 +0200 Subject: [PATCH 28/54] obi-socket: change LED4 back to LED2 --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 8de1a301e..bb19d2dc5 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1107,7 +1107,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1, // GPIO04 Blue LED GPIO_REL1, // GPIO05 (Relay OFF, but used as Relay Switch) 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_LED4, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) + GPIO_LED2, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) GPIO_USER, // GPIO13 GPIO_KEY1, // GPIO14 Button 0, From 0effef5f04c670f1509180391b6569962f0029c6 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 19 Oct 2018 14:29:53 -0300 Subject: [PATCH 29/54] Fix Analog input in Obi Socket Template --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index bb19d2dc5..77f931610 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1112,7 +1112,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO14 Button 0, GPIO_USER, // GPIO16 - GPIO_USER // Analog input + GPIO_ADC0 // ADC0 A0 Analog input }, { "Teckin", // https://www.amazon.de/gp/product/B07D5V139R 0, From d012ce942b5381f6ce67f16d0ae98863b98c1f4c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 20 Oct 2018 17:28:42 +0200 Subject: [PATCH 30/54] Fix JSON error - again Fix JSON error - again (#4108) --- sonoff/xsns_30_mpr121.ino | 50 +++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index d08b8c2db..86191c079 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -1,29 +1,29 @@ /** - * + * * @file xsns_30_mpr121.ino - * + * * @package Sonoff-Tasmota * @subpackage Sensors * @name MPR121 - * + * * @description Driver for up to 4x Freescale MPR121 Proximity Capacitive Touch Sensor Controllers (Only touch buttons). - * + * * @author Rene 'Renne' Bartsch, B.Sc. Informatics, * @copyright Rene 'Renne' Bartsch 2018 * @date $Date$ * @version $Id$ - * - * @link https://github.com/arendst/Sonoff-Tasmota/wiki/MPR121 \endlink - * @link https://www.sparkfun.com/datasheets/Components/MPR121.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3891.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3892.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3893.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3894.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3895.pdf \endlink - * + * + * @link https://github.com/arendst/Sonoff-Tasmota/wiki/MPR121 \endlink + * @link https://www.sparkfun.com/datasheets/Components/MPR121.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3891.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3892.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3893.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3894.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3895.pdf \endlink + * * @license GNU GPL v.3 */ - + /* * 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 @@ -178,9 +178,9 @@ /** * MPR121 sensors status and data struct. * - * The struct mpr121 uses the indices of i2c_addr and id to link the specific sensors to an I2C address and a human-readable ID + * The struct mpr121 uses the indices of i2c_addr and id to link the specific sensors to an I2C address and a human-readable ID * and the indices of the arrays connected, running, current and previous to store sensor status and data of a specific sensor. - * + * */ typedef struct mpr121 mpr121; struct mpr121 { @@ -195,12 +195,12 @@ struct mpr121 { /** * The function Mpr121Init() soft-resets, detects and configures up to 4x MPR121 sensors. - * + * * @param struct *pS Struct with MPR121 status and data. * @return void * @pre None. * @post None. - * + * */ void Mpr121Init(struct mpr121 *pS) { @@ -301,16 +301,16 @@ void Mpr121Init(struct mpr121 *pS) /** * Publishes the sensor information. - * + * * The function Mpr121Show() reads sensor data, checks for over-current exceptions and * creates strings with button states for the web-interface and near real-time/ telemetriy MQTT. - * + * * @param struct *pS Struct with MPR121 status and data. * @param byte function Tasmota function ID. * @return void * @pre Call Mpr121Init() once. * @post None. - * + * */ void Mpr121Show(struct mpr121 *pS, byte function) { @@ -365,7 +365,7 @@ void Mpr121Show(struct mpr121 *pS, byte function) // Append JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"Button%i\":%i"), mqtt_data, (i > 0 ? "," : ""), j, BITC(i, j)); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"Button%i\":%i"), mqtt_data, (j > 0 ? "," : ""), j, BITC(i, j)); } } // for-loop j @@ -392,18 +392,18 @@ void Mpr121Show(struct mpr121 *pS, byte function) /** * The function Xsns30() interfaces Tasmota with the driver. - * + * * It provides the function IDs * FUNC_INIT to initialize a driver, * FUNC_EVERY_50_MSECOND for near real-time operation, * FUNC_JSON_APPEND for telemetry data and * FUNC_WEB_APPEND for displaying data in the Tasmota web-interface - * + * * @param byte function Tasmota function ID. * @return boolean ??? * @pre None. * @post None. - * + * */ boolean Xsns30(byte function) { From 266f7f1fe00626216e12deeeb577aa0c30b216ec Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Oct 2018 12:44:45 +0200 Subject: [PATCH 31/54] Add support for TX20 Add support for La Crosse TX20 Anemometer (#2654, #3146) --- sonoff/_changelog.ino | 1 + sonoff/language/bg-BG.h | 13 +++ sonoff/language/cs-CZ.h | 11 ++ sonoff/language/de-DE.h | 12 +++ sonoff/language/el-GR.h | 12 +++ sonoff/language/en-GB.h | 12 +++ sonoff/language/es-AR.h | 12 +++ sonoff/language/fr-FR.h | 12 +++ sonoff/language/he-HE.h | 12 +++ sonoff/language/hu-HU.h | 12 +++ sonoff/language/it-IT.h | 12 +++ sonoff/language/nl-NL.h | 12 +++ sonoff/language/pl-PL.h | 12 +++ sonoff/language/pt-BR.h | 12 +++ sonoff/language/pt-PT.h | 12 +++ sonoff/language/ru-RU.h | 12 +++ sonoff/language/tr-TR.h | 12 +++ sonoff/language/uk-UK.h | 12 +++ sonoff/language/zh-CN.h | 12 +++ sonoff/language/zh-TW.h | 12 +++ sonoff/sonoff_template.h | 5 +- sonoff/support.ino | 11 ++ sonoff/user_config.h | 2 + sonoff/xsns_35_tx20.ino | 224 +++++++++++++++++++++++++++++++++++++++ tools/decode-status.py | 4 +- 25 files changed, 472 insertions(+), 3 deletions(-) create mode 100644 sonoff/xsns_35_tx20.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b02834394..85951dbae 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.2.1.18 20181019 * Add more API callbacks and document API.md + * Add support for La Crosse TX20 Anemometer (#2654, #3146) * * 6.2.1.17 20181017 * Enable updated non-blocking PubSubClient as default MQTT client diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index c485b79ff..689707bbd 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Няма" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,8 @@ #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 "TX20" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +527,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index ab548ad70..a2978747c 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Zkalibrováno" #define D_HX_CAL_FAIL "Chyba kalibrace" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Není" #define D_SENSOR_DHT11 "DHT11" @@ -515,6 +525,7 @@ #define D_UNIT_HOUR "hod" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 19cbff44b..91d99374d 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "kalibriert" #define D_HX_CAL_FAIL "Kalibrierung fehlgeschlagen" +//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" + // sonoff_template.h #define D_SENSOR_NONE "None" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index c0873dd07..bdc4313de 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Κανένας" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index eed796889..d93e1f237 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "None" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index cf34dbce9..b1c608a63 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrado" #define D_HX_CAL_FAIL "Falló Calibración" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Ninguno" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index b70cbbb8b..5fb4b50b7 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Aucun" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 736ea89aa..f4ed8fffb 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "None" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index b33e4cc41..a5376c5e2 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Nincs" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "ó" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index e819c8558..009fd6ebc 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Nessuno" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index eef55f90a..ca40e56fe 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Ge-ijkt" #define D_HX_CAL_FAIL "Ijken is mislukt" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Geen" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index a99b9e972..73b71d475 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Brak" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Godz" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index fa8caec36..3831a9399 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Nenhum" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "H" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index ae2ee4316..abf47783c 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "Nenhum" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 61c2c2f08..22cf17b5d 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "-нет-" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "А" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Ч" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 1f542af3b..9d0d3fe6a 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "None" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "A" @@ -514,6 +525,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 1b075a4b6..5976f1628 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "-відсутньо-" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "А" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "Г" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 63f687f3e..e24ae4a0d 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "无" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "安" @@ -514,6 +525,7 @@ #define D_UNIT_HOUR "时" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "千欧" #define D_UNIT_KILOWATTHOUR "千瓦时" #define D_UNIT_LUX "勒克斯" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 89222d077..52376aa49 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -462,6 +462,16 @@ #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +//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" + // sonoff_template.h #define D_SENSOR_NONE "None" #define D_SENSOR_DHT11 "DHT11" @@ -507,6 +517,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" // Units #define D_UNIT_AMPERE "安" @@ -515,6 +526,7 @@ #define D_UNIT_HOUR "時" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "千歐" #define D_UNIT_KILOWATTHOUR "千瓦時" #define D_UNIT_LUX "勒克斯" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 77f931610..0f962bfbd 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -128,6 +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_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -182,7 +183,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|" 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_HX711_SCK "|" D_SENSOR_HX711_DAT "|" + D_SENSOR_TX20_TX; /********************************************************************************************/ @@ -363,6 +365,7 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { GPIO_SDM630_TX, // SDM630 Serial interface GPIO_SDM630_RX, // SDM630 Serial interface GPIO_PMS5003, // Plantower PMS5003 Serial interface + GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin GPIO_MP3_DFR562 // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface }; diff --git a/sonoff/support.ino b/sonoff/support.ino index a18de8667..fad0064be 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1013,6 +1013,12 @@ void GetFeatures() #ifdef USE_MP3_PLAYER feature_drv2 |= 0x00002000; // xdrv_14_mp3.ino #endif +#ifdef USE_PCA9685 + feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino +#endif +#ifdef USE_TUYA_DIMMER + feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino +#endif #ifdef NO_EXTRA_4K_HEAP @@ -1186,6 +1192,11 @@ void GetFeatures() #ifdef USE_PZEM_DC feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino #endif +#ifdef USE_TX20_WIND_SENSOR + feature_sns2 |= 0x00002000; // xsns_35_tx20.ino +#endif + + } diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 32fbaa8ca..3eca64536 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -381,6 +381,8 @@ #define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer #define TUYA_DIMMER_ID 3 // Default dimmer Id +#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino new file mode 100644 index 000000000..d24575a64 --- /dev/null +++ b/sonoff/xsns_35_tx20.ino @@ -0,0 +1,224 @@ +/* + xsns_35_Tx20.ino - La Crosse Tx20 wind sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Thomas Eckerstorfer 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_TX20_WIND_SENSOR +/*********************************************************************************************\ + * La Crosse Tx20 wind sensor + * + * 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/ +\*********************************************************************************************/ + +#define TX20_BIT_TIME 1220 // microseconds +#define TX20_RESET_VALUES 60 // seconds + +// The Arduino standard GPIO routines are not enough, +// must use some from the Espressif SDK as well +extern "C" { +#include "gpio.h" +} + +#ifdef USE_WEBSERVER + +const char HTTP_SNS_TX20[] PROGMEM = "%s" + "{s} " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s} " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s} " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s} " D_TX20_WIND_DIRECTION "{m}%s {e}"; + +#endif // USE_WEBSERVER + +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; + +boolean tx20_available = false; + +void Tx20StartRead() +{ + /* 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 + * sb - Wind direction 0 - 15 + * sc - Wind speed 0 - 511 + * sd - Checksum + * se - Wind direction 0 - 15 + * sf - Wind speed 0 - 511 + */ + + 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 (int 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); + } + + 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)) { // 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]); +} + +void Tx20Read() +{ + 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() { + pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); + attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); +} + +void Tx20Show(boolean json) +{ + char wind_speed_string[10]; + char wind_speed_max_string[10]; + char wind_speed_avg_string[10]; + char wind_direction_string[4]; + + dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); + dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); + dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); + GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); + + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), + mqtt_data, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TX20, mqtt_data, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_35 + +boolean Xsns35(byte function) +{ + boolean 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_APPEND: + Tx20Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_TX20_WIND_SENSOR \ No newline at end of file diff --git a/tools/decode-status.py b/tools/decode-status.py index e9da483b3..d7aae3b40 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -110,7 +110,7 @@ a_features = [[ "USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_SENSORS","USE_CLASSIC", "USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", "USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER", - "USE_DISPLAY_SH1106","USE_MP3_PLAYER","","", + "USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER", "","","","", "","","","NO_EXTRA_4K_HEAP", "VTABLES_IN_IRAM","VTABLES_IN_DRAM","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH", @@ -128,7 +128,7 @@ a_features = [[ "USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050", "USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766", "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", - "USE_PZEM_DC","","","", + "USE_PZEM_DC","USE_TX20_WIND_SENSOR","","", "","","","", "","","","", "","","","", From f94f58d019a66501866bcfa012afad509dc2b81a Mon Sep 17 00:00:00 2001 From: synekvl <42292671+synekvl@users.noreply.github.com> Date: Sun, 21 Oct 2018 15:41:47 +0200 Subject: [PATCH 32/54] Update cs-CZ.h --- sonoff/language/cs-CZ.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index a2978747c..23c01a1b3 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -463,14 +463,14 @@ #define D_HX_CAL_FAIL "Chyba kalibrace" //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" +#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" // sonoff_template.h #define D_SENSOR_NONE "Není" @@ -525,7 +525,7 @@ #define D_UNIT_HOUR "hod" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#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" From fabdff0b37045c3b9ec0b55d9e53221c023333ab Mon Sep 17 00:00:00 2001 From: synekvl <42292671+synekvl@users.noreply.github.com> Date: Sun, 21 Oct 2018 16:28:46 +0200 Subject: [PATCH 33/54] Update cs-CZ.h --- sonoff/language/cs-CZ.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 23c01a1b3..b37e2a2fa 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -517,6 +517,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" // Units #define D_UNIT_AMPERE "A" From 3f4320b95d9d59292f4e114ebcb5d3a4c8028105 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Oct 2018 16:30:05 +0200 Subject: [PATCH 34/54] Add optional HX711 GUI Add optional HX711 scale interface to web GUI demonstrating easy GUI plug-in --- sonoff/API.md => API.md | 6 +- sonoff/_changelog.ino | 1 + sonoff/language/bg-BG.h | 7 ++ sonoff/language/cs-CZ.h | 7 ++ sonoff/language/de-DE.h | 7 ++ sonoff/language/el-GR.h | 7 ++ sonoff/language/en-GB.h | 7 ++ sonoff/language/es-AR.h | 7 ++ sonoff/language/fr-FR.h | 7 ++ sonoff/language/he-HE.h | 7 ++ sonoff/language/hu-HU.h | 7 ++ sonoff/language/it-IT.h | 7 ++ sonoff/language/nl-NL.h | 7 ++ sonoff/language/pl-PL.h | 7 ++ sonoff/language/pt-BR.h | 7 ++ sonoff/language/pt-PT.h | 7 ++ sonoff/language/ru-RU.h | 7 ++ sonoff/language/tr-TR.h | 7 ++ sonoff/language/uk-UK.h | 7 ++ sonoff/language/zh-CN.h | 7 ++ sonoff/language/zh-TW.h | 7 ++ sonoff/user_config.h | 1 + sonoff/xdrv_01_webserver.ino | 11 ++- sonoff/xsns_34_hx711.ino | 143 ++++++++++++++++++++++++++++++++--- sonoff/xsns_35_tx20.ino | 8 +- 25 files changed, 280 insertions(+), 23 deletions(-) rename sonoff/API.md => API.md (95%) diff --git a/sonoff/API.md b/API.md similarity index 95% rename from sonoff/API.md rename to API.md index 68442970f..9b43a1456 100644 --- a/sonoff/API.md +++ b/API.md @@ -32,9 +32,9 @@ FUNC_RULES_PROCESS | x | 6.0.0 | x | | | Process spe FUNC_SERIAL | x | | x | | x | Process serial data FUNC_FREE_MEM | | | x | | | Show free memory for debugging FUNC_BUTTON_PRESSED | x | 6.2.1.18 | x | | | When a button is pressed -FUNC_WEB_ADD_BUTTON | | 6.2.1.14 | x | | | Add a Configuration Button to GUI -FUNC_WEB_ADD_MAIN_BUTTON | | 6.2.1.14 | x | | | Add a main button to GUI -FUNC_WEB_ADD_HANDLER | | 6.2.1.14 | x | | | Add a webserver handler +FUNC_WEB_ADD_BUTTON | | 6.2.1.14 | x | x | | Add a Configuration Button to GUI +FUNC_WEB_ADD_MAIN_BUTTON | | 6.2.1.14 | x | x | | Add a main button to GUI +FUNC_WEB_ADD_HANDLER | | 6.2.1.14 | x | x | | Add a webserver handler ## Display Call back Ids The following table lists all Callback Ids for a Display service. diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 85951dbae..e6a95eae2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.18 20181019 * Add more API callbacks and document API.md * Add support for La Crosse TX20 Anemometer (#2654, #3146) + * Add optional HX711 scale interface to web GUI demonstrating easy GUI plug-in * * 6.2.1.17 20181017 * Enable updated non-blocking PubSubClient as default MQTT client diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 689707bbd..1d66ec783 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 23c01a1b3..8a495a1e9 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -461,6 +461,13 @@ #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 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 "Směr větru" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 91d99374d..41f4d20c4 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -461,6 +461,13 @@ #define D_HX_CAL_REFERENCE "Referenzgewicht auflegen" #define D_HX_CAL_DONE "kalibriert" #define D_HX_CAL_FAIL "Kalibrierung fehlgeschlagen" +#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" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index bdc4313de..3a648f86f 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index d93e1f237..9ddead578 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index b1c608a63..d2531dbf5 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -461,6 +461,13 @@ #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 "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" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 5fb4b50b7..c38f08b17 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index f4ed8fffb..c04b28f73 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index a5376c5e2..603ddd19a 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 009fd6ebc..1bf79502d 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index ca40e56fe..ecec2e39e 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 73b71d475..951d9a970 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 3831a9399..79792c15b 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index abf47783c..b2b88fd7a 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 22cf17b5d..3a607ad35 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 9d0d3fe6a..d51e87486 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 5976f1628..dbc3b575f 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index e24ae4a0d..32ee2ccf4 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 52376aa49..46b910654 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -461,6 +461,13 @@ #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" diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 3eca64536..4c0b4fdb3 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -375,6 +375,7 @@ //#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_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 894806919..3cb2b31cb 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -77,10 +77,10 @@ const char HTTP_HEAD[] PROGMEM = "lt=setTimeout(la,{a});" // Settings.web_refresh "}" "function lb(p){" - "la('?d='+p);" + "la('?d='+p);" // ?d related to WebGetArg("d", tmp, sizeof(tmp)); "}" "function lc(p){" - "la('?t='+p);" // ?t related to WebGetArg("t", tmp, sizeof(tmp)); + "la('?t='+p);" // ?t related to WebGetArg("t", tmp, sizeof(tmp)); "}"; const char HTTP_HEAD_RELOAD[] PROGMEM = @@ -293,7 +293,7 @@ const char HTTP_END[] PROGMEM = "" ""; -const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; +const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; // ?o is related to WebGetArg("o", tmp, sizeof(tmp)); const char HTTP_DEVICE_STATE[] PROGMEM = "%s%s"; // {c} = %'>
"), idx, idx); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); page += mqtt_data; } } @@ -606,6 +607,7 @@ void HandleRoot() #ifndef BE_MINIMAL mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); + XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); page += String(mqtt_data); #endif // Not BE_MINIMAL @@ -711,6 +713,7 @@ void HandleConfiguration() mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_BUTTON); + XsnsCall(FUNC_WEB_ADD_BUTTON); page += String(mqtt_data); page += FPSTR(HTTP_BTN_MENU4); diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 91d987ba5..64736f574 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -32,25 +32,30 @@ * - Execute command Sensor34 2 and follow messages shown \*********************************************************************************************/ -#define XSNS_34 34 +#define XSNS_34 34 #ifndef HX_MAX_WEIGHT -#define HX_MAX_WEIGHT 20000 // Default max weight in gram +#define HX_MAX_WEIGHT 20000 // Default max weight in gram #endif #ifndef HX_REFERENCE -#define HX_REFERENCE 250 // Default reference weight for calibration in gram +#define HX_REFERENCE 250 // Default reference weight for calibration in gram #endif #ifndef HX_SCALE -#define HX_SCALE 120 // Default result of measured weight / reference weight when scale is 1 +#define HX_SCALE 120 // Default result of measured weight / reference weight when scale is 1 #endif -#define HX_TIMEOUT 120 // A reading at default 10Hz (pin RATE to Gnd on HX711) can take up to 100 milliseconds -#define HX_SAMPLES 10 // Number of samples for average calculation -#define HX_CAL_TIMEOUT 15 // Calibration step window in number of seconds +#define HX_TIMEOUT 120 // A reading at default 10Hz (pin RATE to Gnd on HX711) can take up to 100 milliseconds +#define HX_SAMPLES 10 // Number of samples for average calculation +#define HX_CAL_TIMEOUT 15 // Calibration step window in number of seconds -#define HX_GAIN_128 1 // Channel A, gain factor 128 -#define HX_GAIN_32 2 // Channel B, gain factor 32 -#define HX_GAIN_64 3 // Channel A, gain factor 64 +#define HX_GAIN_128 1 // Channel A, gain factor 128 +#define HX_GAIN_32 2 // Channel B, gain factor 32 +#define HX_GAIN_64 3 // Channel A, gain factor 64 + +#define D_JSON_WEIGHT_REF "WeightRef" +#define D_JSON_WEIGHT_CAL "WeightCal" +#define D_JSON_WEIGHT_MAX "WeightMax" +#define D_JSON_WEIGHT_ITEM "WeightItem" 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 }; @@ -169,7 +174,7 @@ bool HxCommand() hx_calibrate_timer = 1; HxCalibrationStateTextJson(3); break; - case 3: // WeightSet to user reference + case 3: // WeightRef to user reference if (strstr(XdrvMailbox.data, ",")) { Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10); } @@ -201,7 +206,7 @@ bool HxCommand() if (show_parms) { char item[10]; dtostrfd((float)Settings.weight_item / 10, 1, item); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Sensor34\":{\"WeightSet\":%d,\"WeightCal\":%d,\"WeightMax\":%d,\"WeightItem\":%s}}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s}}"), Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item); } @@ -353,6 +358,109 @@ void HxShow(boolean json) } } +#ifdef USE_WEBSERVER +#ifdef USE_HX711_GUI +/*********************************************************************************************\ + * Optional 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() +{ + if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); + + if (WebServer->hasArg("save")) { + HxSaveSettings(); + HandleConfiguration(); + return; + } + + char tmp[100]; + + if (WebServer->hasArg("reset")) { + snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 1")); // Reset + ExecuteWebCommand(tmp, SRC_WEBGUI); + + HandleRoot(); // Return to main screen + return; + } + + if (WebServer->hasArg("calibrate")) { + WebGetArg("p1", tmp, sizeof(tmp)); + Settings.weight_reference = (!strlen(tmp)) ? 0 : (unsigned long)(CharToDouble(tmp) * 1000); + + HxLogUpdates(); + + snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 2")); // Start calibration + ExecuteWebCommand(tmp, SRC_WEBGUI); + + HandleRoot(); // Return to main screen + return; + } + + String page = FPSTR(HTTP_HEAD); + page.replace(F("{v}"), FPSTR(D_CONFIGURE_HX711)); + page += FPSTR(HTTP_HEAD_STYLE); + page += FPSTR(HTTP_FORM_HX711); + dtostrfd((float)Settings.weight_reference / 1000, 3, tmp); + page.replace("{1", String(tmp)); + dtostrfd((float)Settings.weight_item / 10000, 4, tmp); + page.replace("{2", String(tmp)); + + page += FPSTR(HTTP_FORM_END); + page += FPSTR(HTTP_BTN_CONF); + ShowPage(page); +} + +void HxSaveSettings() +{ + char tmp[100]; + + WebGetArg("p2", tmp, sizeof(tmp)); + Settings.weight_item = (!strlen(tmp)) ? 0 : (uint16_t)(CharToDouble(tmp) * 10000); + + HxLogUpdates(); +} + +void HxLogUpdates() +{ + char weigth_ref_chr[10]; + char weigth_item_chr[10]; + + dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); + dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), + weigth_ref_chr, weigth_item_chr); + AddLog(LOG_LEVEL_INFO); +} + +#endif // USE_HX711_GUI +#endif // USE_WEBSERVER + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -381,6 +489,17 @@ boolean Xsns34(byte function) case FUNC_WEB_APPEND: HxShow(0); break; +#ifdef USE_HX711_GUI + case FUNC_WEB_ADD_MAIN_BUTTON: + strncat_P(mqtt_data, HTTP_BTN_MENU_MAIN_HX711, sizeof(mqtt_data)); + break; + case FUNC_WEB_ADD_BUTTON: + strncat_P(mqtt_data, HTTP_BTN_MENU_HX711, sizeof(mqtt_data)); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); + break; +#endif // USE_HX711_GUI #endif // USE_WEBSERVER } } diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index d24575a64..d87c6de25 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -38,10 +38,10 @@ extern "C" { #ifdef USE_WEBSERVER const char HTTP_SNS_TX20[] PROGMEM = "%s" - "{s} " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s} " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s} " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s} " D_TX20_WIND_DIRECTION "{m}%s {e}"; + "{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 // USE_WEBSERVER From 7fd250d72b184f25770eb1c7c40d3a3dad3cd878 Mon Sep 17 00:00:00 2001 From: synekvl <42292671+synekvl@users.noreply.github.com> Date: Sun, 21 Oct 2018 16:41:34 +0200 Subject: [PATCH 35/54] Update cs-CZ.h --- sonoff/language/cs-CZ.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index b37e2a2fa..2e50ce172 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -461,6 +461,13 @@ #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" From b4162baa6315d023327b784ee57c85d204620342 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Oct 2018 16:48:10 +0200 Subject: [PATCH 36/54] Admin --- RELEASENOTES.md | 10 ++++++++++ sonoff/sonoff_post.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 212e3a7da..a98f96b33 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -79,9 +79,11 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_LM75AD | - | - | x | x | x | | USE_APDS9960 | - | - | - | - | - | | USE_MCP230xx | - | - | - | - | - | +| USE_PCA9685 | - | - | - | - | - | | USE_MPR121 | - | - | - | - | - | | USE_CCS811 | - | - | - | - | - | | USE_MPU6050 | - | - | - | - | - | +| USE_DS3231 | - | - | - | - | - | | | | | | | | | Feature or Sensor | minimal | classic | sonoff | knx | sensors | | USE_SPI | - | - | - | - | - | @@ -90,9 +92,13 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_PMS5003 | - | - | x | x | x | | USE_NOVA_SDS | - | - | x | x | x | | USE_PZEM004T | - | - | x | x | x | +| USE_PZEM_AC | - | - | x | x | x | +| USE_PZEM_DC | - | - | x | x | x | +| USE_MCP39F501 | - | - | x | x | x | | USE_SERIAL_BRIDGE | - | - | x | x | x | | USE_SDM120 | - | - | - | - | x | | USE_SDM630 | - | - | - | - | x | +| USE_MP3_PLAYER | - | - | - | - | - | | USE_IR_REMOTE | - | - | x | x | x | | USE_IR_HVAC | - | - | - | - | x | | USE_IR_RECEIVE | - | - | x | x | x | @@ -101,7 +107,11 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_ARILUX_RF | - | - | x | x | x | | USE_SR04 | - | - | x | x | x | | USE_TM1638 | - | - | - | - | - | +| USE_HX711 | - | - | x | x | x | | USE_RF_FLASH | - | - | x | x | x | +| USE_TUYA_DIMMER | - | - | x | x | x | +| USE_TX20_WIND_SENSOR | - | - | x | x | x | +| USE_DISPLAY | - | - | - | - | - | ## Changelog Version 6.2.1 20180905 diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 3db21b48f..62b3fc88a 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -148,6 +148,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // USE_CLASSIC @@ -243,6 +245,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // BE_MINIMAL From 5f7c986812c07efb551f12361174825e0d119ff7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Oct 2018 16:59:14 +0200 Subject: [PATCH 37/54] Remove duplicate language file --- sonoff/language/bg-BG.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 1d66ec783..9d4d41815 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -525,7 +525,6 @@ #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 "TX20" // Units #define D_UNIT_AMPERE "A" From abbae2f43c6ba471f08a64f0cea6e4474d5f857f Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 21 Oct 2018 17:15:38 +0200 Subject: [PATCH 38/54] Update de-DE.h --- sonoff/language/de-DE.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 41f4d20c4..28d687dae 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -461,21 +461,21 @@ #define D_HX_CAL_REFERENCE "Referenzgewicht auflegen" #define D_HX_CAL_DONE "kalibriert" #define D_HX_CAL_FAIL "Kalibrierung fehlgeschlagen" -#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" +#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 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_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 "E" +#define D_TX20_EAST "O" #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" From a7c912111cd78048170a9b4934dd0dd808f86663 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Oct 2018 17:54:51 +0200 Subject: [PATCH 39/54] Resize HX711 weight_item field Resize HX711 weight_item field from 16 bit to 32 bit --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 7 +++++-- sonoff/xsns_34_hx711.ino | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e6a95eae2..d1f82a2d0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Add more API callbacks and document API.md * Add support for La Crosse TX20 Anemometer (#2654, #3146) * Add optional HX711 scale interface to web GUI demonstrating easy GUI plug-in + * Resize HX711 weight_item field from 16 bit to 32 bit * * 6.2.1.17 20181017 * Enable updated non-blocking PubSubClient as default MQTT client diff --git a/sonoff/settings.h b/sonoff/settings.h index bef70acc5..29aaf2121 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -322,9 +322,12 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A - byte free_71F[157]; // 71F + byte free_71F[153]; // 71F + + unsigned long weight_item; // 7B8 Weight of one item in gram * 10 + + byte free_7BC[2]; // 7BC - uint16_t weight_item; // 7BC Weight of one item in gram * 10 uint16_t weight_max; // 7BE Total max weight in kilogram unsigned long weight_reference; // 7C0 Reference weight in gram unsigned long weight_calibration; // 7C4 diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 64736f574..7e9b7ff30 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -195,7 +195,7 @@ bool HxCommand() break; case 6: // WeightItem if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_item = (uint16_t)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); + Settings.weight_item = (unsigned long)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); } show_parms = true; break; @@ -440,7 +440,7 @@ void HxSaveSettings() char tmp[100]; WebGetArg("p2", tmp, sizeof(tmp)); - Settings.weight_item = (!strlen(tmp)) ? 0 : (uint16_t)(CharToDouble(tmp) * 10000); + Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToDouble(tmp) * 10000); HxLogUpdates(); } From 43ba673b5e5beb48a0cff052d4fc647f5f499921 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 22 Oct 2018 22:40:56 -0300 Subject: [PATCH 40/54] Update Spanish Translation --- sonoff/language/es-AR.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index d2531dbf5..42986a573 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -461,23 +461,23 @@ #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 "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" +#define D_RESET_HX711 "Restableces 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 "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_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 "W" +#define D_TX20_WEST "O" // sonoff_template.h #define D_SENSOR_NONE "Ninguno" From 2c02532e1c2e40cd4af106ca137228dfbc700a76 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 23 Oct 2018 15:51:51 +0200 Subject: [PATCH 41/54] 6.2.1.19 Rename user_config.h 6.2.1.19 20181023 * Fix header file execution order by renaming user_config.h to my_user_config.h * Fix Arduino IDE compilation warning regarding e-paper library --- API.md | 1 + .../library.properties | 9 +++++++++ sonoff/_changelog.ino | 5 ++++- sonoff/{user_config.h => my_user_config.h} | 8 ++++---- sonoff/sonoff.h | 9 ++++++--- sonoff/sonoff.ino | 20 +++++++++++-------- sonoff/user_config_override_sample.h | 8 ++++---- sonoff/xdrv_14_mp3.ino | 4 ++-- sonoff/xsns_34_hx711.ino | 5 +++++ 9 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties rename sonoff/{user_config.h => my_user_config.h} (99%) diff --git a/API.md b/API.md index 9b43a1456..23e45369d 100644 --- a/API.md +++ b/API.md @@ -8,6 +8,7 @@ The following table lists Callback Ids and their availability for a Driver, Sens Callback Id | Bool | Version | xdrv | xsns | xnrg | Description ----------------------------|------|----------|------|------|------|---------------------------------- +FUNC_SETTINGS_OVERRIDE | | 6.2.1.19 | x | | | Override start-up settings FUNC_MODULE_INIT | x | 6.2.1.17 | x | | | Init module specific parameters FUNC_PRE_INIT | | | x | | x | Once GPIO have been established FUNC_INIT | | | x | x | x | At end of initialisation diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties b/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties new file mode 100644 index 000000000..07a9e0a07 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties @@ -0,0 +1,9 @@ +name=Waveshare esp 2.9 inch e-paper display driver +version=1.0 +author=Gerhard Muntz +maintainer=Gerhard Muntz +sentence=ESP8266 library for Waveshare e-paper display. +paragraph= +category=Display +url=https://github.com/gemu2015/Sonoff-Tasmota/tree/displays/lib/esp-epaper-29-ws-20171230-gemu-1.0# +architectures=esp8266 diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d1f82a2d0..c3daa6e42 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.18 20181019 +/* 6.2.1.19 20181023 + * Fix header file execution order by renaming user_config.h to my_user_config.h + * + * 6.2.1.18 20181019 * Add more API callbacks and document API.md * Add support for La Crosse TX20 Anemometer (#2654, #3146) * Add optional HX711 scale interface to web GUI demonstrating easy GUI plug-in diff --git a/sonoff/user_config.h b/sonoff/my_user_config.h similarity index 99% rename from sonoff/user_config.h rename to sonoff/my_user_config.h index 4c0b4fdb3..c6becae97 100644 --- a/sonoff/user_config.h +++ b/sonoff/my_user_config.h @@ -1,5 +1,5 @@ /* - user_config.h - user specific configuration for Sonoff-Tasmota + my_user_config.h - user specific configuration for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef _USER_CONFIG_H_ -#define _USER_CONFIG_H_ +#ifndef _MY_USER_CONFIG_H_ +#define _MY_USER_CONFIG_H_ /*********************************************************************************************\ * This file consists of TWO sections. @@ -410,4 +410,4 @@ #error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with" #endif -#endif // _USER_CONFIG_H_ +#endif // _MY_USER_CONFIG_H_ diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index beacb9f93..70e0e9a3d 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -212,10 +212,13 @@ enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; -enum XsnsFunctions {FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, +enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, + FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, - FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, - 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_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, + FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, + FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 3972d4f40..153e55fb7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -28,13 +28,13 @@ // Location specific includes #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) #include "sonoff_version.h" // Sonoff-Tasmota version information -#include "sonoff.h" // Enumeration used in user_config.h -#include "user_config.h" // Fixed user configurable options +#include "sonoff.h" // Enumeration used in my_user_config.h +#include "my_user_config.h" // Fixed user configurable options #ifdef USE_CONFIG_OVERRIDE - #include "user_config_override.h" // Configuration overrides for user_config.h + #include "user_config_override.h" // Configuration overrides for my_user_config.h #endif #include "sonoff_post.h" // Configuration overrides for all previous includes -#include "i18n.h" // Language support configured by user_config.h +#include "i18n.h" // Language support configured by my_user_config.h #include "sonoff_template.h" // Hardware configuration #ifdef ARDUINO_ESP8266_RELEASE_2_4_0 @@ -2575,6 +2575,10 @@ void setup() GetFeatures(); + if (1 == RtcReboot.fast_reboot_count) { // Allow setting override only when all is well + XdrvCall(FUNC_SETTINGS_OVERRIDE); + } + baudrate = Settings.baudrate * 1200; seriallog_level = Settings.seriallog_level; seriallog_timer = SERIALLOG_TIMER; @@ -2587,19 +2591,19 @@ void setup() sleep = Settings.sleep; // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) - if (RtcReboot.fast_reboot_count > 1) { // Restart twice + if (RtcReboot.fast_reboot_count > 1) { // Restart twice Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI - if (RtcReboot.fast_reboot_count > 2) { // Restart 3 times + if (RtcReboot.fast_reboot_count > 2) { // Restart 3 times for (byte i = 0; i < MAX_RULE_SETS; i++) { if (bitRead(Settings.rule_stop, i)) { bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop } } } - if (RtcReboot.fast_reboot_count > 3) { // Restarted 4 times + if (RtcReboot.fast_reboot_count > 3) { // Restarted 4 times Settings.rule_enabled = 0; // Disable all rules } - if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times + if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic Settings.last_module = SONOFF_BASIC; for (byte i = 0; i < MAX_GPIO_PIN; i++) { diff --git a/sonoff/user_config_override_sample.h b/sonoff/user_config_override_sample.h index 8b3203904..8d0abb22f 100644 --- a/sonoff/user_config_override_sample.h +++ b/sonoff/user_config_override_sample.h @@ -1,5 +1,5 @@ /* - user_config_override.h - user configuration overrides user_config.h for Sonoff-Tasmota + user_config_override.h - user configuration overrides my_user_config.h for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -25,7 +25,7 @@ /*****************************************************************************************************\ * USAGE: - * To modify the stock configuration without changing the user_config.h file: + * To modify the stock configuration without changing the my_user_config.h file: * (1) copy this file to "user_config_override.h" (It will be ignored by Git) * (2) define your own settings below * (3) for platformio: @@ -33,12 +33,12 @@ * ie1 : export PLATFORMIO_BUILD_FLAGS='-DUSE_CONFIG_OVERRIDE' * ie2 : enable in file platformio.ini "build_flags = -Wl,-Tesp8266.flash.1m0.ld -DUSE_CONFIG_OVERRIDE" * for Arduino IDE: - * enable define USE_CONFIG_OVERRIDE in user_config.h + * enable define USE_CONFIG_OVERRIDE in my_user_config.h ****************************************************************************************************** * ATTENTION: * - Changes to SECTION1 PARAMETER defines will only override flash settings if you change define CFG_HOLDER. * - Expect compiler warnings when no ifdef/undef/endif sequence is used. - * - You still need to update user_config.h for major define USE_MQTT_TLS. + * - You still need to update my_user_config.h for major define USE_MQTT_TLS. * - All parameters can be persistent changed online using commands via MQTT, WebConsole or Serial. \*****************************************************************************************************/ diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index 3bbf32bd0..ae0c69fd0 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -141,7 +141,7 @@ void MP3PlayerInit(void) { delay(1000); MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); // reset the player to defaults delay(3000); - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the user_config.h + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the my_user_config.h } return; } @@ -167,7 +167,7 @@ void MP3_CMD(uint8_t mp3cmd,uint16_t val) { MP3Player->write(cmd, sizeof(cmd)); // write mp3 data array to player delay(1000); if (mp3cmd == MP3_CMD_RESET) { - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the user_config.h + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the my_user_config.h } return; } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 7e9b7ff30..e46f1d445 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -215,6 +215,11 @@ bool HxCommand() /*********************************************************************************************/ +long HxWeight() +{ + return (hx_calibrate_step < HX_CAL_FAIL) ? hx_weight : 0; +} + void HxInit() { hx_type = 0; From 19b7a33f6b493b83a3926bbe8c8298d07671be58 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 23 Oct 2018 16:03:57 +0200 Subject: [PATCH 42/54] Prepair for more drivers --- sonoff/xdrv_interface.ino | 48 +++++++++++++++++++++++++++++++++++++++ sonoff/xnrg_interface.ino | 34 ++++++++++++++++++++++++++- sonoff/xsns_interface.ino | 40 ++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index a88d3b5f8..c80bb27d4 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -98,6 +98,54 @@ boolean (* const xdrv_func_ptr[])(byte) PROGMEM = { // Driver Function Pointer &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 + // Optional user defined drivers in range 91 - 99 #ifdef XDRV_91 diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino index 9af865f26..015d5d284 100644 --- a/sonoff/xnrg_interface.ino +++ b/sonoff/xnrg_interface.ino @@ -47,7 +47,39 @@ int (* const xnrg_func_ptr[])(byte) PROGMEM = { // Energy driver Function Poin #endif #ifdef XNRG_08 - &Xnrg08 + &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 }; diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 2f0468b9e..408e68af9 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -178,6 +178,46 @@ boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers &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 + // Optional user defined sensors in range 91 - 99 #ifdef XSNS_91 From 9f4fed1584c8b5c1abb61ee405fb0faefb1aa555 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 23 Oct 2018 17:07:43 +0200 Subject: [PATCH 43/54] Update PubSubClient lib Add delay when waiting for data and flush on disconnect --- lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp index 7d1d3e102..79eb2d52e 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp +++ b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp @@ -209,6 +209,7 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass boolean PubSubClient::readByte(uint8_t * result) { uint32_t previousMillis = millis(); while(!_client->available()) { + delay(1); // Add esp8266 de-blocking (Tasmota #790, EspEasy #1943) uint32_t currentMillis = millis(); if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){ return false; @@ -522,9 +523,12 @@ boolean PubSubClient::unsubscribe(const char* topic) { void PubSubClient::disconnect() { buffer[0] = MQTTDISCONNECT; buffer[1] = 0; - _client->write(buffer,2); + if (_client != NULL) { + _client->write(buffer,2); + _client->flush(); + _client->stop(); + } _state = MQTT_DISCONNECTED; - _client->stop(); lastInActivity = lastOutActivity = millis(); } From 11da866bce0a41b99565ec682b470838bfeeac92 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 24 Oct 2018 12:46:25 -0300 Subject: [PATCH 44/54] KNX: Disabling ESPAsyncUDP Library When using KNX in cores > 2.3.0, the ESPAsyncUDP Library was used instead of the WIFIUDP Library. As now ESPAsyncUDP is no longer mantained and also it does not work in last version of the Arduino STAGE Core, now for all cores KNX will use the WIFIUDP Library. --- lib/esp-knx-ip-0.5.1/esp-knx-ip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/esp-knx-ip-0.5.1/esp-knx-ip.h b/lib/esp-knx-ip-0.5.1/esp-knx-ip.h index 515a5d843..5a4082c32 100644 --- a/lib/esp-knx-ip-0.5.1/esp-knx-ip.h +++ b/lib/esp-knx-ip-0.5.1/esp-knx-ip.h @@ -48,7 +48,7 @@ #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) #ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -#define USE_ASYNC_UDP // UDP WIFI Library Selection for Multicast +//#define USE_ASYNC_UDP // UDP WIFI Library Selection for Multicast #endif #ifdef USE_ASYNC_UDP From b9fda004d29cf775a9666b2803d0fac78be1f422 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 24 Oct 2018 13:58:21 -0300 Subject: [PATCH 45/54] KNX: Delete unnecessary comments --- sonoff/xdrv_11_knx.ino | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 6132133ae..944f1ba90 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -49,14 +49,6 @@ byte Settings.knx_CB_param[MAX_KNX_CB] Type of Output (set relay, t \*********************************************************************************************/ #include // KNX Library - // Note: Inside the file there is a //#define USE_ASYNC_UDP // UDP WIFI Library Selection for Multicast - // If commented out, the esp-knx-ip library will use WIFI_UDP Library that is compatible with ESP8266 Library Version 2.3.0 and up - // If not commented out, the esp-knx-ip library will use ESPAsyncUDP Library that is compatible with ESP8266 Library Version 2.4.0 and up - // The ESPAsyncUDP Library have a more reliable multicast communication - // Please Use it with Patch (https://github.com/me-no-dev/ESPAsyncUDP/pull/21) ) - -//void KNX_CB_Action(message_t const &msg, void *arg); // Define function (action callback) to be called by the Esp-KNX-IP Library - // when an action is requested by another KNX Device address_t KNX_physs_addr; // Physical KNX address of this device address_t KNX_addr; // KNX Address converter variable From 00c99e512b3a35de491c9f87cd02683eecca4a0e Mon Sep 17 00:00:00 2001 From: ascillato Date: Wed, 24 Oct 2018 14:20:34 -0300 Subject: [PATCH 46/54] KNX: Updated ESP-KNX-IP Lib to use only WIFIUDP Lib --- lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp | 5 +---- lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp | 22 ---------------------- lib/esp-knx-ip-0.5.1/esp-knx-ip.h | 19 ------------------- 3 files changed, 1 insertion(+), 45 deletions(-) diff --git a/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp b/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp index 624e08d18..23ee319e6 100644 --- a/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp +++ b/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp @@ -77,13 +77,10 @@ void ESPKNXIP::send(address_t const &receiver, knx_command_type_t ct, uint8_t da DEBUG_PRINTLN(F("")); #endif -#ifdef USE_ASYNC_UDP - udp.writeTo(buf, len, MULTICAST_IP, MULTICAST_PORT); -#else udp.beginPacketMulticast(MULTICAST_IP, MULTICAST_PORT, WiFi.localIP()); udp.write(buf, len); udp.endPacket(); -#endif + } void ESPKNXIP::send_1bit(address_t const &receiver, knx_command_type_t ct, uint8_t bit) diff --git a/lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp b/lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp index 767fa9752..5917e62f3 100644 --- a/lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp +++ b/lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp @@ -95,13 +95,7 @@ void ESPKNXIP::__start() #endif server->begin(); } - -#ifdef USE_ASYNC_UDP - udp.listenMulticast(MULTICAST_IP, MULTICAST_PORT); - udp.onPacket([this](AsyncUDPPacket &packet) { __loop_knx(packet); }); -#else udp.beginMulticast(WiFi.localIP(), MULTICAST_IP, MULTICAST_PORT); -#endif } void ESPKNXIP::save_to_eeprom() @@ -516,9 +510,7 @@ feedback_id_t ESPKNXIP::feedback_register_action(String name, feedback_action_fp void ESPKNXIP::loop() { - #ifndef USE_ASYNC_UDP __loop_knx(); - #endif if (server != nullptr) { __loop_webserver(); @@ -530,15 +522,9 @@ void ESPKNXIP::__loop_webserver() server->handleClient(); } -#ifdef USE_ASYNC_UDP -void ESPKNXIP::__loop_knx(AsyncUDPPacket &packet) -{ - size_t read = packet.length(); -#else void ESPKNXIP::__loop_knx() { int read = udp.parsePacket(); -#endif if (!read) { @@ -548,23 +534,15 @@ void ESPKNXIP::__loop_knx() DEBUG_PRINT(F("LEN: ")); DEBUG_PRINTLN(read); -#ifdef USE_ASYNC_UDP - uint8_t *buf = packet.data(); -#else uint8_t buf[read]; udp.read(buf, read); udp.flush(); -#endif DEBUG_PRINT(F("Got packet:")); #ifdef ESP_KNX_DEBUG -#ifdef USE_ASYNC_UDP - for (size_t i = 0; i < read; ++i) -#else for (int i = 0; i < read; ++i) -#endif { DEBUG_PRINT(F(" 0x")); diff --git a/lib/esp-knx-ip-0.5.1/esp-knx-ip.h b/lib/esp-knx-ip-0.5.1/esp-knx-ip.h index 5a4082c32..e2346c5a3 100644 --- a/lib/esp-knx-ip-0.5.1/esp-knx-ip.h +++ b/lib/esp-knx-ip-0.5.1/esp-knx-ip.h @@ -45,18 +45,7 @@ #include "Arduino.h" #include #include - -#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -//#define USE_ASYNC_UDP // UDP WIFI Library Selection for Multicast -#endif - -#ifdef USE_ASYNC_UDP -#include -#else #include -#endif - #include #include "DPT.h" @@ -529,11 +518,7 @@ class ESPKNXIP { private: void __start(); -#ifdef USE_ASYNC_UDP - void __loop_knx(AsyncUDPPacket &packet); -#else void __loop_knx(); -#endif // Webserver functions void __loop_webserver(); @@ -569,11 +554,7 @@ class ESPKNXIP { ESP8266WebServer *server; address_t physaddr; -#ifdef USE_ASYNC_UDP - AsyncUDP udp; -#else WiFiUDP udp; -#endif callback_assignment_id_t registered_callback_assignments; callback_assignment_id_t free_callback_assignment_slots; From 8899bc83904617d3014856d0ee3afda2d5e5d51a Mon Sep 17 00:00:00 2001 From: ascillato Date: Wed, 24 Oct 2018 14:21:33 -0300 Subject: [PATCH 47/54] KNX: Deleted ESPAsyncUDP Library --- lib/ESPAsyncUDP-master/.travis.yml | 37 -- lib/ESPAsyncUDP-master/README.md | 10 - .../AsyncUDPClient/AsyncUDPClient.ino | 51 --- .../AsyncUDPMulticastServer.ino | 52 --- .../AsyncUDPServer/AsyncUDPServer.ino | 50 -- lib/ESPAsyncUDP-master/keywords.txt | 33 -- lib/ESPAsyncUDP-master/library.json | 17 - lib/ESPAsyncUDP-master/library.properties | 9 - lib/ESPAsyncUDP-master/src/AsyncUDP.cpp | 432 ------------------ lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h | 130 ------ lib/ESPAsyncUDP-master/travis/common.sh | 23 - 11 files changed, 844 deletions(-) delete mode 100644 lib/ESPAsyncUDP-master/.travis.yml delete mode 100644 lib/ESPAsyncUDP-master/README.md delete mode 100644 lib/ESPAsyncUDP-master/examples/AsyncUDPClient/AsyncUDPClient.ino delete mode 100644 lib/ESPAsyncUDP-master/examples/AsyncUDPMulticastServer/AsyncUDPMulticastServer.ino delete mode 100644 lib/ESPAsyncUDP-master/examples/AsyncUDPServer/AsyncUDPServer.ino delete mode 100644 lib/ESPAsyncUDP-master/keywords.txt delete mode 100644 lib/ESPAsyncUDP-master/library.json delete mode 100644 lib/ESPAsyncUDP-master/library.properties delete mode 100644 lib/ESPAsyncUDP-master/src/AsyncUDP.cpp delete mode 100644 lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h delete mode 100644 lib/ESPAsyncUDP-master/travis/common.sh diff --git a/lib/ESPAsyncUDP-master/.travis.yml b/lib/ESPAsyncUDP-master/.travis.yml deleted file mode 100644 index c1ef4ec8f..000000000 --- a/lib/ESPAsyncUDP-master/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -sudo: false -language: bash -os: - - linux - -script: - - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 - - sleep 3 - - export DISPLAY=:1.0 - - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz - - tar xf arduino-1.6.5-linux64.tar.xz - - mv arduino-1.6.5 $HOME/arduino_ide - - export PATH="$HOME/arduino_ide:$PATH" - - which arduino - - mkdir -p $HOME/Arduino/libraries - - cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/ESPAsyncUDP - - cd $HOME/arduino_ide/hardware - - mkdir esp8266com - - cd esp8266com - - git clone https://github.com/esp8266/Arduino.git esp8266 - - cd esp8266/tools - - python get.py - - source $TRAVIS_BUILD_DIR/travis/common.sh - - arduino --board esp8266com:esp8266:generic --save-prefs - - arduino --get-pref sketchbook.path - - build_sketches arduino $HOME/Arduino/libraries/ESPAsyncUDP esp8266 - -notifications: - email: - on_success: change - on_failure: change - webhooks: - urls: - - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false diff --git a/lib/ESPAsyncUDP-master/README.md b/lib/ESPAsyncUDP-master/README.md deleted file mode 100644 index 997a7cc26..000000000 --- a/lib/ESPAsyncUDP-master/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# ESPAsyncUDP -Async UDP Library for ESP8266 Arduino [![Build Status](https://travis-ci.org/me-no-dev/ESPAsyncUDP.svg?branch=master)](https://travis-ci.org/me-no-dev/ESPAsyncUDP) - -[![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -This is a fully asynchronous UDP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP8266 MCUs. - -The library is easy to use and includes support for Unicast, Broadcast and Multicast environments - -Latest GIT version of ESP8266 Arduino might be required for this library to work diff --git a/lib/ESPAsyncUDP-master/examples/AsyncUDPClient/AsyncUDPClient.ino b/lib/ESPAsyncUDP-master/examples/AsyncUDPClient/AsyncUDPClient.ino deleted file mode 100644 index cf528fe12..000000000 --- a/lib/ESPAsyncUDP-master/examples/AsyncUDPClient/AsyncUDPClient.ino +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include "ESPAsyncUDP.h" - -const char * ssid = "***********"; -const char * password = "***********"; - -AsyncUDP udp; - -void setup() -{ - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.println("WiFi Failed"); - while(1) { - delay(1000); - } - } - if(udp.connect(IPAddress(192,168,1,100), 1234)) { - Serial.println("UDP connected"); - udp.onPacket([](AsyncUDPPacket packet) { - Serial.print("UDP Packet Type: "); - Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast"); - Serial.print(", From: "); - Serial.print(packet.remoteIP()); - Serial.print(":"); - Serial.print(packet.remotePort()); - Serial.print(", To: "); - Serial.print(packet.localIP()); - Serial.print(":"); - Serial.print(packet.localPort()); - Serial.print(", Length: "); - Serial.print(packet.length()); - Serial.print(", Data: "); - Serial.write(packet.data(), packet.length()); - Serial.println(); - //reply to the client - packet.printf("Got %u bytes of data", packet.length()); - }); - //Send unicast - udp.print("Hello Server!"); - } -} - -void loop() -{ - delay(1000); - //Send broadcast on port 1234 - udp.broadcastTo("Anyone here?", 1234); -} diff --git a/lib/ESPAsyncUDP-master/examples/AsyncUDPMulticastServer/AsyncUDPMulticastServer.ino b/lib/ESPAsyncUDP-master/examples/AsyncUDPMulticastServer/AsyncUDPMulticastServer.ino deleted file mode 100644 index bb3e69c9b..000000000 --- a/lib/ESPAsyncUDP-master/examples/AsyncUDPMulticastServer/AsyncUDPMulticastServer.ino +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include "ESPAsyncUDP.h" - -const char * ssid = "***********"; -const char * password = "***********"; - -AsyncUDP udp; - -void setup() -{ - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.println("WiFi Failed"); - while(1) { - delay(1000); - } - } - if(udp.listenMulticast(IPAddress(239,1,2,3), 1234)) { - Serial.print("UDP Listening on IP: "); - Serial.println(WiFi.localIP()); - udp.onPacket([](AsyncUDPPacket packet) { - Serial.print("UDP Packet Type: "); - Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast"); - Serial.print(", From: "); - Serial.print(packet.remoteIP()); - Serial.print(":"); - Serial.print(packet.remotePort()); - Serial.print(", To: "); - Serial.print(packet.localIP()); - Serial.print(":"); - Serial.print(packet.localPort()); - Serial.print(", Length: "); - Serial.print(packet.length()); - Serial.print(", Data: "); - Serial.write(packet.data(), packet.length()); - Serial.println(); - //reply to the client - packet.printf("Got %u bytes of data", packet.length()); - }); - //Send multicast - udp.print("Hello!"); - } -} - -void loop() -{ - delay(1000); - //Send multicast - udp.print("Anyone here?"); -} diff --git a/lib/ESPAsyncUDP-master/examples/AsyncUDPServer/AsyncUDPServer.ino b/lib/ESPAsyncUDP-master/examples/AsyncUDPServer/AsyncUDPServer.ino deleted file mode 100644 index fc12a7fc3..000000000 --- a/lib/ESPAsyncUDP-master/examples/AsyncUDPServer/AsyncUDPServer.ino +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include "ESPAsyncUDP.h" - -const char * ssid = "***********"; -const char * password = "***********"; - -AsyncUDP udp; - -void setup() -{ - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.println("WiFi Failed"); - while(1) { - delay(1000); - } - } - if(udp.listen(1234)) { - Serial.print("UDP Listening on IP: "); - Serial.println(WiFi.localIP()); - udp.onPacket([](AsyncUDPPacket packet) { - Serial.print("UDP Packet Type: "); - Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast"); - Serial.print(", From: "); - Serial.print(packet.remoteIP()); - Serial.print(":"); - Serial.print(packet.remotePort()); - Serial.print(", To: "); - Serial.print(packet.localIP()); - Serial.print(":"); - Serial.print(packet.localPort()); - Serial.print(", Length: "); - Serial.print(packet.length()); - Serial.print(", Data: "); - Serial.write(packet.data(), packet.length()); - Serial.println(); - //reply to the client - packet.printf("Got %u bytes of data", packet.length()); - }); - } -} - -void loop() -{ - delay(1000); - //Send broadcast - udp.broadcast("Anyone here?"); -} diff --git a/lib/ESPAsyncUDP-master/keywords.txt b/lib/ESPAsyncUDP-master/keywords.txt deleted file mode 100644 index 67c0b97a7..000000000 --- a/lib/ESPAsyncUDP-master/keywords.txt +++ /dev/null @@ -1,33 +0,0 @@ -####################################### -# Syntax Coloring Map For Ultrasound -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -AsyncUDP KEYWORD1 -AsyncUDPPacket KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -connect KEYWORD2 -connected KEYWORD2 -listen KEYWORD2 -listenMulticast KEYWORD2 -close KEYWORD2 -write KEYWORD2 -broadcast KEYWORD2 -onPacket KEYWORD2 -data KEYWORD2 -length KEYWORD2 -localIP KEYWORD2 -localPort KEYWORD2 -remoteIP KEYWORD2 -remotePort KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### diff --git a/lib/ESPAsyncUDP-master/library.json b/lib/ESPAsyncUDP-master/library.json deleted file mode 100644 index fe300b6e6..000000000 --- a/lib/ESPAsyncUDP-master/library.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name":"ESPAsyncUDP", - "description":"Asynchronous UDP Library for ESP8266", - "keywords":"async,udp,server,client,multicast,broadcast", - "authors": - { - "name": "Hristo Gochkov", - "maintainer": true - }, - "repository": - { - "type": "git", - "url": "https://github.com/me-no-dev/ESPAsyncUDP.git" - }, - "frameworks": "arduino", - "platforms":"espressif" -} diff --git a/lib/ESPAsyncUDP-master/library.properties b/lib/ESPAsyncUDP-master/library.properties deleted file mode 100644 index 1aa6ef1ad..000000000 --- a/lib/ESPAsyncUDP-master/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=ESP Async UDP -version=1.0.0 -author=Me-No-Dev -maintainer=Me-No-Dev -sentence=Async UDP Library for ESP8266 -paragraph=Async UDP Library for ESP8266 -category=Other -url=https://github.com/me-no-dev/ESPAsyncUDP -architectures=* diff --git a/lib/ESPAsyncUDP-master/src/AsyncUDP.cpp b/lib/ESPAsyncUDP-master/src/AsyncUDP.cpp deleted file mode 100644 index 9e433b1f4..000000000 --- a/lib/ESPAsyncUDP-master/src/AsyncUDP.cpp +++ /dev/null @@ -1,432 +0,0 @@ -#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // This Library will only work with ARDUINO_ESP8266_RELEASE_2_4_0 and up - -#include "Arduino.h" -#include "ESPAsyncUDP.h" - -extern "C" { -#include "user_interface.h" -#include "lwip/opt.h" -#include "lwip/inet.h" -#include "lwip/udp.h" -#include "lwip/igmp.h" -} - -AsyncUDPMessage::AsyncUDPMessage(size_t size) -{ - _index = 0; - if(size > 1460) { - size = 1460; - } - _size = size; - _buffer = (uint8_t *)malloc(size); -} - -AsyncUDPMessage::~AsyncUDPMessage() -{ - if(_buffer) { - free(_buffer); - } -} - -size_t AsyncUDPMessage::write(const uint8_t *data, size_t len) -{ - if(_buffer == NULL) { - return 0; - } - size_t s = space(); - if(len > s) { - len = s; - } - memcpy(_buffer + _index, data, len); - _index += len; - return len; -} - -size_t AsyncUDPMessage::write(uint8_t data) -{ - return write(&data, 1); -} - -size_t AsyncUDPMessage::space() -{ - if(_buffer == NULL) { - return 0; - } - return _size - _index; -} - -uint8_t * AsyncUDPMessage::data() -{ - return _buffer; -} - -size_t AsyncUDPMessage::length() -{ - return _index; -} - -void AsyncUDPMessage::flush() -{ - _index = 0; -} - - -AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, ip_addr_t *localIp, uint16_t localPort, ip_addr_t *remoteIp, uint16_t remotePort, uint8_t *data, size_t len) -{ - _udp = udp; - _localIp = localIp; - _localPort = localPort; - _remoteIp = remoteIp; - _remotePort = remotePort; - _data = data; - _len = len; -} - -AsyncUDPPacket::~AsyncUDPPacket() -{ - -} - -uint8_t * AsyncUDPPacket::data() -{ - return _data; -} - -size_t AsyncUDPPacket::length() -{ - return _len; -} - -IPAddress AsyncUDPPacket::localIP() -{ - return IPAddress(_localIp->addr); -} - -uint16_t AsyncUDPPacket::localPort() -{ - return _localPort; -} - -IPAddress AsyncUDPPacket::remoteIP() -{ - return IPAddress(_remoteIp->addr); -} - -uint16_t AsyncUDPPacket::remotePort() -{ - return _remotePort; -} - -bool AsyncUDPPacket::isBroadcast() -{ - return _localIp->addr == 0xFFFFFFFF || _localIp->addr == (uint32_t)(0); -} - -bool AsyncUDPPacket::isMulticast() -{ - return ip_addr_ismulticast(_localIp); -} - -size_t AsyncUDPPacket::write(const uint8_t *data, size_t len) -{ - return _udp->writeTo(data, len, _remoteIp, _remotePort); -} - -size_t AsyncUDPPacket::write(uint8_t data) -{ - return write(&data, 1); -} - -size_t AsyncUDPPacket::send(AsyncUDPMessage &message) -{ - return write(message.data(), message.length()); -} - - - -AsyncUDP::AsyncUDP() -{ - _pcb = NULL; - _connected = false; - _handler = NULL; -} - -AsyncUDP::~AsyncUDP() -{ - close(); -} - -AsyncUDP::operator bool() -{ - return _connected; -} - -bool AsyncUDP::connected() -{ - return _connected; -} - -void AsyncUDP::onPacket(AuPacketHandlerFunctionWithArg cb, void * arg) -{ - onPacket(std::bind(cb, arg, std::placeholders::_1)); -} - -void AsyncUDP::onPacket(AuPacketHandlerFunction cb) -{ - _handler = cb; -} - -void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, ip_addr_t *addr, uint16_t port) -{ - (void)upcb; // its unused, avoid warning - while(pb != NULL) { - if(_handler) { - uint8_t * data = (uint8_t*)((pb)->payload); - size_t len = pb->len; - - ip_hdr* iphdr = reinterpret_cast(data - UDP_HLEN - IP_HLEN); - ip_addr_t daddr; - daddr.addr = iphdr->dest.addr; - - udp_hdr* udphdr = reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN); - uint16_t dport = ntohs(udphdr->dest); - - AsyncUDPPacket packet(this, &daddr, dport, addr, port, data, len); - _handler(packet); - } - - pbuf * this_pb = pb; - pb = pb->next; - this_pb->next = NULL; - pbuf_free(this_pb); - } -} - -#if LWIP_VERSION_MAJOR == 1 -void AsyncUDP::_s_recv(void *arg, udp_pcb *upcb, pbuf *p, ip_addr_t *addr, uint16_t port) -#else -void AsyncUDP::_s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port) -#endif -{ - reinterpret_cast(arg)->_recv(upcb, p, (ip_addr_t *)addr, port); -} - -bool AsyncUDP::listen(ip_addr_t *addr, uint16_t port) -{ - close(); - _pcb = udp_new(); - if(_pcb == NULL) { - return false; - } - err_t err = udp_bind(_pcb, addr, port); - if(err != ERR_OK) { - close(); - return false; - } - udp_recv(_pcb, &_s_recv, (void *) this); - _connected = true; - return true; -} - -bool AsyncUDP::listenMulticast(ip_addr_t *addr, uint16_t port, uint8_t ttl) -{ - close(); - if(!ip_addr_ismulticast(addr)) { - return false; - } - ip_addr_t multicast_if_addr; - struct ip_info ifIpInfo; - int mode = wifi_get_opmode(); - if(mode & STATION_MODE) { - wifi_get_ip_info(STATION_IF, &ifIpInfo); - multicast_if_addr.addr = ifIpInfo.ip.addr; - } else if (mode & SOFTAP_MODE) { - wifi_get_ip_info(SOFTAP_IF, &ifIpInfo); - multicast_if_addr.addr = ifIpInfo.ip.addr; - } else { - return false; - } - if (igmp_joingroup(&multicast_if_addr, addr)!= ERR_OK) { - return false; - } - if(!listen(IPADDR_ANY, port)) { - return false; - } -#if LWIP_VERSION_MAJOR == 1 - udp_set_multicast_netif_addr(_pcb, multicast_if_addr); -#else - udp_set_multicast_netif_addr(_pcb, &multicast_if_addr); -#endif - udp_set_multicast_ttl(_pcb, ttl); - ip_addr_copy(_pcb->remote_ip, *addr); - _pcb->remote_port = port; - return true; -} - -bool AsyncUDP::connect(ip_addr_t *addr, uint16_t port) -{ - close(); - _pcb = udp_new(); - if(_pcb == NULL) { - return false; - } - err_t err = udp_connect(_pcb, addr, port); - if(err != ERR_OK) { - close(); - return false; - } - udp_recv(_pcb, &_s_recv, (void *) this); - _connected = true; - return true; -} - -void AsyncUDP::close() -{ - if(_pcb != NULL) { - if(_connected) { - udp_disconnect(_pcb); - } - udp_remove(_pcb); - _connected = false; - _pcb = NULL; - } -} - -size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, ip_addr_t *addr, uint16_t port) -{ - if(!_pcb && !connect(addr, port)) { - return 0; - } - if(len > 1460) { - len = 1460; - } - pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if(pbt != NULL) { - uint8_t* dst = reinterpret_cast(pbt->payload); - memcpy(dst, data, len); - err_t err = udp_sendto(_pcb, pbt, addr, port); - pbuf_free(pbt); - if(err < ERR_OK) { - return 0; - } - return len; - } - return 0; -} - -bool AsyncUDP::listen(const IPAddress addr, uint16_t port) -{ - ip_addr_t laddr; - laddr.addr = addr; - return listen(&laddr, port); -} - -bool AsyncUDP::listen(uint16_t port) -{ - return listen(IPAddress((uint32_t)INADDR_ANY), port); -} - -bool AsyncUDP::listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl) -{ - ip_addr_t laddr; - laddr.addr = addr; - return listenMulticast(&laddr, port, ttl); -} - -bool AsyncUDP::connect(const IPAddress addr, uint16_t port) -{ - ip_addr_t daddr; - daddr.addr = addr; - return connect(&daddr, port); -} - -size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port) -{ - ip_addr_t daddr; - daddr.addr = addr; - return writeTo(data, len, &daddr, port); -} - -size_t AsyncUDP::write(const uint8_t *data, size_t len) -{ - //return writeTo(data, len, &(_pcb->remote_ip), _pcb->remote_port); - if(_pcb){ // Patch applied (https://github.com/me-no-dev/ESPAsyncUDP/pull/21) - return writeTo(data, len, &(_pcb->remote_ip), _pcb->remote_port); - } - return 0; -} - -size_t AsyncUDP::write(uint8_t data) -{ - return write(&data, 1); -} - -size_t AsyncUDP::broadcastTo(uint8_t *data, size_t len, uint16_t port) -{ - ip_addr_t daddr; - daddr.addr = 0xFFFFFFFF; - return writeTo(data, len, &daddr, port); -} - -size_t AsyncUDP::broadcastTo(const char * data, uint16_t port) -{ - return broadcastTo((uint8_t *)data, strlen(data), port); -} - -size_t AsyncUDP::broadcast(uint8_t *data, size_t len) -{ - if(_pcb->local_port != 0) { - return broadcastTo(data, len, _pcb->local_port); - } - return 0; -} - -size_t AsyncUDP::broadcast(const char * data) -{ - return broadcast((uint8_t *)data, strlen(data)); -} - - -size_t AsyncUDP::sendTo(AsyncUDPMessage &message, ip_addr_t *addr, uint16_t port) -{ - if(!message) { - return 0; - } - return writeTo(message.data(), message.length(), addr, port); -} - -size_t AsyncUDP::sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t port) -{ - //if(!message) { - if((!message) || (!_pcb)) { // Patch applied (https://github.com/me-no-dev/ESPAsyncUDP/pull/21) - return 0; - } - return writeTo(message.data(), message.length(), addr, port); -} - -size_t AsyncUDP::send(AsyncUDPMessage &message) -{ - if(!message) { - return 0; - } - return writeTo(message.data(), message.length(), &(_pcb->remote_ip), _pcb->remote_port); -} - -size_t AsyncUDP::broadcastTo(AsyncUDPMessage &message, uint16_t port) -{ - if(!message) { - return 0; - } - return broadcastTo(message.data(), message.length(), port); -} - -size_t AsyncUDP::broadcast(AsyncUDPMessage &message) -{ - if(!message) { - return 0; - } - return broadcast(message.data(), message.length()); -} - -#endif diff --git a/lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h b/lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h deleted file mode 100644 index 8e5a70b21..000000000 --- a/lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef ESPASYNCUDP_H -#define ESPASYNCUDP_H - -#include "IPAddress.h" -#include "Print.h" -#include -#include "lwip/init.h" - -class AsyncUDP; -class AsyncUDPPacket; -class AsyncUDPMessage; -struct udp_pcb; -struct pbuf; -#if LWIP_VERSION_MAJOR == 1 -struct ip_addr; -typedef struct ip_addr ip_addr_t; -#else -struct ip4_addr; -typedef struct ip4_addr ip_addr_t; -#endif - -class AsyncUDPMessage : public Print -{ -protected: - uint8_t *_buffer; - size_t _index; - size_t _size; -public: - AsyncUDPMessage(size_t size=1460); - virtual ~AsyncUDPMessage(); - size_t write(const uint8_t *data, size_t len); - size_t write(uint8_t data); - size_t space(); - uint8_t * data(); - size_t length(); - void flush(); - operator bool() - { - return _buffer != NULL; - } -}; - -class AsyncUDPPacket : public Print -{ -protected: - AsyncUDP *_udp; - ip_addr_t *_localIp; - uint16_t _localPort; - ip_addr_t *_remoteIp; - uint16_t _remotePort; - uint8_t *_data; - size_t _len; -public: - AsyncUDPPacket(AsyncUDP *udp, ip_addr_t *localIp, uint16_t localPort, ip_addr_t *remoteIp, uint16_t remotePort, uint8_t *data, size_t len); - virtual ~AsyncUDPPacket(); - - uint8_t * data(); - size_t length(); - bool isBroadcast(); - bool isMulticast(); - - IPAddress localIP(); - uint16_t localPort(); - IPAddress remoteIP(); - uint16_t remotePort(); - - size_t send(AsyncUDPMessage &message); - - size_t write(const uint8_t *data, size_t len); - size_t write(uint8_t data); -}; - -typedef std::function AuPacketHandlerFunction; -typedef std::function AuPacketHandlerFunctionWithArg; - -class AsyncUDP : public Print -{ -protected: - udp_pcb *_pcb; - bool _connected; - AuPacketHandlerFunction _handler; - - void _recv(udp_pcb *upcb, pbuf *pb, ip_addr_t *addr, uint16_t port); -#if LWIP_VERSION_MAJOR == 1 - static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, ip_addr_t *addr, uint16_t port); -#else - static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port); -#endif - -public: - AsyncUDP(); - virtual ~AsyncUDP(); - - void onPacket(AuPacketHandlerFunctionWithArg cb, void * arg=NULL); - void onPacket(AuPacketHandlerFunction cb); - - bool listen(ip_addr_t *addr, uint16_t port); - bool listen(const IPAddress addr, uint16_t port); - bool listen(uint16_t port); - - bool listenMulticast(ip_addr_t *addr, uint16_t port, uint8_t ttl=1); - bool listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl=1); - - bool connect(ip_addr_t *addr, uint16_t port); - bool connect(const IPAddress addr, uint16_t port); - - void close(); - - size_t writeTo(const uint8_t *data, size_t len, ip_addr_t *addr, uint16_t port); - size_t writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port); - size_t write(const uint8_t *data, size_t len); - size_t write(uint8_t data); - - size_t broadcastTo(uint8_t *data, size_t len, uint16_t port); - size_t broadcastTo(const char * data, uint16_t port); - size_t broadcast(uint8_t *data, size_t len); - size_t broadcast(const char * data); - - size_t sendTo(AsyncUDPMessage &message, ip_addr_t *addr, uint16_t port); - size_t sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t port); - size_t send(AsyncUDPMessage &message); - - size_t broadcastTo(AsyncUDPMessage &message, uint16_t port); - size_t broadcast(AsyncUDPMessage &message); - - bool connected(); - operator bool(); -}; - -#endif diff --git a/lib/ESPAsyncUDP-master/travis/common.sh b/lib/ESPAsyncUDP-master/travis/common.sh deleted file mode 100644 index 57bede343..000000000 --- a/lib/ESPAsyncUDP-master/travis/common.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -function build_sketches() -{ - local arduino=$1 - local srcpath=$2 - local platform=$3 - local sketches=$(find $srcpath -name *.ino) - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - if [[ -f "$sketchdir/.$platform.skip" ]]; then - echo -e "\n\n ------------ Skipping $sketch ------------ \n\n"; - continue - fi - echo -e "\n\n ------------ Building $sketch ------------ \n\n"; - $arduino --verify $sketch; - local result=$? - if [ $result -ne 0 ]; then - echo "Build failed ($1)" - return $result - fi - done -} From dcd74be61ad8e6cf7d81aff09fd9b41745b662cf Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 24 Oct 2018 16:54:16 -0300 Subject: [PATCH 48/54] Fix Alexa for Core 2.5.0 and backwards compatible Alexa uses Phillips Hue Emulation to control Tasmota. In the Arduino Esp8266 Core v2.3.0 all works fine. In the Arduino Esp8266 Core v2.4.0, 2.4.1 and 2.4.2, a modification in the core is needed in order to make phillips hue work. In the Arduino Esp8266 Core v2.5.0 (actual Stage version), the webserver parsing was modified and this PR fix this modification. The new parsing of the core works fine for a standard phillips hue messages, but for Alexa it splits the command in 2 args. The first arg is empty and the second contains the correct phillips hue commands. --- sonoff/xplg_wemohue.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index d43ca90b1..f8eff5ddc 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -660,11 +660,11 @@ void HueLights(String *path) if ((device < 1) || (device > maxhue)) { device = 1; } - if (1 == WebServer->args()) { + if (WebServer->args()) { response = "["; StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg(0)); + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); if (hue_json.containsKey("on")) { response += FPSTR(HUE_LIGHT_RESPONSE_JSON); From ad3304fddc741f6d61b9ce98a7c2bf1233d525f8 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 24 Oct 2018 17:40:26 -0300 Subject: [PATCH 49/54] Changed WIFI_GATEWAY and WIFI_DNS to a standard IP Changed WIFI_GATEWAY and WIFI_DNS to a standard IP for help new users when they configure that. --- sonoff/my_user_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index c6becae97..fc957e770 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -55,9 +55,9 @@ // -- Wifi ---------------------------------------- #define WIFI_IP_ADDRESS "0.0.0.0" // [IpAddress1] Set to 0.0.0.0 for using DHCP or IP address -#define WIFI_GATEWAY "192.168.2.254" // [IpAddress2] If not using DHCP set Gateway IP address +#define WIFI_GATEWAY "192.168.1.1" // [IpAddress2] If not using DHCP set Gateway IP address #define WIFI_SUBNETMASK "255.255.255.0" // [IpAddress3] If not using DHCP set Network mask -#define WIFI_DNS "192.168.2.27" // [IpAddress4] If not using DHCP set DNS IP address (might be equal to WIFI_GATEWAY) +#define WIFI_DNS "192.168.1.1" // [IpAddress4] If not using DHCP set DNS IP address (might be equal to WIFI_GATEWAY) #define STA_SSID1 "" // [Ssid1] Wifi SSID #define STA_PASS1 "" // [Password1] Wifi password From c1aabf85a40aec67d3ff98a9c2368ed8ecb34b89 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 24 Oct 2018 18:03:27 -0300 Subject: [PATCH 50/54] Reformat options for DS18x20 #define W1_PARASITE_POWER is an option for #define USE_DS18x20 Added space to show that. --- sonoff/my_user_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index fc957e770..e1567cbbd 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -271,9 +271,9 @@ // -- One wire sensors ---------------------------- // WARNING: Select none for default one DS18B20 sensor or enable one of the following two options for multiple sensors -#define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) -//#define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors //#define USE_DS18x20_LEGACY // Optional for more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) +#define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +// #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) From 51ee22273b2aaef490a17c218ebc04b6d317f94e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 25 Oct 2018 10:44:59 +0200 Subject: [PATCH 51/54] Fix invalid JSON Fix invalid JSON floating point result from nan into null (#4147) --- sonoff/_changelog.ino | 3 ++- sonoff/support.ino | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c3daa6e42..0c13b2ef7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.19 20181023 * Fix header file execution order by renaming user_config.h to my_user_config.h - * + * Fix invalid JSON floating point result from nan into null (#4147) + * * 6.2.1.18 20181019 * Add more API callbacks and document API.md * Add support for La Crosse TX20 Anemometer (#2654, #3146) diff --git a/sonoff/support.ino b/sonoff/support.ino index fad0064be..1e960bb16 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -196,7 +196,12 @@ int TextToInt(char *str) char* dtostrfd(double number, unsigned char prec, char *s) { - return dtostrf(number, 1, prec, s); + if (isnan(number)) { + strcpy(s, "null"); + return s; + } else { + return dtostrf(number, 1, prec, s); + } } char* Unescape(char* buffer, uint16_t* size) @@ -630,10 +635,6 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_I2C_SCL == val) { return true; } if (GPIO_I2C_SDA == val) { return true; } #endif -#ifndef USE_SR04 - if (GPIO_SR04_TRIG == val) { return true; } - if (GPIO_SR04_ECHO == val) { return true; } -#endif #ifndef USE_WS2812 if (GPIO_WS2812 == val) { return true; } #endif @@ -706,6 +707,11 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_HX711_SCK == val) { return true; } if (GPIO_HX711_DAT == val) { return true; } #endif +#ifndef USE_TX20_WIND_SENSOR + if (GPIO_TX20_TXD_BLACK == val) { return true; } +#endif + + if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { offset = (GPIO_REL1_INV - GPIO_REL1); } From eefad54be79b44cb32fc82ca601ac0faa2106302 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 25 Oct 2018 14:03:34 +0200 Subject: [PATCH 52/54] Fix invalid JSON Fix invalid JSON floating point result from nan (Not a Number) and inf (Infinity) into null (#4147) --- sonoff/_changelog.ino | 2 +- sonoff/support.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0c13b2ef7..21ceff6b5 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,6 @@ /* 6.2.1.19 20181023 * Fix header file execution order by renaming user_config.h to my_user_config.h - * Fix invalid JSON floating point result from nan into null (#4147) + * Fix invalid JSON floating point result from nan (Not a Number) and inf (Infinity) into null (#4147) * * 6.2.1.18 20181019 * Add more API callbacks and document API.md diff --git a/sonoff/support.ino b/sonoff/support.ino index 1e960bb16..83c154834 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -196,7 +196,7 @@ int TextToInt(char *str) char* dtostrfd(double number, unsigned char prec, char *s) { - if (isnan(number)) { + if ((isnan(number)) || (isinf(number))) { // Fix for JSON output (https://stackoverflow.com/questions/1423081/json-left-out-infinity-and-nan-json-status-in-ecmascript) strcpy(s, "null"); return s; } else { From f58f3c2d31807c291e99c3e64124cc74e389a357 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 25 Oct 2018 14:16:46 +0200 Subject: [PATCH 53/54] Fix rule mqtt#connected trigger Fix rule mqtt#connected trigger when mqtt is disabled (#4149) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_02_mqtt.ino | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 21ceff6b5..8c2cff551 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.19 20181023 * Fix header file execution order by renaming user_config.h to my_user_config.h * Fix invalid JSON floating point result from nan (Not a Number) and inf (Infinity) into null (#4147) + * Fix rule mqtt#connected trigger when mqtt is disabled (#4149) * * 6.2.1.18 20181019 * Add more API callbacks and document API.md diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 89cddbd6c..bb1a86e13 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -398,8 +398,11 @@ void MqttConnected() XdrvCall(FUNC_MQTT_INIT); } mqtt_initial_connection_state = 0; - rules_flag.mqtt_connected = 1; + global_state.mqtt_down = 0; + if (Settings.flag.mqtt_enabled) { + rules_flag.mqtt_connected = 1; + } } #ifdef USE_MQTT_TLS From f2b04092f88040b81a116b6e68ed0301f36f6800 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 25 Oct 2018 18:17:58 +0200 Subject: [PATCH 54/54] Initial release of RF transceiving Initial release of RF transceiving using library RcSwitch (#2702) --- lib/rc-switch-2.6.2.13/.gitignore | 17 + lib/rc-switch-2.6.2.13/.travis.yml | 69 ++ lib/rc-switch-2.6.2.13/RCSwitch.cpp | 701 ++++++++++++++++++ lib/rc-switch-2.6.2.13/RCSwitch.h | 184 +++++ lib/rc-switch-2.6.2.13/README.md | 41 + .../ReceiveDemo_Advanced.ino | 24 + .../examples/ReceiveDemo_Advanced/output.ino | 70 ++ .../ReceiveDemo_Simple/ReceiveDemo_Simple.ino | 29 + .../examples/SendDemo/SendDemo.ino | 57 ++ .../TypeA_WithDIPSwitches.ino | 40 + .../TypeA_WithDIPSwitches_Lightweight.ino | 43 ++ .../TypeB_WithRotaryOrSlidingSwitches.ino | 40 + .../TypeC_Intertechno/TypeC_Intertechno.ino | 40 + .../examples/TypeD_REV/TypeD_REV.ino | 41 + .../examples/Webserver/Webserver.ino | 154 ++++ lib/rc-switch-2.6.2.13/keywords.txt | 57 ++ lib/rc-switch-2.6.2.13/library.json | 21 + lib/rc-switch-2.6.2.13/library.properties | 10 + sonoff/_changelog.ino | 1 + sonoff/language/bg-BG.h | 2 + sonoff/language/cs-CZ.h | 2 + sonoff/language/de-DE.h | 2 + sonoff/language/el-GR.h | 2 + sonoff/language/en-GB.h | 2 + sonoff/language/es-AR.h | 2 + sonoff/language/fr-FR.h | 2 + sonoff/language/he-HE.h | 2 + sonoff/language/hu-HU.h | 2 + sonoff/language/it-IT.h | 2 + sonoff/language/nl-NL.h | 2 + sonoff/language/pl-PL.h | 2 + sonoff/language/pt-BR.h | 2 + sonoff/language/pt-PT.h | 2 + sonoff/language/ru-RU.h | 2 + sonoff/language/tr-TR.h | 2 + sonoff/language/uk-UK.h | 2 + sonoff/language/zh-CN.h | 2 + sonoff/language/zh-TW.h | 2 + sonoff/my_user_config.h | 2 + sonoff/sonoff_template.h | 9 +- sonoff/support.ino | 8 + sonoff/xdrv_17_rcswitch.ino | 184 +++++ tools/decode-status.py | 2 +- 43 files changed, 1879 insertions(+), 3 deletions(-) create mode 100644 lib/rc-switch-2.6.2.13/.gitignore create mode 100644 lib/rc-switch-2.6.2.13/.travis.yml create mode 100644 lib/rc-switch-2.6.2.13/RCSwitch.cpp create mode 100644 lib/rc-switch-2.6.2.13/RCSwitch.h create mode 100644 lib/rc-switch-2.6.2.13/README.md create mode 100644 lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/output.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/SendDemo/SendDemo.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/TypeC_Intertechno/TypeC_Intertechno.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/TypeD_REV/TypeD_REV.ino create mode 100644 lib/rc-switch-2.6.2.13/examples/Webserver/Webserver.ino create mode 100644 lib/rc-switch-2.6.2.13/keywords.txt create mode 100644 lib/rc-switch-2.6.2.13/library.json create mode 100644 lib/rc-switch-2.6.2.13/library.properties create mode 100644 sonoff/xdrv_17_rcswitch.ino diff --git a/lib/rc-switch-2.6.2.13/.gitignore b/lib/rc-switch-2.6.2.13/.gitignore new file mode 100644 index 000000000..d0972bb47 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/.gitignore @@ -0,0 +1,17 @@ +# Mac stuff +.DS_Store + +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + diff --git a/lib/rc-switch-2.6.2.13/.travis.yml b/lib/rc-switch-2.6.2.13/.travis.yml new file mode 100644 index 000000000..16cadf8a2 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/.travis.yml @@ -0,0 +1,69 @@ +language: c +python: + - "2.7" + +# Cache PlatformIO packages using Travis CI container-based infrastructure +cache: + pip: true + directories: + - "~/.platformio" + +env: + - > + PLATFORMIO_CI_SRC=$PWD/examples/Webserver + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/Webserver.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01" + - > + PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Simple + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Simple.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeC_Intertechno + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeC_Intertechno.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeD_REV + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeD_REV.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches_Lightweight + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches_Lightweight.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeB_WithRotaryOrSlidingSwitches + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeB_WithRotaryOrSlidingSwitches.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/SendDemo + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/SendDemo.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01" + - > + PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Advanced + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Advanced.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01" + +before_install: + # Arduino IDE + - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" + - sleep 3 + - export DISPLAY=:1.0 + - wget http://downloads.arduino.cc/arduino-1.6.9-linux64.tar.xz + - tar xf arduino-1.6.9-linux64.tar.xz + - sudo mv arduino-1.6.9 /usr/local/share/arduino + - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino + +install: + # Arduino IDE + - ln -s $PWD /usr/local/share/arduino/libraries/rc-switch + # PlatformIO + - sudo pip install -U platformio + +script: + # Arduino IDE + - arduino --verify --board arduino:avr:uno ${ARDUINOIDE_CI_SRC} + # PlatformIO + - platformio ci --lib="." ${BOARDS} diff --git a/lib/rc-switch-2.6.2.13/RCSwitch.cpp b/lib/rc-switch-2.6.2.13/RCSwitch.cpp new file mode 100644 index 000000000..1a6736e24 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/RCSwitch.cpp @@ -0,0 +1,701 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Andreas Steinel / A.(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + - Johann Richard / .(at)gmail(dot)com + - Vlad Gheorghe / .(at)gmail(dot)com https://github.com/vgheo + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "RCSwitch.h" + +#ifdef RaspberryPi + // PROGMEM and _P functions are for AVR based microprocessors, + // so we must normalize these for the ARM processor: + #define PROGMEM + #define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) +#endif + +#if defined(ESP8266) || defined(ESP32) + // interrupt handler and related code must be in RAM on ESP8266, + // according to issue #46. + #define RECEIVE_ATTR ICACHE_RAM_ATTR +#else + #define RECEIVE_ATTR +#endif + + +/* Format for protocol definitions: + * {pulselength, Sync bit, "0" bit, "1" bit} + * + * pulselength: pulse length in microseconds, e.g. 350 + * Sync bit: {1, 31} means 1 high pulse and 31 low pulses + * (perceived as a 31*pulselength long pulse, total length of sync bit is + * 32*pulselength microseconds), i.e: + * _ + * | |_______________________________ (don't count the vertical bars) + * "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse + * and 3 low pulses, total length (1+3)*pulselength, i.e: + * _ + * | |___ + * "1" bit: waveform for a data bit of value "1", e.g. {3,1}: + * ___ + * | |_ + * + * These are combined to form Tri-State bits when sending or receiving codes. + */ +#if defined(ESP8266) || defined(ESP32) +static const RCSwitch::Protocol proto[] = { +#else +static const RCSwitch::Protocol PROGMEM proto[] = { +#endif + { 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1 + { 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2 + { 100, { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3 + { 380, { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4 + { 500, { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5 + { 450, { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B) + { 150, { 2, 62 }, { 1, 6 }, { 6, 1 }, false } // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote) +}; + +enum { + numProto = sizeof(proto) / sizeof(proto[0]) +}; + +#if not defined( RCSwitchDisableReceiving ) +volatile unsigned long RCSwitch::nReceivedValue = 0; +volatile unsigned int RCSwitch::nReceivedBitlength = 0; +volatile unsigned int RCSwitch::nReceivedDelay = 0; +volatile unsigned int RCSwitch::nReceivedProtocol = 0; +int RCSwitch::nReceiveTolerance = 60; +const unsigned int RCSwitch::nSeparationLimit = 4300; +// separationLimit: minimum microseconds between received codes, closer codes are ignored. +// according to discussion on issue #14 it might be more suitable to set the separation +// limit to the same time as the 'low' part of the sync signal for the current protocol. +unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; +#endif + +RCSwitch::RCSwitch() { + this->nTransmitterPin = -1; + this->setRepeatTransmit(10); + this->setProtocol(1); + #if not defined( RCSwitchDisableReceiving ) + this->nReceiverInterrupt = -1; + this->setReceiveTolerance(60); + RCSwitch::nReceivedValue = 0; + #endif +} + +/** + * Sets the protocol to send. + */ +void RCSwitch::setProtocol(Protocol protocol) { + this->protocol = protocol; +} + +/** + * Sets the protocol to send, from a list of predefined protocols + */ +void RCSwitch::setProtocol(int nProtocol) { + if (nProtocol < 1 || nProtocol > numProto) { + nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ??? + } +#if defined(ESP8266) || defined(ESP32) + this->protocol = proto[nProtocol-1]; +#else + memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol)); +#endif +} + +/** + * Sets the protocol to send with pulse length in microseconds. + */ +void RCSwitch::setProtocol(int nProtocol, int nPulseLength) { + setProtocol(nProtocol); + this->setPulseLength(nPulseLength); +} + + +/** + * Sets pulse length in microseconds + */ +void RCSwitch::setPulseLength(int nPulseLength) { + this->protocol.pulseLength = nPulseLength; +} + +/** + * Sets Repeat Transmits + */ +void RCSwitch::setRepeatTransmit(int nRepeatTransmit) { + this->nRepeatTransmit = nRepeatTransmit; +} + +/** + * Set Receiving Tolerance + */ +#if not defined( RCSwitchDisableReceiving ) +void RCSwitch::setReceiveTolerance(int nPercent) { + RCSwitch::nReceiveTolerance = nPercent; +} +#endif + + +/** + * Enable transmissions + * + * @param nTransmitterPin Arduino Pin to which the sender is connected to + */ +void RCSwitch::enableTransmit(int nTransmitterPin) { + this->nTransmitterPin = nTransmitterPin; + pinMode(this->nTransmitterPin, OUTPUT); +} + +/** + * Disable transmissions + */ +void RCSwitch::disableTransmit() { + this->nTransmitterPin = -1; +} + +/** + * Switch a remote switch on (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOn(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOff(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOn(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) ); +} + +/** + * Switch a remote switch off (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOff(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) ); +} + +/** + * Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOn(const char* sGroup, int nChannel) { + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOn(sGroup, code[nChannel]); +} + +/** + * Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOff(const char* sGroup, int nChannel) { + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOff(sGroup, code[nChannel]); +} + +/** + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOn(const char* sGroup, const char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) ); +} + +/** + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOff(const char* sGroup, const char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) ); +} + + +/** + * Returns a char[13], representing the code word to be send. + * + */ +char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0'; + } + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0'; + } + + sReturn[nReturnPos++] = bStatus ? '0' : 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for type B switches with two rotary/sliding switches. + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-----------------------------+----------+------------+ + * | 4 bits address | 4 bits address | 3 bits | 1 bit | + * | switch group | switch number | not used | on / off | + * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 | + * +-----------------------------+-----------------------------+----------+------------+ + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { + return 0; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F'; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F'; + } + + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Like getCodeWord (Type C = Intertechno) + */ +char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + int nFamily = (int)sFamily - 'a'; + if ( nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { + return 0; + } + + // encode the family into four bits + sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0'; + + // encode the device and group + sReturn[nReturnPos++] = ((nDevice-1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nDevice-1) & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup-1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup-1) & 2) ? 'F' : '0'; + + // encode the status code + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for the REV Switch Type + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-------------------+----------+--------------+ + * | 4 bits address | 3 bits address | 3 bits | 2 bits | + * | switch group | device number | not used | on / off | + * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 | + * +-----------------------------+-------------------+----------+--------------+ + * + * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ + * + * @param sGroup Name of the switch group (A..D, resp. a..d) + * @param nDevice Number of the switch itself (1..3) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + // sGroup must be one of the letters in "abcdABCD" + int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A'; + if ( nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) { + return 0; + } + + for (int i = 0; i < 4; i++) { + sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F'; + } + + for (int i = 1; i <= 3; i++) { + sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F'; + } + + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + + sReturn[nReturnPos++] = bStatus ? '1' : '0'; + sReturn[nReturnPos++] = bStatus ? '0' : '1'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * @param sCodeWord a tristate code word consisting of the letter 0, 1, F + */ +void RCSwitch::sendTriState(const char* sCodeWord) { + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char* p = sCodeWord; *p; p++) { + code <<= 2L; + switch (*p) { + case '0': + // bit pattern 00 + break; + case 'F': + // bit pattern 01 + code |= 1L; + break; + case '1': + // bit pattern 11 + code |= 3L; + break; + } + length += 2; + } + this->send(code, length); +} + +/** + * @param sCodeWord a binary code word consisting of the letter 0, 1 + */ +void RCSwitch::send(const char* sCodeWord) { + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char* p = sCodeWord; *p; p++) { + code <<= 1L; + if (*p != '0') + code |= 1L; + length++; + } + this->send(code, length); +} + +/** + * Transmit the first 'length' bits of the integer 'code'. The + * bits are sent from MSB to LSB, i.e., first the bit at position length-1, + * then the bit at position length-2, and so on, till finally the bit at position 0. + */ +void RCSwitch::send(unsigned long code, unsigned int length) { + if (this->nTransmitterPin == -1) + return; + +#if not defined( RCSwitchDisableReceiving ) + // make sure the receiver is disabled while we transmit + int nReceiverInterrupt_backup = nReceiverInterrupt; + if (nReceiverInterrupt_backup != -1) { + this->disableReceive(); + } +#endif + + for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) { + for (int i = length-1; i >= 0; i--) { + if (code & (1L << i)) + this->transmit(protocol.one); + else + this->transmit(protocol.zero); + } + this->transmit(protocol.syncFactor); + } + + // Disable transmit after sending (i.e., for inverted protocols) + digitalWrite(this->nTransmitterPin, LOW); + +#if not defined( RCSwitchDisableReceiving ) + // enable receiver again if we just disabled it + if (nReceiverInterrupt_backup != -1) { + this->enableReceive(nReceiverInterrupt_backup); + } +#endif +} + +/** + * Transmit a single high-low pulse. + */ +void RCSwitch::transmit(HighLow pulses) { + uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH; + uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW; + + digitalWrite(this->nTransmitterPin, firstLogicLevel); + delayMicroseconds( this->protocol.pulseLength * pulses.high); + digitalWrite(this->nTransmitterPin, secondLogicLevel); + delayMicroseconds( this->protocol.pulseLength * pulses.low); +} + + +#if not defined( RCSwitchDisableReceiving ) +/** + * Enable receiving data + */ +void RCSwitch::enableReceive(int interrupt) { + this->nReceiverInterrupt = interrupt; + this->enableReceive(); +} + +void RCSwitch::enableReceive() { + if (this->nReceiverInterrupt != -1) { + RCSwitch::nReceivedValue = 0; + RCSwitch::nReceivedBitlength = 0; +#if defined(RaspberryPi) // Raspberry Pi + wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); +#else // Arduino + attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); +#endif + } +} + +/** + * Disable receiving data + */ +void RCSwitch::disableReceive() { +#if not defined(RaspberryPi) // Arduino + detachInterrupt(this->nReceiverInterrupt); +#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR + this->nReceiverInterrupt = -1; +} + +bool RCSwitch::available() { + return RCSwitch::nReceivedValue != 0; +} + +void RCSwitch::resetAvailable() { + RCSwitch::nReceivedValue = 0; +} + +unsigned long RCSwitch::getReceivedValue() { + return RCSwitch::nReceivedValue; +} + +unsigned int RCSwitch::getReceivedBitlength() { + return RCSwitch::nReceivedBitlength; +} + +unsigned int RCSwitch::getReceivedDelay() { + return RCSwitch::nReceivedDelay; +} + +unsigned int RCSwitch::getReceivedProtocol() { + return RCSwitch::nReceivedProtocol; +} + +unsigned int* RCSwitch::getReceivedRawdata() { + return RCSwitch::timings; +} + +/* helper function for the receiveProtocol method */ +static inline unsigned int diff(int A, int B) { + return abs(A - B); +} + +/** + * + */ +bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) { +#if defined(ESP8266) || defined(ESP32) + const Protocol &pro = proto[p-1]; +#else + Protocol pro; + memcpy_P(&pro, &proto[p-1], sizeof(Protocol)); +#endif + + unsigned long code = 0; + //Assuming the longer pulse length is the pulse captured in timings[0] + const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high); + const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses; + const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100; + + /* For protocols that start low, the sync period looks like + * _________ + * _____________| |XXXXXXXXXXXX| + * + * |--1st dur--|-2nd dur-|-Start data-| + * + * The 3rd saved duration starts the data. + * + * For protocols that start high, the sync period looks like + * + * ______________ + * | |____________|XXXXXXXXXXXXX| + * + * |-filtered out-|--1st dur--|--Start data--| + * + * The 2nd saved duration starts the data + */ + const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1); + + for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) { + code <<= 1; + if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && + diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) { + // zero + } else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance && + diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) { + // one + code |= 1; + } else { + // Failed + return false; + } + } + + if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = p; + return true; + } + + return false; +} + +void RECEIVE_ATTR RCSwitch::handleInterrupt() { + + static unsigned int changeCount = 0; + static unsigned long lastTime = 0; + static unsigned int repeatCount = 0; + + const long time = micros(); + const unsigned int duration = time - lastTime; + + if (duration > RCSwitch::nSeparationLimit) { + // A long stretch without signal level change occurred. This could + // be the gap between two transmission. + if (diff(duration, RCSwitch::timings[0]) < 200) { + // This long signal is close in length to the long signal which + // started the previously recorded timings; this suggests that + // it may indeed by a a gap between two transmissions (we assume + // here that a sender will send the signal multiple times, + // with roughly the same gap between them). + repeatCount++; + if (repeatCount == 2) { + for(unsigned int i = 1; i <= numProto; i++) { + if (receiveProtocol(i, changeCount)) { + // receive succeeded for protocol i + break; + } + } + repeatCount = 0; + } + } + changeCount = 0; + } + + // detect overflow + if (changeCount >= RCSWITCH_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; + } + + RCSwitch::timings[changeCount++] = duration; + lastTime = time; +} +#endif diff --git a/lib/rc-switch-2.6.2.13/RCSwitch.h b/lib/rc-switch-2.6.2.13/RCSwitch.h new file mode 100644 index 000000000..b7755e0b4 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/RCSwitch.h @@ -0,0 +1,184 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _RCSwitch_h +#define _RCSwitch_h + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific + #include "Energia.h" +#elif defined(RPI) // Raspberry Pi + #define RaspberryPi + + // Include libraries for RPi: + #include /* memcpy */ + #include /* abs */ + #include +#elif defined(SPARK) + #include "application.h" +#else + #include "WProgram.h" +#endif + +#include + + +// At least for the ATTiny X4/X5, receiving has to be disabled due to +// missing libm depencies (udivmodhi4) +#if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ ) +#define RCSwitchDisableReceiving +#endif + +// Number of maximum high/Low changes per packet. +// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync +#define RCSWITCH_MAX_CHANGES 67 + +class RCSwitch { + + public: + RCSwitch(); + + void switchOn(int nGroupNumber, int nSwitchNumber); + void switchOff(int nGroupNumber, int nSwitchNumber); + void switchOn(const char* sGroup, int nSwitchNumber); + void switchOff(const char* sGroup, int nSwitchNumber); + void switchOn(char sFamily, int nGroup, int nDevice); + void switchOff(char sFamily, int nGroup, int nDevice); + void switchOn(const char* sGroup, const char* sDevice); + void switchOff(const char* sGroup, const char* sDevice); + void switchOn(char sGroup, int nDevice); + void switchOff(char sGroup, int nDevice); + + void sendTriState(const char* sCodeWord); + void send(unsigned long code, unsigned int length); + void send(const char* sCodeWord); + + #if not defined( RCSwitchDisableReceiving ) + void enableReceive(int interrupt); + void enableReceive(); + void disableReceive(); + bool available(); + void resetAvailable(); + + unsigned long getReceivedValue(); + unsigned int getReceivedBitlength(); + unsigned int getReceivedDelay(); + unsigned int getReceivedProtocol(); + unsigned int* getReceivedRawdata(); + #endif + + void enableTransmit(int nTransmitterPin); + void disableTransmit(); + void setPulseLength(int nPulseLength); + void setRepeatTransmit(int nRepeatTransmit); + #if not defined( RCSwitchDisableReceiving ) + void setReceiveTolerance(int nPercent); + #endif + + /** + * Description of a single pule, which consists of a high signal + * whose duration is "high" times the base pulse length, followed + * by a low signal lasting "low" times the base pulse length. + * Thus, the pulse overall lasts (high+low)*pulseLength + */ + struct HighLow { + uint8_t high; + uint8_t low; + }; + + /** + * A "protocol" describes how zero and one bits are encoded into high/low + * pulses. + */ + struct Protocol { + /** base pulse length in microseconds, e.g. 350 */ + uint16_t pulseLength; + + HighLow syncFactor; + HighLow zero; + HighLow one; + + /** + * If true, interchange high and low logic levels in all transmissions. + * + * By default, RCSwitch assumes that any signals it sends or receives + * can be broken down into pulses which start with a high signal level, + * followed by a a low signal level. This is e.g. the case for the + * popular PT 2260 encoder chip, and thus many switches out there. + * + * But some devices do it the other way around, and start with a low + * signal level, followed by a high signal level, e.g. the HT6P20B. To + * accommodate this, one can set invertedSignal to true, which causes + * RCSwitch to change how it interprets any HighLow struct FOO: It will + * then assume transmissions start with a low signal lasting + * FOO.high*pulseLength microseconds, followed by a high signal lasting + * FOO.low*pulseLength microseconds. + */ + bool invertedSignal; + }; + + void setProtocol(Protocol protocol); + void setProtocol(int nProtocol); + void setProtocol(int nProtocol, int nPulseLength); + + private: + char* getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus); + char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus); + char* getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus); + char* getCodeWordD(char group, int nDevice, bool bStatus); + void transmit(HighLow pulses); + + #if not defined( RCSwitchDisableReceiving ) + static void handleInterrupt(); + static bool receiveProtocol(const int p, unsigned int changeCount); + int nReceiverInterrupt; + #endif + int nTransmitterPin; + int nRepeatTransmit; + + Protocol protocol; + + #if not defined( RCSwitchDisableReceiving ) + static int nReceiveTolerance; + volatile static unsigned long nReceivedValue; + volatile static unsigned int nReceivedBitlength; + volatile static unsigned int nReceivedDelay; + volatile static unsigned int nReceivedProtocol; + const static unsigned int nSeparationLimit; + /* + * timings[0] contains sync timing, followed by a number of bits + */ + static unsigned int timings[RCSWITCH_MAX_CHANGES]; + #endif + + +}; + +#endif diff --git a/lib/rc-switch-2.6.2.13/README.md b/lib/rc-switch-2.6.2.13/README.md new file mode 100644 index 000000000..bf12543be --- /dev/null +++ b/lib/rc-switch-2.6.2.13/README.md @@ -0,0 +1,41 @@ +# rc-switch +[![Build Status](https://travis-ci.org/sui77/rc-switch.svg?branch=master)](https://travis-ci.org/sui77/rc-switch) + +Use your Arduino or Raspberry Pi to operate remote radio controlled devices + +## Download +https://github.com/sui77/rc-switch/releases/latest + +rc-switch is also listed in the arduino library manager. + +## Wiki +https://github.com/sui77/rc-switch/wiki + +## Info +### Send RC codes + +Use your Arduino or Raspberry Pi to operate remote radio controlled devices. +This will most likely work with all popular low cost power outlet sockets. If +yours doesn't work, you might need to adjust the pulse length. + +All you need is a Arduino or Raspberry Pi, a 315/433MHz AM transmitter and one +or more devices with one of the supported chipsets: + + - SC5262 / SC5272 + - HX2262 / HX2272 + - PT2262 / PT2272 + - EV1527 / RT1527 / FP1527 / HS1527 + - Intertechno outlets + - HT6P20X + +### Receive and decode RC codes + +Find out what codes your remote is sending. Use your remote to control your +Arduino. + +All you need is an Arduino, a 315/433MHz AM receiver (altough there is no +instruction yet, yes it is possible to hack an existing device) and a remote +hand set. + +For the Raspberry Pi, clone the https://github.com/ninjablocks/433Utils project to +compile a sniffer tool and transmission commands. diff --git a/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino new file mode 100644 index 000000000..18380d336 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino @@ -0,0 +1,24 @@ +/* + Example for receiving + + https://github.com/sui77/rc-switch/ + + If you want to visualize a telegram copy the raw data and + paste it into http://test.sui.li/oszi/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol()); + mySwitch.resetAvailable(); + } +} diff --git a/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/output.ino b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/output.ino new file mode 100644 index 000000000..31e61ba69 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/output.ino @@ -0,0 +1,70 @@ +static const char* bin2tristate(const char* bin); +static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength); + +void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) { + + const char* b = dec2binWzerofill(decimal, length); + Serial.print("Decimal: "); + Serial.print(decimal); + Serial.print(" ("); + Serial.print( length ); + Serial.print("Bit) Binary: "); + Serial.print( b ); + Serial.print(" Tri-State: "); + Serial.print( bin2tristate( b) ); + Serial.print(" PulseLength: "); + Serial.print(delay); + Serial.print(" microseconds"); + Serial.print(" Protocol: "); + Serial.println(protocol); + + Serial.print("Raw data: "); + for (unsigned int i=0; i<= length*2; i++) { + Serial.print(raw[i]); + Serial.print(","); + } + Serial.println(); + Serial.println(); +} + +static const char* bin2tristate(const char* bin) { + static char returnValue[50]; + int pos = 0; + int pos2 = 0; + while (bin[pos]!='\0' && bin[pos+1]!='\0') { + if (bin[pos]=='0' && bin[pos+1]=='0') { + returnValue[pos2] = '0'; + } else if (bin[pos]=='1' && bin[pos+1]=='1') { + returnValue[pos2] = '1'; + } else if (bin[pos]=='0' && bin[pos+1]=='1') { + returnValue[pos2] = 'F'; + } else { + return "not applicable"; + } + pos = pos+2; + pos2++; + } + returnValue[pos2] = '\0'; + return returnValue; +} + +static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) { + static char bin[64]; + unsigned int i=0; + + while (Dec > 0) { + bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0'; + Dec = Dec >> 1; + } + + for (unsigned int j = 0; j< bitLength; j++) { + if (j >= bitLength - i) { + bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; + } else { + bin[j] = '0'; + } + } + bin[bitLength] = '\0'; + + return bin; +} diff --git a/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino new file mode 100644 index 000000000..bb1076387 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino @@ -0,0 +1,29 @@ +/* + Simple example for receiving + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + + Serial.print("Received "); + Serial.print( mySwitch.getReceivedValue() ); + Serial.print(" / "); + Serial.print( mySwitch.getReceivedBitlength() ); + Serial.print("bit "); + Serial.print("Protocol: "); + Serial.println( mySwitch.getReceivedProtocol() ); + + mySwitch.resetAvailable(); + } +} diff --git a/lib/rc-switch-2.6.2.13/examples/SendDemo/SendDemo.ino b/lib/rc-switch-2.6.2.13/examples/SendDemo/SendDemo.ino new file mode 100644 index 000000000..5acb4958c --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/SendDemo/SendDemo.ino @@ -0,0 +1,57 @@ +/* + Example for different sending methods + + https://github.com/sui77/rc-switch/ + +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + Serial.begin(9600); + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set protocol (default is 1, will work for most outlets) + // mySwitch.setProtocol(2); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + + // Optional set number of transmission repetitions. + // mySwitch.setRepeatTransmit(15); + +} + +void loop() { + + /* See Example: TypeA_WithDIPSwitches */ + mySwitch.switchOn("11111", "00010"); + delay(1000); + mySwitch.switchOff("11111", "00010"); + delay(1000); + + /* Same switch as above, but using decimal code */ + mySwitch.send(5393, 24); + delay(1000); + mySwitch.send(5396, 24); + delay(1000); + + /* Same switch as above, but using binary code */ + mySwitch.send("000000000001010100010001"); + delay(1000); + mySwitch.send("000000000001010100010100"); + delay(1000); + + /* Same switch as above, but tri-state code */ + mySwitch.sendTriState("00000FFF0F0F"); + delay(1000); + mySwitch.sendTriState("00000FFF0FF0"); + delay(1000); + + delay(20000); +} diff --git a/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino b/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino new file mode 100644 index 000000000..14f7d2a6c --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with a 10 pole DIP switch. + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the setting of the first 5 DIP switches. + // In this example it's ON-ON-OFF-OFF-ON. + // + // The second parameter represents the setting of the last 5 DIP switches. + // In this example the last 5 DIP switches are OFF-ON-OFF-ON-OFF. + mySwitch.switchOn("11001", "01010"); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff("11001", "01010"); + + // Wait another second + delay(1000); + +} diff --git a/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino b/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino new file mode 100644 index 000000000..214daf41a --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino @@ -0,0 +1,43 @@ +/* + This is a minimal sketch without using the library at all but only works for + the 10 pole dip switch sockets. It saves a lot of memory and thus might be + very useful to use with ATTinys :) + + https://github.com/sui77/rc-switch/ +*/ + +int RCLpin = 7; + +void setup() { + pinMode(RCLpin, OUTPUT); +} + +void loop() { + RCLswitch(0b010001000001); // DIPs an Steckdose: 0100010000 An:01 + delay(2000); + + RCLswitch(0b010001000010); // DIPs an Steckdose: 0100010000 Aus:10 + delay(2000); +} + +void RCLswitch(uint16_t code) { + for (int nRepeat=0; nRepeat<6; nRepeat++) { + for (int i=4; i<16; i++) { + RCLtransmit(1,3); + if (((code << (i-4)) & 2048) > 0) { + RCLtransmit(1,3); + } else { + RCLtransmit(3,1); + } + } + RCLtransmit(1,31); + } +} + +void RCLtransmit(int nHighPulses, int nLowPulses) { + digitalWrite(RCLpin, HIGH); + delayMicroseconds( 350 * nHighPulses); + digitalWrite(RCLpin, LOW); + delayMicroseconds( 350 * nLowPulses); +} + diff --git a/lib/rc-switch-2.6.2.13/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino b/lib/rc-switch-2.6.2.13/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino new file mode 100644 index 000000000..e8568e25b --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with two rotary/sliding switches. + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the setting of the first rotary switch. + // In this example it's switched to "1" or "A" or "I". + // + // The second parameter represents the setting of the second rotary switch. + // In this example it's switched to "4" or "D" or "IV". + mySwitch.switchOn(1, 4); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff(1, 4); + + // Wait another second + delay(1000); + +} diff --git a/lib/rc-switch-2.6.2.13/examples/TypeC_Intertechno/TypeC_Intertechno.ino b/lib/rc-switch-2.6.2.13/examples/TypeC_Intertechno/TypeC_Intertechno.ino new file mode 100644 index 000000000..0fc69c7c8 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeC_Intertechno/TypeC_Intertechno.ino @@ -0,0 +1,40 @@ +/* + Example for Intertechno outlets + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the familycode (a, b, c, ... f) + // The second parameter represents the group number + // The third parameter represents the device number + // + // In this example it's family 'b', group #3, device #2 + mySwitch.switchOn('b', 3, 2); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff('b', 3, 2); + + // Wait another second + delay(1000); + +} \ No newline at end of file diff --git a/lib/rc-switch-2.6.2.13/examples/TypeD_REV/TypeD_REV.ino b/lib/rc-switch-2.6.2.13/examples/TypeD_REV/TypeD_REV.ino new file mode 100644 index 000000000..878272945 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeD_REV/TypeD_REV.ino @@ -0,0 +1,41 @@ +/* + Example for REV outlets (e.g. 8342L) + + https://github.com/sui77/rc-switch/ + + Need help? http://forum.ardumote.com +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // set pulse length. + mySwitch.setPulseLength(360); + +} + +void loop() { + + // Switch on: + // The first parameter represents the channel (a, b, c, d) + // The second parameter represents the device number + // + // In this example it's family 'd', device #2 + mySwitch.switchOn('d', 2); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff('d', 2); + + // Wait another second + delay(1000); + +} diff --git a/lib/rc-switch-2.6.2.13/examples/Webserver/Webserver.ino b/lib/rc-switch-2.6.2.13/examples/Webserver/Webserver.ino new file mode 100644 index 000000000..66668e76a --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/Webserver/Webserver.ino @@ -0,0 +1,154 @@ +/* + A simple RCSwitch/Ethernet/Webserver demo + + https://github.com/sui77/rc-switch/ +*/ + +#include +#include +#include + +// Ethernet configuration +uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC Address +uint8_t ip[] = { 192,168,0, 2 }; // IP Address +EthernetServer server(80); // Server Port 80 + +// RCSwitch configuration +RCSwitch mySwitch = RCSwitch(); +int RCTransmissionPin = 7; + +// More to do... +// You should also modify the processCommand() and +// httpResponseHome() functions to fit your needs. + + + +/** + * Setup + */ +void setup() { + Ethernet.begin(mac, ip); + server.begin(); + mySwitch.enableTransmit( RCTransmissionPin ); +} + +/** + * Loop + */ +void loop() { + char* command = httpServer(); +} + +/** + * Command dispatcher + */ +void processCommand(char* command) { + if (strcmp(command, "1-on") == 0) { + mySwitch.switchOn(1,1); + } else if (strcmp(command, "1-off") == 0) { + mySwitch.switchOff(1,1); + } else if (strcmp(command, "2-on") == 0) { + mySwitch.switchOn(1,2); + } else if (strcmp(command, "2-off") == 0) { + mySwitch.switchOff(1,2); + } +} + +/** + * HTTP Response with homepage + */ +void httpResponseHome(EthernetClient c) { + c.println("HTTP/1.1 200 OK"); + c.println("Content-Type: text/html"); + c.println(); + c.println(""); + c.println(""); + c.println( "RCSwitch Webserver Demo"); + c.println( ""); + c.println(""); + c.println(""); + c.println( "

RCSwitch Webserver Demo

"); + c.println( ""); + c.println( ""); + c.println( "
"); + c.println( "https://github.com/sui77/rc-switch/"); + c.println(""); + c.println(""); +} + +/** + * HTTP Redirect to homepage + */ +void httpResponseRedirect(EthernetClient c) { + c.println("HTTP/1.1 301 Found"); + c.println("Location: /"); + c.println(); +} + +/** + * HTTP Response 414 error + * Command must not be longer than 30 characters + **/ +void httpResponse414(EthernetClient c) { + c.println("HTTP/1.1 414 Request URI too long"); + c.println("Content-Type: text/plain"); + c.println(); + c.println("414 Request URI too long"); +} + +/** + * Process HTTP requests, parse first request header line and + * call processCommand with GET query string (everything after + * the ? question mark in the URL). + */ +char* httpServer() { + EthernetClient client = server.available(); + if (client) { + char sReturnCommand[32]; + int nCommandPos=-1; + sReturnCommand[0] = '\0'; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + if ((c == '\n') || (c == ' ' && nCommandPos>-1)) { + sReturnCommand[nCommandPos] = '\0'; + if (strcmp(sReturnCommand, "\0") == 0) { + httpResponseHome(client); + } else { + processCommand(sReturnCommand); + httpResponseRedirect(client); + } + break; + } + if (nCommandPos>-1) { + sReturnCommand[nCommandPos++] = c; + } + if (c == '?' && nCommandPos == -1) { + nCommandPos = 0; + } + } + if (nCommandPos > 30) { + httpResponse414(client); + sReturnCommand[0] = '\0'; + break; + } + } + if (nCommandPos!=-1) { + sReturnCommand[nCommandPos] = '\0'; + } + // give the web browser time to receive the data + delay(1); + client.stop(); + + return sReturnCommand; + } + return '\0'; +} \ No newline at end of file diff --git a/lib/rc-switch-2.6.2.13/keywords.txt b/lib/rc-switch-2.6.2.13/keywords.txt new file mode 100644 index 000000000..2474367c4 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/keywords.txt @@ -0,0 +1,57 @@ +####################################### +# Syntax Coloring Map For RCSwitch +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +RCSwitch KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +########## +#SENDS Begin +########## +switchOn KEYWORD2 +switchOff KEYWORD2 +sendTriState KEYWORD2 +send KEYWORD2 +########## +#SENDS End +########## + +########## +#RECEIVE Begin +########## +enableReceive KEYWORD2 +disableReceive KEYWORD2 +available KEYWORD2 +resetAvailable KEYWORD2 +setReceiveTolerance KEYWORD2 +getReceivedValue KEYWORD2 +getReceivedBitlength KEYWORD2 +getReceivedDelay KEYWORD2 +getReceivedProtocol KEYWORD2 +getReceivedRawdata KEYWORD2 +########## +#RECEIVE End +########## + +########## +#OTHERS Begin +########## +enableTransmit KEYWORD2 +disableTransmit KEYWORD2 +setPulseLength KEYWORD2 +setProtocol KEYWORD2 +setRepeatTransmit KEYWORD2 +########## +#OTHERS End +########## + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/lib/rc-switch-2.6.2.13/library.json b/lib/rc-switch-2.6.2.13/library.json new file mode 100644 index 000000000..1d7d2e367 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/library.json @@ -0,0 +1,21 @@ +{ + "name": "rc-switch", + "description": "Use your Arduino or Raspberry Pi to operate remote radio controlled devices", + "keywords": "rf, radio, wireless", + "authors": + { + "name": "Suat Ozgur" + }, + "repository": + { + "type": "git", + "url": "https://github.com/sui77/rc-switch.git" + }, + "version": "2.6.2", + "frameworks": [ + "arduino", + "energia", + "wiringpi" + ], + "platforms": "*" +} diff --git a/lib/rc-switch-2.6.2.13/library.properties b/lib/rc-switch-2.6.2.13/library.properties new file mode 100644 index 000000000..b4c7388d6 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/library.properties @@ -0,0 +1,10 @@ +name=rc-switch +version=2.6.2 +author=sui77 +maintainer=sui77,fingolfin +sentence=Operate 433/315Mhz devices. +paragraph=Use your Arduino, ESP8266/ESP32 or Raspberry Pi to operate remote radio controlled devices. This will most likely work with all popular low cost power outlet sockets. +category=Device Control +url=https://github.com/sui77/rc-switch +architectures=avr,esp8266,esp32 +includes=RCSwitch.h diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 8c2cff551..563e555d1 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Fix header file execution order by renaming user_config.h to my_user_config.h * Fix invalid JSON floating point result from nan (Not a Number) and inf (Infinity) into null (#4147) * Fix rule mqtt#connected trigger when mqtt is disabled (#4149) + * Initial release of RF transceiving using library RcSwitch (#2702) * * 6.2.1.18 20181019 * Add more API callbacks and document API.md diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 9d4d41815..7f56e33d3 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 2e50ce172..a29f5741a 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 28d687dae..9f11e57ca 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 3a648f86f..beaaef57d 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 9ddead578..4e3aa0080 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 42986a573..39f198681 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index c38f08b17..44ecea2b1 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index c04b28f73..73b44c67b 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 603ddd19a..532d45643 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 1bf79502d..61f361b89 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index ecec2e39e..d2e913357 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 951d9a970..0f1303b30 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 79792c15b..54d8448d7 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index b2b88fd7a..0c8e03d62 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 3a607ad35..11fdf90b0 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index d51e87486..86838d0df 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index dbc3b575f..efc125351 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 32ee2ccf4..3414bc8d1 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 46b910654..b5f14dace 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -525,6 +525,8 @@ #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" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e1567cbbd..e970bcdf5 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -384,6 +384,8 @@ #define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) +#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code) + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 0f962bfbd..13a6ffd0c 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -129,6 +129,8 @@ enum UserSelectablePins { GPIO_HX711_SCK, // HX711 Load Cell clock GPIO_HX711_DAT, // HX711 Load Cell data GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin + GPIO_RFSEND, // RF transmitter + GPIO_RFRECV, // RF receiver GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -184,7 +186,8 @@ 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_TX20_TX "|" + D_SENSOR_RFSEND "|" D_SENSOR_RFRECV; /********************************************************************************************/ @@ -341,6 +344,8 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { GPIO_WS2812, // WS2812 Led string GPIO_IRSEND, // IR remote GPIO_IRRECV, // IR receiver + GPIO_RFSEND, // RF transmitter + GPIO_RFRECV, // RF receiver GPIO_SR04_TRIG, // SR04 Trigger pin GPIO_SR04_ECHO, // SR04 Echo pin GPIO_TM16CLK, // TM1638 Clock @@ -366,7 +371,7 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { GPIO_SDM630_RX, // SDM630 Serial interface GPIO_PMS5003, // Plantower PMS5003 Serial interface GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin - GPIO_MP3_DFR562 // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface + GPIO_MP3_DFR562 // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { diff --git a/sonoff/support.ino b/sonoff/support.ino index 83c154834..88545e211 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -710,6 +710,10 @@ boolean GetUsedInModule(byte val, uint8_t *arr) #ifndef USE_TX20_WIND_SENSOR if (GPIO_TX20_TXD_BLACK == val) { return true; } #endif +#ifndef USE_RC_SWITCH + if (GPIO_RFSEND == val) { return true; } + if (GPIO_RFRECV == val) { return true; } +#endif if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { @@ -1025,6 +1029,10 @@ void GetFeatures() #ifdef USE_TUYA_DIMMER feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino #endif +#ifdef USE_RC_SWITCH + feature_drv2 |= 0x00010000; // xdrv_17_rcswitch.ino +#endif + #ifdef NO_EXTRA_4K_HEAP diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino new file mode 100644 index 000000000..6c65dd3b0 --- /dev/null +++ b/sonoff/xdrv_17_rcswitch.ino @@ -0,0 +1,184 @@ +/* + xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Sonoff-Tasmota + + Copyright (C) 2017 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_RC_SWITCH +/*********************************************************************************************\ + * RF send and receive using RCSwitch library +\*********************************************************************************************/ + +#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" + +#include + +RCSwitch mySwitch = RCSwitch(); + +#define RF_TIME_AVOID_DUPLICATE 500 // Milliseconds + +unsigned long rf_lasttime = 0; + +void RfReceiveCheck() +{ + if (mySwitch.available()) { + + unsigned long value = mySwitch.getReceivedValue(); + unsigned int bit_length = mySwitch.getReceivedBitlength(); + unsigned int delay = mySwitch.getReceivedDelay(); + unsigned int protocol = mySwitch.getReceivedProtocol(); + + snprintf_P(log_data, sizeof(log_data), PSTR("RFR: BitLen %d, Delay %d, Protocol %d, Value %lX (%u)"), + bit_length, delay, protocol, value, value); + AddLog(LOG_LEVEL_DEBUG); + + unsigned long now = millis(); + if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (value > 0)) { + rf_lasttime = now; + + char stemp[16]; + if (Settings.flag.rf_receive_decimal) { + snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)value); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"%lX\""), (uint32_t)value); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_DATA "\":%s}}"), + protocol, bit_length, stemp); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, value); // Send value as Domoticz Counter value +#endif // USE_DOMOTICZ + } + mySwitch.resetAvailable(); + } +} + +void RfInit() +{ + if (pin[GPIO_RFSEND] < 99) { + mySwitch.enableTransmit(pin[GPIO_RFSEND]); + } + if (pin[GPIO_RFRECV] < 99) { + mySwitch.enableReceive(pin[GPIO_RFRECV]); + } +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +/* + * ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(3) + 40 = 96 + RFsend: + { "protocol":1, "pulse":320, "repeat":15, "bits":24, "data":551502015 } +*/ + +boolean RfSendCommand() +{ + boolean serviced = true; + + boolean error = false; + char dataBufUc[XdrvMailbox.data_len]; + + uint32_t protocol = 0; + uint32_t pulse = 0; + uint32_t repeat = 0; + uint32_t bits = 0; + uint32_t data = 0; + + UpperCase(dataBufUc, XdrvMailbox.data); + if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_RFSEND))) { + if (XdrvMailbox.data_len) { + StaticJsonBuffer<128> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (!root.success()) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_INVALID_JSON "\"}")); // JSON decode failed + } + else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_DONE "\"}")); + + char parm_uc[10]; + protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; + pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))]; + repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; + bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; + data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], NULL, 0); + + if (!protocol) { protocol = 1; } + mySwitch.setProtocol(protocol); + if (!pulse) { pulse = 350; } // Default pulse length for protocol 1 + mySwitch.setPulseLength(pulse); + if (!repeat) { repeat = 10; } // Default at init + mySwitch.setRepeatTransmit(repeat); + if (!bits) { bits = 24; } // Default 24 bits + if (data) { + mySwitch.send(data, bits); + } + else { + error = true; + } + } + } + else { + error = true; + } + if (error) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_PROTOCOL ", " D_JSON_RF_PULSE ", " D_JSON_RF_REPEAT ", " D_JSON_RF_BITS " " D_JSON_OR " " D_JSON_RF_DATA "\"}")); + } + } + else serviced = false; // Unknown command + + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XDRV_17 + +boolean Xdrv17(byte function) +{ + boolean result = false; + + if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { + switch (function) { + case FUNC_INIT: + RfInit(); + break; + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_RFRECV] < 99) { + RfReceiveCheck(); + } + break; + case FUNC_COMMAND: + if (pin[GPIO_RFSEND] < 99) { + result = RfSendCommand(); + } + break; + } + } + return result; +} + +#endif // USE_RC_SWITCH diff --git a/tools/decode-status.py b/tools/decode-status.py index d7aae3b40..efa060ecd 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -111,7 +111,7 @@ a_features = [[ "USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", "USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER", "USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER", - "","","","", + "USE_RC_SWITCH","","","", "","","","NO_EXTRA_4K_HEAP", "VTABLES_IN_IRAM","VTABLES_IN_DRAM","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH", "PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY","PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH","DEBUG_THEO","USE_DEBUG_DRIVER"