mirror of https://github.com/arendst/Tasmota.git
commit
a64b839729
|
@ -62,7 +62,7 @@ There is **NO CONFLICT** with MQTT, Home Assistant, Web, etc. Tests show fast re
|
|||
## Sonoff-Tasmota
|
||||
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
|
||||
|
||||
Current version is **5.12.0g** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
Current version is **5.12.0h** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
|
||||
### ATTENTION All versions
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# TasmotaSerial
|
||||
|
||||
Implementation of software serial library for the ESP8266 at 9600 baud
|
||||
Implementation of software serial library for the ESP8266
|
||||
|
||||
Allows for several instances to be active at the same time.
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"name": "TasmotaSerial",
|
||||
"version": "1.0.0",
|
||||
"version": "1.2.0",
|
||||
"keywords": [
|
||||
"serial", "io", "TasmotaSerial"
|
||||
],
|
||||
"description": "Implementation of software serial for ESP8266 at 9600 baud.",
|
||||
"description": "Implementation of software serial for ESP8266.",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
|
@ -1,8 +1,8 @@
|
|||
name=TasmotaSerial
|
||||
version=1.0
|
||||
version=1.2.0
|
||||
author=Theo Arends
|
||||
maintainer=Theo Arends <theo@arends.com>
|
||||
sentence=Implementation of software serial for ESP8266 at 9600 baud.
|
||||
sentence=Implementation of software serial for ESP8266.
|
||||
paragraph=
|
||||
category=Signal Input/Output
|
||||
url=
|
|
@ -87,9 +87,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin)
|
|||
m_in_pos = m_out_pos = 0;
|
||||
if (m_rx_pin > -1) {
|
||||
m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE);
|
||||
if (m_buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
if (m_buffer == NULL) return;
|
||||
// Use getCycleCount() loop to get as exact timing as possible
|
||||
m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE;
|
||||
pinMode(m_rx_pin, INPUT);
|
||||
|
@ -111,7 +109,8 @@ bool TasmotaSerial::isValidGPIOpin(int pin)
|
|||
bool TasmotaSerial::begin(long speed) {
|
||||
// Use getCycleCount() loop to get as exact timing as possible
|
||||
m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed;
|
||||
return m_valid && (speed <= TM_SERIAL_BAUDRATE);
|
||||
m_high_speed = (speed > 9600);
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
bool TasmotaSerial::begin() {
|
||||
|
@ -123,17 +122,13 @@ void TasmotaSerial::flush() {
|
|||
}
|
||||
|
||||
int TasmotaSerial::peek() {
|
||||
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) {
|
||||
return -1;
|
||||
}
|
||||
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
|
||||
return m_buffer[m_out_pos];
|
||||
}
|
||||
|
||||
int TasmotaSerial::read()
|
||||
{
|
||||
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) {
|
||||
return -1;
|
||||
}
|
||||
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
|
||||
uint8_t ch = m_buffer[m_out_pos];
|
||||
m_out_pos = (m_out_pos +1) % TM_SERIAL_BUFFER_SIZE;
|
||||
return ch;
|
||||
|
@ -142,23 +137,20 @@ int TasmotaSerial::read()
|
|||
int TasmotaSerial::available()
|
||||
{
|
||||
int avail = m_in_pos - m_out_pos;
|
||||
if (avail < 0) {
|
||||
avail += TM_SERIAL_BUFFER_SIZE;
|
||||
}
|
||||
if (avail < 0) avail += TM_SERIAL_BUFFER_SIZE;
|
||||
return avail;
|
||||
}
|
||||
|
||||
#ifdef TM_SERIAL_USE_IRAM
|
||||
#define TM_SERIAL_WAIT { while (ESP.getCycleCount()-start < wait) optimistic_yield(1); wait += m_bit_time; } // Watchdog timeouts
|
||||
#define TM_SERIAL_WAIT { while (ESP.getCycleCount()-start < wait) if (!m_high_speed) optimistic_yield(1); wait += m_bit_time; } // Watchdog timeouts
|
||||
#else
|
||||
#define TM_SERIAL_WAIT { while (ESP.getCycleCount()-start < wait); wait += m_bit_time; }
|
||||
#endif
|
||||
|
||||
size_t TasmotaSerial::write(uint8_t b)
|
||||
{
|
||||
if (-1 == m_tx_pin) {
|
||||
return 0;
|
||||
}
|
||||
if (-1 == m_tx_pin) return 0;
|
||||
if (m_high_speed) cli(); // Disable interrupts in order to get a clean transmit
|
||||
unsigned long wait = m_bit_time;
|
||||
digitalWrite(m_tx_pin, HIGH);
|
||||
unsigned long start = ESP.getCycleCount();
|
||||
|
@ -173,6 +165,7 @@ size_t TasmotaSerial::write(uint8_t b)
|
|||
// Stop bit
|
||||
digitalWrite(m_tx_pin, HIGH);
|
||||
TM_SERIAL_WAIT;
|
||||
if (m_high_speed) sei();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -191,9 +184,7 @@ void TasmotaSerial::rxRead()
|
|||
for (int i = 0; i < 8; i++) {
|
||||
TM_SERIAL_WAIT;
|
||||
rec >>= 1;
|
||||
if (digitalRead(m_rx_pin)) {
|
||||
rec |= 0x80;
|
||||
}
|
||||
if (digitalRead(m_rx_pin)) rec |= 0x80;
|
||||
}
|
||||
// Stop bit
|
||||
TM_SERIAL_WAIT;
|
|
@ -20,12 +20,12 @@
|
|||
#ifndef TasmotaSerial_h
|
||||
#define TasmotaSerial_h
|
||||
/*********************************************************************************************\
|
||||
* TasmotaSerial supports up to 9600 baud with fixed buffer size of 64 bytes using optional no iram
|
||||
* TasmotaSerial supports up to 115200 baud with fixed buffer size of 64 bytes using optional no iram
|
||||
*
|
||||
* Based on EspSoftwareSerial v3.3.1 by Peter Lerup (https://github.com/plerup/espsoftwareserial)
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define TM_SERIAL_BAUDRATE 9600 // Max supported baudrate
|
||||
#define TM_SERIAL_BAUDRATE 9600 // Default baudrate
|
||||
#define TM_SERIAL_BUFFER_SIZE 64 // Receive buffer size
|
||||
|
||||
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
|
@ -57,6 +57,7 @@ class TasmotaSerial : public Stream {
|
|||
|
||||
// Member variables
|
||||
bool m_valid;
|
||||
bool m_high_speed;
|
||||
int m_rx_pin;
|
||||
int m_tx_pin;
|
||||
unsigned long m_bit_time;
|
|
@ -1,5 +1,15 @@
|
|||
/* 5.12.0g
|
||||
* Add support for MQTT to hardware serial bridge using commands Baudrate and SerialSend. Currently supports 8N1 and text only (#2182)
|
||||
/* 5.12.0h
|
||||
* Add optional Arduino OTA support to be enabled in user_config.h (#1998)
|
||||
* Add support for Software Serial bridge using commands SerialDelimiter, SBaudrate and SSerialSend. Supports 8N1 and text only (#2190)
|
||||
* Add support for Hardware Serial bridge using commands SerialDelimiter, Baudrate and SerialSend. Supports 8N1 and text only (#2182)
|
||||
* Add support for Zengge WF017 PWM Led strip controller (#2202)
|
||||
* Add PWM status to command State if PWM enabled (#2203)
|
||||
* Add command HSBColor Hue,Sat,Bri (#1642, #2203)
|
||||
* Add command Channel 0..100 to control dimmer value for individual color channels (#2111, #2203)
|
||||
* Add Channel status information (#2211)
|
||||
* Add all FriendlyNames to Status information (#2208)
|
||||
* Change status display of Ssid and SetOption
|
||||
* Change default option SetOption15 from 0 to 1 providing better initial PWM experience
|
||||
*
|
||||
* 5.12.0f
|
||||
* Add compile time support for WS2812 BRG and RBG led configurations to be defined in user_config.h (#1690)
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#define D_JSON_GATEWAY "Gateway"
|
||||
#define D_JSON_HEAPSIZE "Heap"
|
||||
#define D_JSON_HIGH "High"
|
||||
#define D_JSON_HSBCOLOR "HSBColor"
|
||||
#define D_JSON_HUMIDITY "Humidity"
|
||||
#define D_JSON_I2CSCAN_DEVICES_FOUND_AT "Device(s) found at"
|
||||
#define D_JSON_I2CSCAN_UNKNOWN_ERROR_AT "Unknown error at"
|
||||
|
@ -242,13 +243,16 @@
|
|||
#define D_CMND_CFGDUMP "CfgDump"
|
||||
#define D_CMND_I2CSCAN "I2CScan"
|
||||
#define D_CMND_SERIALSEND "SerialSend"
|
||||
#define D_CMND_SERIALDELIMITER "SerialDelimiter"
|
||||
#define D_CMND_BAUDRATE "Baudrate"
|
||||
#define D_CMND_EXCEPTION "Exception"
|
||||
|
||||
// Commands xdrv_01_light.ino
|
||||
#define D_CMND_CHANNEL "Channel"
|
||||
#define D_CMND_COLOR "Color"
|
||||
#define D_CMND_COLORTEMPERATURE "CT"
|
||||
#define D_CMND_DIMMER "Dimmer"
|
||||
#define D_CMND_HSBCOLOR "HSBColor"
|
||||
#define D_CMND_LED "Led"
|
||||
#define D_CMND_LEDTABLE "LedTable"
|
||||
#define D_CMND_FADE "Fade"
|
||||
|
@ -340,6 +344,11 @@
|
|||
#define D_CMND_DISP_SIZE "Size"
|
||||
#define D_CMND_DISP_TEXT "Text"
|
||||
|
||||
// Commands xdrv_08_serial_bridge.ino
|
||||
#define D_CMND_SSERIALSEND "SSerialSend"
|
||||
#define D_CMND_SBAUDRATE "SBaudrate"
|
||||
#define D_JSON_SSERIALRECEIVED "SSerialReceived"
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
#ifndef MY_LANGUAGE
|
||||
|
@ -477,4 +486,4 @@ const char S_INFORMATION[] PROGMEM = D_INFORMATION;
|
|||
const char S_RESTART[] PROGMEM = D_RESTART;
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
#endif // _I18N_H_
|
||||
#endif // _I18N_H_
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -427,6 +427,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -427,6 +427,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "Háttérvil"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "Luz negra"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
#define D_SENSOR_BACKLIGHT "BkLight"
|
||||
#define D_SENSOR_PMS5003 "PMS5003"
|
||||
#define D_SENSOR_SDS0X1 "SDS0X1"
|
||||
#define D_SENSOR_SBR_RX "SerBr Rx"
|
||||
#define D_SENSOR_SBR_TX "SerBr Tx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -192,9 +192,8 @@ struct SYSCFG {
|
|||
uint16_t ws_wakeup; // 3AA Not used since 5.8.0
|
||||
char friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC
|
||||
char switch_topic[33]; // 430
|
||||
|
||||
byte free_451[2]; // 451
|
||||
|
||||
char serial_delimiter; // 451
|
||||
uint8_t sbaudrate; // 452
|
||||
uint8_t sleep; // 453
|
||||
uint16_t domoticz_switch_idx[MAX_DOMOTICZ_IDX]; // 454
|
||||
uint16_t domoticz_sensor_idx[MAX_DOMOTICZ_SNS_IDX]; // 45C
|
||||
|
|
|
@ -450,6 +450,7 @@ void SettingsDefaultSet2()
|
|||
Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN;
|
||||
Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN;
|
||||
Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN;
|
||||
Settings.flag.pwm_control = 1;
|
||||
Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE;
|
||||
|
||||
Settings.flag2.emulation = EMULATION;
|
||||
|
@ -458,6 +459,8 @@ void SettingsDefaultSet2()
|
|||
Settings.timezone = APP_TIMEZONE;
|
||||
strlcpy(Settings.ota_url, OTA_URL, sizeof(Settings.ota_url));
|
||||
Settings.baudrate = APP_BAUDRATE / 1200;
|
||||
Settings.sbaudrate = SOFT_BAUDRATE / 1200;
|
||||
Settings.serial_delimiter = 0xff;
|
||||
|
||||
Settings.seriallog_level = SERIAL_LOG_LEVEL;
|
||||
// Settings.sta_active = 0;
|
||||
|
@ -523,14 +526,14 @@ void SettingsDefaultSet2()
|
|||
// Settings.energy_max_voltage = 0;
|
||||
// Settings.energy_min_current = 0;
|
||||
// Settings.energy_max_current = 0;
|
||||
// Settings.energy_max_power_limit = 0; // MaxPowerLimit
|
||||
// Settings.energy_max_power_limit = 0; // MaxPowerLimit
|
||||
Settings.energy_max_power_limit_hold = MAX_POWER_HOLD;
|
||||
Settings.energy_max_power_limit_window = MAX_POWER_WINDOW;
|
||||
// Settings.energy_max_power_safe_limit = 0; // MaxSafePowerLimit
|
||||
// Settings.energy_max_power_safe_limit = 0; // MaxSafePowerLimit
|
||||
Settings.energy_max_power_safe_limit_hold = SAFE_POWER_HOLD;
|
||||
Settings.energy_max_power_safe_limit_window = SAFE_POWER_WINDOW;
|
||||
// Settings.energy_max_energy = 0; // MaxEnergy
|
||||
// Settings.energy_max_energy_start = 0; // MaxEnergyStart
|
||||
// Settings.energy_max_energy = 0; // MaxEnergy
|
||||
// Settings.energy_max_energy_start = 0; // MaxEnergyStart
|
||||
|
||||
SettingsDefaultSet_3_2_4();
|
||||
|
||||
|
@ -903,6 +906,10 @@ void SettingsDelta()
|
|||
if (Settings.version < 0x050C0007) {
|
||||
Settings.baudrate = APP_BAUDRATE / 1200;
|
||||
}
|
||||
if (Settings.version < 0x050C0008) {
|
||||
Settings.sbaudrate = SOFT_BAUDRATE / 1200;
|
||||
Settings.serial_delimiter = 0xff;
|
||||
}
|
||||
|
||||
Settings.version = VERSION;
|
||||
SettingsSave(1);
|
||||
|
|
|
@ -98,6 +98,7 @@ typedef unsigned long power_t; // Power (Relay) type
|
|||
#define MAX_BACKLOG 16 // Max number of commands in backlog (chk backlog_index and backlog_pointer code)
|
||||
#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds
|
||||
|
||||
#define SOFT_BAUDRATE 9600 // Default software serial baudrate
|
||||
#define APP_BAUDRATE 115200 // Default serial baudrate
|
||||
#define SERIAL_POLLING 100 // Serial receive polling in ms
|
||||
#define MAX_STATUS 11 // Max number of status lines
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
|
||||
====================================================*/
|
||||
|
||||
#define VERSION 0x050C0007 // 5.12.0g
|
||||
#define VERSION 0x050C0008 // 5.12.0h
|
||||
|
||||
// Location specific includes
|
||||
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
|
@ -54,8 +54,14 @@
|
|||
#include <ESP8266WebServer.h> // WifiManager, Webserver
|
||||
#include <DNSServer.h> // WifiManager
|
||||
#endif // USE_WEBSERVER
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
#include <ArduinoOTA.h> // Arduino OTA
|
||||
#ifndef USE_DISCOVERY
|
||||
#define USE_DISCOVERY
|
||||
#endif
|
||||
#endif // USE_ARDUINO_OTA
|
||||
#ifdef USE_DISCOVERY
|
||||
#include <ESP8266mDNS.h> // MQTT, Webserver
|
||||
#include <ESP8266mDNS.h> // MQTT, Webserver, Arduino OTA
|
||||
#endif // USE_DISCOVERY
|
||||
#ifdef USE_I2C
|
||||
#include <Wire.h> // I2C support library
|
||||
|
@ -76,7 +82,7 @@ enum TasmotaCommands {
|
|||
CMND_LOGHOST, CMND_LOGPORT, CMND_IPADDRESS, CMND_NTPSERVER, CMND_AP, CMND_SSID, CMND_PASSWORD, CMND_HOSTNAME,
|
||||
CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_EMULATION,
|
||||
CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE,
|
||||
CMND_CFGDUMP, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_EXCEPTION };
|
||||
CMND_CFGDUMP, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_EXCEPTION };
|
||||
const char kTasmotaCommands[] PROGMEM =
|
||||
D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|"
|
||||
D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SENSOR "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|"
|
||||
|
@ -86,7 +92,7 @@ const char kTasmotaCommands[] PROGMEM =
|
|||
D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|"
|
||||
D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_EMULATION "|"
|
||||
D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|"
|
||||
D_CMND_CFGDUMP "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE
|
||||
D_CMND_CFGDUMP "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER
|
||||
#ifdef DEBUG_THEO
|
||||
"|" D_CMND_EXCEPTION
|
||||
#endif
|
||||
|
@ -176,7 +182,6 @@ uint8_t i2c_flg = 0; // I2C configured
|
|||
uint8_t spi_flg = 0; // SPI configured
|
||||
uint8_t light_type = 0; // Light types
|
||||
bool pwm_present = false; // Any PWM channel configured with SetOption15 0
|
||||
|
||||
boolean mdns_begun = false;
|
||||
|
||||
char my_version[33]; // Composed version string
|
||||
|
@ -737,15 +742,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
|||
Settings.pwm_value[index -1] = payload;
|
||||
analogWrite(pin[GPIO_PWM1 + index -1], bitRead(pwm_inverted, index -1) ? Settings.pwm_range - payload : payload);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PWM "\":{"));
|
||||
bool first = true;
|
||||
for (byte i = 0; i < MAX_PWMS; i++) {
|
||||
if (pin[GPIO_PWM1 + i] < 99) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ",", i+1, Settings.pwm_value[i]);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"),mqtt_data);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{"));
|
||||
MqttShowPWMState(); // Render the PWM status to MQTT
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
else if (CMND_PWMFREQUENCY == command_code) {
|
||||
if ((1 == payload) || ((payload >= 100) && (payload <= 4000))) {
|
||||
|
@ -821,15 +820,35 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
|||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200);
|
||||
}
|
||||
else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 2)) {
|
||||
else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 3)) {
|
||||
SetSeriallog(LOG_LEVEL_NONE);
|
||||
Settings.flag.mqtt_serial = 1;
|
||||
if (data_len > 0) {
|
||||
if (1 == index) Serial.printf("%s\n", dataBuf);
|
||||
if (2 == index) Serial.printf("%s", dataBuf);
|
||||
if (1 == index) {
|
||||
Serial.printf("%s\n", dataBuf);
|
||||
}
|
||||
else if (2 == index) {
|
||||
Serial.printf("%s", dataBuf);
|
||||
}
|
||||
else if (3 == index) {
|
||||
uint16_t dat_len = data_len;
|
||||
Serial.printf("%s", Unescape(dataBuf, &dat_len));
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
|
||||
}
|
||||
}
|
||||
else if (CMND_SERIALDELIMITER == command_code) {
|
||||
if ((data_len > 0) && (payload < 256)) {
|
||||
if (payload > 0) {
|
||||
Settings.serial_delimiter = payload;
|
||||
} else {
|
||||
uint16_t dat_len = data_len;
|
||||
Unescape(dataBuf, &dat_len);
|
||||
Settings.serial_delimiter = dataBuf[0];
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.serial_delimiter);
|
||||
}
|
||||
else if (CMND_SERIALLOG == command_code) {
|
||||
if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
|
||||
Settings.flag.mqtt_serial = 0;
|
||||
|
@ -1229,6 +1248,7 @@ void ExecuteCommand(char *cmnd)
|
|||
void PublishStatus(uint8_t payload)
|
||||
{
|
||||
uint8_t option = 1;
|
||||
char stemp[MAX_FRIENDLYNAMES * (sizeof(Settings.friendlyname[0]) +4)];
|
||||
|
||||
// Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX
|
||||
if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) option++;
|
||||
|
@ -1237,8 +1257,13 @@ void PublishStatus(uint8_t payload)
|
|||
if (!energy_flg && (9 == payload)) payload = 99;
|
||||
|
||||
if ((0 == payload) || (99 == payload)) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d,\"" D_CMND_FRIENDLYNAME "\":\"%s\",\"" D_CMND_TOPIC "\":\"%s\",\"" D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"),
|
||||
Settings.module +1, Settings.friendlyname[0], mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_power_retain);
|
||||
uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present;
|
||||
stemp[0] = '\0';
|
||||
for (byte i = 0; i < maxfn; i++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), Settings.friendlyname[i]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d,\"" D_CMND_FRIENDLYNAME "\":[%s],\"" D_CMND_TOPIC "\":\"%s\",\"" D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"),
|
||||
Settings.module +1, stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_power_retain);
|
||||
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS));
|
||||
}
|
||||
|
||||
|
@ -1255,8 +1280,8 @@ void PublishStatus(uint8_t payload)
|
|||
}
|
||||
|
||||
if ((0 == payload) || (3 == payload)) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "1\":\"%s\",\"" D_CMND_SSID "2\":\"%s\",\"" D_CMND_TELEPERIOD "\":%d,\"" D_CMND_SETOPTION "\":\"%08X\"}}"),
|
||||
Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period, Settings.flag.data);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_CMND_SETOPTION "\":[\"%08X\",\"%08X\"]}}"),
|
||||
Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period, Settings.flag.data, Settings.flag2.data);
|
||||
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3"));
|
||||
}
|
||||
|
||||
|
@ -1313,6 +1338,19 @@ void PublishStatus(uint8_t payload)
|
|||
|
||||
}
|
||||
|
||||
void MqttShowPWMState()
|
||||
{
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_PWM "\":{"), mqtt_data);
|
||||
bool first = true;
|
||||
for (byte i = 0; i < MAX_PWMS; i++) {
|
||||
if (pin[GPIO_PWM1 + i] < 99) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ",", i+1, Settings.pwm_value[i]);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
|
||||
void MqttShowState()
|
||||
{
|
||||
char stemp1[33];
|
||||
|
@ -1331,6 +1369,11 @@ void MqttShowState()
|
|||
}
|
||||
}
|
||||
|
||||
if (pwm_present) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data);
|
||||
MqttShowPWMState();
|
||||
}
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"),
|
||||
mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str());
|
||||
}
|
||||
|
@ -1871,6 +1914,86 @@ void StateLoop()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
/*********************************************************************************************\
|
||||
* Allow updating via the Arduino OTA-protocol.
|
||||
*
|
||||
* - Once started disables current wifi clients and udp
|
||||
* - Perform restart when done to re-init wifi clients
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool arduino_ota_triggered = false;
|
||||
uint16_t arduino_ota_progress_dot_count = 0;
|
||||
|
||||
void ArduinoOTAInit()
|
||||
{
|
||||
ArduinoOTA.setPort(8266);
|
||||
ArduinoOTA.setHostname(Settings.hostname);
|
||||
if (Settings.web_password[0] !=0) ArduinoOTA.setPassword(Settings.web_password);
|
||||
|
||||
ArduinoOTA.onStart([]()
|
||||
{
|
||||
SettingsSave(1); // Free flash for OTA update
|
||||
#ifdef USE_WEBSERVER
|
||||
if (Settings.webserver) StopWebserver();
|
||||
#endif // USE_WEBSERVER
|
||||
#ifdef USE_ARILUX_RF
|
||||
AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine
|
||||
#endif // USE_ARILUX_RF
|
||||
if (Settings.flag.mqtt_enabled) MqttDisconnect();
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED));
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
arduino_ota_triggered = true;
|
||||
arduino_ota_progress_dot_count = 0;
|
||||
delay(100); // Allow time for message xfer
|
||||
});
|
||||
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total)
|
||||
{
|
||||
if ((LOG_LEVEL_DEBUG <= seriallog_level)) {
|
||||
arduino_ota_progress_dot_count++;
|
||||
Serial.printf(".");
|
||||
if (!(arduino_ota_progress_dot_count % 80)) Serial.println();
|
||||
}
|
||||
});
|
||||
|
||||
ArduinoOTA.onError([](ota_error_t error)
|
||||
{
|
||||
/*
|
||||
From ArduinoOTA.h:
|
||||
typedef enum { OTA_AUTH_ERROR, OTA_BEGIN_ERROR, OTA_CONNECT_ERROR, OTA_RECEIVE_ERROR, OTA_END_ERROR } ota_error_t;
|
||||
*/
|
||||
char error_str[100];
|
||||
|
||||
if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) Serial.println();
|
||||
switch (error) {
|
||||
case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break;
|
||||
case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break;
|
||||
case OTA_END_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_7), sizeof(error_str)); break;
|
||||
default:
|
||||
snprintf_P(error_str, sizeof(error_str), PSTR(D_UPLOAD_ERROR_CODE " %d"), error);
|
||||
}
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
delay(100); // Allow time for message xfer
|
||||
ESP.restart();
|
||||
});
|
||||
|
||||
ArduinoOTA.onEnd([]()
|
||||
{
|
||||
if ((LOG_LEVEL_DEBUG <= seriallog_level)) Serial.println();
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING));
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
delay(100); // Allow time for message xfer
|
||||
ESP.restart();
|
||||
});
|
||||
|
||||
ArduinoOTA.begin();
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266"));
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
#endif // USE_ARDUINO_OTA
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void SerialInput()
|
||||
|
@ -1927,17 +2050,26 @@ void SerialInput()
|
|||
|
||||
if (serial_in_byte > 127) { // binary data...
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
}
|
||||
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;
|
||||
serial_polling_window = millis();
|
||||
} else {
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
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) {
|
||||
if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && (serial_in_byte != Settings.serial_delimiter)) { // 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1955,24 +2087,7 @@ void SerialInput()
|
|||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
/*
|
||||
else if (serial_in_byte == '\n') {
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
if (!Settings.flag.mqtt_serial) {
|
||||
seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (byte)LOG_LEVEL_INFO : Settings.seriallog_level;
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), serial_in_buffer);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
ExecuteCommand(serial_in_buffer);
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
||||
}
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
else if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) {
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (byte)LOG_LEVEL_INFO : Settings.seriallog_level;
|
||||
|
@ -1991,8 +2106,6 @@ void SerialInput()
|
|||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
||||
serial_in_byte_counter = 0;
|
||||
serial_polling_window = 0;
|
||||
Serial.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2289,6 +2402,11 @@ void setup()
|
|||
#endif // BE_MINIMAL
|
||||
|
||||
RtcInit();
|
||||
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
ArduinoOTAInit();
|
||||
#endif // USE_ARDUINO_OTA
|
||||
|
||||
XsnsCall(FUNC_INIT);
|
||||
}
|
||||
|
||||
|
@ -2310,6 +2428,12 @@ void loop()
|
|||
|
||||
SerialInput();
|
||||
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
ArduinoOTA.handle();
|
||||
// Once OTA is triggered, only handle that and dont do other stuff. (otherwise it fails)
|
||||
while (arduino_ota_triggered) ArduinoOTA.handle();
|
||||
#endif // USE_ARDUINO_OTA
|
||||
|
||||
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
|
||||
delay(sleep); // https://github.com/esp8266/Arduino/issues/2021
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ void WifiWpsStatusCallback(wps_cb_status status);
|
|||
#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code)
|
||||
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code)
|
||||
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
||||
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
|
||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram)
|
||||
#define USE_IR_HVAC // Support for HVAC system using IR (+2k code)
|
||||
#define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram)
|
||||
|
|
|
@ -89,6 +89,8 @@ enum UserSelectablePins {
|
|||
GPIO_BACKLIGHT, // Display backlight control
|
||||
GPIO_PMS5003, // Plantower PMS5003 Serial interface
|
||||
GPIO_SDS0X1, // Nova Fitness SDS011 Serial interface
|
||||
GPIO_SBR_TX, // Serial Bridge Serial interface
|
||||
GPIO_SBR_RX, // Serial Bridge Serial interface
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
||||
|
@ -130,7 +132,8 @@ const char kSensorNames[] PROGMEM =
|
|||
D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_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;
|
||||
D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1 "|"
|
||||
D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
|
@ -177,6 +180,7 @@ enum SupportedModules {
|
|||
SONOFF_DUAL_R2,
|
||||
ARILUX_LC06,
|
||||
SONOFF_S31,
|
||||
ZENGGE_ZF_WF017,
|
||||
MAXMODULE };
|
||||
|
||||
/********************************************************************************************/
|
||||
|
@ -231,6 +235,7 @@ const uint8_t kNiceList[MAXMODULE] PROGMEM = {
|
|||
ARILUX_LC01,
|
||||
ARILUX_LC06,
|
||||
ARILUX_LC11,
|
||||
ZENGGE_ZF_WF017,
|
||||
HUAFAN_SS,
|
||||
KMC_70011,
|
||||
AILIGHT,
|
||||
|
@ -786,6 +791,19 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||
GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On)
|
||||
GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off)
|
||||
0, 0, 0, 0
|
||||
},
|
||||
{ "Zengge WF017", // Zenggee ZJ-WF017-A (ESP12S)) - https://www.ebay.com/p/Smartphone-Android-IOS-WiFi-Music-Controller-for-RGB-5050-3528-LED-Strip-Light/534446632?_trksid=p2047675.l2644
|
||||
GPIO_KEY1, // GPIO00 Optional Button
|
||||
0,
|
||||
GPIO_USER, // GPIO02 Empty pad
|
||||
0,
|
||||
GPIO_USER, // GPIO04 W2 - PWM5
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, // Flash connection
|
||||
GPIO_PWM2, // GPIO12 RGB LED Green
|
||||
GPIO_PWM1, // GPIO13 RGB LED Red
|
||||
GPIO_PWM3, // GPIO14 RGB LED Blue
|
||||
0, 0, 0
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -816,20 +834,6 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||
0, 0
|
||||
}
|
||||
|
||||
{ "Zengge WF017", // Zenggee ZJ-WF017-A (ESP12S)) - https://www.ebay.com/p/Smartphone-Android-IOS-WiFi-Music-Controller-for-RGB-5050-3528-LED-Strip-Light/534446632?_trksid=p2047675.l2644
|
||||
GPIO_KEY1, // GPIO00 Optional Button
|
||||
0,
|
||||
GPIO_USER, // GPIO02 Empty pad
|
||||
0,
|
||||
GPIO_USER, // GPIO04 W2 - PWM5
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, // Flash connection
|
||||
GPIO_PWM2, // GPIO12 RGB LED Green
|
||||
GPIO_PWM1, // GPIO13 RGB LED Red
|
||||
GPIO_PWM3, // GPIO14 RGB LED Blue
|
||||
0, 0, 0
|
||||
}
|
||||
|
||||
{ "SMPW701E", // SM-PW701E WLAN Socket (#1190)
|
||||
0, 0, 0, 0,
|
||||
GPIO_LED1_INV, // GPIO04 Blue Led (0 = On, 1 = Off)
|
||||
|
|
|
@ -197,6 +197,50 @@ char* dtostrfd(double number, unsigned char prec, char *s)
|
|||
return dtostrf(number, 1, prec, s);
|
||||
}
|
||||
|
||||
char* Unescape(char* buffer, uint16_t* size)
|
||||
{
|
||||
uint8_t* read = (uint8_t*)buffer;
|
||||
uint8_t* write = (uint8_t*)buffer;
|
||||
uint16_t start_size = *size;
|
||||
uint16_t end_size = *size;
|
||||
uint8_t che = 0;
|
||||
|
||||
while (start_size > 0) {
|
||||
uint8_t ch = *read++;
|
||||
start_size--;
|
||||
if (ch != '\\') {
|
||||
*write++ = ch;
|
||||
} else {
|
||||
if (start_size > 0) {
|
||||
uint8_t chi = *read++;
|
||||
start_size--;
|
||||
end_size--;
|
||||
switch (chi) {
|
||||
case '\\': che = '\\'; break; // 5C Backslash
|
||||
case 'a': che = '\a'; break; // 07 Bell (Alert)
|
||||
case 'b': che = '\b'; break; // 08 Backspace
|
||||
case 'e': che = '\e'; break; // 1B Escape
|
||||
case 'f': che = '\f'; break; // 0C Formfeed
|
||||
case 'n': che = '\n'; break; // 0A Linefeed (Newline)
|
||||
case 'r': che = '\r'; break; // 0D Carriage return
|
||||
case 's': che = ' '; break; // 20 Space
|
||||
case 't': che = '\t'; break; // 09 Horizontal tab
|
||||
case 'v': che = '\v'; break; // 0B Vertical tab
|
||||
// case '?': che = '\?'; break; // 3F Question mark
|
||||
default : {
|
||||
che = chi;
|
||||
*write++ = ch;
|
||||
end_size++;
|
||||
}
|
||||
}
|
||||
*write++ = che;
|
||||
}
|
||||
}
|
||||
}
|
||||
*size = end_size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
boolean ParseIp(uint32_t* addr, const char* str)
|
||||
{
|
||||
uint8_t *part = (uint8_t*)addr;
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
|
||||
// -- Ota -----------------------------------------
|
||||
#define OTA_URL "http://sonoff.maddox.co.uk/tasmota/sonoff.ino.bin" // [OtaUrl]
|
||||
//#define USE_ARDUINO_OTA // Add optional support for Arduino OTA (+4k5 code)
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Select ONE of possible MQTT library types below
|
||||
|
@ -223,6 +224,7 @@
|
|||
#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code)
|
||||
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code)
|
||||
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
||||
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
|
||||
|
||||
// -- Low level interface devices -----------------
|
||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram)
|
||||
|
|
|
@ -55,10 +55,12 @@
|
|||
|
||||
enum LightCommands {
|
||||
CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE,
|
||||
CMND_PIXELS, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION, CMND_WIDTH, CMND_UNDOCA };
|
||||
CMND_PIXELS, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION,
|
||||
CMND_WIDTH, CMND_CHANNEL, CMND_HSBCOLOR, CMND_UNDOCA };
|
||||
const char kLightCommands[] PROGMEM =
|
||||
D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_LED "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|"
|
||||
D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" D_CMND_WIDTH "|UNDOCA" ;
|
||||
D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|"
|
||||
D_CMND_WIDTH "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ;
|
||||
|
||||
struct LRgbColor {
|
||||
uint8_t R, G, B;
|
||||
|
@ -535,6 +537,8 @@ void LightState(uint8_t append)
|
|||
{
|
||||
char scolor[25];
|
||||
char scommand[33];
|
||||
float hsb[3];
|
||||
int16_t h,s,b;
|
||||
|
||||
if (append) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data);
|
||||
|
@ -546,6 +550,19 @@ void LightState(uint8_t append)
|
|||
mqtt_data, scommand, GetStateText(light_power), Settings.light_dimmer);
|
||||
if (light_subtype > LST_SINGLE) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor));
|
||||
// Add status for HSB
|
||||
LightGetHsb(&hsb[0],&hsb[1],&hsb[2]);
|
||||
// Scale these percentages up to the numbers expected byt he client
|
||||
h = round(hsb[0] * 360);
|
||||
s = round(hsb[1] * 100);
|
||||
b = round(hsb[2] * 100);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), mqtt_data, h,s,b);
|
||||
// Add status for each channel
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_CHANNEL "\":[" ), mqtt_data);
|
||||
for (byte i = 0; i < light_subtype; i++) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d" ), mqtt_data, (i > 0 ? "," : ""), round(light_current_color[i]/2.55));
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]" ), mqtt_data);
|
||||
}
|
||||
if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLORTEMPERATURE "\":%d"), mqtt_data, LightGetColorTemp());
|
||||
|
@ -1053,6 +1070,47 @@ boolean LightCommand()
|
|||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor);
|
||||
}
|
||||
}
|
||||
else if ((CMND_CHANNEL == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= light_subtype ) ) {
|
||||
// Set "Channel" directly - this allows Color and Direct PWM control to coexist
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
||||
uint8_t level = XdrvMailbox.payload;
|
||||
light_current_color[XdrvMailbox.index-1] = round(level * 2.55);
|
||||
LightSetColor();
|
||||
coldim = true;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, round(light_current_color[XdrvMailbox.index -1] / 2.55));
|
||||
}
|
||||
else if ((CMND_HSBCOLOR == command_code) && ( light_subtype >= LST_RGB)) {
|
||||
// Implement method to "direct set" color by HSB (HSB is passed comma separated, 0<H<360 0<S<100 0<B<100 )
|
||||
uint16_t HSB[3];
|
||||
bool validHSB = true;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
char *substr;
|
||||
|
||||
if (0 == i) {
|
||||
substr = strtok(XdrvMailbox.data, ",");
|
||||
} else {
|
||||
substr = strtok(NULL, ",");
|
||||
}
|
||||
if (substr != NULL) {
|
||||
HSB[i] = atoi(substr);
|
||||
} else {
|
||||
validHSB = false;
|
||||
}
|
||||
}
|
||||
if (validHSB) {
|
||||
// Translate to fractional elements as required by LightHsbToRgb
|
||||
// Keep the results <=1 in the event someone passes something
|
||||
// out of range.
|
||||
LightSetHsb(( (HSB[0]>360) ? (HSB[0] % 360) : HSB[0] ) /360.0,
|
||||
( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0,
|
||||
( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0,
|
||||
0);
|
||||
} else {
|
||||
LightState(0);
|
||||
}
|
||||
}
|
||||
#ifdef USE_WS2812 // ***********************************************************************
|
||||
else if ((CMND_LED == command_code) && (LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
xdrv_08_serial_bridge.ino - serial bridge support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends and Dániel Zoltán Tolnai
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_SERIAL_BRIDGE
|
||||
/*********************************************************************************************\
|
||||
* Serial Bridge using Software Serial library (TasmotaSerial)
|
||||
\*********************************************************************************************/
|
||||
#define SERIAL_BRIDGE_BUFFER_SIZE 130
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
|
||||
enum SerialBridgeCommands { CMND_SSERIALSEND, CMND_SBAUDRATE };
|
||||
const char kSerialBridgeCommands[] PROGMEM = D_CMND_SSERIALSEND "|" D_CMND_SBAUDRATE;
|
||||
|
||||
TasmotaSerial *SerialBridgeSerial;
|
||||
|
||||
uint8_t serial_bridge_active = 1;
|
||||
uint8_t serial_bridge_in_byte_counter = 0;
|
||||
unsigned long serial_bridge_polling_window = 0;
|
||||
char serial_bridge_buffer[SERIAL_BRIDGE_BUFFER_SIZE];
|
||||
|
||||
void SerialBridgeInput()
|
||||
{
|
||||
while (SerialBridgeSerial->available()) {
|
||||
yield();
|
||||
uint8_t serial_in_byte = SerialBridgeSerial->read();
|
||||
|
||||
if (serial_in_byte > 127) { // binary data...
|
||||
serial_bridge_in_byte_counter = 0;
|
||||
SerialBridgeSerial->flush();
|
||||
return;
|
||||
}
|
||||
if (serial_in_byte) {
|
||||
if ((serial_in_byte_counter < sizeof(serial_bridge_buffer) -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits
|
||||
serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte;
|
||||
serial_bridge_polling_window = millis(); // Wait for more data
|
||||
} else {
|
||||
serial_bridge_polling_window = 0; // Publish now
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) {
|
||||
serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // serial data completed
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED));
|
||||
serial_bridge_in_byte_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void SerialBridgeInit(void)
|
||||
{
|
||||
serial_bridge_active = 0;
|
||||
if ((pin[GPIO_SBR_RX] < 99) && (pin[GPIO_SBR_TX] < 99)) {
|
||||
SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]);
|
||||
if (SerialBridgeSerial->begin(Settings.sbaudrate * 1200)) { // Baud rate is stored div 1200 so it fits into one byte
|
||||
serial_bridge_active = 1;
|
||||
SerialBridgeSerial->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
boolean SerialBridgeCommand()
|
||||
{
|
||||
char command [CMDSZ];
|
||||
boolean serviced = true;
|
||||
|
||||
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kSerialBridgeCommands);
|
||||
if ((CMND_SSERIALSEND == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (1 == XdrvMailbox.index) {
|
||||
SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len);
|
||||
SerialBridgeSerial->write("\n");
|
||||
}
|
||||
else if (2 == XdrvMailbox.index) {
|
||||
SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len);
|
||||
}
|
||||
else if (3 == XdrvMailbox.index) {
|
||||
SerialBridgeSerial->write(Unescape(XdrvMailbox.data, &XdrvMailbox.data_len), XdrvMailbox.data_len);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
|
||||
}
|
||||
}
|
||||
else if (CMND_SBAUDRATE == command_code) {
|
||||
char *p;
|
||||
int baud = strtol(XdrvMailbox.data, &p, 10);
|
||||
if (baud > 0) {
|
||||
baud /= 1200; // Make it a valid baudrate
|
||||
Settings.sbaudrate = (1 == XdrvMailbox.payload) ? SOFT_BAUDRATE / 1200 : baud;
|
||||
SerialBridgeSerial->begin(Settings.sbaudrate * 1200); // Reinitialize serial port with new baud rate
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE, command, Settings.sbaudrate * 1200);
|
||||
}
|
||||
else {
|
||||
serviced = false; // Unknown command
|
||||
}
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XDRV_08
|
||||
|
||||
boolean Xdrv08(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (serial_bridge_active) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
SerialBridgeInit();
|
||||
break;
|
||||
case FUNC_LOOP:
|
||||
SerialBridgeInput();
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = SerialBridgeCommand();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_SERIAL_BRIDGE
|
Loading…
Reference in New Issue