mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-31 06:36:33 +00:00
Merge branch 'development' into development
This commit is contained in:
commit
c55ad6bd39
0
lib/Adafruit_SGP30-1.0.0.13/.github/ISSUE_TEMPLATE.md → lib/Adafruit_SGP30-1.0.3/.github/ISSUE_TEMPLATE.md
vendored
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/.github/ISSUE_TEMPLATE.md → lib/Adafruit_SGP30-1.0.3/.github/ISSUE_TEMPLATE.md
vendored
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/.github/PULL_REQUEST_TEMPLATE.md → lib/Adafruit_SGP30-1.0.3/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/.github/PULL_REQUEST_TEMPLATE.md → lib/Adafruit_SGP30-1.0.3/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/.gitignore → lib/Adafruit_SGP30-1.0.3/.gitignore
vendored
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/.gitignore → lib/Adafruit_SGP30-1.0.3/.gitignore
vendored
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/.travis.yml → lib/Adafruit_SGP30-1.0.3/.travis.yml
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/.travis.yml → lib/Adafruit_SGP30-1.0.3/.travis.yml
Normal file → Executable file
58
lib/Adafruit_SGP30-1.0.0.13/Adafruit_SGP30.cpp → lib/Adafruit_SGP30-1.0.3/Adafruit_SGP30.cpp
Normal file → Executable file
58
lib/Adafruit_SGP30-1.0.0.13/Adafruit_SGP30.cpp → lib/Adafruit_SGP30-1.0.3/Adafruit_SGP30.cpp
Normal file → Executable file
@ -37,7 +37,7 @@
|
|||||||
//#define I2C_DEBUG
|
//#define I2C_DEBUG
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Instantiates a new SGP30 class
|
@brief Instantiates a new SGP30 class
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@ -45,7 +45,7 @@ Adafruit_SGP30::Adafruit_SGP30() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Setups the hardware and detects a valid SGP30. Initializes I2C
|
@brief Setups the hardware and detects a valid SGP30. Initializes I2C
|
||||||
then reads the serialnumber and checks that we are talking to an SGP30
|
then reads the serialnumber and checks that we are talking to an SGP30
|
||||||
@param theWire Optional pointer to I2C interface, otherwise use Wire
|
@param theWire Optional pointer to I2C interface, otherwise use Wire
|
||||||
@ -60,31 +60,32 @@ boolean Adafruit_SGP30::begin(TwoWire *theWire) {
|
|||||||
_i2c = theWire;
|
_i2c = theWire;
|
||||||
}
|
}
|
||||||
|
|
||||||
_i2c->begin();
|
// assume i2c initialized already to avoid resetting clock stretching
|
||||||
|
// _i2c->begin();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t command[2];
|
uint8_t command[2];
|
||||||
command[0] = 0x36;
|
command[0] = 0x36;
|
||||||
command[1] = 0x82;
|
command[1] = 0x82;
|
||||||
if (! readWordFromCommand(command, 2, 10, serialnumber, 3))
|
if (! readWordFromCommand(command, 2, 10, serialnumber, 3))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint16_t featureset;
|
uint16_t featureset;
|
||||||
command[0] = 0x20;
|
command[0] = 0x20;
|
||||||
command[1] = 0x2F;
|
command[1] = 0x2F;
|
||||||
if (! readWordFromCommand(command, 2, 10, &featureset, 1))
|
if (! readWordFromCommand(command, 2, 10, &featureset, 1))
|
||||||
return false;
|
return false;
|
||||||
//Serial.print("Featureset 0x"); Serial.println(featureset, HEX);
|
//Serial.print("Featureset 0x"); Serial.println(featureset, HEX);
|
||||||
if (featureset != SGP30_FEATURESET)
|
if (featureset != SGP30_FEATURESET)
|
||||||
return false;
|
return false;
|
||||||
if (! IAQinit())
|
if (! IAQinit())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Commands the sensor to begin the IAQ algorithm. Must be called after startup.
|
@brief Commands the sensor to begin the IAQ algorithm. Must be called after startup.
|
||||||
@returns True if command completed successfully, false if something went wrong!
|
@returns True if command completed successfully, false if something went wrong!
|
||||||
*/
|
*/
|
||||||
@ -97,7 +98,7 @@ boolean Adafruit_SGP30::IAQinit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Commands the sensor to take a single eCO2/VOC measurement. Places results in {@link TVOC} and {@link eCO2}
|
@brief Commands the sensor to take a single eCO2/VOC measurement. Places results in {@link TVOC} and {@link eCO2}
|
||||||
@returns True if command completed successfully, false if something went wrong!
|
@returns True if command completed successfully, false if something went wrong!
|
||||||
*/
|
*/
|
||||||
@ -113,9 +114,9 @@ boolean Adafruit_SGP30::IAQmeasure(void) {
|
|||||||
eCO2 = reply[0];
|
eCO2 = reply[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Request baseline calibration values for both CO2 and TVOC IAQ calculations. Places results in parameter memory locaitons.
|
@brief Request baseline calibration values for both CO2 and TVOC IAQ calculations. Places results in parameter memory locaitons.
|
||||||
@param eco2_base A pointer to a uint16_t which we will save the calibration value to
|
@param eco2_base A pointer to a uint16_t which we will save the calibration value to
|
||||||
@param tvoc_base A pointer to a uint16_t which we will save the calibration value to
|
@param tvoc_base A pointer to a uint16_t which we will save the calibration value to
|
||||||
@ -135,7 +136,7 @@ boolean Adafruit_SGP30::getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Assign baseline calibration values for both CO2 and TVOC IAQ calculations.
|
@brief Assign baseline calibration values for both CO2 and TVOC IAQ calculations.
|
||||||
@param eco2_base A uint16_t which we will save the calibration value from
|
@param eco2_base A uint16_t which we will save the calibration value from
|
||||||
@param tvoc_base A uint16_t which we will save the calibration value from
|
@param tvoc_base A uint16_t which we will save the calibration value from
|
||||||
@ -157,7 +158,30 @@ boolean Adafruit_SGP30::setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@brief Set the absolute humidity value [mg/m^3] for compensation to increase precision of TVOC and eCO2.
|
||||||
|
@param absolute_humidity A uint32_t [mg/m^3] which we will be used for compensation. If the absolute humidity is set to zero, humidity compensation will be disabled.
|
||||||
|
@returns True if command completed successfully, false if something went wrong!
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
boolean Adafruit_SGP30::setHumidity(uint32_t absolute_humidity) {
|
||||||
|
if (absolute_humidity > 256000) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ah_scaled = (uint16_t)(((uint64_t)absolute_humidity * 256 * 16777) >> 24);
|
||||||
|
uint8_t command[5];
|
||||||
|
command[0] = 0x20;
|
||||||
|
command[1] = 0x61;
|
||||||
|
command[2] = ah_scaled >> 8;
|
||||||
|
command[3] = ah_scaled & 0xFF;
|
||||||
|
command[4] = generateCRC(command+2, 2);
|
||||||
|
|
||||||
|
return readWordFromCommand(command, 5, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
@brief I2C low level interfacing
|
@brief I2C low level interfacing
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@ -186,16 +210,16 @@ boolean Adafruit_SGP30::readWordFromCommand(uint8_t command[], uint8_t commandLe
|
|||||||
|
|
||||||
delay(delayms);
|
delay(delayms);
|
||||||
|
|
||||||
if (readlen == 0)
|
if (readlen == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
uint8_t replylen = readlen * (SGP30_WORD_LEN +1);
|
uint8_t replylen = readlen * (SGP30_WORD_LEN +1);
|
||||||
if (_i2c->requestFrom(_i2caddr, replylen) != replylen)
|
if (_i2c->requestFrom(_i2caddr, replylen) != replylen)
|
||||||
return false;
|
return false;
|
||||||
uint8_t replybuffer[replylen];
|
uint8_t replybuffer[replylen];
|
||||||
#ifdef I2C_DEBUG
|
#ifdef I2C_DEBUG
|
||||||
Serial.print("\t\t<- ");
|
Serial.print("\t\t<- ");
|
||||||
#endif
|
#endif
|
||||||
for (uint8_t i=0; i<replylen; i++) {
|
for (uint8_t i=0; i<replylen; i++) {
|
||||||
replybuffer[i] = _i2c->read();
|
replybuffer[i] = _i2c->read();
|
||||||
#ifdef I2C_DEBUG
|
#ifdef I2C_DEBUG
|
1
lib/Adafruit_SGP30-1.0.0.13/Adafruit_SGP30.h → lib/Adafruit_SGP30-1.0.3/Adafruit_SGP30.h
Normal file → Executable file
1
lib/Adafruit_SGP30-1.0.0.13/Adafruit_SGP30.h → lib/Adafruit_SGP30-1.0.3/Adafruit_SGP30.h
Normal file → Executable file
@ -42,6 +42,7 @@ class Adafruit_SGP30 {
|
|||||||
|
|
||||||
boolean getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base);
|
boolean getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base);
|
||||||
boolean setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base);
|
boolean setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base);
|
||||||
|
boolean setHumidity(uint32_t absolute_humidity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last measurement of the IAQ-calculated Total Volatile Organic Compounds in ppb. This value is set when you call {@link IAQmeasure()}
|
* The last measurement of the IAQ-calculated Total Volatile Organic Compounds in ppb. This value is set when you call {@link IAQmeasure()}
|
0
lib/Adafruit_SGP30-1.0.0.13/README.md → lib/Adafruit_SGP30-1.0.3/README.md
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/README.md → lib/Adafruit_SGP30-1.0.3/README.md
Normal file → Executable file
16
lib/Adafruit_SGP30-1.0.0.13/examples/sgp30test/sgp30test.ino → lib/Adafruit_SGP30-1.0.3/examples/sgp30test/sgp30test.ino
Normal file → Executable file
16
lib/Adafruit_SGP30-1.0.0.13/examples/sgp30test/sgp30test.ino → lib/Adafruit_SGP30-1.0.3/examples/sgp30test/sgp30test.ino
Normal file → Executable file
@ -3,6 +3,17 @@
|
|||||||
|
|
||||||
Adafruit_SGP30 sgp;
|
Adafruit_SGP30 sgp;
|
||||||
|
|
||||||
|
/* return absolute humidity [mg/m^3] with approximation formula
|
||||||
|
* @param temperature [°C]
|
||||||
|
* @param humidity [%RH]
|
||||||
|
*/
|
||||||
|
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
|
||||||
|
// approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
|
||||||
|
const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
|
||||||
|
const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
|
||||||
|
return absoluteHumidityScaled;
|
||||||
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
Serial.println("SGP30 test");
|
Serial.println("SGP30 test");
|
||||||
@ -22,6 +33,11 @@ void setup() {
|
|||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
void loop() {
|
void loop() {
|
||||||
|
// If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humditiy compensation for the air quality signals
|
||||||
|
//float temperature = 22.1; // [°C]
|
||||||
|
//float humidity = 45.2; // [%RH]
|
||||||
|
//sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));
|
||||||
|
|
||||||
if (! sgp.IAQmeasure()) {
|
if (! sgp.IAQmeasure()) {
|
||||||
Serial.println("Measurement failed");
|
Serial.println("Measurement failed");
|
||||||
return;
|
return;
|
2
lib/Adafruit_SGP30-1.0.0.13/library.properties → lib/Adafruit_SGP30-1.0.3/library.properties
Normal file → Executable file
2
lib/Adafruit_SGP30-1.0.0.13/library.properties → lib/Adafruit_SGP30-1.0.3/library.properties
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
name=Adafruit SGP30 Sensor
|
name=Adafruit SGP30 Sensor
|
||||||
version=1.0.2
|
version=1.0.3
|
||||||
author=Adafruit
|
author=Adafruit
|
||||||
maintainer=Adafruit <info@adafruit.com>
|
maintainer=Adafruit <info@adafruit.com>
|
||||||
sentence=This is an Arduino library for the Adafruit SGP30 Gas / Air Quality Sensor
|
sentence=This is an Arduino library for the Adafruit SGP30 Gas / Air Quality Sensor
|
0
lib/Adafruit_SGP30-1.0.0.13/license.txt → lib/Adafruit_SGP30-1.0.3/license.txt
Normal file → Executable file
0
lib/Adafruit_SGP30-1.0.0.13/license.txt → lib/Adafruit_SGP30-1.0.3/license.txt
Normal file → Executable file
10
platformio.ini
Normal file → Executable file
10
platformio.ini
Normal file → Executable file
@ -65,9 +65,9 @@ build_flags = ${esp82xx_defaults.build_flags}
|
|||||||
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||||
-DVTABLES_IN_FLASH
|
-DVTABLES_IN_FLASH
|
||||||
|
|
||||||
[core_2_5_1]
|
[core_2_5_2]
|
||||||
; *** Esp8266 core for Arduino version 2.5.1
|
; *** Esp8266 core for Arduino version 2.5.2
|
||||||
platform = espressif8266@~2.1.1
|
platform = espressif8266@~2.2.0
|
||||||
build_flags = ${esp82xx_defaults.build_flags}
|
build_flags = ${esp82xx_defaults.build_flags}
|
||||||
-Wl,-Teagle.flash.1m.ld
|
-Wl,-Teagle.flash.1m.ld
|
||||||
; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473
|
; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473
|
||||||
@ -133,8 +133,8 @@ build_flags = ${esp82xx_defaults.build_flags}
|
|||||||
;build_flags = ${core_2_3_0.build_flags}
|
;build_flags = ${core_2_3_0.build_flags}
|
||||||
;platform = ${core_2_4_2.platform}
|
;platform = ${core_2_4_2.platform}
|
||||||
;build_flags = ${core_2_4_2.build_flags}
|
;build_flags = ${core_2_4_2.build_flags}
|
||||||
platform = ${core_2_5_1.platform}
|
platform = ${core_2_5_2.platform}
|
||||||
build_flags = ${core_2_5_1.build_flags}
|
build_flags = ${core_2_5_2.build_flags}
|
||||||
;platform = ${core_stage.platform}
|
;platform = ${core_stage.platform}
|
||||||
;build_flags = ${core_stage.build_flags}
|
;build_flags = ${core_stage.build_flags}
|
||||||
|
|
||||||
|
621
scripter.md
Normal file
621
scripter.md
Normal file
@ -0,0 +1,621 @@
|
|||||||
|
**Script Language for Tasmota**
|
||||||
|
|
||||||
|
As an alternative to rules. (about 14,2k flash size, variable ram size)
|
||||||
|
|
||||||
|
In submenu Configuration =\> edit script
|
||||||
|
1535 bytes max script size (uses rules buffer)
|
||||||
|
|
||||||
|
to enable:
|
||||||
|
\#define USE_SCRIPT
|
||||||
|
\#undef USE_RULES
|
||||||
|
|
||||||
|
|
||||||
|
Up to 50 variables (45 numeric and 5 strings, maybe changed by #define)
|
||||||
|
Freely definable variable names (all names are intentionally case sensitive)
|
||||||
|
Nested if,then,else up to a level of 8
|
||||||
|
Math operators **+,-,\*,/,%,&,|,^**
|
||||||
|
all operators may be used in the op= form e.g. **+=**
|
||||||
|
Left right evaluation with optional brackets
|
||||||
|
all numbers are float
|
||||||
|
e.g. temp=hum\*(100/37.5)+temp-(timer\*hum%10)
|
||||||
|
no spaces allowed between math operations
|
||||||
|
Comparison operators **==,!=,\>,\>=,<,<=**
|
||||||
|
**and** , **or** support
|
||||||
|
|
||||||
|
strings support **+** and **+=** operators
|
||||||
|
string comparison **==,!=**
|
||||||
|
max string size = 19 chars (default, can be increased or decreased by optional >D parameter)
|
||||||
|
|
||||||
|
**Comments** start with **;**
|
||||||
|
|
||||||
|
**Sections** defined:
|
||||||
|
|
||||||
|
>**\>D ssize**
|
||||||
|
ssize = optional max stringsize (default=19)
|
||||||
|
define and init variables here, must be the first section, no other code allowed
|
||||||
|
**p:**vname specifies permanent vars (the number of permanent vars is limited by tasmota rules space (50 bytes)
|
||||||
|
numeric var=4 bytes, string var=lenght of string+1)
|
||||||
|
**t:**vname specifies countdown timers, if >0 they are decremented in seconds until zero is reached. see example below
|
||||||
|
**i:**vname specifies auto increment counters if >=0 (in seconds)
|
||||||
|
**m:**vname specifies a median filter variable with 5 entries (for elimination of outliers)
|
||||||
|
**M:**vname specifies a moving average filter variable with 8 entries (for smoothing data)
|
||||||
|
(max 5 filters in total m+M)
|
||||||
|
|
||||||
|
>all variable names length taken together may not exceed 256 characters, so keep variable names as short as possible.
|
||||||
|
memory is dynamically allocated as a result of the D section.
|
||||||
|
copying a string to a number or reverse is supported
|
||||||
|
|
||||||
|
>**\>B**
|
||||||
|
executed on BOOT time
|
||||||
|
|
||||||
|
>**\>T**
|
||||||
|
executed on teleperiod time (**SENSOR** and **STATE**), get tele vars only in this section
|
||||||
|
|
||||||
|
>**\>S**
|
||||||
|
executed every second
|
||||||
|
|
||||||
|
>**\>E**
|
||||||
|
executed e.g. on power change and mqtt **RESULT**
|
||||||
|
|
||||||
|
>**\>R**
|
||||||
|
executed on restart, p vars are saved automatically after this call
|
||||||
|
|
||||||
|
|
||||||
|
special variables (read only):
|
||||||
|
|
||||||
|
>**upsecs** = seconds since start
|
||||||
|
**uptime** = minutes since start
|
||||||
|
**time** = minutes since midnight
|
||||||
|
**sunrise** = sunrise minutes since midnight
|
||||||
|
**sunset** = sunset minutes since midnight
|
||||||
|
**tper** = teleperiod (may be set also)
|
||||||
|
**tstamp** = timestamp (local date and time)
|
||||||
|
**topic** = mqtt topic
|
||||||
|
**gtopic** = mqtt group topic
|
||||||
|
**prefixn** = prefix n = 1-3
|
||||||
|
**pwr[x]** = tasmota power state (x = 1-N)
|
||||||
|
**sw[x]** = tasmota switch state (x = 1-N)
|
||||||
|
>**pin[x]** = gpio pin level (x = 0-16)
|
||||||
|
**pn[x]** = pin number for sensor code x, 99 if none
|
||||||
|
**pd[x]** = defined sensor for gpio pin nr x none=999
|
||||||
|
**gtmp** = global temperature
|
||||||
|
**ghum** = global humidity
|
||||||
|
**gprs** = global pressure
|
||||||
|
**pow(x y)** = calculates the power of x^y
|
||||||
|
**med(n x)** = calculates a 5 value median filter of x (2 filters possible n=0,1)
|
||||||
|
**int(x)** = gets the integer part of x (like floor)
|
||||||
|
**hn(x)** = converts x (0..255) zu a hex nibble string
|
||||||
|
**mqtts** = state of mqtt disconnected=0, connected>0
|
||||||
|
**wifis** = state of wifi disconnected=0, connected>0
|
||||||
|
|
||||||
|
>**hours** = hours
|
||||||
|
**mins** = mins
|
||||||
|
**secs** = seconds
|
||||||
|
**day** = day of month
|
||||||
|
**wday** = day of week
|
||||||
|
**month** = month
|
||||||
|
**year** = year
|
||||||
|
|
||||||
|
these variables are cleared after reading true
|
||||||
|
>**chg[var]** = true if a variables value was changed (numeric vars only)
|
||||||
|
**upd[var]** = true if a variable was updated
|
||||||
|
**boot** = true on BOOT
|
||||||
|
**tinit** = true on time init
|
||||||
|
**tset** = true on time set
|
||||||
|
**mqttc** = true on mqtt connect
|
||||||
|
**mqttd** = true on mqtt disconnect
|
||||||
|
**wific** = true on wifi connect
|
||||||
|
**wifid** = true on wifi disconnect
|
||||||
|
|
||||||
|
system vars (for debugging)
|
||||||
|
>**stack** = stack size
|
||||||
|
**heap** = heap size
|
||||||
|
**ram** = used ram size
|
||||||
|
**slen** = script length
|
||||||
|
**micros** = running microseconds
|
||||||
|
**millis** = running milliseconds
|
||||||
|
**loglvl** = loglevel of script cmds, may be set also
|
||||||
|
|
||||||
|
remarks:
|
||||||
|
if you define a variable with the same name as a special
|
||||||
|
variable that special variable is discarded
|
||||||
|
|
||||||
|
|
||||||
|
**Tasmota** cmds start with **=\>**
|
||||||
|
within cmds you can replace text with variables with **%varname%**
|
||||||
|
a single percent sign must be given as **%%**
|
||||||
|
|
||||||
|
**special** cmds:
|
||||||
|
|
||||||
|
>**=\> print** prints to info log for debugging
|
||||||
|
|
||||||
|
to save code space nearly no error messages are provided. However it is taken care of that at least it should not crash on syntax errors.
|
||||||
|
if a variable does not exist a **???** is given on commands
|
||||||
|
if a **SENSOR** or **STATUS** or **RESULT** message or a var does not exist the destination variable is NOT updated.
|
||||||
|
|
||||||
|
2 possibilities for conditionals:
|
||||||
|
>**if** a==b
|
||||||
|
**and** x==y
|
||||||
|
**or** k==i
|
||||||
|
**then** => do this
|
||||||
|
**else** => do that
|
||||||
|
**endif**
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
>**if** a==b
|
||||||
|
**and** x==y
|
||||||
|
**or** k==i **{**
|
||||||
|
=> do this
|
||||||
|
**} else {**
|
||||||
|
=> do that
|
||||||
|
**}**
|
||||||
|
|
||||||
|
you may NOT mix both methods
|
||||||
|
|
||||||
|
also possible e.g.
|
||||||
|
|
||||||
|
>if var1-var2==var3*var4
|
||||||
|
then
|
||||||
|
|
||||||
|
remarks:
|
||||||
|
the last closing bracket must be on a single line
|
||||||
|
the condition may not be enclosed in brackets
|
||||||
|
|
||||||
|
>**break** exits a section or terminates a for next loop
|
||||||
|
**dprecx** sets decimal precision to x (0-9)
|
||||||
|
**svars** save permanent vars
|
||||||
|
**delay(x)** pauses x milliseconds (should be as short as possible)
|
||||||
|
**spin(x m)** set gpio pin x (0-16) to value m (0,1) only the last bit is used, so even values set the pin to zero and uneven values set the pin to 1
|
||||||
|
**spinm(x m)** set pin mode gpio pin x (0-16) to mode m (input=0,output=1)
|
||||||
|
|
||||||
|
>**#name** names a subroutine, subroutines are called with **=#name**
|
||||||
|
**#name(param)** names a subroutines with a parameter is called with **=#name(param)**
|
||||||
|
subroutines end with the next '#' or '>' line or break, may be nested
|
||||||
|
params can be numbers or strings and on mismatch are converted
|
||||||
|
|
||||||
|
>**for var from to inc**
|
||||||
|
**next**
|
||||||
|
specifies a for next loop, (loop count must not be less then 1)
|
||||||
|
|
||||||
|
>**switch x**
|
||||||
|
**case a**
|
||||||
|
**case b**
|
||||||
|
**ends**
|
||||||
|
specifies a switch case selector
|
||||||
|
|
||||||
|
**konsole script cmds**
|
||||||
|
>**script 1 or 0** switch script on or off
|
||||||
|
**script >cmdline** executes the script cmdline
|
||||||
|
can be used e.g. to set variables e.g. **script >mintmp=15**
|
||||||
|
more then one line may be executed seperated by a semicolon e.g. **script >mintmp=15;maxtemp=40**
|
||||||
|
script itself cant be set because the size would not fit the mqtt buffers
|
||||||
|
|
||||||
|
***example script***
|
||||||
|
meant to show some of the possibilities
|
||||||
|
(actually this code ist too large)
|
||||||
|
|
||||||
|
**\>D**
|
||||||
|
; define all vars here
|
||||||
|
p:mintmp=10 (p:means permanent)
|
||||||
|
p:maxtmp=30
|
||||||
|
t:timer1=30 (t:means countdown timer)
|
||||||
|
t:mt=0
|
||||||
|
i:count=0 (i:means auto counter)
|
||||||
|
hello="hello world"
|
||||||
|
string="xxx"
|
||||||
|
url="[192.168.178.86]"
|
||||||
|
hum=0
|
||||||
|
temp=0
|
||||||
|
timer=0
|
||||||
|
dimmer=0
|
||||||
|
sw=0
|
||||||
|
rssi=0
|
||||||
|
param=0
|
||||||
|
|
||||||
|
col=""
|
||||||
|
ocol=""
|
||||||
|
chan1=0
|
||||||
|
chan2=0
|
||||||
|
chan3=0
|
||||||
|
|
||||||
|
ahum=0
|
||||||
|
atemp=0
|
||||||
|
tcnt=0
|
||||||
|
hour=0
|
||||||
|
state=1
|
||||||
|
m:med5=0
|
||||||
|
M:movav=0
|
||||||
|
|
||||||
|
**\>B**
|
||||||
|
|
||||||
|
string=hello+"how are you?"
|
||||||
|
=\>print BOOT executed
|
||||||
|
=\>print %hello%
|
||||||
|
=\>mp3track 1
|
||||||
|
|
||||||
|
; list gpio pin definitions
|
||||||
|
for cnt 0 16 1
|
||||||
|
tmp=pd[cnt]
|
||||||
|
=>print %cnt% = %tmp%
|
||||||
|
next
|
||||||
|
|
||||||
|
; get gpio pin for relais 1
|
||||||
|
tmp=pn[21]
|
||||||
|
=>print relais 1 is on pin %tmp%
|
||||||
|
|
||||||
|
; pulse relais over raw gpio
|
||||||
|
spin(tmp 1)
|
||||||
|
delay(100)
|
||||||
|
spin(tmp 0)
|
||||||
|
|
||||||
|
; raw pin level
|
||||||
|
=>print level of gpio1 %pin[1]%
|
||||||
|
|
||||||
|
; pulse over tasmota cmd
|
||||||
|
=>power 1
|
||||||
|
delay(100)
|
||||||
|
=>power 0
|
||||||
|
|
||||||
|
**\>T**
|
||||||
|
|
||||||
|
hum=BME280#Humidity
|
||||||
|
temp=BME280#Temperature
|
||||||
|
rssi=Wifi#RSSI
|
||||||
|
string=SleepMode
|
||||||
|
|
||||||
|
; add to median filter
|
||||||
|
median=temp
|
||||||
|
; add to moving average filter
|
||||||
|
movav=hum
|
||||||
|
|
||||||
|
; show filtered results
|
||||||
|
=>print %median% %movav%
|
||||||
|
|
||||||
|
if chg[rssi]>0
|
||||||
|
then =>print rssi changed to %rssi%
|
||||||
|
endif
|
||||||
|
|
||||||
|
if temp\>30
|
||||||
|
and hum\>70
|
||||||
|
then =\>print damn hot!
|
||||||
|
endif
|
||||||
|
|
||||||
|
**\>S**
|
||||||
|
|
||||||
|
; every second but not completely reliable time here
|
||||||
|
; use upsecs and uptime or best t: for reliable timers
|
||||||
|
|
||||||
|
; call subrountines with parameters
|
||||||
|
=#sub1("hallo")
|
||||||
|
=#sub2(999)
|
||||||
|
|
||||||
|
; stop timer after expired
|
||||||
|
if timer1==0
|
||||||
|
then timer1=-1
|
||||||
|
=>print timer1 expired
|
||||||
|
endif
|
||||||
|
|
||||||
|
; auto counter with restart
|
||||||
|
if count>=10
|
||||||
|
then =>print 10 seconds over
|
||||||
|
count=0
|
||||||
|
endif
|
||||||
|
|
||||||
|
if upsecs%5==0
|
||||||
|
then =\>print %upsecs% (every 5 seconds)
|
||||||
|
endif
|
||||||
|
|
||||||
|
; not recommended for reliable timers
|
||||||
|
timer+=1
|
||||||
|
if timer\>=5
|
||||||
|
then =\>print 5 seconds over (may be)
|
||||||
|
timer=0
|
||||||
|
endif
|
||||||
|
|
||||||
|
dimmer+=1
|
||||||
|
if dimmer\>100
|
||||||
|
then dimmer=0
|
||||||
|
endif
|
||||||
|
|
||||||
|
=\>dimmer %dimmer%
|
||||||
|
=\>WebSend %url% dimmer %dimmer%
|
||||||
|
|
||||||
|
; show on display
|
||||||
|
dprec0
|
||||||
|
=\>displaytext [c1l1f1s2p20] dimmer=%dimmer%
|
||||||
|
|
||||||
|
=\>print %upsecs% %uptime% %time% %sunrise% %sunset% %tstamp%
|
||||||
|
|
||||||
|
if time\>sunset
|
||||||
|
and time< sunrise
|
||||||
|
then
|
||||||
|
; night time
|
||||||
|
if pwr[1]==0
|
||||||
|
then =\>power1 1
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
; day time
|
||||||
|
if pwr[1]\>0
|
||||||
|
then =\>power1 0
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
; clr display on boot
|
||||||
|
if boot\>0
|
||||||
|
then =\>displaytext [z]
|
||||||
|
endif
|
||||||
|
|
||||||
|
; frost warning
|
||||||
|
if temp<0
|
||||||
|
and mt<=0
|
||||||
|
then =#sendmail("frost alert")
|
||||||
|
; alarm only every 5 minutes
|
||||||
|
mt=300
|
||||||
|
=>mp3track 2
|
||||||
|
endif
|
||||||
|
|
||||||
|
; var has been updated
|
||||||
|
if upd[hello]>0
|
||||||
|
then =>print %hello%
|
||||||
|
endif
|
||||||
|
|
||||||
|
; send to Thingspeak every 60 seconds
|
||||||
|
; average data in between
|
||||||
|
if upsecs%60==0
|
||||||
|
then
|
||||||
|
ahum/=tcnt
|
||||||
|
atemp/=tcnt
|
||||||
|
=>Websend [184.106.153.149:80]/update?key=PYUZMVWCICBW492&field1=%atemp%&field2=%ahum%
|
||||||
|
tcnt=0
|
||||||
|
atemp=0
|
||||||
|
ahum=0
|
||||||
|
else
|
||||||
|
ahum+=hum
|
||||||
|
atemp+=temp
|
||||||
|
tcnt+=1
|
||||||
|
endif
|
||||||
|
|
||||||
|
hour=int(time/60)
|
||||||
|
if chg[hour]>0
|
||||||
|
then
|
||||||
|
; exactly every hour
|
||||||
|
=>print full hour reached
|
||||||
|
endif
|
||||||
|
|
||||||
|
if time>5 {
|
||||||
|
=>print more then 5 minutes after midnight
|
||||||
|
} else {
|
||||||
|
=>print less then 5 minutes after midnight
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
; publish abs hum every teleperiod time
|
||||||
|
if mqtts>0
|
||||||
|
and upsecs%tper==0
|
||||||
|
then
|
||||||
|
; calc abs humidity
|
||||||
|
tmp=pow(2.718281828 (17.67\*temp)/(temp+243.5))
|
||||||
|
tmp=(6.112\*tmp\*hum\*18.01534)/((273.15+temp)\*8.31447215)
|
||||||
|
; publish median filtered value
|
||||||
|
=>Publish tele/%topic%/SENSOR {"Script":{"abshum":%med(0 tmp)%}}
|
||||||
|
endif
|
||||||
|
|
||||||
|
;switch case state machine
|
||||||
|
switch state
|
||||||
|
case 1
|
||||||
|
=>print state=%state% , start
|
||||||
|
state+=1
|
||||||
|
case 2
|
||||||
|
=>print state=%state%
|
||||||
|
state+=1
|
||||||
|
case 3
|
||||||
|
=>print state=%state% , reset
|
||||||
|
state=1
|
||||||
|
ends
|
||||||
|
|
||||||
|
|
||||||
|
; subroutines
|
||||||
|
\#sub1(string)
|
||||||
|
=>print sub1: %string%
|
||||||
|
\#sub2(param)
|
||||||
|
=>print sub2: %param%
|
||||||
|
|
||||||
|
\#sendmail(string)
|
||||||
|
=>sendmail [smtp.gmail.com:465:user:passwd:<sender@gmail.de>:<rec@gmail.de>:alarm] %string%
|
||||||
|
|
||||||
|
**\>E**
|
||||||
|
=\>print event executed!
|
||||||
|
|
||||||
|
|
||||||
|
; check if switch changed state
|
||||||
|
sw=sw[1]
|
||||||
|
if chg[sw]>0
|
||||||
|
then =\>power1 %sw%
|
||||||
|
endif
|
||||||
|
|
||||||
|
hello="event occured"
|
||||||
|
|
||||||
|
; check for Color change (Color is a string)
|
||||||
|
col=Color
|
||||||
|
; color change needs 2 string vars
|
||||||
|
if col!=ocol
|
||||||
|
then ocol=col
|
||||||
|
=>print color changed %col%
|
||||||
|
endif
|
||||||
|
|
||||||
|
; or check change of color channels
|
||||||
|
chan1=Channel[1]
|
||||||
|
chan2=Channel[2]
|
||||||
|
chan3=Channel[3]
|
||||||
|
|
||||||
|
if chg[chan1]>0
|
||||||
|
or chg[chan2]>0
|
||||||
|
or chg[chan3]>0
|
||||||
|
then => color has changed
|
||||||
|
endif
|
||||||
|
|
||||||
|
; compose color string for red
|
||||||
|
col=hn(255)+hn(0)+hn(0)
|
||||||
|
=>color %col%
|
||||||
|
|
||||||
|
**\>R**
|
||||||
|
=\>print restarting now
|
||||||
|
|
||||||
|
**a real example**
|
||||||
|
epaper 29 with sgp30 and bme280
|
||||||
|
some vars are set from iobroker
|
||||||
|
DisplayText substituted to save script space
|
||||||
|
\>D
|
||||||
|
hum=0
|
||||||
|
temp=0
|
||||||
|
press=0
|
||||||
|
ahum=0
|
||||||
|
tvoc=0
|
||||||
|
eco2=0
|
||||||
|
zwz=0
|
||||||
|
wr1=0
|
||||||
|
wr2=0
|
||||||
|
wr3=0
|
||||||
|
otmp=0
|
||||||
|
pwl=0
|
||||||
|
tmp=0
|
||||||
|
DT="DisplayText"
|
||||||
|
; preset units in case they are not available
|
||||||
|
punit="hPa"
|
||||||
|
tunit="C"
|
||||||
|
|
||||||
|
\>B
|
||||||
|
;reset auto draw
|
||||||
|
=>%DT% [zD0]
|
||||||
|
;clr display and draw a frame
|
||||||
|
=>%DT% [x0y20h296x0y40h296]
|
||||||
|
|
||||||
|
\>T
|
||||||
|
; get tele vars
|
||||||
|
temp=BME280#Temperature
|
||||||
|
hum=BME280#Humidity
|
||||||
|
press=BME280#Pressure
|
||||||
|
tvoc=SGP30#TVOC
|
||||||
|
eco2=SGP30#eCO2
|
||||||
|
ahum=SGP30#aHumidity
|
||||||
|
tunit=TempUnit
|
||||||
|
punit=PressureUnit
|
||||||
|
|
||||||
|
\>S
|
||||||
|
// update display every teleperiod time
|
||||||
|
if upsecs%tper==0
|
||||||
|
then
|
||||||
|
dprec2
|
||||||
|
=>%DT% [f1p7x0y5]%temp% %tunit%
|
||||||
|
=>%DT% [p5x70y5]%hum% %%[x250y5t]
|
||||||
|
=>%DT% [p11x140y5]%press% %punit%
|
||||||
|
=>%DT% [p10x30y25]TVOC: %tvoc% ppb
|
||||||
|
=>%DT% [p10x160y25]eCO2: %eco2% ppm
|
||||||
|
=>%DT% [p10c26l5]ahum: %ahum% g^m3
|
||||||
|
|
||||||
|
dprec0
|
||||||
|
=>%DT% [p25c1l5]WR 1 (Dach) : %wr1% W
|
||||||
|
=>%DT% [p25c1l6]WR 2 (Garage): %-wr3% W
|
||||||
|
=>%DT% [p25c1l7]WR 3 (Garten): %-wr2% W
|
||||||
|
=>%DT% [p25c1l8]Aussentemperatur: %otmp% C
|
||||||
|
=>%DT% [x170y95r120:30f2p6x185y100] %pwl% %%
|
||||||
|
; now update screen
|
||||||
|
=>%DT% [d]
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
\>E
|
||||||
|
|
||||||
|
\>R
|
||||||
|
|
||||||
|
**another real example**
|
||||||
|
ILI 9488 color LCD Display shows various energy graphs
|
||||||
|
display switches on and off with proximity sensor
|
||||||
|
BMP280 and vl5310x
|
||||||
|
some vars are set from iobroker
|
||||||
|
|
||||||
|
**>D**
|
||||||
|
temp=0
|
||||||
|
press=0
|
||||||
|
zwz=0
|
||||||
|
wr1=0
|
||||||
|
wr2=0
|
||||||
|
wr3=0
|
||||||
|
otmp=0
|
||||||
|
pwl=0
|
||||||
|
tmp=0
|
||||||
|
dist=0
|
||||||
|
DT="DisplayText"
|
||||||
|
punit="hPa"
|
||||||
|
tunit="C"
|
||||||
|
hour=0
|
||||||
|
|
||||||
|
**>B**
|
||||||
|
=>%DT% [z]
|
||||||
|
|
||||||
|
// define 2 graphs, 2. has 3 tracks
|
||||||
|
=>%DT% [zCi1G2656:5:20:400:80:1440:-5000:5000:3Ci7f3x410y20]+5000 W[x410y95]-5000 W [Ci7f1x70y3] Zweirichtungsz~80hler - 24 Stunden
|
||||||
|
=>%DT% [Ci1G2657:5:120:400:80:1440:0:5000:3Ci7f3x410y120]+5000 W[x410y195]0 W [Ci7f1x70y103] Wechselrichter 1-3 - 24 Stunden
|
||||||
|
=>%DT% [Ci1G2658:5:120:400:80:1440:0:5000:16][Ci1G2659:5:120:400:80:1440:0:5000:5]
|
||||||
|
=>%DT% [f1s1b0:260:260:100:50:2:11:4:2:Rel 1:b1:370:260:100:50:2:11:4:2:Dsp off:]
|
||||||
|
=>mp3volume 100
|
||||||
|
=>mp3track 4
|
||||||
|
|
||||||
|
**>T**
|
||||||
|
; get some tele vars
|
||||||
|
temp=BMP280#Temperature
|
||||||
|
press=BMP280#Pressure
|
||||||
|
tunit=TempUnit
|
||||||
|
punit=PressureUnit
|
||||||
|
dist=VL53L0X#Distance
|
||||||
|
|
||||||
|
; check proximity sensor to switch display on/off
|
||||||
|
; to prevent burn in
|
||||||
|
if dist>300
|
||||||
|
then
|
||||||
|
if pwr[2]>0
|
||||||
|
then
|
||||||
|
=>power2 0
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
if pwr[2]==0
|
||||||
|
then
|
||||||
|
=>power2 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
**>S**
|
||||||
|
; update graph every teleperiod
|
||||||
|
if upsecs%tper==0
|
||||||
|
then
|
||||||
|
dprec2
|
||||||
|
=>%DT% [f1Ci3x40y260w30Ci1]
|
||||||
|
=>%DT% [Ci7x120y220t]
|
||||||
|
=>%DT% [Ci7x180y220T]
|
||||||
|
=>%DT% [Ci7p8x120y240]%temp% %tunit%
|
||||||
|
=>%DT% [Ci7x120y260]%press% %punit%
|
||||||
|
=>%DT% [Ci7x120y280]%dist% mm
|
||||||
|
dprec0
|
||||||
|
=>%DT% [g0:%zwz%g1:%wr1%g2:%-wr2%g3:%-wr3%]
|
||||||
|
if zwz>0
|
||||||
|
then
|
||||||
|
=>%DT% [p-8x410y55Ci2Bi0]%zwz% W
|
||||||
|
else
|
||||||
|
=>%DT% [p-8x410y55Ci3Bi0]%zwz% W
|
||||||
|
endif
|
||||||
|
=>%DT% [p-8x410y140Ci3Bi0]%wr1% W
|
||||||
|
=>%DT% [p-8x410y155Ci16Bi0]%-wr2% W
|
||||||
|
=>%DT% [p-8x410y170Ci5Bi0]%-wr3% W
|
||||||
|
endif
|
||||||
|
|
||||||
|
; chime every full hour
|
||||||
|
hour=int(time/60)
|
||||||
|
if chg[hour]>0
|
||||||
|
then =>mp3track 4
|
||||||
|
endif
|
||||||
|
|
||||||
|
**>E**
|
||||||
|
|
||||||
|
**>R**
|
@ -513,6 +513,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Бутон" // Suffix "1"
|
#define D_SENSOR_BUTTON "Бутон" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Реле" // Suffix "1i"
|
#define D_SENSOR_RELAY "Реле" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Брояч" // Suffix "1"
|
#define D_SENSOR_COUNTER "Брояч" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -578,6 +579,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Tlačítko" // Suffix "1"
|
#define D_SENSOR_BUTTON "Tlačítko" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1",
|
#define D_SENSOR_PWM "PWM" // Suffix "1",
|
||||||
#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1"
|
#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Botón" // Suffix "1"
|
#define D_SENSOR_BUTTON "Botón" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Contador" // Suffix "1"
|
#define D_SENSOR_COUNTER "Contador" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IR Rx"
|
#define D_SENSOR_IRRECV "IR Rx"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Bouton" // Suffix "1"
|
#define D_SENSOR_BUTTON "Bouton" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relais" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relais" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "LED" // Suffix "1i"
|
#define D_SENSOR_LED "LED" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Compteur" // Suffix "1"
|
#define D_SENSOR_COUNTER "Compteur" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "RécptIR"
|
#define D_SENSOR_IRRECV "RécptIR"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "לחצן" // Suffix "1"
|
#define D_SENSOR_BUTTON "לחצן" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "ממסר" // Suffix "1i"
|
#define D_SENSOR_RELAY "ממסר" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "לד" // Suffix "1i"
|
#define D_SENSOR_LED "לד" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "מונה" // Suffix "1"
|
#define D_SENSOR_COUNTER "מונה" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Gomb" // Suffix "1"
|
#define D_SENSOR_BUTTON "Gomb" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "LED" // Suffix "1i"
|
#define D_SENSOR_LED "LED" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Számláló" // Suffix "1"
|
#define D_SENSOR_COUNTER "Számláló" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IR vevő"
|
#define D_SENSOR_IRRECV "IR vevő"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relais" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relais" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Teller" // Suffix "1"
|
#define D_SENSOR_COUNTER "Teller" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Przyci" // Suffix "1"
|
#define D_SENSOR_BUTTON "Przyci" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Przek" // Suffix "1i"
|
#define D_SENSOR_RELAY "Przek" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Liczni" // Suffix "1"
|
#define D_SENSOR_COUNTER "Liczni" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Botão" // Suffix "1"
|
#define D_SENSOR_BUTTON "Botão" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Contador" // Suffix "1"
|
#define D_SENSOR_COUNTER "Contador" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Botão" // Suffix "1"
|
#define D_SENSOR_BUTTON "Botão" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Contador" // Suffix "1"
|
#define D_SENSOR_COUNTER "Contador" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Кнопка" // Suffix "1"
|
#define D_SENSOR_BUTTON "Кнопка" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Реле" // Suffix "1i"
|
#define D_SENSOR_RELAY "Реле" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Счетчик" // Suffix "1"
|
#define D_SENSOR_COUNTER "Счетчик" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Tlačidlo" // Suffix "1"
|
#define D_SENSOR_BUTTON "Tlačidlo" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relé" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1",
|
#define D_SENSOR_PWM "PWM" // Suffix "1",
|
||||||
#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1"
|
#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Knapp" // Suffix "1"
|
#define D_SENSOR_BUTTON "Knapp" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relä" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relä" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Räknare" // Suffix "1"
|
#define D_SENSOR_COUNTER "Räknare" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Кнопка" // Suffix "1"
|
#define D_SENSOR_BUTTON "Кнопка" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Реле" // Suffix "1i"
|
#define D_SENSOR_RELAY "Реле" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Лічильник" // Suffix "1"
|
#define D_SENSOR_COUNTER "Лічильник" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -512,6 +512,7 @@
|
|||||||
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
#define D_SENSOR_BUTTON "Button" // Suffix "1"
|
||||||
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
|
||||||
#define D_SENSOR_LED "Led" // Suffix "1i"
|
#define D_SENSOR_LED "Led" // Suffix "1i"
|
||||||
|
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
|
||||||
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
#define D_SENSOR_PWM "PWM" // Suffix "1"
|
||||||
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
|
||||||
#define D_SENSOR_IRRECV "IRrecv"
|
#define D_SENSOR_IRRECV "IRrecv"
|
||||||
@ -577,6 +578,7 @@
|
|||||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||||
|
#define D_SENSOR_ARIRFSEL "ALux IrSel"
|
||||||
#define D_SENSOR_TXD "Serial Tx"
|
#define D_SENSOR_TXD "Serial Tx"
|
||||||
#define D_SENSOR_RXD "Serial Rx"
|
#define D_SENSOR_RXD "Serial Rx"
|
||||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||||
|
@ -275,7 +275,8 @@
|
|||||||
#define USE_WEBSERVER // Enable web server and Wifi Manager (+66k code, +8k mem)
|
#define USE_WEBSERVER // Enable web server and Wifi Manager (+66k code, +8k mem)
|
||||||
#define WEB_PORT 80 // Web server Port for User and Admin mode
|
#define WEB_PORT 80 // Web server Port for User and Admin mode
|
||||||
#define WEB_USERNAME "admin" // Web server Admin mode user name
|
#define WEB_USERNAME "admin" // Web server Admin mode user name
|
||||||
#define USE_EMULATION // Enable Belkin WeMo and Hue Bridge emulation for Alexa (+22k code, +2k mem)
|
#define USE_EMULATION_HUE // Enable Hue Bridge emulation for Alexa (+14k code, +2k mem common)
|
||||||
|
#define USE_EMULATION_WEMO // Enable Belkin WeMo emulation for Alexa (+6k code, +2k mem common)
|
||||||
|
|
||||||
// -- mDNS ----------------------------------------
|
// -- mDNS ----------------------------------------
|
||||||
#define USE_DISCOVERY // Enable mDNS for the following services (+8k code, +0.3k mem)
|
#define USE_DISCOVERY // Enable mDNS for the following services (+8k code, +0.3k mem)
|
||||||
@ -288,8 +289,11 @@
|
|||||||
#define USE_SUNRISE // Add support for Sunrise and sunset tools (+16k)
|
#define USE_SUNRISE // Add support for Sunrise and sunset tools (+16k)
|
||||||
#define SUNRISE_DAWN_ANGLE DAWN_NORMAL // Select desired Dawn Angle from (DAWN_NORMAL, DAWN_CIVIL, DAWN_NAUTIC, DAWN_ASTRONOMIC)
|
#define SUNRISE_DAWN_ANGLE DAWN_NORMAL // Select desired Dawn Angle from (DAWN_NORMAL, DAWN_CIVIL, DAWN_NAUTIC, DAWN_ASTRONOMIC)
|
||||||
|
|
||||||
// -- Rules ---------------------------------------
|
// -- Rules or Script ----------------------------
|
||||||
#define USE_RULES // Add support for rules (+4k4 code)
|
// Select none or only one of the below defines
|
||||||
|
#define USE_RULES // Add support for rules (+8k code)
|
||||||
|
//#define USE_SCRIPT // Add support for script (+15k code)
|
||||||
|
|
||||||
// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)
|
// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)
|
||||||
// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code)
|
// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code)
|
||||||
|
|
||||||
@ -342,6 +346,7 @@
|
|||||||
// #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem)
|
// #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem)
|
||||||
// #define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code)
|
// #define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code)
|
||||||
// #define USE_SCD30 // Enable Sensiron SCd30 CO2 sensor (I2C address 0x61) (+3k3 code)
|
// #define USE_SCD30 // Enable Sensiron SCd30 CO2 sensor (I2C address 0x61) (+3k3 code)
|
||||||
|
#define USE_SPS30 // Enable Sensiron SPS30 particle sensor (I2C address 0x69) (+1.7 code)
|
||||||
#define USE_ADE7953 // Enable ADE7953 Energy monitor as used on Shelly 2.5 (I2C address 0x38) (+1k5)
|
#define USE_ADE7953 // Enable ADE7953 Energy monitor as used on Shelly 2.5 (I2C address 0x38) (+1k5)
|
||||||
|
|
||||||
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
||||||
|
@ -211,8 +211,9 @@ struct SYSCFG {
|
|||||||
uint8_t weblog_level; // 1AC
|
uint8_t weblog_level; // 1AC
|
||||||
uint8_t mqtt_fingerprint[2][20]; // 1AD
|
uint8_t mqtt_fingerprint[2][20]; // 1AD
|
||||||
|
|
||||||
uint8_t free_1D5[20]; // 1D5 Free since 5.12.0e
|
uint8_t free_1D5[19]; // 1D5 Free since 5.12.0e
|
||||||
|
|
||||||
|
uint8_t sps30_inuse_hours; // 1E8
|
||||||
char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6
|
char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6
|
||||||
uint16_t mqtt_port; // 20A - Keep together
|
uint16_t mqtt_port; // 20A - Keep together
|
||||||
char mqtt_client[33]; // 20C - Keep together
|
char mqtt_client[33]; // 20C - Keep together
|
||||||
@ -345,7 +346,7 @@ struct SYSCFG {
|
|||||||
uint16_t weight_max; // 7BE Total max weight in kilogram
|
uint16_t weight_max; // 7BE Total max weight in kilogram
|
||||||
unsigned long weight_reference; // 7C0 Reference weight in gram
|
unsigned long weight_reference; // 7C0 Reference weight in gram
|
||||||
unsigned long weight_calibration; // 7C4
|
unsigned long weight_calibration; // 7C4
|
||||||
unsigned long energy_frequency_calibration; // 7C8
|
unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight
|
||||||
uint16_t web_refresh; // 7CC
|
uint16_t web_refresh; // 7CC
|
||||||
char mems[MAX_RULE_MEMS][10]; // 7CE
|
char mems[MAX_RULE_MEMS][10]; // 7CE
|
||||||
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
|
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
|
||||||
|
@ -444,6 +444,7 @@ void SettingsSaveAll(void)
|
|||||||
Settings.power = 0;
|
Settings.power = 0;
|
||||||
}
|
}
|
||||||
XsnsCall(FUNC_SAVE_BEFORE_RESTART);
|
XsnsCall(FUNC_SAVE_BEFORE_RESTART);
|
||||||
|
XdrvCall(FUNC_SAVE_BEFORE_RESTART);
|
||||||
#ifdef USE_EEPROM
|
#ifdef USE_EEPROM
|
||||||
EepromCommit();
|
EepromCommit();
|
||||||
#endif
|
#endif
|
||||||
|
@ -143,7 +143,10 @@ uint8_t backlog_pointer = 0; // Command backlog pointer
|
|||||||
uint8_t sleep; // Current copy of Settings.sleep
|
uint8_t sleep; // Current copy of Settings.sleep
|
||||||
uint8_t blinkspeed = 1; // LED blink rate
|
uint8_t blinkspeed = 1; // LED blink rate
|
||||||
uint8_t pin[GPIO_MAX]; // Possible pin configurations
|
uint8_t pin[GPIO_MAX]; // Possible pin configurations
|
||||||
|
uint8_t leds_present = 0; // Max number of LED supported
|
||||||
uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off))
|
uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off))
|
||||||
|
uint8_t led_power = 0; // LED power state
|
||||||
|
uint8_t ledlnk_inverted = 0; // Link LED inverted flag (1 = (0 = On, 1 = Off))
|
||||||
uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted)
|
uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted)
|
||||||
uint8_t counter_no_pullup = 0; // Counter input pullup flag (1 = No pullup)
|
uint8_t counter_no_pullup = 0; // Counter input pullup flag (1 = No pullup)
|
||||||
uint8_t energy_flg = 0; // Energy monitor configured
|
uint8_t energy_flg = 0; // Energy monitor configured
|
||||||
@ -370,19 +373,56 @@ void SetDevicePower(power_t rpower, int source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetLedPowerIdx(uint8_t led, uint8_t state)
|
||||||
|
{
|
||||||
|
if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present
|
||||||
|
if (pin[GPIO_LED2] < 99) { led = 1; }
|
||||||
|
}
|
||||||
|
if (pin[GPIO_LED1 + led] < 99) {
|
||||||
|
uint8_t mask = 1 << led;
|
||||||
|
if (state) {
|
||||||
|
state = 1;
|
||||||
|
led_power |= mask;
|
||||||
|
} else {
|
||||||
|
led_power &= (0xFF ^ mask);
|
||||||
|
}
|
||||||
|
digitalWrite(pin[GPIO_LED1 + led], bitRead(led_inverted, led) ? !state : state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetLedPower(uint8_t state)
|
void SetLedPower(uint8_t state)
|
||||||
{
|
{
|
||||||
if (state) { state = 1; }
|
if (99 == pin[GPIO_LEDLNK]) { // Legacy - Only use LED1 and/or LED2
|
||||||
|
SetLedPowerIdx(0, state);
|
||||||
|
} else {
|
||||||
|
power_t mask = 1;
|
||||||
|
for (uint8_t i = 0; i < leds_present; i++) { // Map leds to power
|
||||||
|
bool tstate = (power & mask);
|
||||||
|
SetLedPowerIdx(i, tstate);
|
||||||
|
mask <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t led_pin = 0;
|
void SetLedPowerAll(uint8_t state)
|
||||||
if (pin[GPIO_LED2] < 99) { led_pin = 1; }
|
{
|
||||||
digitalWrite(pin[GPIO_LED1 + led_pin], (bitRead(led_inverted, led_pin)) ? !state : state);
|
for (uint8_t i = 0; i < leds_present; i++) {
|
||||||
|
SetLedPowerIdx(i, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLedLink(uint8_t state)
|
void SetLedLink(uint8_t state)
|
||||||
{
|
{
|
||||||
if (state) { state = 1; }
|
uint8_t led_pin = pin[GPIO_LEDLNK];
|
||||||
digitalWrite(pin[GPIO_LED1], (bitRead(led_inverted, 0)) ? !state : state);
|
uint8_t led_inv = ledlnk_inverted;
|
||||||
|
if (99 == led_pin) { // Legacy - LED1 is status
|
||||||
|
led_pin = pin[GPIO_LED1];
|
||||||
|
led_inv = bitRead(led_inverted, 0);
|
||||||
|
}
|
||||||
|
if (led_pin < 99) {
|
||||||
|
if (state) { state = 1; }
|
||||||
|
digitalWrite(led_pin, (led_inv) ? !state : state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GetFanspeed(void)
|
uint8_t GetFanspeed(void)
|
||||||
@ -1422,7 +1462,8 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
|||||||
}
|
}
|
||||||
Response_P(S_JSON_COMMAND_NVALUE, command, Settings.altitude);
|
Response_P(S_JSON_COMMAND_NVALUE, command, Settings.altitude);
|
||||||
}
|
}
|
||||||
else if (CMND_LEDPOWER == command_code) {
|
else if ((CMND_LEDPOWER == command_code) && (index > 0) && (index <= MAX_LEDS)) {
|
||||||
|
/*
|
||||||
if ((payload >= 0) && (payload <= 2)) {
|
if ((payload >= 0) && (payload <= 2)) {
|
||||||
Settings.ledstate &= 8;
|
Settings.ledstate &= 8;
|
||||||
switch (payload) {
|
switch (payload) {
|
||||||
@ -1435,15 +1476,83 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
blinks = 0;
|
blinks = 0;
|
||||||
SetLedPower(Settings.ledstate &8);
|
SetLedPowerIdx(index -1, Settings.ledstate &8);
|
||||||
}
|
}
|
||||||
Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(bitRead(Settings.ledstate, 3)));
|
Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(bitRead(Settings.ledstate, 3)));
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if (99 == pin[GPIO_LEDLNK]) {
|
||||||
|
if ((payload >= 0) && (payload <= 2)) {
|
||||||
|
Settings.ledstate &= 8;
|
||||||
|
switch (payload) {
|
||||||
|
case 0: // Off
|
||||||
|
case 1: // On
|
||||||
|
Settings.ledstate = payload << 3;
|
||||||
|
break;
|
||||||
|
case 2: // Toggle
|
||||||
|
Settings.ledstate ^= 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
blinks = 0;
|
||||||
|
SetLedPower(Settings.ledstate &8);
|
||||||
|
}
|
||||||
|
Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(bitRead(Settings.ledstate, 3)));
|
||||||
|
} else {
|
||||||
|
if ((payload >= 0) && (payload <= 2)) {
|
||||||
|
Settings.ledstate &= 8; // Disable power control
|
||||||
|
uint8_t mask = 1 << (index -1); // Led to control
|
||||||
|
switch (payload) {
|
||||||
|
case 0: // Off
|
||||||
|
led_power &= (0xFF ^ mask);
|
||||||
|
case 1: // On
|
||||||
|
led_power |= mask;
|
||||||
|
break;
|
||||||
|
case 2: // Toggle
|
||||||
|
led_power ^= mask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
blinks = 0;
|
||||||
|
SetLedPowerIdx(index -1, (led_power & mask));
|
||||||
|
}
|
||||||
|
Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(bitRead(led_power, index -1)));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (99 == pin[GPIO_LEDLNK]) { index = 1; }
|
||||||
|
if ((payload >= 0) && (payload <= 2)) {
|
||||||
|
Settings.ledstate &= 8; // Disable power control
|
||||||
|
uint8_t mask = 1 << (index -1); // Led to control
|
||||||
|
switch (payload) {
|
||||||
|
case 0: // Off
|
||||||
|
led_power &= (0xFF ^ mask);
|
||||||
|
Settings.ledstate = 0;
|
||||||
|
break;
|
||||||
|
case 1: // On
|
||||||
|
led_power |= mask;
|
||||||
|
Settings.ledstate = 8;
|
||||||
|
break;
|
||||||
|
case 2: // Toggle
|
||||||
|
led_power ^= mask;
|
||||||
|
Settings.ledstate ^= 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
blinks = 0;
|
||||||
|
if (99 == pin[GPIO_LEDLNK]) {
|
||||||
|
SetLedPower(Settings.ledstate &8);
|
||||||
|
} else {
|
||||||
|
SetLedPowerIdx(index -1, (led_power & mask));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t state = bitRead(led_power, index -1);
|
||||||
|
if (99 == pin[GPIO_LEDLNK]) {
|
||||||
|
state = bitRead(Settings.ledstate, 3);
|
||||||
|
}
|
||||||
|
Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(state));
|
||||||
}
|
}
|
||||||
else if (CMND_LEDSTATE == command_code) {
|
else if (CMND_LEDSTATE == command_code) {
|
||||||
if ((payload >= 0) && (payload < MAX_LED_OPTION)) {
|
if ((payload >= 0) && (payload < MAX_LED_OPTION)) {
|
||||||
Settings.ledstate = payload;
|
Settings.ledstate = payload;
|
||||||
if (!Settings.ledstate) {
|
if (!Settings.ledstate) {
|
||||||
SetLedPower(0);
|
SetLedPowerAll(0);
|
||||||
SetLedLink(0);
|
SetLedLink(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1469,7 +1578,12 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
|||||||
Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}"));
|
Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}"));
|
||||||
type = (char*)topicBuf;
|
type = (char*)topicBuf;
|
||||||
}
|
}
|
||||||
if (mqtt_data[0] != '\0') { MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); }
|
if (mqtt_data[0] != '\0') {
|
||||||
|
MqttPublishPrefixTopic_P(RESULT_OR_STAT, type);
|
||||||
|
#ifdef USE_SCRIPT
|
||||||
|
XdrvRulesProcess();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
fallback_topic_flag = false;
|
fallback_topic_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1838,6 +1952,9 @@ void MqttPublishTeleState(void)
|
|||||||
mqtt_data[0] = '\0';
|
mqtt_data[0] = '\0';
|
||||||
MqttShowState();
|
MqttShowState();
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN);
|
||||||
|
#ifdef USE_SCRIPT
|
||||||
|
RulesTeleperiod(); // Allow rule based HA messages
|
||||||
|
#endif // USE_SCRIPT
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MqttShowSensor(void)
|
bool MqttShowSensor(void)
|
||||||
@ -1922,7 +2039,7 @@ void PerformEverySecond(void)
|
|||||||
mqtt_data[0] = '\0';
|
mqtt_data[0] = '\0';
|
||||||
if (MqttShowSensor()) {
|
if (MqttShowSensor()) {
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
#ifdef USE_RULES
|
#if defined(USE_RULES) || defined(USE_SCRIPT)
|
||||||
RulesTeleperiod(); // Allow rule based HA messages
|
RulesTeleperiod(); // Allow rule based HA messages
|
||||||
#endif // USE_RULES
|
#endif // USE_RULES
|
||||||
}
|
}
|
||||||
@ -2025,8 +2142,6 @@ void Every250mSeconds(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) {
|
if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) {
|
||||||
// if ( (!Settings.flag.global_state && global_state.data) || ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) ) {
|
|
||||||
// SetLedPower(blinkstate); // Set led on or off
|
|
||||||
SetLedLink(blinkstate); // Set led on or off
|
SetLedLink(blinkstate); // Set led on or off
|
||||||
}
|
}
|
||||||
if (!blinkstate) {
|
if (!blinkstate) {
|
||||||
@ -2176,7 +2291,9 @@ void Every250mSeconds(void)
|
|||||||
SettingsDefault();
|
SettingsDefault();
|
||||||
restart_flag = 2;
|
restart_flag = 2;
|
||||||
}
|
}
|
||||||
SettingsSaveAll();
|
if (2 == restart_flag) {
|
||||||
|
SettingsSaveAll();
|
||||||
|
}
|
||||||
restart_flag--;
|
restart_flag--;
|
||||||
if (restart_flag <= 0) {
|
if (restart_flag <= 0) {
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING));
|
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING));
|
||||||
@ -2449,6 +2566,10 @@ void GpioInit(void)
|
|||||||
bitSet(led_inverted, mpin - GPIO_LED1_INV);
|
bitSet(led_inverted, mpin - GPIO_LED1_INV);
|
||||||
mpin -= (GPIO_LED1_INV - GPIO_LED1);
|
mpin -= (GPIO_LED1_INV - GPIO_LED1);
|
||||||
}
|
}
|
||||||
|
else if (mpin == GPIO_LEDLNK_INV) {
|
||||||
|
ledlnk_inverted = 1;
|
||||||
|
mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK);
|
||||||
|
}
|
||||||
else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) {
|
else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) {
|
||||||
bitSet(pwm_inverted, mpin - GPIO_PWM1_INV);
|
bitSet(pwm_inverted, mpin - GPIO_PWM1_INV);
|
||||||
mpin -= (GPIO_PWM1_INV - GPIO_PWM1);
|
mpin -= (GPIO_PWM1_INV - GPIO_PWM1);
|
||||||
@ -2560,10 +2681,24 @@ void GpioInit(void)
|
|||||||
|
|
||||||
for (uint8_t i = 0; i < MAX_LEDS; i++) {
|
for (uint8_t i = 0; i < MAX_LEDS; i++) {
|
||||||
if (pin[GPIO_LED1 +i] < 99) {
|
if (pin[GPIO_LED1 +i] < 99) {
|
||||||
pinMode(pin[GPIO_LED1 +i], OUTPUT);
|
#ifdef USE_ARILUX_RF
|
||||||
digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i));
|
if ((3 == i) && (leds_present < 2) && (99 == pin[GPIO_ARIRFSEL])) {
|
||||||
|
pin[GPIO_ARIRFSEL] = pin[GPIO_LED4]; // Legacy support where LED4 was Arilux RF enable
|
||||||
|
pin[GPIO_LED4] = 99;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
pinMode(pin[GPIO_LED1 +i], OUTPUT);
|
||||||
|
leds_present++;
|
||||||
|
digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i));
|
||||||
|
#ifdef USE_ARILUX_RF
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (pin[GPIO_LEDLNK] < 99) {
|
||||||
|
pinMode(pin[GPIO_LEDLNK], OUTPUT);
|
||||||
|
digitalWrite(pin[GPIO_LEDLNK], ledlnk_inverted);
|
||||||
|
}
|
||||||
|
|
||||||
ButtonInit();
|
ButtonInit();
|
||||||
SwitchInit();
|
SwitchInit();
|
||||||
@ -2645,6 +2780,13 @@ void setup(void)
|
|||||||
sleep = Settings.sleep;
|
sleep = Settings.sleep;
|
||||||
#ifndef USE_EMULATION
|
#ifndef USE_EMULATION
|
||||||
Settings.flag2.emulation = 0;
|
Settings.flag2.emulation = 0;
|
||||||
|
#else
|
||||||
|
#ifndef USE_EMULATION_WEMO
|
||||||
|
if (EMUL_WEMO == Settings.flag2.emulation) { Settings.flag2.emulation = 0; }
|
||||||
|
#endif
|
||||||
|
#ifndef USE_EMULATION_HUE
|
||||||
|
if (EMUL_HUE == Settings.flag2.emulation) { Settings.flag2.emulation = 0; }
|
||||||
|
#endif
|
||||||
#endif // USE_EMULATION
|
#endif // USE_EMULATION
|
||||||
|
|
||||||
if (Settings.param[P_BOOT_LOOP_OFFSET]) {
|
if (Settings.param[P_BOOT_LOOP_OFFSET]) {
|
||||||
|
@ -46,6 +46,13 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
|||||||
* Default global defines
|
* Default global defines
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef USE_EMULATION_HUE
|
||||||
|
#define USE_EMULATION
|
||||||
|
#endif
|
||||||
|
#ifdef USE_EMULATION_WEMO
|
||||||
|
#define USE_EMULATION
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
#define MODULE SONOFF_BASIC // [Module] Select default model
|
#define MODULE SONOFF_BASIC // [Module] Select default model
|
||||||
#endif
|
#endif
|
||||||
|
@ -171,7 +171,7 @@ enum UserSelectablePins {
|
|||||||
GPIO_DCKI, // my92x1 CLK input
|
GPIO_DCKI, // my92x1 CLK input
|
||||||
GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2)
|
GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2)
|
||||||
GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2)
|
GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2)
|
||||||
GPIO_ARIRFRCV, // AliLux RF Receive input
|
GPIO_ARIRFRCV, // AriLux RF Receive input
|
||||||
GPIO_TXD, // Serial interface
|
GPIO_TXD, // Serial interface
|
||||||
GPIO_RXD, // Serial interface
|
GPIO_RXD, // Serial interface
|
||||||
GPIO_ROT1A, // Rotary switch1 A Pin
|
GPIO_ROT1A, // Rotary switch1 A Pin
|
||||||
@ -181,6 +181,9 @@ enum UserSelectablePins {
|
|||||||
GPIO_HRE_CLOCK, // Clock/Power line for HR-E Water Meter
|
GPIO_HRE_CLOCK, // Clock/Power line for HR-E Water Meter
|
||||||
GPIO_HRE_DATA, // Data line for HR-E Water Meter
|
GPIO_HRE_DATA, // Data line for HR-E Water Meter
|
||||||
GPIO_ADE7953_IRQ, // ADE7953 IRQ
|
GPIO_ADE7953_IRQ, // ADE7953 IRQ
|
||||||
|
GPIO_LEDLNK, // Link led
|
||||||
|
GPIO_LEDLNK_INV, // Inverted link led
|
||||||
|
GPIO_ARIRFSEL, // Arilux RF Receive input selected
|
||||||
GPIO_SENSOR_END };
|
GPIO_SENSOR_END };
|
||||||
|
|
||||||
// Programmer selectable GPIO functionality
|
// Programmer selectable GPIO functionality
|
||||||
@ -246,6 +249,8 @@ const char kSensorNames[] PROGMEM =
|
|||||||
D_SENSOR_ROTARY "1a|" D_SENSOR_ROTARY "1b|" D_SENSOR_ROTARY "2a|" D_SENSOR_ROTARY "2b|"
|
D_SENSOR_ROTARY "1a|" D_SENSOR_ROTARY "1b|" D_SENSOR_ROTARY "2a|" D_SENSOR_ROTARY "2b|"
|
||||||
D_SENSOR_HRE_CLOCK "|" D_SENSOR_HRE_DATA "|"
|
D_SENSOR_HRE_CLOCK "|" D_SENSOR_HRE_DATA "|"
|
||||||
D_SENSOR_ADE7953_IRQ "|"
|
D_SENSOR_ADE7953_IRQ "|"
|
||||||
|
D_SENSOR_LED_LINK "|" D_SENSOR_LED_LINK "i|"
|
||||||
|
D_SENSOR_ARIRFSEL "|"
|
||||||
;
|
;
|
||||||
|
|
||||||
// User selectable ADC0 functionality
|
// User selectable ADC0 functionality
|
||||||
@ -448,6 +453,8 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
|||||||
GPIO_LED3_INV,
|
GPIO_LED3_INV,
|
||||||
GPIO_LED4,
|
GPIO_LED4,
|
||||||
GPIO_LED4_INV,
|
GPIO_LED4_INV,
|
||||||
|
GPIO_LEDLNK, // Link led
|
||||||
|
GPIO_LEDLNK_INV, // Inverted link led
|
||||||
GPIO_PWM1, // RGB Red or C Cold White
|
GPIO_PWM1, // RGB Red or C Cold White
|
||||||
GPIO_PWM1_INV,
|
GPIO_PWM1_INV,
|
||||||
GPIO_PWM2, // RGB Green or CW Warm White
|
GPIO_PWM2, // RGB Green or CW Warm White
|
||||||
@ -616,7 +623,8 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
|||||||
GPIO_ROT2B, // Rotary switch2 B Pin
|
GPIO_ROT2B, // Rotary switch2 B Pin
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ARILUX_RF
|
#ifdef USE_ARILUX_RF
|
||||||
GPIO_ARIRFRCV, // AliLux RF Receive input
|
GPIO_ARIRFRCV, // AriLux RF Receive input
|
||||||
|
GPIO_ARIRFSEL, // Arilux RF Receive input selected
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_HRE
|
#ifdef USE_HRE
|
||||||
GPIO_HRE_CLOCK,
|
GPIO_HRE_CLOCK,
|
||||||
@ -1109,9 +1117,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
0, 0
|
0, 0
|
||||||
},
|
},
|
||||||
{ "Huafan SS", // Hua Fan Smart Socket (ESP8266) - like Sonoff Pow
|
{ "Huafan SS", // Hua Fan Smart Socket (ESP8266) - like Sonoff Pow
|
||||||
GPIO_LED1_INV, // GPIO00 Blue Led (0 = On, 1 = Off) - Link status
|
GPIO_LEDLNK_INV, // GPIO00 Blue Led (0 = On, 1 = Off) - Link status
|
||||||
0, 0,
|
0, 0,
|
||||||
GPIO_LED2_INV, // GPIO03 Red Led (0 = On, 1 = Off) - Power status
|
GPIO_LED1_INV, // GPIO03 Red Led (0 = On, 1 = Off) - Power status
|
||||||
GPIO_KEY1, // GPIO04 Button
|
GPIO_KEY1, // GPIO04 Button
|
||||||
GPIO_REL1_INV, // GPIO05 Relay (0 = On, 1 = Off)
|
GPIO_REL1_INV, // GPIO05 Relay (0 = On, 1 = Off)
|
||||||
// GPIO06 (SD_CLK Flash)
|
// GPIO06 (SD_CLK Flash)
|
||||||
@ -1304,7 +1312,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
GPIO_PWM3, // GPIO12 RGB LED Blue
|
GPIO_PWM3, // GPIO12 RGB LED Blue
|
||||||
GPIO_USER, // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White as used on Arilux LC10)
|
GPIO_USER, // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White as used on Arilux LC10)
|
||||||
GPIO_PWM1, // GPIO14 RGB LED Red
|
GPIO_PWM1, // GPIO14 RGB LED Red
|
||||||
GPIO_LED4_INV, // GPIO15 RF receiver control (Arilux LC10)
|
GPIO_ARIRFSEL, // GPIO15 RF receiver control (Arilux LC10)
|
||||||
0, 0
|
0, 0
|
||||||
},
|
},
|
||||||
{ "Luani HVIO", // ESP8266_HVIO
|
{ "Luani HVIO", // ESP8266_HVIO
|
||||||
@ -1350,7 +1358,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
// (PwmFrequency 1111Hz)
|
// (PwmFrequency 1111Hz)
|
||||||
GPIO_KEY1, // GPIO00 Optional Button
|
GPIO_KEY1, // GPIO00 Optional Button
|
||||||
GPIO_USER, // GPIO01 Serial RXD and Optional sensor
|
GPIO_USER, // GPIO01 Serial RXD and Optional sensor
|
||||||
GPIO_LED4_INV, // GPIO02 RF receiver control
|
GPIO_ARIRFSEL, // GPIO02 RF receiver control
|
||||||
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
|
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
|
||||||
GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional)
|
GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional)
|
||||||
GPIO_PWM1, // GPIO05 RGB LED Red
|
GPIO_PWM1, // GPIO05 RGB LED Red
|
||||||
@ -1370,7 +1378,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
// (PwmFrequency 540Hz)
|
// (PwmFrequency 540Hz)
|
||||||
GPIO_KEY1, // GPIO00 Optional Button
|
GPIO_KEY1, // GPIO00 Optional Button
|
||||||
GPIO_USER, // GPIO01 Serial RXD and Optional sensor
|
GPIO_USER, // GPIO01 Serial RXD and Optional sensor
|
||||||
GPIO_LED4_INV, // GPIO02 RF receiver control
|
GPIO_ARIRFSEL, // GPIO02 RF receiver control
|
||||||
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
|
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
|
||||||
GPIO_PWM2, // GPIO04 RGB LED Green
|
GPIO_PWM2, // GPIO04 RGB LED Green
|
||||||
GPIO_PWM1, // GPIO05 RGB LED Red
|
GPIO_PWM1, // GPIO05 RGB LED Red
|
||||||
@ -1498,9 +1506,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
// https://www.amazon.de/Steckdose-Homecube-intelligente-Verbrauchsanzeige-funktioniert/dp/B076Q2LKHG/ref=sr_1_fkmr0_1
|
// https://www.amazon.de/Steckdose-Homecube-intelligente-Verbrauchsanzeige-funktioniert/dp/B076Q2LKHG/ref=sr_1_fkmr0_1
|
||||||
// https://www.amazon.de/Intelligente-Stromverbrauch-Fernsteurung-Schaltbare-Energieklasse/dp/B076WZQS4S/ref=sr_1_1
|
// https://www.amazon.de/Intelligente-Stromverbrauch-Fernsteurung-Schaltbare-Energieklasse/dp/B076WZQS4S/ref=sr_1_1
|
||||||
// https://www.aliexpress.com/store/product/BlitzWolf-BW-SHP6-EU-Plug-Metering-Version-WIFI-Smart-Socket-220V-240V-10A-Work-with-Amazon/1965360_32945504669.html
|
// https://www.aliexpress.com/store/product/BlitzWolf-BW-SHP6-EU-Plug-Metering-Version-WIFI-Smart-Socket-220V-240V-10A-Work-with-Amazon/1965360_32945504669.html
|
||||||
GPIO_LED2_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status
|
GPIO_LED1_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status
|
||||||
GPIO_USER, // GPIO01 Serial RXD and Optional sensor
|
GPIO_USER, // GPIO01 Serial RXD and Optional sensor
|
||||||
GPIO_LED1_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status
|
GPIO_LEDLNK_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status
|
||||||
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
|
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
|
||||||
0,
|
0,
|
||||||
GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power
|
GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power
|
||||||
@ -1624,7 +1632,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
0,
|
0,
|
||||||
GPIO_KEY1, // GPIO01 Serial TXD and Button
|
GPIO_KEY1, // GPIO01 Serial TXD and Button
|
||||||
0,
|
0,
|
||||||
GPIO_LED2_INV, // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) - Power status
|
GPIO_LED1_INV, // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) - Power status
|
||||||
GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power
|
GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power
|
||||||
GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage
|
GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage
|
||||||
// GPIO06 (SD_CLK Flash)
|
// GPIO06 (SD_CLK Flash)
|
||||||
@ -1634,7 +1642,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
||||||
// GPIO11 (SD_CMD Flash)
|
// GPIO11 (SD_CMD Flash)
|
||||||
GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage)
|
GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage)
|
||||||
GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link status
|
GPIO_LEDLNK_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link status
|
||||||
GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On)
|
GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On)
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
@ -1678,7 +1686,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
},
|
},
|
||||||
{ "Gosund SP1 v23", // https://www.amazon.de/gp/product/B0777BWS1P
|
{ "Gosund SP1 v23", // https://www.amazon.de/gp/product/B0777BWS1P
|
||||||
0,
|
0,
|
||||||
GPIO_LED1_INV, // GPIO01 Serial RXD and LED1 (blue) inv - Link status
|
GPIO_LEDLNK_INV, // GPIO01 Serial RXD and LED1 (blue) inv - Link status
|
||||||
0,
|
0,
|
||||||
GPIO_KEY1, // GPIO03 Serial TXD and Button
|
GPIO_KEY1, // GPIO03 Serial TXD and Button
|
||||||
GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power
|
GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power
|
||||||
@ -1690,7 +1698,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
||||||
// GPIO11 (SD_CMD Flash)
|
// GPIO11 (SD_CMD Flash)
|
||||||
GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage)
|
GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage)
|
||||||
GPIO_LED2_INV, // GPIO13 LED2 (red) inv - Power status
|
GPIO_LED1_INV, // GPIO13 LED2 (red) inv - Power status
|
||||||
GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On)
|
GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On)
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
@ -1728,8 +1736,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
||||||
// GPIO11 (SD_CMD Flash)
|
// GPIO11 (SD_CMD Flash)
|
||||||
GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage)
|
GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage)
|
||||||
GPIO_LED2_INV, // GPIO13 Red Led (0 = On, 1 = Off) - Power status
|
GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) - Power status
|
||||||
GPIO_LED1_INV, // GPIO14 Blue Led (0 = On, 1 = Off) - Link status
|
GPIO_LEDLNK_INV, // GPIO14 Blue Led (0 = On, 1 = Off) - Link status
|
||||||
GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On)
|
GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On)
|
||||||
0, 0
|
0, 0
|
||||||
},
|
},
|
||||||
@ -1757,9 +1765,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
{ "Teckin US", // Teckin SP20 US with Energy Monitoring
|
{ "Teckin US", // Teckin SP20 US with Energy Monitoring
|
||||||
// https://www.amazon.com/Outlet-Compatible-Monitoring-Function-Required/dp/B079Q5W22B
|
// https://www.amazon.com/Outlet-Compatible-Monitoring-Function-Required/dp/B079Q5W22B
|
||||||
// https://www.amazon.com/Outlet-ZOOZEE-Monitoring-Function-Compatible/dp/B07J2LR5KN
|
// https://www.amazon.com/Outlet-ZOOZEE-Monitoring-Function-Compatible/dp/B07J2LR5KN
|
||||||
GPIO_LED2_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status
|
GPIO_LED1_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status
|
||||||
0,
|
0,
|
||||||
GPIO_LED1_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status
|
GPIO_LEDLNK_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status
|
||||||
0,
|
0,
|
||||||
GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On)
|
GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On)
|
||||||
GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power
|
GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power
|
||||||
@ -1809,8 +1817,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
|
0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
|
||||||
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
||||||
// GPIO11 (SD_CMD Flash)
|
// GPIO11 (SD_CMD Flash)
|
||||||
GPIO_LED1_INV, // GPIO12 Green LED - Link status
|
GPIO_LEDLNK_INV, // GPIO12 Green LED - Link status
|
||||||
GPIO_LED2, // GPIO13 Red LED - Power status
|
GPIO_LED1, // GPIO13 Red LED - Power status
|
||||||
0, 0, 0, 0
|
0, 0, 0, 0
|
||||||
},
|
},
|
||||||
{ "YTF IR Bridge", // https://www.aliexpress.com/item/Tuya-universal-Smart-IR-Hub-remote-control-Voice-Control-AC-TV-Work-With-Alexa-Google-Home/32951202513.html
|
{ "YTF IR Bridge", // https://www.aliexpress.com/item/Tuya-universal-Smart-IR-Hub-remote-control-Voice-Control-AC-TV-Work-With-Alexa-Google-Home/32951202513.html
|
||||||
@ -1854,7 +1862,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
},
|
},
|
||||||
{ "KA10", // SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y
|
{ "KA10", // SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y
|
||||||
0, // GPIO00
|
0, // GPIO00
|
||||||
GPIO_LED1_INV, // GPIO01 Blue LED - Link status
|
GPIO_LEDLNK_INV, // GPIO01 Blue LED - Link status
|
||||||
0, // GPIO02
|
0, // GPIO02
|
||||||
GPIO_KEY1, // GPIO03 Button
|
GPIO_KEY1, // GPIO03 Button
|
||||||
GPIO_HJL_CF, // GPIO04 BL0937 CF power
|
GPIO_HJL_CF, // GPIO04 BL0937 CF power
|
||||||
@ -1866,7 +1874,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
|
||||||
// GPIO11 (SD_CMD Flash)
|
// GPIO11 (SD_CMD Flash)
|
||||||
GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage)
|
GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage)
|
||||||
GPIO_LED2, // GPIO13 Red LED - Power status
|
GPIO_LED1, // GPIO13 Red LED - Power status
|
||||||
GPIO_REL1, // GPIO14 Relay 1
|
GPIO_REL1, // GPIO14 Relay 1
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
@ -1923,7 +1931,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
},
|
},
|
||||||
{ "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring)
|
{ "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring)
|
||||||
// https://www.ebay.com/itm/332595697006
|
// https://www.ebay.com/itm/332595697006
|
||||||
GPIO_LED2_INV, // GPIO00 Red LED
|
GPIO_LED1_INV, // GPIO00 Red LED
|
||||||
0, // GPIO01 Serial RXD
|
0, // GPIO01 Serial RXD
|
||||||
0, // GPIO02
|
0, // GPIO02
|
||||||
GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage)
|
GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage)
|
||||||
@ -1938,7 +1946,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
GPIO_REL1, // GPIO12 Relay
|
GPIO_REL1, // GPIO12 Relay
|
||||||
GPIO_KEY1, // GPIO13 Button
|
GPIO_KEY1, // GPIO13 Button
|
||||||
GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current
|
GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current
|
||||||
GPIO_LED1_INV, // GPIO15 Blue LED - Link status
|
GPIO_LEDLNK_INV, // GPIO15 Blue LED - Link status
|
||||||
0, 0
|
0, 0
|
||||||
},
|
},
|
||||||
{ "SYF05", // Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726
|
{ "SYF05", // Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726
|
||||||
@ -2070,7 +2078,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
GPIO_PWM3, // GPIO12 RGB LED Blue
|
GPIO_PWM3, // GPIO12 RGB LED Blue
|
||||||
GPIO_PWM4, // GPIO13 RGBW LED White
|
GPIO_PWM4, // GPIO13 RGBW LED White
|
||||||
GPIO_PWM1, // GPIO14 RGB LED Red
|
GPIO_PWM1, // GPIO14 RGB LED Red
|
||||||
GPIO_LED4_INV, // GPIO15 RF receiver control
|
GPIO_ARIRFSEL, // GPIO15 RF receiver control
|
||||||
0, 0
|
0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,6 @@
|
|||||||
#ifndef _SONOFF_VERSION_H_
|
#ifndef _SONOFF_VERSION_H_
|
||||||
#define _SONOFF_VERSION_H_
|
#define _SONOFF_VERSION_H_
|
||||||
|
|
||||||
const uint32_t VERSION = 0x0605000B;
|
const uint32_t VERSION = 0x0605000C;
|
||||||
|
|
||||||
#endif // _SONOFF_VERSION_H_
|
#endif // _SONOFF_VERSION_H_
|
||||||
|
@ -674,6 +674,42 @@ double FastPrecisePow(double a, double b)
|
|||||||
return r * u.d;
|
return r * u.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float FastPrecisePowf(const float x, const float y)
|
||||||
|
{
|
||||||
|
// return (float)(pow((double)x, (double)y));
|
||||||
|
return (float)FastPrecisePow(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TaylorLog(double x)
|
||||||
|
{
|
||||||
|
// https://stackoverflow.com/questions/46879166/finding-the-natural-logarithm-of-a-number-using-taylor-series-in-c
|
||||||
|
|
||||||
|
if (x <= 0.0) { return NAN; }
|
||||||
|
double z = (x + 1) / (x - 1); // We start from power -1, to make sure we get the right power in each iteration;
|
||||||
|
double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); // Store step to not have to calculate it each time
|
||||||
|
double totalValue = 0;
|
||||||
|
double powe = 1;
|
||||||
|
double y;
|
||||||
|
for (int count = 0; count < 10; count++) { // Experimental number of 10 iterations
|
||||||
|
z *= step;
|
||||||
|
y = (1 / powe) * z;
|
||||||
|
totalValue = totalValue + y;
|
||||||
|
powe = powe + 2;
|
||||||
|
}
|
||||||
|
totalValue *= 2;
|
||||||
|
/*
|
||||||
|
char logxs[33];
|
||||||
|
dtostrfd(x, 8, logxs);
|
||||||
|
double log1 = log(x);
|
||||||
|
char log1s[33];
|
||||||
|
dtostrfd(log1, 8, log1s);
|
||||||
|
char log2s[33];
|
||||||
|
dtostrfd(totalValue, 8, log2s);
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("input %s, log %s, taylor %s"), logxs, log1s, log2s);
|
||||||
|
*/
|
||||||
|
return totalValue;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t SqrtInt(uint32_t num)
|
uint32_t SqrtInt(uint32_t num)
|
||||||
{
|
{
|
||||||
if (num <= 1) {
|
if (num <= 1) {
|
||||||
|
@ -49,8 +49,8 @@ void GetFeatures(void)
|
|||||||
#ifdef WEBSERVER_ADVERTISE
|
#ifdef WEBSERVER_ADVERTISE
|
||||||
feature_drv1 |= 0x00000100; // xdrv_02_webserver.ino
|
feature_drv1 |= 0x00000100; // xdrv_02_webserver.ino
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_EMULATION
|
#ifdef USE_EMULATION_HUE
|
||||||
feature_drv1 |= 0x00000200; // xplg_wemohue.ino
|
feature_drv1 |= 0x00000200; // xdrv_20_hue.ino
|
||||||
#endif
|
#endif
|
||||||
#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT)
|
#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT)
|
||||||
feature_drv1 |= 0x00000400; // xdrv_01_mqtt.ino
|
feature_drv1 |= 0x00000400; // xdrv_01_mqtt.ino
|
||||||
@ -180,9 +180,13 @@ void GetFeatures(void)
|
|||||||
#ifdef USE_SM16716
|
#ifdef USE_SM16716
|
||||||
feature_drv2 |= 0x00040000; // xdrv_04_light.ino
|
feature_drv2 |= 0x00040000; // xdrv_04_light.ino
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_SCRIPT
|
||||||
|
feature_drv2 |= 0x00080000; // xdrv_10_scripter.ino
|
||||||
|
#endif
|
||||||
|
#ifdef USE_EMULATION_WEMO
|
||||||
|
feature_drv2 |= 0x00100000; // xdrv_21_wemo.ino
|
||||||
|
#endif
|
||||||
|
|
||||||
// feature_drv2 |= 0x00080000;
|
|
||||||
// feature_drv2 |= 0x00100000;
|
|
||||||
// feature_drv2 |= 0x00200000;
|
// feature_drv2 |= 0x00200000;
|
||||||
// feature_drv2 |= 0x00400000;
|
// feature_drv2 |= 0x00400000;
|
||||||
|
|
||||||
|
136
sonoff/support_udp.ino
Normal file
136
sonoff/support_udp.ino
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
support_udp.ino - Udp support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2019 Heiko Krupp 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_EMULATION
|
||||||
|
|
||||||
|
#define UDP_BUFFER_SIZE 200 // Max UDP buffer size needed for M-SEARCH message
|
||||||
|
#define UDP_MSEARCH_SEND_DELAY 1500 // Delay in ms before M-Search response is send
|
||||||
|
|
||||||
|
#include <Ticker.h>
|
||||||
|
Ticker TickerMSearch;
|
||||||
|
|
||||||
|
IPAddress udp_remote_ip; // M-Search remote IP address
|
||||||
|
uint16_t udp_remote_port; // M-Search remote port
|
||||||
|
|
||||||
|
bool udp_connected = false;
|
||||||
|
bool udp_response_mutex = false; // M-Search response mutex to control re-entry
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* UPNP/SSDP search targets
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**";
|
||||||
|
const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice";
|
||||||
|
const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all";
|
||||||
|
const char SSDP_ALL[] PROGMEM = "ssdp:all";
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* UDP support routines
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
bool UdpDisconnect(void)
|
||||||
|
{
|
||||||
|
if (udp_connected) {
|
||||||
|
PortUdp.flush();
|
||||||
|
WiFiUDP::stopAll();
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED));
|
||||||
|
udp_connected = false;
|
||||||
|
}
|
||||||
|
return udp_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UdpConnect(void)
|
||||||
|
{
|
||||||
|
if (!udp_connected) {
|
||||||
|
// Simple Service Discovery Protocol (SSDP)
|
||||||
|
if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) {
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED));
|
||||||
|
udp_response_mutex = false;
|
||||||
|
udp_connected = true;
|
||||||
|
} else {
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED));
|
||||||
|
udp_connected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return udp_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PollUdp(void)
|
||||||
|
{
|
||||||
|
if (udp_connected) {
|
||||||
|
if (PortUdp.parsePacket()) {
|
||||||
|
char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP/SSDP packet
|
||||||
|
|
||||||
|
int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1);
|
||||||
|
packet_buffer[len] = 0;
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len);
|
||||||
|
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer);
|
||||||
|
|
||||||
|
// Simple Service Discovery Protocol (SSDP)
|
||||||
|
if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) {
|
||||||
|
udp_response_mutex = true;
|
||||||
|
|
||||||
|
udp_remote_ip = PortUdp.remoteIP();
|
||||||
|
udp_remote_port = PortUdp.remotePort();
|
||||||
|
|
||||||
|
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"),
|
||||||
|
// udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer);
|
||||||
|
|
||||||
|
uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); // 1500 - 2200 msec
|
||||||
|
|
||||||
|
LowerCase(packet_buffer, packet_buffer);
|
||||||
|
RemoveSpace(packet_buffer);
|
||||||
|
|
||||||
|
#ifdef USE_EMULATION_WEMO
|
||||||
|
if (EMUL_WEMO == Settings.flag2.emulation) {
|
||||||
|
if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { // type1 echo dot 2g, echo 1g's
|
||||||
|
TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || // type2 Echo 2g (echo & echo plus)
|
||||||
|
(strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) ||
|
||||||
|
(strstr_P(packet_buffer, SSDP_ALL) != nullptr)) {
|
||||||
|
TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // USE_EMULATION_WEMO
|
||||||
|
|
||||||
|
#ifdef USE_EMULATION_HUE
|
||||||
|
if (EMUL_HUE == Settings.flag2.emulation) {
|
||||||
|
if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) ||
|
||||||
|
(strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) ||
|
||||||
|
(strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) ||
|
||||||
|
(strstr_P(packet_buffer, SSDP_ALL) != nullptr)) {
|
||||||
|
TickerMSearch.attach_ms(response_delay, HueRespondToMSearch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // USE_EMULATION_HUE
|
||||||
|
|
||||||
|
udp_response_mutex = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_EMULATION
|
@ -131,7 +131,7 @@ void WifiConfig(uint8_t type)
|
|||||||
{
|
{
|
||||||
if (!wifi_config_type) {
|
if (!wifi_config_type) {
|
||||||
if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; }
|
if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; }
|
||||||
#if defined(USE_WEBSERVER) && defined(USE_EMULATION)
|
#ifdef USE_EMULATION
|
||||||
UdpDisconnect();
|
UdpDisconnect();
|
||||||
#endif // USE_EMULATION
|
#endif // USE_EMULATION
|
||||||
WiFi.disconnect(); // Solve possible Wifi hangs
|
WiFi.disconnect(); // Solve possible Wifi hangs
|
||||||
@ -159,7 +159,7 @@ void WifiConfig(uint8_t type)
|
|||||||
#ifdef USE_SMARTCONFIG
|
#ifdef USE_SMARTCONFIG
|
||||||
else if (WIFI_SMARTCONFIG == wifi_config_type) {
|
else if (WIFI_SMARTCONFIG == wifi_config_type) {
|
||||||
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_1_SMARTCONFIG " " D_ACTIVE_FOR_3_MINUTES));
|
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_1_SMARTCONFIG " " D_ACTIVE_FOR_3_MINUTES));
|
||||||
WiFi.mode(WIFI_STA); // Disable AP mode
|
WiFi.mode(WIFI_STA); // Disable AP mode
|
||||||
WiFi.beginSmartConfig();
|
WiFi.beginSmartConfig();
|
||||||
}
|
}
|
||||||
#endif // USE_SMARTCONFIG
|
#endif // USE_SMARTCONFIG
|
||||||
@ -211,7 +211,7 @@ void WifiBegin(uint8_t flag, uint8_t channel)
|
|||||||
{
|
{
|
||||||
const char kWifiPhyMode[] = " BGN";
|
const char kWifiPhyMode[] = " BGN";
|
||||||
|
|
||||||
#if defined(USE_WEBSERVER) && defined(USE_EMULATION)
|
#ifdef USE_EMULATION
|
||||||
UdpDisconnect();
|
UdpDisconnect();
|
||||||
#endif // USE_EMULATION
|
#endif // USE_EMULATION
|
||||||
|
|
||||||
@ -565,7 +565,7 @@ void WifiCheck(uint8_t param)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
WifiSetState(0);
|
WifiSetState(0);
|
||||||
#if defined(USE_WEBSERVER) && defined(USE_EMULATION)
|
#ifdef USE_EMULATION
|
||||||
UdpDisconnect();
|
UdpDisconnect();
|
||||||
#endif // USE_EMULATION
|
#endif // USE_EMULATION
|
||||||
mdns_begun = 0;
|
mdns_begun = 0;
|
||||||
|
@ -493,9 +493,6 @@ void StartWebserver(int type, IPAddress ipweb)
|
|||||||
WebServer->on("/rs", HandleRestoreConfiguration);
|
WebServer->on("/rs", HandleRestoreConfiguration);
|
||||||
WebServer->on("/rt", HandleResetConfiguration);
|
WebServer->on("/rt", HandleResetConfiguration);
|
||||||
WebServer->on("/in", HandleInformation);
|
WebServer->on("/in", HandleInformation);
|
||||||
#ifdef USE_EMULATION
|
|
||||||
HueWemoAddHandlers();
|
|
||||||
#endif // USE_EMULATION
|
|
||||||
XdrvCall(FUNC_WEB_ADD_HANDLER);
|
XdrvCall(FUNC_WEB_ADD_HANDLER);
|
||||||
XsnsCall(FUNC_WEB_ADD_HANDLER);
|
XsnsCall(FUNC_WEB_ADD_HANDLER);
|
||||||
#endif // Not FIRMWARE_MINIMAL
|
#endif // Not FIRMWARE_MINIMAL
|
||||||
@ -1532,11 +1529,19 @@ void HandleOtherConfiguration(void)
|
|||||||
#ifdef USE_EMULATION
|
#ifdef USE_EMULATION
|
||||||
WSContentSend_P(PSTR("<p></p><fieldset><legend><b> " D_EMULATION " </b></legend><p>")); // Keep close to Friendlynames so do not use <br/>
|
WSContentSend_P(PSTR("<p></p><fieldset><legend><b> " D_EMULATION " </b></legend><p>")); // Keep close to Friendlynames so do not use <br/>
|
||||||
for (uint8_t i = 0; i < EMUL_MAX; i++) {
|
for (uint8_t i = 0; i < EMUL_MAX; i++) {
|
||||||
WSContentSend_P(PSTR("<input id='r%d' name='b2' type='radio' value='%d'%s><b>%s</b> %s<br/>"), // Different id only used for labels
|
#ifndef USE_EMULATION_WEMO
|
||||||
i, i,
|
if (i == EMUL_WEMO) { i++; }
|
||||||
(i == Settings.flag2.emulation) ? " checked" : "",
|
#endif
|
||||||
GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions),
|
#ifndef USE_EMULATION_HUE
|
||||||
(i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE);
|
if (i == EMUL_HUE) { i++; }
|
||||||
|
#endif
|
||||||
|
if (i < EMUL_MAX) {
|
||||||
|
WSContentSend_P(PSTR("<input id='r%d' name='b2' type='radio' value='%d'%s><b>%s</b> %s<br/>"), // Different id only used for labels
|
||||||
|
i, i,
|
||||||
|
(i == Settings.flag2.emulation) ? " checked" : "",
|
||||||
|
GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions),
|
||||||
|
(i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WSContentSend_P(PSTR("</p></fieldset>"));
|
WSContentSend_P(PSTR("</p></fieldset>"));
|
||||||
#endif // USE_EMULATION
|
#endif // USE_EMULATION
|
||||||
@ -2189,11 +2194,13 @@ void HandleNotFound(void)
|
|||||||
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the error page.
|
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the error page.
|
||||||
|
|
||||||
#ifdef USE_EMULATION
|
#ifdef USE_EMULATION
|
||||||
|
#ifdef USE_EMULATION_HUE
|
||||||
String path = WebServer->uri();
|
String path = WebServer->uri();
|
||||||
if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith("/api"))) {
|
if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith("/api"))) {
|
||||||
HandleHueApi(&path);
|
HandleHueApi(&path);
|
||||||
} else
|
} else
|
||||||
#endif // USE_EMULATION
|
#endif // USE_EMULATION_HUE
|
||||||
|
#endif // USE_EMULATION
|
||||||
{
|
{
|
||||||
WSContentBegin(404, CT_PLAIN);
|
WSContentBegin(404, CT_PLAIN);
|
||||||
WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args());
|
WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args());
|
||||||
@ -2430,7 +2437,16 @@ bool WebCommand(void)
|
|||||||
}
|
}
|
||||||
#ifdef USE_EMULATION
|
#ifdef USE_EMULATION
|
||||||
else if (CMND_EMULATION == command_code) {
|
else if (CMND_EMULATION == command_code) {
|
||||||
|
#if defined(USE_EMULATION_WEMO) && defined(USE_EMULATION_HUE)
|
||||||
if ((XdrvMailbox.payload >= EMUL_NONE) && (XdrvMailbox.payload < EMUL_MAX)) {
|
if ((XdrvMailbox.payload >= EMUL_NONE) && (XdrvMailbox.payload < EMUL_MAX)) {
|
||||||
|
#else
|
||||||
|
#ifndef USE_EMULATION_WEMO
|
||||||
|
if ((EMUL_NONE == XdrvMailbox.payload) || (EMUL_HUE == XdrvMailbox.payload)) {
|
||||||
|
#endif
|
||||||
|
#ifndef USE_EMULATION_HUE
|
||||||
|
if ((EMUL_NONE == XdrvMailbox.payload) || (EMUL_WEMO == XdrvMailbox.payload)) {
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
Settings.flag2.emulation = XdrvMailbox.payload;
|
Settings.flag2.emulation = XdrvMailbox.payload;
|
||||||
restart_flag = 2;
|
restart_flag = 2;
|
||||||
}
|
}
|
||||||
|
@ -423,7 +423,7 @@ void MqttReconnect(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_WEBSERVER) && defined(USE_EMULATION)
|
#ifdef USE_EMULATION
|
||||||
UdpDisconnect();
|
UdpDisconnect();
|
||||||
#endif // USE_EMULATION
|
#endif // USE_EMULATION
|
||||||
|
|
||||||
|
@ -716,6 +716,8 @@ void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *
|
|||||||
if (r_b) *r_b = b;
|
if (r_b) *r_b = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define POW FastPrecisePowf
|
||||||
|
|
||||||
void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) {
|
void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) {
|
||||||
float x = 0.31271f; // default medium white
|
float x = 0.31271f; // default medium white
|
||||||
float y = 0.32902f;
|
float y = 0.32902f;
|
||||||
@ -726,9 +728,9 @@ void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x,
|
|||||||
float b = (float)i_b / 255.0f;
|
float b = (float)i_b / 255.0f;
|
||||||
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
|
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
|
||||||
// Gamma correction
|
// Gamma correction
|
||||||
r = (r > 0.04045f) ? powf((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f);
|
r = (r > 0.04045f) ? POW((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f);
|
||||||
g = (g > 0.04045f) ? powf((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f);
|
g = (g > 0.04045f) ? POW((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f);
|
||||||
b = (b > 0.04045f) ? powf((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f);
|
b = (b > 0.04045f) ? POW((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f);
|
||||||
|
|
||||||
// conversion to X, Y, Z
|
// conversion to X, Y, Z
|
||||||
// Y is also the Luminance
|
// Y is also the Luminance
|
||||||
@ -762,9 +764,9 @@ void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_
|
|||||||
r = r / max; // normalize to max == 1.0
|
r = r / max; // normalize to max == 1.0
|
||||||
g = g / max;
|
g = g / max;
|
||||||
b = b / max;
|
b = b / max;
|
||||||
r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * powf(r, (1.0f / 2.4f)) - 0.055f;
|
r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * POW(r, (1.0f / 2.4f)) - 0.055f;
|
||||||
g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * powf(g, (1.0f / 2.4f)) - 0.055f;
|
g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * POW(g, (1.0f / 2.4f)) - 0.055f;
|
||||||
b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * powf(b, (1.0f / 2.4f)) - 0.055f;
|
b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * POW(b, (1.0f / 2.4f)) - 0.055f;
|
||||||
//
|
//
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, "XyToRgb XZ (%s %s) rgb (%s %s %s)",
|
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, "XyToRgb XZ (%s %s) rgb (%s %s %s)",
|
||||||
// String(X,5).c_str(), String(Z,5).c_str(),
|
// String(X,5).c_str(), String(Z,5).c_str(),
|
||||||
@ -1105,23 +1107,24 @@ void AriluxRfHandler(void)
|
|||||||
|
|
||||||
void AriluxRfInit(void)
|
void AriluxRfInit(void)
|
||||||
{
|
{
|
||||||
if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_LED4] < 99)) {
|
if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) {
|
||||||
if (Settings.last_module != Settings.module) {
|
if (Settings.last_module != Settings.module) {
|
||||||
Settings.rf_code[1][6] = 0;
|
Settings.rf_code[1][6] = 0;
|
||||||
Settings.rf_code[1][7] = 0;
|
Settings.rf_code[1][7] = 0;
|
||||||
Settings.last_module = Settings.module;
|
Settings.last_module = Settings.module;
|
||||||
}
|
}
|
||||||
arilux_rf_received_value = 0;
|
arilux_rf_received_value = 0;
|
||||||
digitalWrite(pin[GPIO_LED4], !bitRead(led_inverted, 3)); // Turn on RF
|
|
||||||
|
digitalWrite(pin[GPIO_ARIRFSEL], 0); // Turn on RF
|
||||||
attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE);
|
attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AriluxRfDisable(void)
|
void AriluxRfDisable(void)
|
||||||
{
|
{
|
||||||
if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_LED4] < 99)) {
|
if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) {
|
||||||
detachInterrupt(pin[GPIO_ARIRFRCV]);
|
detachInterrupt(pin[GPIO_ARIRFRCV]);
|
||||||
digitalWrite(pin[GPIO_LED4], bitRead(led_inverted, 3)); // Turn off RF
|
digitalWrite(pin[GPIO_ARIRFSEL], 1); // Turn off RF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_ARILUX_RF
|
#endif // USE_ARILUX_RF
|
||||||
@ -1351,8 +1354,9 @@ void LightInit(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pin[GPIO_ARIRFRCV] < 99) {
|
if (pin[GPIO_ARIRFRCV] < 99) {
|
||||||
if (pin[GPIO_LED4] < 99) {
|
if (pin[GPIO_ARIRFSEL] < 99) {
|
||||||
digitalWrite(pin[GPIO_LED4], bitRead(led_inverted, 3)); // Turn off RF
|
pinMode(pin[GPIO_ARIRFSEL], OUTPUT);
|
||||||
|
digitalWrite(pin[GPIO_ARIRFSEL], 1); // Turn off RF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ void TimerEverySecond(void)
|
|||||||
if (time == set_time) {
|
if (time == set_time) {
|
||||||
if (xtimer.days & days) {
|
if (xtimer.days & days) {
|
||||||
Settings.timer[i].arm = xtimer.repeat;
|
Settings.timer[i].arm = xtimer.repeat;
|
||||||
#ifdef USE_RULES
|
#if defined(USE_RULES) || defined(USE_SCRIPT)
|
||||||
if (3 == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands
|
if (3 == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands
|
||||||
Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1);
|
Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1);
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
@ -359,7 +359,8 @@ bool TimerCommand(void)
|
|||||||
Settings.timer[index -1].data = Settings.timer[XdrvMailbox.payload -1].data; // Copy timer
|
Settings.timer[index -1].data = Settings.timer[XdrvMailbox.payload -1].data; // Copy timer
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifndef USE_RULES
|
//#ifndef USE_RULES
|
||||||
|
#if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0
|
||||||
if (devices_present) {
|
if (devices_present) {
|
||||||
#endif
|
#endif
|
||||||
StaticJsonBuffer<256> jsonBuffer;
|
StaticJsonBuffer<256> jsonBuffer;
|
||||||
@ -437,7 +438,8 @@ bool TimerCommand(void)
|
|||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
#ifndef USE_RULES
|
//#ifndef USE_RULES
|
||||||
|
#if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0
|
||||||
} else {
|
} else {
|
||||||
Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); // No outputs defined so nothing to control
|
Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); // No outputs defined so nothing to control
|
||||||
error = 1;
|
error = 1;
|
||||||
@ -630,7 +632,7 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM =
|
|||||||
"if(%d>0){" // Create Output and Action drop down boxes
|
"if(%d>0){" // Create Output and Action drop down boxes
|
||||||
"eb('oa').innerHTML=\"<b>" D_TIMER_OUTPUT "</b> <span><select style='width:60px;' id='d1' name='d1'></select></span> <b>" D_TIMER_ACTION "</b> <select style='width:99px;' id='p1' name='p1'></select>\";"
|
"eb('oa').innerHTML=\"<b>" D_TIMER_OUTPUT "</b> <span><select style='width:60px;' id='d1' name='d1'></select></span> <b>" D_TIMER_ACTION "</b> <select style='width:99px;' id='p1' name='p1'></select>\";"
|
||||||
"o=qs('#p1');ce('" D_OFF "',o);ce('" D_ON "',o);ce('" D_TOGGLE "',o);" // Create offset direction select options
|
"o=qs('#p1');ce('" D_OFF "',o);ce('" D_ON "',o);ce('" D_TOGGLE "',o);" // Create offset direction select options
|
||||||
#ifdef USE_RULES
|
#if defined(USE_RULES) || defined(USE_SCRIPT)
|
||||||
"ce('" D_RULE "',o);"
|
"ce('" D_RULE "',o);"
|
||||||
#else
|
#else
|
||||||
"ce('" D_BLINK "',o);"
|
"ce('" D_BLINK "',o);"
|
||||||
@ -768,7 +770,7 @@ bool Xdrv09(uint8_t function)
|
|||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
#ifdef USE_TIMERS_WEB
|
#ifdef USE_TIMERS_WEB
|
||||||
case FUNC_WEB_ADD_BUTTON:
|
case FUNC_WEB_ADD_BUTTON:
|
||||||
#ifdef USE_RULES
|
#if defined(USE_RULES) || defined(USE_SCRIPT)
|
||||||
WSContentSend_P(HTTP_BTN_MENU_TIMER);
|
WSContentSend_P(HTTP_BTN_MENU_TIMER);
|
||||||
#else
|
#else
|
||||||
if (devices_present) { WSContentSend_P(HTTP_BTN_MENU_TIMER); }
|
if (devices_present) { WSContentSend_P(HTTP_BTN_MENU_TIMER); }
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_RULES
|
#ifdef USE_RULES
|
||||||
|
#ifndef USE_SCRIPT
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Rules based heavily on ESP Easy implementation
|
* Rules based heavily on ESP Easy implementation
|
||||||
*
|
*
|
||||||
@ -586,6 +587,16 @@ void RulesEverySecond(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RulesSaveBeforeRestart(void)
|
||||||
|
{
|
||||||
|
if (Settings.rule_enabled) { // Any rule enabled
|
||||||
|
char json_event[32];
|
||||||
|
|
||||||
|
strncpy_P(json_event, PSTR("{\"System\":{\"Save\":1}}"), sizeof(json_event));
|
||||||
|
RulesProcessEvent(json_event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RulesSetPower(void)
|
void RulesSetPower(void)
|
||||||
{
|
{
|
||||||
rules_new_power = XdrvMailbox.index;
|
rules_new_power = XdrvMailbox.index;
|
||||||
@ -1278,6 +1289,9 @@ bool Xdrv10(uint8_t function)
|
|||||||
case FUNC_RULES_PROCESS:
|
case FUNC_RULES_PROCESS:
|
||||||
result = RulesProcess();
|
result = RulesProcess();
|
||||||
break;
|
break;
|
||||||
|
case FUNC_SAVE_BEFORE_RESTART:
|
||||||
|
RulesSaveBeforeRestart();
|
||||||
|
break;
|
||||||
#ifdef SUPPORT_MQTT_EVENT
|
#ifdef SUPPORT_MQTT_EVENT
|
||||||
case FUNC_MQTT_DATA:
|
case FUNC_MQTT_DATA:
|
||||||
result = RulesMqttData();
|
result = RulesMqttData();
|
||||||
@ -1287,4 +1301,5 @@ bool Xdrv10(uint8_t function)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // Do not USE_SCRIPT
|
||||||
#endif // USE_RULES
|
#endif // USE_RULES
|
2238
sonoff/xdrv_10_scripter.ino
Normal file
2238
sonoff/xdrv_10_scripter.ino
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
xplg_wemohue.ino - wemo and hue support for Sonoff-Tasmota
|
xdrv_20_hue.ino - Philips Hue support for Sonoff-Tasmota
|
||||||
|
|
||||||
Copyright (C) 2019 Heiko Krupp and Theo Arends
|
Copyright (C) 2019 Heiko Krupp and Theo Arends
|
||||||
|
|
||||||
@ -17,93 +17,10 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(USE_WEBSERVER) && defined(USE_EMULATION)
|
#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE)
|
||||||
/*********************************************************************************************\
|
|
||||||
* Belkin WeMo and Philips Hue bridge emulation
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
#define UDP_BUFFER_SIZE 200 // Max UDP buffer size needed for M-SEARCH message
|
|
||||||
#define UDP_MSEARCH_SEND_DELAY 1500 // Delay in ms before M-Search response is send
|
|
||||||
|
|
||||||
#include <Ticker.h>
|
|
||||||
Ticker TickerMSearch;
|
|
||||||
|
|
||||||
IPAddress udp_remote_ip; // M-Search remote IP address
|
|
||||||
uint16_t udp_remote_port; // M-Search remote port
|
|
||||||
|
|
||||||
bool udp_connected = false;
|
|
||||||
bool udp_response_mutex = false; // M-Search response mutex to control re-entry
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* UPNP search targets
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**";
|
|
||||||
const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice";
|
|
||||||
const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all";
|
|
||||||
const char SSDP_ALL[] PROGMEM = "ssdp:all";
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* WeMo UPNP support routines
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
const char WEMO_MSEARCH[] PROGMEM =
|
|
||||||
"HTTP/1.1 200 OK\r\n"
|
|
||||||
"CACHE-CONTROL: max-age=86400\r\n"
|
|
||||||
"DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n"
|
|
||||||
"EXT:\r\n"
|
|
||||||
"LOCATION: http://%s:80/setup.xml\r\n"
|
|
||||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
|
|
||||||
"01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n"
|
|
||||||
"SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"
|
|
||||||
"ST: %s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice
|
|
||||||
"USN: uuid:%s::%s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice
|
|
||||||
"X-User-Agent: redsonic\r\n"
|
|
||||||
"\r\n";
|
|
||||||
|
|
||||||
String WemoSerialnumber(void)
|
|
||||||
{
|
|
||||||
char serial[16];
|
|
||||||
|
|
||||||
snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId());
|
|
||||||
return String(serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
String WemoUuid(void)
|
|
||||||
{
|
|
||||||
char uuid[27];
|
|
||||||
|
|
||||||
snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str());
|
|
||||||
return String(uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WemoRespondToMSearch(int echo_type)
|
|
||||||
{
|
|
||||||
char message[TOPSZ];
|
|
||||||
|
|
||||||
TickerMSearch.detach();
|
|
||||||
if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) {
|
|
||||||
char type[24];
|
|
||||||
if (1 == echo_type) { // type1 echo 1g & dot 2g
|
|
||||||
strcpy_P(type, URN_BELKIN_DEVICE);
|
|
||||||
} else { // type2 echo 2g (echo, plus, show)
|
|
||||||
strcpy_P(type, UPNP_ROOTDEVICE);
|
|
||||||
}
|
|
||||||
char response[400];
|
|
||||||
snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type);
|
|
||||||
PortUdp.write(response);
|
|
||||||
PortUdp.endPacket();
|
|
||||||
snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT));
|
|
||||||
} else {
|
|
||||||
snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE));
|
|
||||||
}
|
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"),
|
|
||||||
echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port);
|
|
||||||
|
|
||||||
udp_response_mutex = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
|
* Philips Hue bridge emulation
|
||||||
|
*
|
||||||
* Hue Bridge UPNP support routines
|
* Hue Bridge UPNP support routines
|
||||||
* Need to send 3 response packets with varying ST and USN
|
* Need to send 3 response packets with varying ST and USN
|
||||||
*
|
*
|
||||||
@ -111,6 +28,8 @@ void WemoRespondToMSearch(int echo_type)
|
|||||||
* Philips Lighting is 00:17:88:00:00:00
|
* Philips Lighting is 00:17:88:00:00:00
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define XDRV_20 20
|
||||||
|
|
||||||
const char HUE_RESPONSE[] PROGMEM =
|
const char HUE_RESPONSE[] PROGMEM =
|
||||||
"HTTP/1.1 200 OK\r\n"
|
"HTTP/1.1 200 OK\r\n"
|
||||||
"HOST: 239.255.255.250:1900\r\n"
|
"HOST: 239.255.255.250:1900\r\n"
|
||||||
@ -187,256 +106,6 @@ void HueRespondToMSearch(void)
|
|||||||
udp_response_mutex = false;
|
udp_response_mutex = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Belkin WeMo and Philips Hue bridge UDP multicast support
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
bool UdpDisconnect(void)
|
|
||||||
{
|
|
||||||
if (udp_connected) {
|
|
||||||
PortUdp.flush();
|
|
||||||
WiFiUDP::stopAll();
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED));
|
|
||||||
udp_connected = false;
|
|
||||||
}
|
|
||||||
return udp_connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UdpConnect(void)
|
|
||||||
{
|
|
||||||
if (!udp_connected) {
|
|
||||||
// Simple Service Discovery Protocol (SSDP)
|
|
||||||
if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) {
|
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED));
|
|
||||||
udp_response_mutex = false;
|
|
||||||
udp_connected = true;
|
|
||||||
} else {
|
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED));
|
|
||||||
udp_connected = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return udp_connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PollUdp(void)
|
|
||||||
{
|
|
||||||
if (udp_connected) {
|
|
||||||
if (PortUdp.parsePacket()) {
|
|
||||||
char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP/SSDP packet
|
|
||||||
|
|
||||||
int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1);
|
|
||||||
packet_buffer[len] = 0;
|
|
||||||
|
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len);
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer);
|
|
||||||
|
|
||||||
if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) {
|
|
||||||
udp_response_mutex = true;
|
|
||||||
|
|
||||||
udp_remote_ip = PortUdp.remoteIP();
|
|
||||||
udp_remote_port = PortUdp.remotePort();
|
|
||||||
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"),
|
|
||||||
// udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer);
|
|
||||||
|
|
||||||
uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); // 1500 - 2200 msec
|
|
||||||
|
|
||||||
LowerCase(packet_buffer, packet_buffer);
|
|
||||||
RemoveSpace(packet_buffer);
|
|
||||||
if (EMUL_WEMO == Settings.flag2.emulation) {
|
|
||||||
if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { // type1 echo dot 2g, echo 1g's
|
|
||||||
TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || // type2 Echo 2g (echo & echo plus)
|
|
||||||
(strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) ||
|
|
||||||
(strstr_P(packet_buffer, SSDP_ALL) != nullptr)) {
|
|
||||||
TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) ||
|
|
||||||
(strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) ||
|
|
||||||
(strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) ||
|
|
||||||
(strstr_P(packet_buffer, SSDP_ALL) != nullptr)) {
|
|
||||||
TickerMSearch.attach_ms(response_delay, HueRespondToMSearch);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
udp_response_mutex = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Wemo web server additions
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
const char WEMO_EVENTSERVICE_XML[] PROGMEM =
|
|
||||||
"<scpd xmlns=\"urn:Belkin:service-1-0\">"
|
|
||||||
"<actionList>"
|
|
||||||
"<action>"
|
|
||||||
"<name>SetBinaryState</name>"
|
|
||||||
"<argumentList>"
|
|
||||||
"<argument>"
|
|
||||||
"<retval/>"
|
|
||||||
"<name>BinaryState</name>"
|
|
||||||
"<relatedStateVariable>BinaryState</relatedStateVariable>"
|
|
||||||
"<direction>in</direction>"
|
|
||||||
"</argument>"
|
|
||||||
"</argumentList>"
|
|
||||||
"</action>"
|
|
||||||
"<action>"
|
|
||||||
"<name>GetBinaryState</name>"
|
|
||||||
"<argumentList>"
|
|
||||||
"<argument>"
|
|
||||||
"<retval/>"
|
|
||||||
"<name>BinaryState</name>"
|
|
||||||
"<relatedStateVariable>BinaryState</relatedStateVariable>"
|
|
||||||
"<direction>out</direction>"
|
|
||||||
"</argument>"
|
|
||||||
"</argumentList>"
|
|
||||||
"</action>"
|
|
||||||
"</actionList>"
|
|
||||||
"<serviceStateTable>"
|
|
||||||
"<stateVariable sendEvents=\"yes\">"
|
|
||||||
"<name>BinaryState</name>"
|
|
||||||
"<dataType>bool</dataType>"
|
|
||||||
"<defaultValue>0</defaultValue>"
|
|
||||||
"</stateVariable>"
|
|
||||||
"<stateVariable sendEvents=\"yes\">"
|
|
||||||
"<name>level</name>"
|
|
||||||
"<dataType>string</dataType>"
|
|
||||||
"<defaultValue>0</defaultValue>"
|
|
||||||
"</stateVariable>"
|
|
||||||
"</serviceStateTable>"
|
|
||||||
"</scpd>\r\n\r\n";
|
|
||||||
|
|
||||||
const char WEMO_METASERVICE_XML[] PROGMEM =
|
|
||||||
"<scpd xmlns=\"urn:Belkin:service-1-0\">"
|
|
||||||
"<specVersion>"
|
|
||||||
"<major>1</major>"
|
|
||||||
"<minor>0</minor>"
|
|
||||||
"</specVersion>"
|
|
||||||
"<actionList>"
|
|
||||||
"<action>"
|
|
||||||
"<name>GetMetaInfo</name>"
|
|
||||||
"<argumentList>"
|
|
||||||
"<retval />"
|
|
||||||
"<name>GetMetaInfo</name>"
|
|
||||||
"<relatedStateVariable>MetaInfo</relatedStateVariable>"
|
|
||||||
"<direction>in</direction>"
|
|
||||||
"</argumentList>"
|
|
||||||
"</action>"
|
|
||||||
"</actionList>"
|
|
||||||
"<serviceStateTable>"
|
|
||||||
"<stateVariable sendEvents=\"yes\">"
|
|
||||||
"<name>MetaInfo</name>"
|
|
||||||
"<dataType>string</dataType>"
|
|
||||||
"<defaultValue>0</defaultValue>"
|
|
||||||
"</stateVariable>"
|
|
||||||
"</serviceStateTable>"
|
|
||||||
"</scpd>\r\n\r\n";
|
|
||||||
|
|
||||||
const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM =
|
|
||||||
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
|
||||||
"<s:Body>"
|
|
||||||
"<u:%cetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">"
|
|
||||||
"<BinaryState>%d</BinaryState>"
|
|
||||||
"</u:%cetBinaryStateResponse>"
|
|
||||||
"</s:Body>"
|
|
||||||
"</s:Envelope>\r\n";
|
|
||||||
|
|
||||||
const char WEMO_SETUP_XML[] PROGMEM =
|
|
||||||
"<?xml version=\"1.0\"?>"
|
|
||||||
"<root xmlns=\"urn:Belkin:device-1-0\">"
|
|
||||||
"<device>"
|
|
||||||
"<deviceType>urn:Belkin:device:controllee:1</deviceType>"
|
|
||||||
"<friendlyName>{x1</friendlyName>"
|
|
||||||
"<manufacturer>Belkin International Inc.</manufacturer>"
|
|
||||||
"<modelName>Socket</modelName>"
|
|
||||||
"<modelNumber>3.1415</modelNumber>"
|
|
||||||
"<UDN>uuid:{x2</UDN>"
|
|
||||||
"<serialNumber>{x3</serialNumber>"
|
|
||||||
"<binaryState>0</binaryState>"
|
|
||||||
"<serviceList>"
|
|
||||||
"<service>"
|
|
||||||
"<serviceType>urn:Belkin:service:basicevent:1</serviceType>"
|
|
||||||
"<serviceId>urn:Belkin:serviceId:basicevent1</serviceId>"
|
|
||||||
"<controlURL>/upnp/control/basicevent1</controlURL>"
|
|
||||||
"<eventSubURL>/upnp/event/basicevent1</eventSubURL>"
|
|
||||||
"<SCPDURL>/eventservice.xml</SCPDURL>"
|
|
||||||
"</service>"
|
|
||||||
"<service>"
|
|
||||||
"<serviceType>urn:Belkin:service:metainfo:1</serviceType>"
|
|
||||||
"<serviceId>urn:Belkin:serviceId:metainfo1</serviceId>"
|
|
||||||
"<controlURL>/upnp/control/metainfo1</controlURL>"
|
|
||||||
"<eventSubURL>/upnp/event/metainfo1</eventSubURL>"
|
|
||||||
"<SCPDURL>/metainfoservice.xml</SCPDURL>"
|
|
||||||
"</service>"
|
|
||||||
"</serviceList>"
|
|
||||||
"</device>"
|
|
||||||
"</root>\r\n";
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
void HandleUpnpEvent(void)
|
|
||||||
{
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT));
|
|
||||||
|
|
||||||
char event[500];
|
|
||||||
strlcpy(event, WebServer->arg(0).c_str(), sizeof(event));
|
|
||||||
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), event);
|
|
||||||
|
|
||||||
//differentiate get and set state
|
|
||||||
char state = 'G';
|
|
||||||
if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) {
|
|
||||||
state = 'S';
|
|
||||||
uint8_t power = POWER_TOGGLE;
|
|
||||||
if (strstr_P(event, PSTR("State>1</Binary")) != nullptr) {
|
|
||||||
power = POWER_ON;
|
|
||||||
}
|
|
||||||
else if (strstr_P(event, PSTR("State>0</Binary")) != nullptr) {
|
|
||||||
power = POWER_OFF;
|
|
||||||
}
|
|
||||||
if (power != POWER_TOGGLE) {
|
|
||||||
uint8_t device = (light_type) ? devices_present : 1; // Select either a configured light or relay1
|
|
||||||
ExecuteCommandPower(device, power, SRC_WEMO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state);
|
|
||||||
WSSend(200, CT_XML, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleUpnpService(void)
|
|
||||||
{
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE));
|
|
||||||
|
|
||||||
WSSend(200, CT_PLAIN, FPSTR(WEMO_EVENTSERVICE_XML));
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleUpnpMetaService(void)
|
|
||||||
{
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_META_SERVICE));
|
|
||||||
|
|
||||||
WSSend(200, CT_PLAIN, FPSTR(WEMO_METASERVICE_XML));
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleUpnpSetupWemo(void)
|
|
||||||
{
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP));
|
|
||||||
|
|
||||||
String setup_xml = FPSTR(WEMO_SETUP_XML);
|
|
||||||
setup_xml.replace("{x1", Settings.friendlyname[0]);
|
|
||||||
setup_xml.replace("{x2", WemoUuid());
|
|
||||||
setup_xml.replace("{x3", WemoSerialnumber());
|
|
||||||
WSSend(200, CT_XML, setup_xml);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Hue web server additions
|
* Hue web server additions
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -970,19 +639,22 @@ void HandleHueApi(String *path)
|
|||||||
else HueGlobalConfig(path);
|
else HueGlobalConfig(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HueWemoAddHandlers(void)
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
bool Xdrv20(uint8_t function)
|
||||||
{
|
{
|
||||||
if (devices_present) {
|
bool result = false;
|
||||||
if (EMUL_WEMO == Settings.flag2.emulation) {
|
|
||||||
WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent);
|
if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) {
|
||||||
WebServer->on("/eventservice.xml", HandleUpnpService);
|
switch (function) {
|
||||||
WebServer->on("/metainfoservice.xml", HandleUpnpMetaService);
|
case FUNC_WEB_ADD_HANDLER:
|
||||||
WebServer->on("/setup.xml", HandleUpnpSetupWemo);
|
WebServer->on("/description.xml", HandleUpnpSetupHue);
|
||||||
}
|
break;
|
||||||
if (EMUL_HUE == Settings.flag2.emulation) {
|
|
||||||
WebServer->on("/description.xml", HandleUpnpSetupHue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_WEBSERVER && USE_EMULATION
|
#endif // USE_WEBSERVER && USE_EMULATION && USE_EMULATION_HUE
|
271
sonoff/xdrv_21_wemo.ino
Normal file
271
sonoff/xdrv_21_wemo.ino
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
xdrv_21_wemo.ino - wemo support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2019 Heiko Krupp 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined (USE_EMULATION_WEMO)
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Belkin WeMo emulation
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define XDRV_21 21
|
||||||
|
|
||||||
|
const char WEMO_MSEARCH[] PROGMEM =
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"CACHE-CONTROL: max-age=86400\r\n"
|
||||||
|
"DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n"
|
||||||
|
"EXT:\r\n"
|
||||||
|
"LOCATION: http://%s:80/setup.xml\r\n"
|
||||||
|
"OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
|
||||||
|
"01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n"
|
||||||
|
"SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"
|
||||||
|
"ST: %s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice
|
||||||
|
"USN: uuid:%s::%s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice
|
||||||
|
"X-User-Agent: redsonic\r\n"
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
String WemoSerialnumber(void)
|
||||||
|
{
|
||||||
|
char serial[16];
|
||||||
|
|
||||||
|
snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId());
|
||||||
|
return String(serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
String WemoUuid(void)
|
||||||
|
{
|
||||||
|
char uuid[27];
|
||||||
|
|
||||||
|
snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str());
|
||||||
|
return String(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WemoRespondToMSearch(int echo_type)
|
||||||
|
{
|
||||||
|
char message[TOPSZ];
|
||||||
|
|
||||||
|
TickerMSearch.detach();
|
||||||
|
if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) {
|
||||||
|
char type[24];
|
||||||
|
if (1 == echo_type) { // type1 echo 1g & dot 2g
|
||||||
|
strcpy_P(type, URN_BELKIN_DEVICE);
|
||||||
|
} else { // type2 echo 2g (echo, plus, show)
|
||||||
|
strcpy_P(type, UPNP_ROOTDEVICE);
|
||||||
|
}
|
||||||
|
char response[400];
|
||||||
|
snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type);
|
||||||
|
PortUdp.write(response);
|
||||||
|
PortUdp.endPacket();
|
||||||
|
snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT));
|
||||||
|
} else {
|
||||||
|
snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE));
|
||||||
|
}
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"),
|
||||||
|
echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port);
|
||||||
|
|
||||||
|
udp_response_mutex = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Wemo web server additions
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
const char WEMO_EVENTSERVICE_XML[] PROGMEM =
|
||||||
|
"<scpd xmlns=\"urn:Belkin:service-1-0\">"
|
||||||
|
"<actionList>"
|
||||||
|
"<action>"
|
||||||
|
"<name>SetBinaryState</name>"
|
||||||
|
"<argumentList>"
|
||||||
|
"<argument>"
|
||||||
|
"<retval/>"
|
||||||
|
"<name>BinaryState</name>"
|
||||||
|
"<relatedStateVariable>BinaryState</relatedStateVariable>"
|
||||||
|
"<direction>in</direction>"
|
||||||
|
"</argument>"
|
||||||
|
"</argumentList>"
|
||||||
|
"</action>"
|
||||||
|
"<action>"
|
||||||
|
"<name>GetBinaryState</name>"
|
||||||
|
"<argumentList>"
|
||||||
|
"<argument>"
|
||||||
|
"<retval/>"
|
||||||
|
"<name>BinaryState</name>"
|
||||||
|
"<relatedStateVariable>BinaryState</relatedStateVariable>"
|
||||||
|
"<direction>out</direction>"
|
||||||
|
"</argument>"
|
||||||
|
"</argumentList>"
|
||||||
|
"</action>"
|
||||||
|
"</actionList>"
|
||||||
|
"<serviceStateTable>"
|
||||||
|
"<stateVariable sendEvents=\"yes\">"
|
||||||
|
"<name>BinaryState</name>"
|
||||||
|
"<dataType>bool</dataType>"
|
||||||
|
"<defaultValue>0</defaultValue>"
|
||||||
|
"</stateVariable>"
|
||||||
|
"<stateVariable sendEvents=\"yes\">"
|
||||||
|
"<name>level</name>"
|
||||||
|
"<dataType>string</dataType>"
|
||||||
|
"<defaultValue>0</defaultValue>"
|
||||||
|
"</stateVariable>"
|
||||||
|
"</serviceStateTable>"
|
||||||
|
"</scpd>\r\n\r\n";
|
||||||
|
|
||||||
|
const char WEMO_METASERVICE_XML[] PROGMEM =
|
||||||
|
"<scpd xmlns=\"urn:Belkin:service-1-0\">"
|
||||||
|
"<specVersion>"
|
||||||
|
"<major>1</major>"
|
||||||
|
"<minor>0</minor>"
|
||||||
|
"</specVersion>"
|
||||||
|
"<actionList>"
|
||||||
|
"<action>"
|
||||||
|
"<name>GetMetaInfo</name>"
|
||||||
|
"<argumentList>"
|
||||||
|
"<retval />"
|
||||||
|
"<name>GetMetaInfo</name>"
|
||||||
|
"<relatedStateVariable>MetaInfo</relatedStateVariable>"
|
||||||
|
"<direction>in</direction>"
|
||||||
|
"</argumentList>"
|
||||||
|
"</action>"
|
||||||
|
"</actionList>"
|
||||||
|
"<serviceStateTable>"
|
||||||
|
"<stateVariable sendEvents=\"yes\">"
|
||||||
|
"<name>MetaInfo</name>"
|
||||||
|
"<dataType>string</dataType>"
|
||||||
|
"<defaultValue>0</defaultValue>"
|
||||||
|
"</stateVariable>"
|
||||||
|
"</serviceStateTable>"
|
||||||
|
"</scpd>\r\n\r\n";
|
||||||
|
|
||||||
|
const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM =
|
||||||
|
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||||
|
"<s:Body>"
|
||||||
|
"<u:%cetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">"
|
||||||
|
"<BinaryState>%d</BinaryState>"
|
||||||
|
"</u:%cetBinaryStateResponse>"
|
||||||
|
"</s:Body>"
|
||||||
|
"</s:Envelope>\r\n";
|
||||||
|
|
||||||
|
const char WEMO_SETUP_XML[] PROGMEM =
|
||||||
|
"<?xml version=\"1.0\"?>"
|
||||||
|
"<root xmlns=\"urn:Belkin:device-1-0\">"
|
||||||
|
"<device>"
|
||||||
|
"<deviceType>urn:Belkin:device:controllee:1</deviceType>"
|
||||||
|
"<friendlyName>{x1</friendlyName>"
|
||||||
|
"<manufacturer>Belkin International Inc.</manufacturer>"
|
||||||
|
"<modelName>Socket</modelName>"
|
||||||
|
"<modelNumber>3.1415</modelNumber>"
|
||||||
|
"<UDN>uuid:{x2</UDN>"
|
||||||
|
"<serialNumber>{x3</serialNumber>"
|
||||||
|
"<binaryState>0</binaryState>"
|
||||||
|
"<serviceList>"
|
||||||
|
"<service>"
|
||||||
|
"<serviceType>urn:Belkin:service:basicevent:1</serviceType>"
|
||||||
|
"<serviceId>urn:Belkin:serviceId:basicevent1</serviceId>"
|
||||||
|
"<controlURL>/upnp/control/basicevent1</controlURL>"
|
||||||
|
"<eventSubURL>/upnp/event/basicevent1</eventSubURL>"
|
||||||
|
"<SCPDURL>/eventservice.xml</SCPDURL>"
|
||||||
|
"</service>"
|
||||||
|
"<service>"
|
||||||
|
"<serviceType>urn:Belkin:service:metainfo:1</serviceType>"
|
||||||
|
"<serviceId>urn:Belkin:serviceId:metainfo1</serviceId>"
|
||||||
|
"<controlURL>/upnp/control/metainfo1</controlURL>"
|
||||||
|
"<eventSubURL>/upnp/event/metainfo1</eventSubURL>"
|
||||||
|
"<SCPDURL>/metainfoservice.xml</SCPDURL>"
|
||||||
|
"</service>"
|
||||||
|
"</serviceList>"
|
||||||
|
"</device>"
|
||||||
|
"</root>\r\n";
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
void HandleUpnpEvent(void)
|
||||||
|
{
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT));
|
||||||
|
|
||||||
|
char event[500];
|
||||||
|
strlcpy(event, WebServer->arg(0).c_str(), sizeof(event));
|
||||||
|
|
||||||
|
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), event);
|
||||||
|
|
||||||
|
//differentiate get and set state
|
||||||
|
char state = 'G';
|
||||||
|
if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) {
|
||||||
|
state = 'S';
|
||||||
|
uint8_t power = POWER_TOGGLE;
|
||||||
|
if (strstr_P(event, PSTR("State>1</Binary")) != nullptr) {
|
||||||
|
power = POWER_ON;
|
||||||
|
}
|
||||||
|
else if (strstr_P(event, PSTR("State>0</Binary")) != nullptr) {
|
||||||
|
power = POWER_OFF;
|
||||||
|
}
|
||||||
|
if (power != POWER_TOGGLE) {
|
||||||
|
uint8_t device = (light_type) ? devices_present : 1; // Select either a configured light or relay1
|
||||||
|
ExecuteCommandPower(device, power, SRC_WEMO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state);
|
||||||
|
WSSend(200, CT_XML, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleUpnpService(void)
|
||||||
|
{
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE));
|
||||||
|
|
||||||
|
WSSend(200, CT_PLAIN, FPSTR(WEMO_EVENTSERVICE_XML));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleUpnpMetaService(void)
|
||||||
|
{
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_META_SERVICE));
|
||||||
|
|
||||||
|
WSSend(200, CT_PLAIN, FPSTR(WEMO_METASERVICE_XML));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleUpnpSetupWemo(void)
|
||||||
|
{
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP));
|
||||||
|
|
||||||
|
String setup_xml = FPSTR(WEMO_SETUP_XML);
|
||||||
|
setup_xml.replace("{x1", Settings.friendlyname[0]);
|
||||||
|
setup_xml.replace("{x2", WemoUuid());
|
||||||
|
setup_xml.replace("{x3", WemoSerialnumber());
|
||||||
|
WSSend(200, CT_XML, setup_xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
bool Xdrv21(uint8_t function)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (devices_present && (EMUL_WEMO == Settings.flag2.emulation)) {
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_WEB_ADD_HANDLER:
|
||||||
|
WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent);
|
||||||
|
WebServer->on("/eventservice.xml", HandleUpnpService);
|
||||||
|
WebServer->on("/metainfoservice.xml", HandleUpnpMetaService);
|
||||||
|
WebServer->on("/setup.xml", HandleUpnpSetupWemo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_WEBSERVER && USE_EMULATION && USE_EMULATION_WEMO
|
@ -233,26 +233,27 @@ void HlwSnsInit(void)
|
|||||||
void HlwDrvInit(void)
|
void HlwDrvInit(void)
|
||||||
{
|
{
|
||||||
if (!energy_flg) {
|
if (!energy_flg) {
|
||||||
hlw_model_type = 0; // HLW8012
|
hlw_model_type = 0; // HLW8012
|
||||||
if (pin[GPIO_HJL_CF] < 99) {
|
if (pin[GPIO_HJL_CF] < 99) {
|
||||||
pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF];
|
pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF];
|
||||||
pin[GPIO_HJL_CF] = 99;
|
pin[GPIO_HJL_CF] = 99;
|
||||||
hlw_model_type = 1; // HJL-01/BL0937
|
hlw_model_type = 1; // HJL-01/BL0937
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pin[GPIO_HLW_CF] < 99) { // HLW8012 or HJL-01 based device
|
if (pin[GPIO_HLW_CF] < 99) { // HLW8012 or HJL-01 based device Power monitor
|
||||||
|
|
||||||
hlw_ui_flag = 1; // Voltage on high
|
hlw_ui_flag = 1; // Voltage on high
|
||||||
if (pin[GPIO_NRG_SEL_INV] < 99) {
|
if (pin[GPIO_NRG_SEL_INV] < 99) {
|
||||||
pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV];
|
pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV];
|
||||||
pin[GPIO_NRG_SEL_INV] = 99;
|
pin[GPIO_NRG_SEL_INV] = 99;
|
||||||
hlw_ui_flag = 0; // Voltage on low
|
hlw_ui_flag = 0; // Voltage on low
|
||||||
}
|
}
|
||||||
|
|
||||||
if (99 == pin[GPIO_NRG_SEL]) {
|
if (pin[GPIO_NRG_CF1] < 99) { // Voltage and/or Current monitor
|
||||||
energy_current_available = false;
|
if (99 == pin[GPIO_NRG_SEL]) { // Voltage and/or Current selector
|
||||||
}
|
energy_current_available = false; // Assume Voltage
|
||||||
if (99 == pin[GPIO_NRG_CF1]) {
|
}
|
||||||
|
} else {
|
||||||
energy_current_available = false;
|
energy_current_available = false;
|
||||||
energy_voltage_available = false;
|
energy_voltage_available = false;
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,7 @@ void CseEverySecond(void)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow"));
|
||||||
|
cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
EnergyUpdateToday();
|
EnergyUpdateToday();
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ void AdcEverySecond(void)
|
|||||||
int adc = AdcRead(2);
|
int adc = AdcRead(2);
|
||||||
// Steinhart-Hart equation for thermistor as temperature sensor
|
// Steinhart-Hart equation for thermistor as temperature sensor
|
||||||
double Rt = (adc * ANALOG_NTC_BRIDGE_RESISTANCE) / (1024.0 * ANALOG_V33 - (double)adc);
|
double Rt = (adc * ANALOG_NTC_BRIDGE_RESISTANCE) / (1024.0 * ANALOG_V33 - (double)adc);
|
||||||
double T = ANALOG_NTC_B_COEFFICIENT / (ANALOG_NTC_B_COEFFICIENT / ANALOG_T0 + log(Rt / ANALOG_NTC_RESISTANCE));
|
double T = ANALOG_NTC_B_COEFFICIENT / (ANALOG_NTC_B_COEFFICIENT / ANALOG_T0 + TaylorLog(Rt / ANALOG_NTC_RESISTANCE));
|
||||||
adc_temp = ConvertTemp(TO_CELSIUS(T));
|
adc_temp = ConvertTemp(TO_CELSIUS(T));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,9 +149,9 @@ void SenseairShow(bool json)
|
|||||||
GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes);
|
GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes);
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
ResponseAppend_P(PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2);
|
ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2);
|
||||||
if (senseair_type != 2) {
|
if (senseair_type != 2) {
|
||||||
ResponseAppend_P(PSTR("%s,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity);
|
ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity);
|
||||||
}
|
}
|
||||||
ResponseJsonEnd();
|
ResponseJsonEnd();
|
||||||
#ifdef USE_DOMOTICZ
|
#ifdef USE_DOMOTICZ
|
||||||
|
@ -34,55 +34,122 @@ Adafruit_SGP30 sgp;
|
|||||||
|
|
||||||
uint8_t sgp30_type = 0;
|
uint8_t sgp30_type = 0;
|
||||||
uint8_t sgp30_ready = 0;
|
uint8_t sgp30_ready = 0;
|
||||||
uint8_t sgp30_counter = 0;
|
float sgp30_abshum;
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
void sgp30_Init(void) {
|
||||||
|
if (sgp.begin()) {
|
||||||
|
sgp30_type = 1;
|
||||||
|
// snprintf_P(log_data, sizeof(log_data), PSTR("SGP: Serialnumber 0x%04X-0x%04X-0x%04X"), sgp.serialnumber[0], sgp.serialnumber[1], sgp.serialnumber[2]);
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "SGP30", 0x58);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define POW_FUNC pow
|
||||||
|
#define POW_FUNC FastPrecisePow
|
||||||
|
|
||||||
|
float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit) {
|
||||||
|
//taken from https://carnotcycle.wordpress.com/2012/08/04/how-to-convert-relative-humidity-to-absolute-humidity/
|
||||||
|
//precision is about 0.1°C in range -30 to 35°C
|
||||||
|
//August-Roche-Magnus 6.1094 exp(17.625 x T)/(T + 243.04)
|
||||||
|
//Buck (1981) 6.1121 exp(17.502 x T)/(T + 240.97)
|
||||||
|
//reference https://www.eas.ualberta.ca/jdwilson/EAS372_13/Vomel_CIRES_satvpformulae.html
|
||||||
|
float temp = NAN;
|
||||||
|
const float mw = 18.01534; // molar mass of water g/mol
|
||||||
|
const float r = 8.31447215; // Universal gas constant J/mol/K
|
||||||
|
|
||||||
|
if (isnan(temperature) || isnan(humidity) ) {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempUnit != 'C') {
|
||||||
|
temperature = (temperature - 32.0) * (5.0 / 9.0); /*conversion to [°C]*/
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = POW_FUNC(2.718281828, (17.67 * temperature) / (temperature + 243.5));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//return (6.112 * temp * humidity * 2.1674) / (273.15 + temperature); //simplified version
|
||||||
|
return (6.112 * temp * humidity * mw) / ((273.15 + temperature) * r); //long version
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SAVE_PERIOD 30
|
||||||
|
|
||||||
void Sgp30Update(void) // Perform every second to ensure proper operation of the baseline compensation algorithm
|
void Sgp30Update(void) // Perform every second to ensure proper operation of the baseline compensation algorithm
|
||||||
{
|
{
|
||||||
sgp30_ready = 0;
|
sgp30_ready = 0;
|
||||||
if (!sgp30_type) {
|
if (!sgp.IAQmeasure() || !sgp30_type) {
|
||||||
if (sgp.begin()) {
|
// retry to init every 100 seconds
|
||||||
sgp30_type = 1;
|
if (21 == (uptime %100)) {
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SGP: Serialnumber 0x%04X-0x%04X-0x%04X"), sgp.serialnumber[0], sgp.serialnumber[1], sgp.serialnumber[2]);
|
sgp30_Init();
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "SGP30", 0x58);
|
|
||||||
}
|
}
|
||||||
} else {
|
return; // Measurement failed
|
||||||
if (!sgp.IAQmeasure()) return; // Measurement failed
|
}
|
||||||
sgp30_counter++;
|
if (global_update) {
|
||||||
if (30 == sgp30_counter) {
|
// abs hum in mg/m3
|
||||||
sgp30_counter = 0;
|
sgp30_abshum=sgp30_AbsoluteHumidity(global_temperature,global_humidity,TempUnit());
|
||||||
|
sgp.setHumidity(sgp30_abshum*1000);
|
||||||
|
}
|
||||||
|
sgp30_ready = 1;
|
||||||
|
|
||||||
uint16_t TVOC_base;
|
// these should normally be stored permanently and used for fast restart
|
||||||
uint16_t eCO2_base;
|
if (!(uptime%SAVE_PERIOD)) {
|
||||||
|
// store settings every N seconds
|
||||||
|
uint16_t TVOC_base;
|
||||||
|
uint16_t eCO2_base;
|
||||||
|
|
||||||
|
if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; // Failed to get baseline readings
|
||||||
|
// snprintf_P(log_data, sizeof(log_data), PSTR("SGP: Baseline values eCO2 0x%04X, TVOC 0x%04X"), eCO2_base, TVOC_base);
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; // Failed to get baseline readings
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SGP: Baseline values eCO2 0x%04X, TVOC 0x%04X"), eCO2_base, TVOC_base);
|
|
||||||
}
|
|
||||||
sgp30_ready = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
const char HTTP_SNS_SGP30[] PROGMEM =
|
const char HTTP_SNS_SGP30[] PROGMEM =
|
||||||
"{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
"{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||||
"{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}";
|
"{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}";
|
||||||
|
const char HTTP_SNS_AHUM[] PROGMEM = "{s}SGP30 " "Abs Humidity" "{m}%s g/m3{e}";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define D_JSON_AHUM "aHumidity"
|
||||||
|
|
||||||
void Sgp30Show(bool json)
|
void Sgp30Show(bool json)
|
||||||
{
|
{
|
||||||
if (sgp30_ready) {
|
if (sgp30_ready) {
|
||||||
|
char abs_hum[33];
|
||||||
|
|
||||||
|
if (global_update) {
|
||||||
|
// has humidity + temperature
|
||||||
|
dtostrfd(sgp30_abshum,4,abs_hum);
|
||||||
|
}
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), sgp.eCO2, sgp.TVOC);
|
ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC);
|
||||||
|
if (global_update) {
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_AHUM "\":%s"),abs_hum);
|
||||||
|
}
|
||||||
|
ResponseAppend_P(PSTR("}"));
|
||||||
#ifdef USE_DOMOTICZ
|
#ifdef USE_DOMOTICZ
|
||||||
if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2);
|
if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2);
|
||||||
#endif // USE_DOMOTICZ
|
#endif // USE_DOMOTICZ
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
} else {
|
} else {
|
||||||
WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC);
|
WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC);
|
||||||
|
if (global_update) {
|
||||||
|
WSContentSend_PD(HTTP_SNS_AHUM, abs_hum);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Interface
|
* Interface
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -93,6 +160,9 @@ bool Xsns21(uint8_t function)
|
|||||||
|
|
||||||
if (i2c_flg) {
|
if (i2c_flg) {
|
||||||
switch (function) {
|
switch (function) {
|
||||||
|
case FUNC_INIT:
|
||||||
|
sgp30_Init();
|
||||||
|
break;
|
||||||
case FUNC_EVERY_SECOND:
|
case FUNC_EVERY_SECOND:
|
||||||
Sgp30Update();
|
Sgp30Update();
|
||||||
break;
|
break;
|
||||||
@ -110,4 +180,4 @@ bool Xsns21(uint8_t function)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_SGP30
|
#endif // USE_SGP30
|
||||||
#endif // USE_I2C
|
#endif // USE_I2C
|
||||||
|
@ -374,21 +374,11 @@ void calculateColorTemperature(void)
|
|||||||
n = (xc - 0.3320F) / (0.1858F - yc);
|
n = (xc - 0.3320F) / (0.1858F - yc);
|
||||||
|
|
||||||
/* Calculate the final CCT */
|
/* Calculate the final CCT */
|
||||||
color_data.cct = (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F;
|
color_data.cct = (449.0F * FastPrecisePowf(n, 3)) + (3525.0F * FastPrecisePowf(n, 2)) + (6823.3F * n) + 5520.33F;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Taken from the Adafruit-Library
|
|
||||||
* @brief Implements missing powf function
|
|
||||||
*/
|
|
||||||
|
|
||||||
float powf(const float x, const float y)
|
|
||||||
{
|
|
||||||
return (float)(pow((double)x, (double)y));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Getters and setters for register values
|
* Getters and setters for register values
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -62,6 +62,7 @@ enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL,
|
|||||||
const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE;
|
const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE;
|
||||||
|
|
||||||
long hx_weight = 0;
|
long hx_weight = 0;
|
||||||
|
long hx_last_weight = 0;
|
||||||
long hx_sum_weight = 0;
|
long hx_sum_weight = 0;
|
||||||
long hx_offset = 0;
|
long hx_offset = 0;
|
||||||
long hx_scale = 1;
|
long hx_scale = 1;
|
||||||
@ -116,11 +117,18 @@ long HxRead()
|
|||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
void HxReset(void)
|
void HxResetPart(void)
|
||||||
{
|
{
|
||||||
hx_tare_flg = true;
|
hx_tare_flg = true;
|
||||||
hx_sum_weight = 0;
|
hx_sum_weight = 0;
|
||||||
hx_sample_count = 0;
|
hx_sample_count = 0;
|
||||||
|
hx_last_weight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HxReset(void)
|
||||||
|
{
|
||||||
|
HxResetPart();
|
||||||
|
Settings.energy_frequency_calibration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HxCalibrationStateTextJson(uint8_t msg_id)
|
void HxCalibrationStateTextJson(uint8_t msg_id)
|
||||||
@ -147,6 +155,7 @@ void HxCalibrationStateTextJson(uint8_t msg_id)
|
|||||||
* Sensor34 5 <weight in gram> - Set max weight
|
* Sensor34 5 <weight in gram> - Set max weight
|
||||||
* Sensor34 6 - Show item weigth in decigram
|
* Sensor34 6 - Show item weigth in decigram
|
||||||
* Sensor34 6 <weight in decigram> - Set item weight
|
* Sensor34 6 <weight in decigram> - Set item weight
|
||||||
|
* Sensor34 7 - Save current weight to be used as start weight on restart
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
bool HxCommand(void)
|
bool HxCommand(void)
|
||||||
@ -199,6 +208,10 @@ bool HxCommand(void)
|
|||||||
}
|
}
|
||||||
show_parms = true;
|
show_parms = true;
|
||||||
break;
|
break;
|
||||||
|
case 7: // WeightSave
|
||||||
|
Settings.energy_frequency_calibration = hx_weight;
|
||||||
|
Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
serviced = false;
|
serviced = false;
|
||||||
}
|
}
|
||||||
@ -238,8 +251,7 @@ void HxInit(void)
|
|||||||
if (!Settings.weight_reference) { Settings.weight_reference = HX_REFERENCE; }
|
if (!Settings.weight_reference) { Settings.weight_reference = HX_REFERENCE; }
|
||||||
hx_scale = Settings.weight_calibration;
|
hx_scale = Settings.weight_calibration;
|
||||||
HxRead();
|
HxRead();
|
||||||
HxReset();
|
HxResetPart();
|
||||||
|
|
||||||
hx_type = 1;
|
hx_type = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,7 +266,16 @@ void HxEvery100mSecond(void)
|
|||||||
long average = hx_sum_weight / hx_sample_count; // grams
|
long average = hx_sum_weight / hx_sample_count; // grams
|
||||||
long value = average - hx_offset; // grams
|
long value = average - hx_offset; // grams
|
||||||
hx_weight = value / hx_scale; // grams
|
hx_weight = value / hx_scale; // grams
|
||||||
if (hx_weight < 0) { hx_weight = 0; }
|
if (hx_weight < 0) {
|
||||||
|
if (Settings.energy_frequency_calibration) {
|
||||||
|
long difference = Settings.energy_frequency_calibration + hx_weight;
|
||||||
|
hx_last_weight = difference;
|
||||||
|
if (difference < 0) { HxReset(); } // Cancel last weight as there seems to be no more weight on the scale
|
||||||
|
}
|
||||||
|
hx_weight = 0;
|
||||||
|
} else {
|
||||||
|
hx_last_weight = Settings.energy_frequency_calibration;
|
||||||
|
}
|
||||||
|
|
||||||
if (hx_tare_flg) {
|
if (hx_tare_flg) {
|
||||||
hx_tare_flg = false;
|
hx_tare_flg = false;
|
||||||
@ -313,6 +334,8 @@ void HxEvery100mSecond(void)
|
|||||||
if (!hx_calibrate_timer) {
|
if (!hx_calibrate_timer) {
|
||||||
hx_calibrate_step = HX_CAL_END; // End of calibration
|
hx_calibrate_step = HX_CAL_END; // End of calibration
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
hx_weight += hx_last_weight; // grams
|
||||||
}
|
}
|
||||||
|
|
||||||
hx_sum_weight = 0;
|
hx_sum_weight = 0;
|
||||||
@ -320,6 +343,12 @@ void HxEvery100mSecond(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HxSaveBeforeRestart()
|
||||||
|
{
|
||||||
|
Settings.energy_frequency_calibration = hx_weight;
|
||||||
|
hx_sample_count = HX_SAMPLES +1; // Stop updating hx_weight
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
const char HTTP_HX711_WEIGHT[] PROGMEM =
|
const char HTTP_HX711_WEIGHT[] PROGMEM =
|
||||||
"{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
"{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||||
@ -484,6 +513,9 @@ bool Xsns34(uint8_t function)
|
|||||||
case FUNC_JSON_APPEND:
|
case FUNC_JSON_APPEND:
|
||||||
HxShow(1);
|
HxShow(1);
|
||||||
break;
|
break;
|
||||||
|
case FUNC_SAVE_BEFORE_RESTART:
|
||||||
|
HxSaveBeforeRestart();
|
||||||
|
break;
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
case FUNC_WEB_SENSOR:
|
case FUNC_WEB_SENSOR:
|
||||||
HxShow(0);
|
HxShow(0);
|
||||||
|
299
sonoff/xsns_44_sps30.ino
Normal file
299
sonoff/xsns_44_sps30.ino
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
xsns_44_sps30.ino - Sensirion SPS30
|
||||||
|
|
||||||
|
Copyright (C) 2019 Gerhard Mutz 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
#ifdef USE_SPS30
|
||||||
|
|
||||||
|
#define XSNS_44 44
|
||||||
|
|
||||||
|
#define SPS30_ADDR 0x69
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <twi.h>
|
||||||
|
|
||||||
|
uint8_t sps30_ready = 0;
|
||||||
|
struct SPS30 {
|
||||||
|
float PM1_0;
|
||||||
|
float PM2_5;
|
||||||
|
float PM4_0;
|
||||||
|
float PM10;
|
||||||
|
float NCPM0_5;
|
||||||
|
float NCPM1_0;
|
||||||
|
float NCPM2_5;
|
||||||
|
float NCPM4_0;
|
||||||
|
float NCPM10;
|
||||||
|
float TYPSIZ;
|
||||||
|
} sps30_result;
|
||||||
|
|
||||||
|
#define SPS_CMD_START_MEASUREMENT 0x0010
|
||||||
|
#define SPS_CMD_START_MEASUREMENT_ARG 0x0300
|
||||||
|
#define SPS_CMD_STOP_MEASUREMENT 0x0104
|
||||||
|
#define SPS_CMD_READ_MEASUREMENT 0x0300
|
||||||
|
#define SPS_CMD_GET_DATA_READY 0x0202
|
||||||
|
#define SPS_CMD_AUTOCLEAN_INTERVAL 0x8004
|
||||||
|
#define SPS_CMD_CLEAN 0x5607
|
||||||
|
#define SPS_CMD_GET_ACODE 0xd025
|
||||||
|
#define SPS_CMD_GET_SERIAL 0xd033
|
||||||
|
#define SPS_CMD_RESET 0xd304
|
||||||
|
#define SPS_WRITE_DELAY_US 20000
|
||||||
|
#define SPS_MAX_SERIAL_LEN 32
|
||||||
|
|
||||||
|
uint8_t sps30_calc_CRC(uint8_t *data) {
|
||||||
|
uint8_t crc = 0xFF;
|
||||||
|
for (uint8_t i = 0; i < 2; i++) {
|
||||||
|
crc ^= data[i];
|
||||||
|
for(uint8_t bit = 8; bit > 0; --bit) {
|
||||||
|
if(crc & 0x80) {
|
||||||
|
crc = (crc << 1) ^ 0x31u;
|
||||||
|
} else {
|
||||||
|
crc = (crc << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop);
|
||||||
|
|
||||||
|
void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen) {
|
||||||
|
unsigned char cmdb[2];
|
||||||
|
uint8_t tmp[3];
|
||||||
|
uint8_t index=0;
|
||||||
|
memset(data,0,dlen);
|
||||||
|
uint8_t twi_buff[64];
|
||||||
|
|
||||||
|
Wire.beginTransmission(SPS30_ADDR);
|
||||||
|
cmdb[0]=cmd>>8;
|
||||||
|
cmdb[1]=cmd;
|
||||||
|
Wire.write(cmdb,2);
|
||||||
|
Wire.endTransmission();
|
||||||
|
|
||||||
|
// need 60 bytes max
|
||||||
|
dlen/=2;
|
||||||
|
dlen*=3;
|
||||||
|
|
||||||
|
twi_readFrom(SPS30_ADDR,twi_buff,dlen,1);
|
||||||
|
|
||||||
|
uint8_t bind=0;
|
||||||
|
while (bind<dlen) {
|
||||||
|
tmp[0] = twi_buff[bind++];
|
||||||
|
tmp[1] = twi_buff[bind++];
|
||||||
|
tmp[2] = twi_buff[bind++];
|
||||||
|
if (sps30_calc_CRC(tmp)!=tmp[2]) {
|
||||||
|
// chksum error
|
||||||
|
index+=2;
|
||||||
|
} else {
|
||||||
|
data[index++]=tmp[0];
|
||||||
|
data[index++]=tmp[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sps30_cmd(uint16_t cmd) {
|
||||||
|
unsigned char cmdb[6];
|
||||||
|
Wire.beginTransmission(SPS30_ADDR);
|
||||||
|
cmdb[0]=cmd>>8;
|
||||||
|
cmdb[1]=cmd;
|
||||||
|
|
||||||
|
if (cmd==SPS_CMD_START_MEASUREMENT) {
|
||||||
|
cmdb[2]=SPS_CMD_START_MEASUREMENT_ARG>>8;
|
||||||
|
cmdb[3]=SPS_CMD_START_MEASUREMENT_ARG&0xff;
|
||||||
|
cmdb[4]=sps30_calc_CRC(&cmdb[2]);
|
||||||
|
Wire.write(cmdb,5);
|
||||||
|
} else {
|
||||||
|
Wire.write(cmdb,2);
|
||||||
|
}
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPS30_Detect() {
|
||||||
|
|
||||||
|
if (!I2cDevice(SPS30_ADDR)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t dcode[32];
|
||||||
|
sps30_get_data(SPS_CMD_GET_SERIAL,dcode,sizeof(dcode));
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("sps30 found with serial: %s"),dcode);
|
||||||
|
sps30_cmd(SPS_CMD_START_MEASUREMENT);
|
||||||
|
sps30_ready = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define D_UNIT_PM "ug/m3"
|
||||||
|
#define D_UNIT_NCPM "#/m3"
|
||||||
|
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
|
const char HTTP_SNS_SPS30_a[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_PM "{e}";
|
||||||
|
const char HTTP_SNS_SPS30_b[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_NCPM "{e}";
|
||||||
|
const char HTTP_SNS_SPS30_c[] PROGMEM ="{s}SPS30 " "TYPSIZ" "{m}%s " "um" "{e}";
|
||||||
|
#endif // USE_WEBSERVER
|
||||||
|
|
||||||
|
#define PMDP 2
|
||||||
|
|
||||||
|
#define SPS30_HOURS Settings.sps30_inuse_hours
|
||||||
|
//#define SPS30_HOURS sps30_inuse_hours
|
||||||
|
//uint8_t sps30_inuse_hours;
|
||||||
|
|
||||||
|
void SPS30_Every_Second() {
|
||||||
|
|
||||||
|
if (!sps30_ready) return;
|
||||||
|
|
||||||
|
if (uptime%10==0) {
|
||||||
|
uint8_t vars[sizeof(float)*10];
|
||||||
|
sps30_get_data(SPS_CMD_READ_MEASUREMENT,vars,sizeof(vars));
|
||||||
|
float *fp=&sps30_result.PM1_0;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint8_t array[4];
|
||||||
|
float value;
|
||||||
|
} ByteToFloat;
|
||||||
|
|
||||||
|
ByteToFloat conv;
|
||||||
|
|
||||||
|
for (uint8_t count=0; count<10; count++) {
|
||||||
|
for (uint8_t i = 0; i < 4; i++){
|
||||||
|
conv.array[3-i] = vars[count*sizeof(float)+i];
|
||||||
|
}
|
||||||
|
*fp++=conv.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uptime%3600==0 && uptime>60) {
|
||||||
|
// should auto clean once per week runtime
|
||||||
|
// so count hours, should be in Settings
|
||||||
|
SPS30_HOURS++;
|
||||||
|
if (SPS30_HOURS>(7*24)) {
|
||||||
|
sps30_cmd(SPS_CMD_CLEAN);
|
||||||
|
SPS30_HOURS=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPS30_Show(bool json) {
|
||||||
|
char str[64];
|
||||||
|
if (!sps30_ready) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json) {
|
||||||
|
dtostrfd(sps30_result.PM1_0,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"SPS30\":{\"" "PM1_0" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.PM2_5,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "PM2_5" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.PM4_0,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "PM4_0" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.PM10,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "PM10" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.NCPM0_5,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "NCPM0_5" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.NCPM1_0,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "NCPM1_0" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.NCPM2_5,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "NCPM2_5" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.NCPM4_0,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "NCPM4_0" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.NCPM10,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "NCPM10" "\":%s"), str);
|
||||||
|
dtostrfd(sps30_result.TYPSIZ,PMDP,str);
|
||||||
|
ResponseAppend_P(PSTR(",\"" "TYPSIZ" "\":%s}"), str);
|
||||||
|
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
|
} else {
|
||||||
|
dtostrfd(sps30_result.PM1_0,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 1.0",str);
|
||||||
|
dtostrfd(sps30_result.PM2_5,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 2.5",str);
|
||||||
|
dtostrfd(sps30_result.PM4_0,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 4.0",str);
|
||||||
|
dtostrfd(sps30_result.PM10,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 10",str);
|
||||||
|
dtostrfd(sps30_result.NCPM0_5,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 0.5",str);
|
||||||
|
dtostrfd(sps30_result.NCPM1_0,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 1.0",str);
|
||||||
|
dtostrfd(sps30_result.NCPM2_5,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 2.5",str);
|
||||||
|
dtostrfd(sps30_result.NCPM4_0,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 4.0",str);
|
||||||
|
dtostrfd(sps30_result.NCPM10,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 10",str);
|
||||||
|
dtostrfd(sps30_result.TYPSIZ,PMDP,str);
|
||||||
|
WSContentSend_PD(HTTP_SNS_SPS30_c,str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool XSNS_44_cmd(void) {
|
||||||
|
boolean serviced = true;
|
||||||
|
const char S_JSON_SPS30[] = "{\"" D_CMND_SENSOR "%d\":%s}";
|
||||||
|
|
||||||
|
if (XdrvMailbox.data_len > 0) {
|
||||||
|
char *cp=XdrvMailbox.data;
|
||||||
|
if (*cp=='c') {
|
||||||
|
// clean cmd
|
||||||
|
sps30_cmd(SPS_CMD_CLEAN);
|
||||||
|
cp++;
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SPS30, XSNS_44,"clean_fan");
|
||||||
|
} else {
|
||||||
|
serviced=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return serviced;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
bool Xsns44(byte function)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (i2c_flg) {
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_INIT:
|
||||||
|
SPS30_Detect();
|
||||||
|
break;
|
||||||
|
case FUNC_EVERY_SECOND:
|
||||||
|
SPS30_Every_Second();
|
||||||
|
break;
|
||||||
|
case FUNC_JSON_APPEND:
|
||||||
|
SPS30_Show(1);
|
||||||
|
break;
|
||||||
|
case FUNC_COMMAND_SENSOR:
|
||||||
|
if (XSNS_44 == XdrvMailbox.index) {
|
||||||
|
result = XSNS_44_cmd();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
|
case FUNC_WEB_SENSOR:
|
||||||
|
SPS30_Show(0);
|
||||||
|
break;
|
||||||
|
#endif // USE_WEBSERVER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_SPS30
|
||||||
|
#endif // USE_I2C
|
@ -908,11 +908,9 @@ Setting_6_5_0_10['flag3'][0].update ({
|
|||||||
'use_underscore': ('<L', (0x3A0,1,14), (None, None, ('SetOption', '"SetOption64 {}".format($)')) ),
|
'use_underscore': ('<L', (0x3A0,1,14), (None, None, ('SetOption', '"SetOption64 {}".format($)')) ),
|
||||||
})
|
})
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
# ======================================================================
|
|
||||||
Setting_6_5_0_11 = copy.deepcopy(Setting_6_5_0_10)
|
Setting_6_5_0_11 = copy.deepcopy(Setting_6_5_0_10)
|
||||||
Setting_6_5_0_11['flag3'][0].update ({
|
Setting_6_5_0_11['flag3'][0].update ({
|
||||||
'tuya_show_dimmer': ('<L', (0x3A0,1,15), (None, None, ('SetOption', '"SetOption65 {}".format($)')) ),
|
'tuya_show_dimmer': ('<L', (0x3A0,1,15), (None, None, ('SetOption', '"SetOption65 {}".format($)')) ),
|
||||||
})
|
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
Settings = [
|
Settings = [
|
||||||
(0x605000B, 0xe00, Setting_6_5_0_11),
|
(0x605000B, 0xe00, Setting_6_5_0_11),
|
||||||
|
@ -106,7 +106,9 @@ a_setoption = [[
|
|||||||
"Enable normal sleep instead of dynamic sleep",
|
"Enable normal sleep instead of dynamic sleep",
|
||||||
"Force local operation when button/switch topic is set",
|
"Force local operation when button/switch topic is set",
|
||||||
"Do not use retain flag on HOLD messages",
|
"Do not use retain flag on HOLD messages",
|
||||||
"","","",
|
"Do not scan relay power state at restart",
|
||||||
|
"Use _ instead of - as sensor index separator",
|
||||||
|
"",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
@ -116,7 +118,7 @@ a_setoption = [[
|
|||||||
a_features = [[
|
a_features = [[
|
||||||
"","","USE_I2C","USE_SPI",
|
"","","USE_I2C","USE_SPI",
|
||||||
"USE_DISCOVERY","USE_ARDUINO_OTA","USE_MQTT_TLS","USE_WEBSERVER",
|
"USE_DISCOVERY","USE_ARDUINO_OTA","USE_MQTT_TLS","USE_WEBSERVER",
|
||||||
"WEBSERVER_ADVERTISE","USE_EMULATION","MQTT_PUBSUBCLIENT","MQTT_TASMOTAMQTT",
|
"WEBSERVER_ADVERTISE","USE_EMULATION_HUE","MQTT_PUBSUBCLIENT","MQTT_TASMOTAMQTT",
|
||||||
"MQTT_ESPMQTTARDUINO","MQTT_HOST_DISCOVERY","USE_ARILUX_RF","USE_WS2812",
|
"MQTT_ESPMQTTARDUINO","MQTT_HOST_DISCOVERY","USE_ARILUX_RF","USE_WS2812",
|
||||||
"USE_WS2812_DMA","USE_IR_REMOTE","USE_IR_HVAC","USE_IR_RECEIVE",
|
"USE_WS2812_DMA","USE_IR_REMOTE","USE_IR_HVAC","USE_IR_RECEIVE",
|
||||||
"USE_DOMOTICZ","USE_DISPLAY","USE_HOME_ASSISTANT","USE_SERIAL_BRIDGE",
|
"USE_DOMOTICZ","USE_DISPLAY","USE_HOME_ASSISTANT","USE_SERIAL_BRIDGE",
|
||||||
@ -127,8 +129,8 @@ a_features = [[
|
|||||||
"FIRMWARE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD",
|
"FIRMWARE_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_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER",
|
||||||
"USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER",
|
"USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER",
|
||||||
"USE_RC_SWITCH","USE_ARMTRONIX_DIMMERS","","",
|
"USE_RC_SWITCH","USE_ARMTRONIX_DIMMERS","USE_SM16716","USE_SCRIPT",
|
||||||
"","","","NO_EXTRA_4K_HEAP",
|
"USE_EMULATION_WEMO","","","NO_EXTRA_4K_HEAP",
|
||||||
"VTABLES_IN_IRAM","VTABLES_IN_DRAM","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH",
|
"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"
|
"PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY","PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH","DEBUG_THEO","USE_DEBUG_DRIVER"
|
||||||
],[
|
],[
|
||||||
|
Loading…
x
Reference in New Issue
Block a user