mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 11:16:34 +00:00
Merge branch 'development' into pre-release-9.1.0
This commit is contained in:
commit
68f8ea6f39
@ -142,6 +142,7 @@
|
||||
| USE_EZOORP | - | - | - | - | - | - | - |
|
||||
| USE_EZOPH | - | - | - | - | - | - | - |
|
||||
| USE_EZOPRS | - | - | - | - | - | - | - |
|
||||
| USE_EZORGB | - | - | - | - | - | - | - |
|
||||
| USE_EZORTD | - | - | - | - | - | - | - |
|
||||
| | | | | | | | |
|
||||
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
|
||||
|
@ -16,17 +16,20 @@ All notable changes to this project will be documented in this file.
|
||||
- Support for EZO PRS sensors by Christopher Tremblay (#9659)
|
||||
- Support for EZO FLO sensors by Christopher Tremblay (#9697)
|
||||
- Support for EZO DO sensors by Christopher Tremblay (#9707)
|
||||
- Support for EZO RGB sensors by Christopher Tremblay (#9723)
|
||||
- Zigbee reduce battery drain (#9642)
|
||||
- Zigbee command ``ZbMap`` to describe Zigbee topology (#9651)
|
||||
- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR
|
||||
- Command ``Gpios 255`` to show all possible GPIO configurations
|
||||
- Command ``SwitchText`` to change JSON switch names by barbudor (#9691)
|
||||
- Command ``SetOption114 1`` to detach Swiches from Relays and enable MQTT action state for all the SwitchModes returning `{"Switch1":{"Action":"ON"}}`
|
||||
- HM10 Beacon support and refactoring by Christian Baars (#9702)
|
||||
|
||||
### Changed
|
||||
- PlatformIO library structure redesigned for compilation speed by Jason2866
|
||||
- Zigbee flash storage refactor adding commands ``ZbProbe``, ``ZbStatus2`` and ``ZbRestore`` (#9641)
|
||||
- Default otaurl in my_user_config.h to http://ota.tasmota.com/tasmota/release/tasmota.bin.gz
|
||||
- When ``SetOption73 1`` JSON result from `{"ACTION":"SINGLE"}` to `{"Button1":{"Action":"SINGLE"}}`
|
||||
|
||||
### Fixed
|
||||
- Rule Break not working as expected when ONCE is enabled (#9245)
|
||||
|
@ -87,3 +87,4 @@ Index | Define | Driver | Device | Address(es) | Description
|
||||
55 | USE_EZOPRS | xsns_78 | EZOPRS | 0x61 - 0x70 | Pressure sensor
|
||||
55 | USE_EZOFLO | xsns_78 | EZOFLO | 0x61 - 0x70 | Flow meter sensor
|
||||
55 | USE_EZODO | xsns_78 | EZODO | 0x61 - 0x70 | Disolved Oxygen sensor
|
||||
55 | USE_EZORGB | xsns_78 | EZORGB | 0x61 - 0x70 | Color sensor
|
||||
|
@ -61,9 +61,10 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||
### Added
|
||||
- Command ``Gpios 255`` to show all possible GPIO configurations
|
||||
- Command ``NoDelay`` for immediate backlog command execution by Erik Montnemery (#9544)
|
||||
- Command ``SwitchMode 15`` sending only MQTT message on switch change (#9593)
|
||||
- Command ``ShutterChange`` to increment change position (#9594)
|
||||
- Command ``SwitchMode 15`` sending only MQTT message on switch change (#9593)
|
||||
- Command ``SetOption113 1`` to set dimmer low on rotary dial after power off
|
||||
- Command ``SetOption114 1`` to detach Swiches from Relays and enable MQTT action state for all the SwitchModes
|
||||
- Command ``SwitchText`` to change JSON switch names by barbudor (#9691)
|
||||
- Zigbee command ``ZbData`` for better support of device specific data
|
||||
- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR
|
||||
@ -89,6 +90,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||
- TLS fingerprint ``#define MQTT_FINGERPRINT`` from string to hexnumbers (#9570)
|
||||
- Command ``Status`` output for disabled status types now returns {"Command":"Error"}
|
||||
- MAX31865 driver to support up to 6 thermocouples selected by ``MX31865 CS`` instead of ``SSPI CS`` (#9103)
|
||||
- When ``SetOption73 1`` JSON result from `{"ACTION":"SINGLE"}` to `{"Button1":{"Action":"SINGLE"}}`
|
||||
|
||||
### Changed
|
||||
- Command ``Gpio17`` replaces command ``Adc``
|
||||
|
@ -37,9 +37,11 @@
|
||||
#define D_JSON_BAUDRATE "Baudrate"
|
||||
#define D_JSON_BLINK "Blink"
|
||||
#define D_JSON_BLOCKED_LOOP "Blocked Loop"
|
||||
#define D_JSON_BLUE "Blue"
|
||||
#define D_JSON_BOOTVERSION "Boot"
|
||||
#define D_JSON_BOOTCOUNT "BootCount"
|
||||
#define D_JSON_BSSID "BSSId"
|
||||
#define D_JSON_BUTTON "Button"
|
||||
#define D_JSON_BUILDDATETIME "BuildDateTime"
|
||||
#define D_JSON_CHANNEL "Channel"
|
||||
#define D_JSON_CO2 "CarbonDioxide"
|
||||
@ -82,6 +84,7 @@
|
||||
#define D_JSON_FROM "from"
|
||||
#define D_JSON_GAS "Gas"
|
||||
#define D_JSON_GATEWAY "Gateway"
|
||||
#define D_JSON_GREEN "Green"
|
||||
#define D_JSON_GROUPS "Groups"
|
||||
#define D_JSON_HALTING "Halting"
|
||||
#define D_JSON_HEAPSIZE "Heap"
|
||||
@ -132,6 +135,7 @@
|
||||
#define D_JSON_PROGRAMSIZE "ProgramSize"
|
||||
#define D_JSON_PSRMAXMEMORY "PsrMax"
|
||||
#define D_JSON_PSRFREEMEMORY "PsrFree"
|
||||
#define D_JSON_RED "Red"
|
||||
#define D_JSON_REFERENCETEMPERATURE "ReferenceTemperature"
|
||||
#define D_JSON_REMAINING "Remaining"
|
||||
#define D_JSON_RESET "Reset"
|
||||
@ -728,6 +732,8 @@ const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSO
|
||||
const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}";
|
||||
const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}";
|
||||
|
||||
const char S_JSON_SVALUE_ACTION_SVALUE[] PROGMEM = "{\"%s\":{\"Action\":\"%s\"}}";
|
||||
|
||||
const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}";
|
||||
|
||||
const char JSON_SNS_ILLUMINANCE[] PROGMEM = ",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}";
|
||||
@ -787,6 +793,9 @@ const char HTTP_SNS_O2[] PROGMEM = "{s}%s " D_O2 "{
|
||||
const char HTTP_SNS_LITERS[] PROGMEM = "{s}%s " D_VOLUME "{m}%s " D_UNIT_LITERS "{e}";
|
||||
const char HTTP_SNS_LPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_LITERS_PER_MIN "{e}";
|
||||
const char HTTP_SNS_DO[] PROGMEM = "{s}%s " D_DO "{m}%s " D_UNIT_PARTS_PER_MILLION "{e}";
|
||||
const char HTTP_SNS_COLOR_RED[] PROGMEM = "{s}%s " D_COLOR_RED "{m}%u " "{e}";
|
||||
const char HTTP_SNS_COLOR_GREEN[] PROGMEM = "{s}%s " D_COLOR_GREEN "{m}%u " "{e}";
|
||||
const char HTTP_SNS_COLOR_BLUE[] PROGMEM = "{s}%s " D_COLOR_BLUE "{m}%u " "{e}";
|
||||
|
||||
const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU;
|
||||
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
it-IT.h - localization for Italian - Italy for Tasmota
|
||||
|
||||
Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 30.10.2020
|
||||
Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 02.11.2020
|
||||
|
||||
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
|
||||
@ -84,7 +84,7 @@
|
||||
#define D_DISABLED "Disabilitato/a"
|
||||
#define D_DISTANCE "Distanza"
|
||||
#define D_DNS_SERVER "Server DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DO "Ossigeno dissolto"
|
||||
#define D_DONE "Completato"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -501,9 +501,9 @@
|
||||
|
||||
// xsns_27_apds9960.ino
|
||||
#define D_GESTURE "Gesture"
|
||||
#define D_COLOR_RED "Red"
|
||||
#define D_COLOR_GREEN "Green"
|
||||
#define D_COLOR_BLUE "Blue"
|
||||
#define D_COLOR_RED "红"
|
||||
#define D_COLOR_GREEN "绿"
|
||||
#define D_COLOR_BLUE "蓝"
|
||||
#define D_CCT "CCT"
|
||||
#define D_PROXIMITY "Proximity"
|
||||
|
||||
|
@ -572,6 +572,7 @@
|
||||
// #define USE_EZOPRS // [I2cDriver55] Enable support for EZO's PRS sensor (+0k7 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZOFLO // [I2cDriver55] Enable support for EZO's FLO sensor (+0k4 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZODO // [I2cDriver55] Enable support for EZO's DO sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZORGB // [I2cDriver55] Enable support for EZO's RGB sensor (+0k5 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
|
||||
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
||||
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
|
||||
|
@ -44,7 +44,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
||||
uint32_t ws_clock_reverse : 1; // bit 16 (v5.8.1) - SetOption16 - Switch between clockwise or counter-clockwise
|
||||
uint32_t decimal_text : 1; // bit 17 (v5.8.1) - SetOption17 - Switch between decimal or hexadecimal output (0 = hexadecimal, 1 = decimal)
|
||||
uint32_t light_signal : 1; // bit 18 (v5.10.0c) - SetOption18 - Pair light signal with CO2 sensor
|
||||
uint32_t hass_discovery : 1; // bit 19 (v5.11.1a) - SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
|
||||
uint32_t hass_discovery : 1; // bit 19 (v5.11.1a) - SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
|
||||
uint32_t not_power_linked : 1; // bit 20 (v5.11.1f) - SetOption20 - Control power in relation to Dimmer/Color/Ct changes
|
||||
uint32_t no_power_on_check : 1; // bit 21 (v5.11.1i) - SetOption21 - Show voltage even if powered off
|
||||
uint32_t mqtt_serial : 1; // bit 22 (v5.12.0f) - CMND_SERIALSEND and CMND_SERIALLOG
|
||||
@ -139,7 +139,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
||||
typedef union { // Restricted by MISRA-C Rule 18.4 but so useful...
|
||||
uint32_t data; // Allow bit manipulation using SetOption
|
||||
struct { // SetOption114 .. SetOption145
|
||||
uint32_t spare00 : 1; // bit 0
|
||||
uint32_t mqtt_switches : 1; // bit 0 (V9.0.0.3) - SetOption114 - Detach Swiches from relays and enable MQTT action state for all the SwitchModes
|
||||
//uint32_t spare00 : 1; // bit 0
|
||||
uint32_t spare01 : 1; // bit 1
|
||||
uint32_t spare02 : 1; // bit 2
|
||||
uint32_t spare03 : 1; // bit 3
|
||||
|
@ -61,23 +61,21 @@ struct TOUCH_BUTTON {
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void ButtonPullupFlag(uint8 button_bit)
|
||||
{
|
||||
void ButtonPullupFlag(uint32_t button_bit) {
|
||||
bitSet(Button.no_pullup_mask, button_bit);
|
||||
}
|
||||
|
||||
void ButtonInvertFlag(uint8 button_bit)
|
||||
{
|
||||
void ButtonInvertFlag(uint32_t button_bit) {
|
||||
bitSet(Button.inverted_mask, button_bit);
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
void ButtonTouchFlag(uint8 button_bit)
|
||||
{
|
||||
void ButtonTouchFlag(uint32_t button_bit) {
|
||||
bitSet(Button.touch_mask, button_bit);
|
||||
}
|
||||
#endif // ESP32
|
||||
void ButtonInit(void)
|
||||
{
|
||||
|
||||
void ButtonInit(void) {
|
||||
Button.present = 0;
|
||||
#ifdef ESP8266
|
||||
if ((SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type)) {
|
||||
@ -101,8 +99,7 @@ void ButtonInit(void)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ButtonSerial(uint8_t serial_in_byte)
|
||||
{
|
||||
uint8_t ButtonSerial(uint8_t serial_in_byte) {
|
||||
if (Button.dual_receive_count) {
|
||||
Button.dual_receive_count--;
|
||||
if (Button.dual_receive_count) {
|
||||
@ -133,8 +130,7 @@ uint8_t ButtonSerial(uint8_t serial_in_byte)
|
||||
* SetOption73 (0) - Decouple button from relay and send just mqtt topic
|
||||
\*********************************************************************************************/
|
||||
|
||||
void ButtonHandler(void)
|
||||
{
|
||||
void ButtonHandler(void) {
|
||||
if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit
|
||||
|
||||
uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command
|
||||
@ -355,8 +351,8 @@ void ButtonHandler(void)
|
||||
}
|
||||
}
|
||||
|
||||
void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold)
|
||||
{
|
||||
/*
|
||||
void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) {
|
||||
char scommand[CMDSZ];
|
||||
char stopic[TOPSZ];
|
||||
char mqttstate[7];
|
||||
@ -371,9 +367,21 @@ void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold)
|
||||
MqttPublish(stopic);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void ButtonLoop(void)
|
||||
{
|
||||
void MqttButtonTopic(uint32_t button_id, uint32_t action, uint32_t hold) {
|
||||
SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9);
|
||||
|
||||
if (!Settings.flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
|
||||
char scommand[10];
|
||||
snprintf_P(scommand, sizeof(scommand), PSTR(D_JSON_BUTTON "%d"), button_id);
|
||||
char mqttstate[7];
|
||||
Response_P(S_JSON_SVALUE_ACTION_SVALUE, scommand, (hold) ? SettingsText(SET_STATE_TXT4) : GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress));
|
||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, scommand);
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonLoop(void) {
|
||||
if (Button.present) {
|
||||
if (TimeReached(Button.debounce)) {
|
||||
SetNextTimeInterval(Button.debounce, Settings.button_debounce); // ButtonDebounce (50)
|
||||
|
@ -391,7 +391,7 @@ void CmndPower(void)
|
||||
|
||||
void CmndStatus(void)
|
||||
{
|
||||
uint32_t payload = XdrvMailbox.payload;
|
||||
int32_t payload = XdrvMailbox.payload;
|
||||
|
||||
if (payload > MAX_STATUS) { return; } // {"Command":"Error"}
|
||||
if (!Settings.flag.mqtt_enabled && (6 == payload)) { return; } // SetOption3 - Enable MQTT
|
||||
@ -402,7 +402,7 @@ void CmndStatus(void)
|
||||
char stemp[200];
|
||||
char stemp2[TOPSZ];
|
||||
|
||||
if (0 == payload) {
|
||||
if ((0 == payload) || (-99 == payload)) {
|
||||
uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present;
|
||||
#ifdef USE_SONOFF_IFAN
|
||||
if (IsModuleIfan()) { maxfn = 1; }
|
||||
|
@ -652,7 +652,9 @@ void ResponseAppendFeatures(void)
|
||||
#if defined(USE_I2C) && defined(USE_EZODO)
|
||||
feature7 |= 0x00000100;
|
||||
#endif
|
||||
// feature7 |= 0x00000200;
|
||||
#if defined(USE_I2C) && defined(USE_EZORGB)
|
||||
feature7 |= 0x00000200;
|
||||
#endif
|
||||
// feature7 |= 0x00000400;
|
||||
// feature7 |= 0x00000800;
|
||||
|
||||
|
@ -34,6 +34,10 @@ const uint8_t AC_PERIOD = (20 + SWITCH_FAST_PROBE_INTERVAL - 1) / SWITCH_FAST_PR
|
||||
#define SM_NO_TIMER_MASK 0xFF
|
||||
#define SM_FIRST_PRESS 0x40
|
||||
#define SM_SECOND_PRESS 0x80
|
||||
#define POWER_NONE 99
|
||||
|
||||
const char kSwitchPressStates[] PROGMEM =
|
||||
"||||POWER_INCREMENT|POWER_INV|POWER_CLEAR|POWER_RELEASE|POWER_100|";
|
||||
|
||||
#include <Ticker.h>
|
||||
|
||||
@ -52,28 +56,23 @@ struct SWITCH {
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void SwitchPullupFlag(uint16 switch_bit)
|
||||
{
|
||||
void SwitchPullupFlag(uint32 switch_bit) {
|
||||
bitSet(Switch.no_pullup_mask, switch_bit);
|
||||
}
|
||||
|
||||
void SwitchSetVirtual(uint32_t index, uint8_t state)
|
||||
{
|
||||
void SwitchSetVirtual(uint32_t index, uint32_t state) {
|
||||
Switch.virtual_state[index] = state;
|
||||
}
|
||||
|
||||
uint8_t SwitchGetVirtual(uint32_t index)
|
||||
{
|
||||
uint8_t SwitchGetVirtual(uint32_t index) {
|
||||
return Switch.virtual_state[index];
|
||||
}
|
||||
|
||||
uint8_t SwitchLastState(uint32_t index)
|
||||
{
|
||||
uint8_t SwitchLastState(uint32_t index) {
|
||||
return Switch.last_state[index];
|
||||
}
|
||||
|
||||
bool SwitchState(uint32_t index)
|
||||
{
|
||||
bool SwitchState(uint32_t index) {
|
||||
uint32_t switchmode = Settings.switchmode[index];
|
||||
return ((FOLLOW_INV == switchmode) ||
|
||||
(PUSHBUTTON_INV == switchmode) ||
|
||||
@ -86,17 +85,16 @@ bool SwitchState(uint32_t index)
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void SwitchProbe(void)
|
||||
{
|
||||
if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit
|
||||
void SwitchProbe(void) {
|
||||
if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit
|
||||
|
||||
uint8_t state_filter;
|
||||
uint8_t debounce_flags = Settings.switch_debounce % 10;
|
||||
uint8_t force_high = debounce_flags &1; // 51, 101, 151 etc
|
||||
uint8_t force_low = debounce_flags &2; // 52, 102, 152 etc
|
||||
uint8_t ac_detect = debounce_flags == 9;
|
||||
uint8_t switch_probe_interval;
|
||||
uint8_t first_change = Switch.first_change;
|
||||
uint32_t state_filter;
|
||||
uint32_t switch_probe_interval;
|
||||
uint32_t first_change = Switch.first_change;
|
||||
uint32_t debounce_flags = Settings.switch_debounce % 10;
|
||||
bool force_high = (debounce_flags &1); // 51, 101, 151 etc
|
||||
bool force_low = (debounce_flags &2); // 52, 102, 152 etc
|
||||
bool ac_detect = (debounce_flags == 9);
|
||||
|
||||
if (ac_detect) {
|
||||
switch_probe_interval = SWITCH_FAST_PROBE_INTERVAL;
|
||||
@ -117,7 +115,7 @@ void SwitchProbe(void)
|
||||
// Olimex user_switch2.c code to fix 50Hz induced pulses
|
||||
if (1 == digitalRead(Pin(GPIO_SWT1, i))) {
|
||||
|
||||
if (ac_detect) { // Enabled with SwitchDebounce x9
|
||||
if (ac_detect) { // Enabled with SwitchDebounce x9
|
||||
Switch.state[i] |= 0x80;
|
||||
if (Switch.state[i] > 0x80) {
|
||||
Switch.state[i]--;
|
||||
@ -128,9 +126,9 @@ void SwitchProbe(void)
|
||||
}
|
||||
} else {
|
||||
|
||||
if (force_high) { // Enabled with SwitchDebounce x1
|
||||
if (force_high) { // Enabled with SwitchDebounce x1
|
||||
if (1 == Switch.virtual_state[i]) {
|
||||
Switch.state[i] = state_filter; // With noisy input keep current state 1 unless constant 0
|
||||
Switch.state[i] = state_filter; // With noisy input keep current state 1 unless constant 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +141,7 @@ void SwitchProbe(void)
|
||||
}
|
||||
} else {
|
||||
|
||||
if (ac_detect) { // Enabled with SwitchDebounce x9
|
||||
if (ac_detect) { // Enabled with SwitchDebounce x9
|
||||
/*
|
||||
* Moes MS-104B and similar devices using an AC detection circuitry
|
||||
* on their switch inputs generating an ~4 ms long low pulse every
|
||||
@ -174,9 +172,9 @@ void SwitchProbe(void)
|
||||
}
|
||||
} else {
|
||||
|
||||
if (force_low) { // Enabled with SwitchDebounce x2
|
||||
if (force_low) { // Enabled with SwitchDebounce x2
|
||||
if (0 == Switch.virtual_state[i]) {
|
||||
Switch.state[i] = 0; // With noisy input keep current state 0 unless constant 1
|
||||
Switch.state[i] = 0; // With noisy input keep current state 0 unless constant 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,9 +191,8 @@ void SwitchProbe(void)
|
||||
TickerSwitch.attach_ms(switch_probe_interval, SwitchProbe); // Re-arm as core 2.3.0 does only support ONCE mode
|
||||
}
|
||||
|
||||
void SwitchInit(void)
|
||||
{
|
||||
uint8_t ac_detect = Settings.switch_debounce % 10 == 9;
|
||||
void SwitchInit(void) {
|
||||
bool ac_detect = (Settings.switch_debounce % 10 == 9);
|
||||
|
||||
Switch.present = 0;
|
||||
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
|
||||
@ -230,58 +227,64 @@ void SwitchInit(void)
|
||||
* Switch handler
|
||||
\*********************************************************************************************/
|
||||
|
||||
void SwitchHandler(uint8_t mode)
|
||||
{
|
||||
if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit
|
||||
void SwitchHandler(uint32_t mode) {
|
||||
if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit
|
||||
|
||||
uint16_t loops_per_second = 1000 / Settings.switch_debounce;
|
||||
uint32_t loops_per_second = 1000 / Settings.switch_debounce;
|
||||
|
||||
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
|
||||
if (PinUsed(GPIO_SWT1, i) || (mode)) {
|
||||
uint8_t button = Switch.virtual_state[i];
|
||||
uint8_t switchflag = POWER_TOGGLE +1;
|
||||
uint32_t button = Switch.virtual_state[i];
|
||||
uint32_t switchflag = POWER_TOGGLE +1;
|
||||
uint32_t mqtt_action = POWER_NONE;
|
||||
|
||||
if (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK)) {
|
||||
Switch.hold_timer[i]--;
|
||||
if ((Switch.hold_timer[i] & SM_TIMER_MASK) == loops_per_second * Settings.param[P_HOLD_TIME] / 25) {
|
||||
if ((Settings.switchmode[i] == PUSHHOLDMULTI) & (NOT_PRESSED == Switch.last_state[i])) {
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
|
||||
}
|
||||
if ((Settings.switchmode[i] == PUSHHOLDMULTI_INV) & (PRESSED == Switch.last_state[i])) {
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
|
||||
}
|
||||
}
|
||||
if (0 == (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK))) {
|
||||
switch (Settings.switchmode[i]) {
|
||||
case TOGGLEMULTI:
|
||||
switchflag = POWER_TOGGLE; // Toggle after hold
|
||||
switchflag = POWER_TOGGLE; // Toggle after hold
|
||||
break;
|
||||
case FOLLOWMULTI:
|
||||
switchflag = button &1; // Follow wall switch state after hold
|
||||
switchflag = button &1; // Follow wall switch state after hold
|
||||
break;
|
||||
case FOLLOWMULTI_INV:
|
||||
switchflag = ~button &1; // Follow inverted wall switch state after hold
|
||||
switchflag = ~button &1; // Follow inverted wall switch state after hold
|
||||
break;
|
||||
case PUSHHOLDMULTI:
|
||||
if (NOT_PRESSED == button) {
|
||||
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
|
||||
mqtt_action = POWER_INCREMENT;
|
||||
} else {
|
||||
Switch.hold_timer[i]= 0;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT
|
||||
mqtt_action = POWER_CLEAR;
|
||||
}
|
||||
break;
|
||||
case PUSHHOLDMULTI_INV:
|
||||
if (PRESSED == button) {
|
||||
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
|
||||
mqtt_action = POWER_INCREMENT;
|
||||
|
||||
} else {
|
||||
Switch.hold_timer[i]= 0;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT
|
||||
mqtt_action = POWER_CLEAR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT
|
||||
mqtt_action = POWER_HOLD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -291,22 +294,22 @@ void SwitchHandler(uint8_t mode)
|
||||
switch (Settings.switchmode[i]) {
|
||||
case TOGGLE:
|
||||
case PUSHBUTTON_TOGGLE:
|
||||
switchflag = POWER_TOGGLE; // Toggle
|
||||
switchflag = POWER_TOGGLE; // Toggle
|
||||
break;
|
||||
case FOLLOW:
|
||||
switchflag = button &1; // Follow wall switch state
|
||||
switchflag = button &1; // Follow wall switch state
|
||||
break;
|
||||
case FOLLOW_INV:
|
||||
switchflag = ~button &1; // Follow inverted wall switch state
|
||||
switchflag = ~button &1; // Follow inverted wall switch state
|
||||
break;
|
||||
case PUSHBUTTON:
|
||||
if (PRESSED == button) {
|
||||
switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd
|
||||
switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd
|
||||
}
|
||||
break;
|
||||
case PUSHBUTTON_INV:
|
||||
if (NOT_PRESSED == button) {
|
||||
switchflag = POWER_TOGGLE; // Toggle with releasing pushbutton from Gnd
|
||||
switchflag = POWER_TOGGLE; // Toggle with releasing pushbutton from Gnd
|
||||
}
|
||||
break;
|
||||
case PUSHBUTTONHOLD:
|
||||
@ -314,8 +317,8 @@ void SwitchHandler(uint8_t mode)
|
||||
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; // Start timer on button press
|
||||
}
|
||||
if ((NOT_PRESSED == button) && (Switch.hold_timer[i])) {
|
||||
Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer...
|
||||
switchflag = POWER_TOGGLE; // ...and Toggle
|
||||
Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer...
|
||||
switchflag = POWER_TOGGLE; // ...and Toggle
|
||||
}
|
||||
break;
|
||||
case PUSHBUTTONHOLD_INV:
|
||||
@ -323,8 +326,8 @@ void SwitchHandler(uint8_t mode)
|
||||
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; // Start timer on button press...
|
||||
}
|
||||
if ((PRESSED == button) && (Switch.hold_timer[i])) {
|
||||
Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer.
|
||||
switchflag = POWER_TOGGLE; // ...and Toggle
|
||||
Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer.
|
||||
switchflag = POWER_TOGGLE; // ...and Toggle
|
||||
}
|
||||
break;
|
||||
case TOGGLEMULTI:
|
||||
@ -332,30 +335,34 @@ void SwitchHandler(uint8_t mode)
|
||||
case FOLLOWMULTI_INV:
|
||||
if (Switch.hold_timer[i]) {
|
||||
Switch.hold_timer[i] = 0;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT
|
||||
mqtt_action = POWER_HOLD;
|
||||
} else {
|
||||
Switch.hold_timer[i] = loops_per_second / 2; // 0.5 second multi press window
|
||||
Switch.hold_timer[i] = loops_per_second / 2; // 0.5 second multi press window
|
||||
}
|
||||
break;
|
||||
case PUSHHOLDMULTI:
|
||||
if (NOT_PRESSED == button) {
|
||||
if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) {
|
||||
Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT
|
||||
mqtt_action = POWER_INV;
|
||||
}
|
||||
} else {
|
||||
if ((Switch.hold_timer[i] & SM_TIMER_MASK) > loops_per_second * Settings.param[P_HOLD_TIME] / 25) {
|
||||
if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) {
|
||||
Switch.hold_timer[i]= SM_FIRST_PRESS;
|
||||
switchflag = POWER_TOGGLE; // Toggle with pushbutton
|
||||
switchflag = POWER_TOGGLE; // Toggle with pushbutton
|
||||
}
|
||||
else{
|
||||
SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT
|
||||
mqtt_action = POWER_100;
|
||||
Switch.hold_timer[i]= 0;
|
||||
}
|
||||
} else {
|
||||
Switch.hold_timer[i]= 0;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT
|
||||
mqtt_action = POWER_RELEASE;
|
||||
}
|
||||
}
|
||||
Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10;
|
||||
@ -364,33 +371,36 @@ void SwitchHandler(uint8_t mode)
|
||||
if (PRESSED == button) {
|
||||
if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) {
|
||||
Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT
|
||||
mqtt_action = POWER_INV;
|
||||
}
|
||||
} else {
|
||||
if ((Switch.hold_timer[i] & SM_TIMER_MASK)> loops_per_second * Settings.param[P_HOLD_TIME] / 25) {
|
||||
if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) {
|
||||
Switch.hold_timer[i]= SM_FIRST_PRESS;
|
||||
switchflag = POWER_TOGGLE; // Toggle with pushbutton
|
||||
switchflag = POWER_TOGGLE; // Toggle with pushbutton
|
||||
}
|
||||
else{
|
||||
SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT
|
||||
mqtt_action = POWER_100;
|
||||
Switch.hold_timer[i]= 0;
|
||||
}
|
||||
} else {
|
||||
Switch.hold_timer[i]= 0;
|
||||
SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT
|
||||
SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT
|
||||
mqtt_action = POWER_RELEASE;
|
||||
}
|
||||
}
|
||||
Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10;
|
||||
break;
|
||||
case PUSHON:
|
||||
if (PRESSED == button) {
|
||||
switchflag = POWER_ON; // Power ON with pushbutton to Gnd
|
||||
switchflag = POWER_ON; // Power ON with pushbutton to Gnd
|
||||
}
|
||||
break;
|
||||
case PUSHON_INV:
|
||||
if (NOT_PRESSED == button) {
|
||||
switchflag = POWER_ON; // Power ON with releasing pushbutton from Gnd
|
||||
switchflag = POWER_ON; // Power ON with releasing pushbutton from Gnd
|
||||
}
|
||||
break;
|
||||
case PUSH_IGNORE:
|
||||
@ -400,16 +410,34 @@ void SwitchHandler(uint8_t mode)
|
||||
Switch.last_state[i] = button;
|
||||
}
|
||||
if (switchflag <= POWER_TOGGLE) {
|
||||
if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT
|
||||
ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present)
|
||||
if (!Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Swiches from relays and enable MQTT action state for all the SwitchModes
|
||||
if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT
|
||||
ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present)
|
||||
}
|
||||
} else { mqtt_action = switchflag; }
|
||||
}
|
||||
if ((mqtt_action != POWER_NONE) && Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Swiches from relays and enable MQTT action state for all the SwitchModes
|
||||
if (!Settings.flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
|
||||
char mqtt_state_str[16];
|
||||
char *mqtt_state = mqtt_state_str;
|
||||
if (mqtt_action <= 3) {
|
||||
if (mqtt_action != 3) { SendKey(KEY_SWITCH, i +1, mqtt_action); }
|
||||
mqtt_state = SettingsText(SET_STATE_TXT1 + mqtt_action);
|
||||
} else {
|
||||
GetTextIndexed(mqtt_state_str, sizeof(mqtt_state_str), mqtt_action, kSwitchPressStates);
|
||||
}
|
||||
Response_P(S_JSON_SVALUE_ACTION_SVALUE, GetSwitchText(i).c_str(), mqtt_state);
|
||||
char scommand[10];
|
||||
snprintf_P(scommand, sizeof(scommand), PSTR(D_JSON_SWITCH "%d"), i +1);
|
||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, scommand);
|
||||
}
|
||||
mqtt_action = POWER_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchLoop(void)
|
||||
{
|
||||
void SwitchLoop(void) {
|
||||
if (Switch.present) {
|
||||
if (TimeReached(Switch.debounce)) {
|
||||
SetNextTimeInterval(Switch.debounce, Settings.switch_debounce);
|
||||
|
@ -497,7 +497,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state)
|
||||
XdrvCall(FUNC_ANY_KEY);
|
||||
XdrvMailbox.payload = payload_save;
|
||||
#ifdef USE_PWM_DIMMER
|
||||
result = true;
|
||||
if (PWM_DIMMER == TasmotaGlobal.module_type) result = true;
|
||||
}
|
||||
#endif // USE_PWM_DIMMER
|
||||
return result;
|
||||
|
@ -136,7 +136,8 @@
|
||||
//#define USE_EZOO2 // [I2cDriver55] Enable support for EZO's O2 sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
//#define USE_EZOPRS // [I2cDriver55] Enable support for EZO's PRS sensor (+0k7 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
//#define USE_EZOFLO // [I2cDriver55] Enable support for EZO's FLO sensor (+0k4 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZODO // [I2cDriver55] Enable support for EZO's DO sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZODO // [I2cDriver55] Enable support for EZO's DO sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZORGB // [I2cDriver55] Enable support for EZO's RGB sensor (+0k5 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
|
||||
#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code)
|
||||
#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code)
|
||||
|
@ -352,13 +352,11 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain
|
||||
* prefix 6 = tele using subtopic or RESULT
|
||||
*/
|
||||
char romram[64];
|
||||
char stopic[TOPSZ];
|
||||
|
||||
snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); // SetOption4 - Switch between MQTT RESULT or COMMAND
|
||||
for (uint32_t i = 0; i < strlen(romram); i++) {
|
||||
romram[i] = toupper(romram[i]);
|
||||
}
|
||||
UpperCase(romram, romram);
|
||||
|
||||
prefix &= 3;
|
||||
char stopic[TOPSZ];
|
||||
GetTopic_P(stopic, prefix, TasmotaGlobal.mqtt_topic, romram);
|
||||
MqttPublish(stopic, retained);
|
||||
|
||||
|
@ -1618,8 +1618,8 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) {
|
||||
if ((0x0000 == profileid) && (0x00 == srcendpoint)) {
|
||||
// ZDO request
|
||||
// Report LQI
|
||||
Z_Device & device = zigbee_devices.getShortAddr(srcaddr);
|
||||
if (srcaddr != localShortAddr) {
|
||||
Z_Device & device = zigbee_devices.getShortAddr(srcaddr);
|
||||
device.setLQI(linkquality);
|
||||
device.setLastSeenNow();
|
||||
}
|
||||
|
@ -86,9 +86,6 @@ const char HTTP_SNS_GESTURE[] PROGMEM = "{s}%s " D_GESTURE "{m}%s{e}";
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
|
||||
#ifdef USE_APDS9960_COLOR
|
||||
const char HTTP_SNS_COLOR_RED[] PROGMEM = "{s}%s " D_COLOR_RED "{m}%u{e}";
|
||||
const char HTTP_SNS_COLOR_GREEN[] PROGMEM = "{s}%s " D_COLOR_GREEN "{m}%u{e}";
|
||||
const char HTTP_SNS_COLOR_BLUE[] PROGMEM = "{s}%s " D_COLOR_BLUE "{m}%u{e}";
|
||||
const char HTTP_SNS_CCT[] PROGMEM = "{s}%s " D_CCT "{m}%u " D_UNIT_KELVIN "{e}";
|
||||
#endif // USE_APDS9960_COLOR
|
||||
|
||||
|
@ -373,6 +373,7 @@ class MI32SensorCallback : public NimBLEClientCallbacks {
|
||||
}
|
||||
void onDisconnect(NimBLEClient* pclient) {
|
||||
MI32.mode.connected = 0;
|
||||
MI32.mode.willReadBatt = 0;
|
||||
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("disconnected %s"), kMI32DeviceType[(MIBLEsensors[MI32.state.sensor].type)-1]);
|
||||
}
|
||||
bool onConnParamsUpdateRequest(NimBLEClient* MI32Client, const ble_gap_upd_params* params) {
|
||||
@ -859,7 +860,7 @@ void MI32StartScanTask(){
|
||||
xTaskCreatePinnedToCore(
|
||||
MI32ScanTask, /* Function to implement the task */
|
||||
"MI32ScanTask", /* Name of the task */
|
||||
4096, /* Stack size in words */
|
||||
2048, /* Stack size in words */
|
||||
NULL, /* Task input parameter */
|
||||
0, /* Priority of the task */
|
||||
NULL, /* Task handle. */
|
||||
@ -1660,7 +1661,7 @@ void MI32EverySecond(bool restart){
|
||||
if(_beacon.active == false) continue;
|
||||
_activeBeacons++;
|
||||
_beacon.time++;
|
||||
Response_P(PSTR("{\"Beacon%u\":{\"Time\":%u}}"), _beacon.time);
|
||||
Response_P(PSTR("{\"Beacon%u\":{\"Time\":%u}}"), _idx, _beacon.time);
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
if(_activeBeacons==0) MI32.mode.activeBeacon = 0;
|
||||
@ -1843,7 +1844,7 @@ bool MI32Cmd(void) {
|
||||
switch(XdrvMailbox.index){
|
||||
case 0:
|
||||
MI32.state.beaconScanCounter = 8;
|
||||
Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,PSTR("\"scanning\""));
|
||||
Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,PSTR("scanning"));
|
||||
break;
|
||||
case 1: case 2: case 3: case 4:
|
||||
char _MAC[18];
|
||||
@ -1880,7 +1881,7 @@ bool MI32Cmd(void) {
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0916{m}%u%s / %u{e}";
|
||||
const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0916a{m}%u%s / %u{e}";
|
||||
const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}";
|
||||
const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}";
|
||||
const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}";
|
||||
|
@ -18,13 +18,13 @@
|
||||
*/
|
||||
#ifdef USE_I2C
|
||||
|
||||
#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) || defined(USE_EZOO2) || defined(USE_EZOPRS) || defined(USE_EZOFLO) || defined(USE_EZODO)
|
||||
#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) || defined(USE_EZOO2) || defined(USE_EZOPRS) || defined(USE_EZOFLO) || defined(USE_EZODO) || defined(USE_EZORGB)
|
||||
#define USE_EZO
|
||||
#endif
|
||||
#if defined(USE_EZO)
|
||||
|
||||
#define D_EZO_DELAY 300 // Minimum delay for any instruction
|
||||
#define D_EZO_MAX_BUF 40 // Maximum response
|
||||
#define D_EZO_MAX_BUF 52 // Maximum response
|
||||
|
||||
const char D_EZO_NAME[] PROGMEM = "EZO";
|
||||
|
||||
|
82
tasmota/xsns_78_ezorgb.ino
Normal file
82
tasmota/xsns_78_ezorgb.ino
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
xsns_78_ezorgb.ino - EZO RGB I2C RGB sensor support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Christopher Tremblay
|
||||
|
||||
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_EZORGB
|
||||
|
||||
#define EZO_RGB_READ_LATENCY 400
|
||||
|
||||
struct EZORGB : public EZOStruct {
|
||||
EZORGB(uint32_t addr) : EZOStruct(addr), R(-1), G(-1), B(-6), Lux(0), hasLux(false) {}
|
||||
|
||||
virtual void ProcessMeasurement(void)
|
||||
{
|
||||
char data[D_EZO_MAX_BUF];
|
||||
char *next;
|
||||
// R, G, B, Lux
|
||||
|
||||
EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_RGB_READ_LATENCY);
|
||||
|
||||
R = atoi(data);
|
||||
next = strchr(data, ',') + 1;
|
||||
G = atoi(next);
|
||||
next = strchr(next, ',') + 1;
|
||||
B = atoi(next);
|
||||
|
||||
next = strstr_P(next, PSTR(",Lux"));
|
||||
hasLux = (next != nullptr);
|
||||
if (hasLux) {
|
||||
Lux = atoi(next + sizeof(",Lux") - 1);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Show(bool json, const char *name)
|
||||
{
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RED "\":%d,\"" D_JSON_GREEN "\":%d,\"" D_JSON_BLUE "\":%d"), name, R, G, B);
|
||||
if (hasLux) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%d"), Lux);
|
||||
}
|
||||
ResponseJsonEnd();
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_COLOR_RED, name, R);
|
||||
WSContentSend_PD(HTTP_SNS_COLOR_GREEN, name, G);
|
||||
WSContentSend_PD(HTTP_SNS_COLOR_BLUE, name, B);
|
||||
|
||||
if (hasLux) {
|
||||
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, name, Lux);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static const char id[] PROGMEM;
|
||||
|
||||
private:
|
||||
uint16_t R, G, B;
|
||||
uint16_t Lux;
|
||||
bool hasLux;
|
||||
};
|
||||
|
||||
const char EZORGB::id[] PROGMEM = "RGB";
|
||||
|
||||
#endif // USE_EZORGB
|
||||
#endif // USE_I2C
|
@ -106,7 +106,11 @@ const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
||||
#else
|
||||
EZOStruct::id,
|
||||
#endif
|
||||
EZOStruct::id, // "RGB"
|
||||
#ifdef USE_EZORGB
|
||||
EZORGB::id,
|
||||
#else
|
||||
EZOStruct::id,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define CREATE_EZO_CLASS(CLASS) \
|
||||
@ -267,6 +271,9 @@ private:
|
||||
#endif
|
||||
#ifdef USE_EZOHUM
|
||||
CREATE_EZO_CLASS(HUM)
|
||||
#endif
|
||||
#ifdef USE_EZORGB
|
||||
CREATE_EZO_CLASS(RGB)
|
||||
#endif
|
||||
}
|
||||
count++;
|
||||
|
@ -168,7 +168,8 @@ a_setoption = [[
|
||||
"Use friendly name in zigbee topic (use with SetOption89)",
|
||||
"Set dimmer low on rotary dial after power off"
|
||||
],[
|
||||
"","","","",
|
||||
"Detach Swiches from Relays and enable MQTT action state for all the SwitchModes",
|
||||
"","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
@ -235,7 +236,7 @@ a_features = [[
|
||||
],[
|
||||
"USE_EZOORP","USE_EZORTD","USE_EZOHUM","USE_EZOEC",
|
||||
"USE_EZOCO2","USE_EZOO2","USE_EZOPRS","USE_EZOFLO",
|
||||
"USE_EZODO","","","",
|
||||
"USE_EZODO","USE_EZORGB","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
|
Loading…
x
Reference in New Issue
Block a user