Fix prep for Buttons V2

Fix prep for Buttons V2 for ESP32 (#8177)
This commit is contained in:
Theo Arends 2020-04-14 17:18:34 +02:00
parent 1de275c82b
commit fe63ddbd20
3 changed files with 330 additions and 320 deletions

View File

@ -1243,11 +1243,11 @@ void SettingsDelta(void)
Settings.ex_serial_config = TS_SERIAL_8N1; Settings.ex_serial_config = TS_SERIAL_8N1;
} }
if (Settings.version < 0x07010204) { if (Settings.version < 0x07010204) {
if (Settings.flag3.mqtt_buttons == 1) { if (Settings.flag3.mqtt_buttons == 1) {
strlcpy(Settings.ex_cors_domain, CORS_ENABLED_ALL, sizeof(Settings.ex_cors_domain)); strlcpy(Settings.ex_cors_domain, CORS_ENABLED_ALL, sizeof(Settings.ex_cors_domain));
} else { } else {
Settings.ex_cors_domain[0] = 0; Settings.ex_cors_domain[0] = 0;
} }
} }
if (Settings.version < 0x07010205) { if (Settings.version < 0x07010205) {
Settings.seriallog_level = Settings.ex_seriallog_level; // 09E -> 452 Settings.seriallog_level = Settings.ex_seriallog_level; // 09E -> 452

View File

@ -24,6 +24,7 @@
\*********************************************************************************************/ \*********************************************************************************************/
#define MAX_BUTTON_COMMANDS 5 // Max number of button commands supported #define MAX_BUTTON_COMMANDS 5 // Max number of button commands supported
const char kCommands[] PROGMEM = const char kCommands[] PROGMEM =
D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1";

View File

@ -1,316 +1,325 @@
/* /*
support_button.ino - button support for Tasmota support_button.ino - button support for Tasmota
Copyright (C) 2020 Theo Arends Copyright (C) 2020 Theo Arends
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define BUTTON_V2 //#define BUTTON_V2
#ifdef BUTTON_V2 #ifdef BUTTON_V2
/*********************************************************************************************\ /*********************************************************************************************\
* Button support * Button support
\*********************************************************************************************/ \*********************************************************************************************/
#define MAX_BUTTON_COMMANDS 3 // Max number of button commands supported #define MAX_BUTTON_COMMANDS_V2 3 // Max number of button commands supported
#define MAX_RELAY_BUTTON1 4 // Max number of relay controlled by button1 #define MAX_RELAY_BUTTON1 4 // Max number of relay controlled by button1
const char kCommands[] PROGMEM = const char kCommands[] PROGMEM =
D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1";
//D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; //D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1";
const char kMultiPress[] PROGMEM = const char kMultiPress[] PROGMEM =
"|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|"; "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|";
struct BUTTON { struct BUTTON {
unsigned long debounce = 0; // Button debounce timer unsigned long debounce = 0; // Button debounce timer
uint16_t hold_timer[MAX_KEYS] = { 0 }; // Timer for button hold uint16_t hold_timer[MAX_KEYS] = { 0 }; // Timer for button hold
uint16_t dual_code = 0; // Sonoff dual received code uint16_t dual_code = 0; // Sonoff dual received code
uint8_t last_state[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states uint8_t last_state[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states
uint8_t window_timer[MAX_KEYS] = { 0 }; // Max time between button presses to record press count uint8_t window_timer[MAX_KEYS] = { 0 }; // Max time between button presses to record press count
uint8_t press_counter[MAX_KEYS] = { 0 }; // Number of button presses within Button.window_timer uint8_t press_counter[MAX_KEYS] = { 0 }; // Number of button presses within Button.window_timer
uint8_t dual_receive_count = 0; // Sonoff dual input flag uint8_t dual_receive_count = 0; // Sonoff dual input flag
uint8_t no_pullup_mask = 0; // key no pullup flag (1 = no pullup) uint8_t no_pullup_mask = 0; // key no pullup flag (1 = no pullup)
uint8_t inverted_mask = 0; // Key inverted flag (1 = inverted) uint8_t inverted_mask = 0; // Key inverted flag (1 = inverted)
uint8_t present = 0; // Number of buttons found flag uint8_t present = 0; // Number of buttons found flag
uint8_t adc = 99; // ADC0 button number uint8_t adc = 99; // ADC0 button number
} Button; } Button;
/********************************************************************************************/ /********************************************************************************************/
void ButtonPullupFlag(uint8 button_bit) void ButtonPullupFlag(uint8 button_bit)
{ {
bitSet(Button.no_pullup_mask, button_bit); bitSet(Button.no_pullup_mask, button_bit);
} }
void ButtonInvertFlag(uint8 button_bit) void ButtonInvertFlag(uint8 button_bit)
{ {
bitSet(Button.inverted_mask, button_bit); bitSet(Button.inverted_mask, button_bit);
} }
void ButtonInit(void) void ButtonInit(void)
{ {
Button.present = 0; Button.present = 0;
for (uint32_t i = 0; i < MAX_KEYS; i++) { for (uint32_t i = 0; i < MAX_KEYS; i++) {
if (pin[GPIO_KEY1 +i] < 99) { if (pin[GPIO_KEY1 +i] < 99) {
Button.present++; Button.present++;
pinMode(pin[GPIO_KEY1 +i], bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); pinMode(pin[GPIO_KEY1 +i], bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
} }
#ifndef USE_ADC_VCC #ifndef USE_ADC_VCC
else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) { else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) {
Button.present++; Button.present++;
Button.adc = i; Button.adc = i;
} }
#endif // USE_ADC_VCC #endif // USE_ADC_VCC
} }
} }
uint8_t ButtonSerial(uint8_t serial_in_byte) uint8_t ButtonSerial(uint8_t serial_in_byte)
{ {
if (Button.dual_receive_count) { if (Button.dual_receive_count) {
Button.dual_receive_count--; Button.dual_receive_count--;
if (Button.dual_receive_count) { if (Button.dual_receive_count) {
Button.dual_code = (Button.dual_code << 8) | serial_in_byte; Button.dual_code = (Button.dual_code << 8) | serial_in_byte;
serial_in_byte = 0; serial_in_byte = 0;
} else { } else {
if (serial_in_byte != 0xA1) { if (serial_in_byte != 0xA1) {
Button.dual_code = 0; // 0xA1 - End of Sonoff dual button code Button.dual_code = 0; // 0xA1 - End of Sonoff dual button code
} }
} }
} }
if (0xA0 == serial_in_byte) { // 0xA0 - Start of Sonoff dual button code if (0xA0 == serial_in_byte) { // 0xA0 - Start of Sonoff dual button code
serial_in_byte = 0; serial_in_byte = 0;
Button.dual_code = 0; Button.dual_code = 0;
Button.dual_receive_count = 3; Button.dual_receive_count = 3;
} }
return serial_in_byte; return serial_in_byte;
} }
/*********************************************************************************************\ /*********************************************************************************************\
* Button handler with single press only or multi-press and hold on all buttons * Button handler with single press only or multi-press and hold on all buttons
* *
* ButtonDebounce (50) - Debounce time in mSec * ButtonDebounce (50) - Debounce time in mSec
* SetOption1 (0) - If set do not execute config commands * SetOption1 (0) - If set do not execute config commands
* SetOption11 (0) - If set perform single press action on double press and reverse * SetOption11 (0) - If set perform single press action on double press and reverse
* SetOption13 (0) - If set act on single press only * SetOption13 (0) - If set act on single press only
* SetOption32 (40) - Max button hold time in Seconds * SetOption32 (40) - Max button hold time in Seconds
* SetOption40 (0) - Number of 0.1 seconds until hold is discarded if SetOption1 1 and SetOption13 0 * SetOption40 (0) - Number of 0.1 seconds until hold is discarded if SetOption1 1 and SetOption13 0
* SetOption73 (0) - Decouple button from relay and send just mqtt topic * SetOption73 (0) - Decouple button from relay and send just mqtt topic
\*********************************************************************************************/ \*********************************************************************************************/
void ButtonHandler(void) void ButtonHandler(void)
{ {
if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit if (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 uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command
uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50)
char scmnd[20]; char scmnd[20];
char scommand[CMDSZ]; char scommand[CMDSZ];
char stopic[TOPSZ]; char stopic[TOPSZ];
// uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; // uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present;
// for (uint32_t button_index = 0; button_index < maxdev; button_index++) { // for (uint32_t button_index = 0; button_index < maxdev; button_index++) {
for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) {
uint8_t button = NOT_PRESSED; uint8_t button = NOT_PRESSED;
uint8_t button_present = 0; uint8_t button_present = 0;
if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { #ifdef ESP8266
button_present = 1; if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) {
if (Button.dual_code) { button_present = 1;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code); if (Button.dual_code) {
button = PRESSED; AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code);
if (0xF500 == Button.dual_code) { // Button hold button = PRESSED;
Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; // SetOption32 (40) if (0xF500 == Button.dual_code) { // Button hold
hold_time_extent = 1; Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; // SetOption32 (40)
} hold_time_extent = 1;
Button.dual_code = 0; }
} Button.dual_code = 0;
} }
else if (pin[GPIO_KEY1 +button_index] < 99) { }
button_present = 1; else
button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(Button.inverted_mask, button_index)); #endif // ESP8266
} if (pin[GPIO_KEY1 +button_index] < 99) {
#ifndef USE_ADC_VCC button_present = 1;
if (Button.adc == button_index) { button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(Button.inverted_mask, button_index));
button_present = 1; }
if (ADC0_BUTTON_INV == my_adc0) { #ifndef USE_ADC_VCC
button = (AdcRead(1) < 128); if (Button.adc == button_index) {
} button_present = 1;
else if (ADC0_BUTTON == my_adc0) { if (ADC0_BUTTON_INV == my_adc0) {
button = (AdcRead(1) > 128); button = (AdcRead(1) < 128);
} }
} else if (ADC0_BUTTON == my_adc0) {
#endif // USE_ADC_VCC button = (AdcRead(1) > 128);
}
if (button_present) { }
XdrvMailbox.index = button_index; #endif // USE_ADC_VCC
XdrvMailbox.payload = button;
if (XdrvCall(FUNC_BUTTON_PRESSED)) { if (button_present) {
// Serviced XdrvMailbox.index = button_index;
} XdrvMailbox.payload = button;
else if (SONOFF_4CHPRO == my_module_type) { if (XdrvCall(FUNC_BUTTON_PRESSED)) {
if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; } // Serviced
}
bool button_pressed = false; #ifdef ESP8266
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { else if (SONOFF_4CHPRO == my_module_type) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; }
Button.hold_timer[button_index] = loops_per_second;
button_pressed = true; bool button_pressed = false;
} if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
if ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index])) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); Button.hold_timer[button_index] = loops_per_second;
if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second button_pressed = true;
} }
if (button_pressed) { if ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index])) {
if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1);
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second
}
} if (button_pressed) {
} if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
} else { ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { }
}
if (Settings.flag.button_single && !Settings.flag3.mqtt_buttons) { // SetOption13 (0) - Allow only single button press for immediate action, SetOption73 (0) - Decouple button from relay and send just mqtt topic }
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); #endif // ESP8266
if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set else {
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
} if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
} else { if (Settings.flag.button_single && !Settings.flag3.mqtt_buttons) { // SetOption13 (0) - Allow only single button press for immediate action, SetOption73 (0) - Decouple button from relay and send just mqtt topic
Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]); if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
} }
blinks = 201;
} } else {
Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1;
if (NOT_PRESSED == button) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]);
Button.hold_timer[button_index] = 0; Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window
} else { }
Button.hold_timer[button_index]++; blinks = 201;
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action }
if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only if (NOT_PRESSED == button) {
ExecuteCommand(scmnd, SRC_BUTTON); Button.hold_timer[button_index] = 0;
} } else {
} else { Button.hold_timer[button_index]++;
if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
Button.press_counter[button_index] = 0; if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only
snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_index +1); ExecuteCommand(scmnd, SRC_BUTTON);
GetTopic_P(stopic, STAT, mqtt_topic, scommand); }
Response_P(S_JSON_COMMAND_SVALUE, "ACTION", GetStateText(3)); } else {
MqttPublish(stopic); if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold
} Button.press_counter[button_index] = 0;
SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
} else { snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_index +1);
if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer GetTopic_P(stopic, STAT, mqtt_topic, scommand);
Button.press_counter[button_index] = 0; Response_P(S_JSON_COMMAND_SVALUE, "ACTION", GetStateText(3));
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); MqttPublish(stopic);
ExecuteCommand(scmnd, SRC_BUTTON); }
} SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set
} } else {
} if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
} Button.press_counter[button_index] = 0;
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1"));
if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press ExecuteCommand(scmnd, SRC_BUTTON);
if (Button.window_timer[button_index]) { }
Button.window_timer[button_index]--; }
} else { }
if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS +6)) { }
bool single_press = false;
if (Button.press_counter[button_index] < 3) { // Single or Double press if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press
if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { if (Button.window_timer[button_index]) {
single_press = true; Button.window_timer[button_index]--;
} else { } else {
single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); // SetOption11 (0) if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS_V2 +6)) {
if ((1 == Button.present) && (2 == devices_present)) { // Single Button with two devices only bool single_press = false;
if (Settings.flag.button_swap) { // SetOption11 (0) if (Button.press_counter[button_index] < 3) { // Single or Double press
Button.press_counter[button_index] = (single_press) ? 1 : 2; #ifdef ESP8266
} if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) {
// } else { single_press = true;
// if (!Settings.flag3.mqtt_buttons && button_index != 0) { } else
// Button.press_counter[button_index] = 1; #endif // ESP8266
// } {
} single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); // SetOption11 (0)
} if ((1 == Button.present) && (2 == devices_present)) { // Single Button with two devices only
} if (Settings.flag.button_swap) { // SetOption11 (0)
#if defined(USE_LIGHT) && defined(ROTARY_V1) Button.press_counter[button_index] = (single_press) ? 1 : 2;
if (!((0 == button_index) && RotaryButtonPressed())) { }
#endif // } else {
if (!Settings.flag3.mqtt_buttons && single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set // if (!Settings.flag3.mqtt_buttons && button_index != 0) {
// Success // Button.press_counter[button_index] = 1;
} else { // }
if (Button.press_counter[button_index] < 6) { // Single to Penta press }
if (WifiState() > WIFI_RESTART) { // Wifimanager active }
restart_flag = 1; }
} #if defined(USE_LIGHT) && defined(ROTARY_V1)
if (!Settings.flag3.mqtt_buttons) { if (!((0 == button_index) && RotaryButtonPressed())) {
if (Button.press_counter[button_index] == 1) { // By default first press always send a TOGGLE (2) #endif
ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); if (!Settings.flag3.mqtt_buttons && single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
} else { // Success
SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9); // 2,3,4 and 5 press send just the key value (11,12,13 and 14) for rules } else {
if (0 == button_index) { // First button can toggle up to 4 relays if present if (Button.press_counter[button_index] < 6) { // Single to Penta press
if ((Button.press_counter[button_index] > 1 && pin[GPIO_REL1 + Button.press_counter[button_index]-1] < 99) && Button.press_counter[button_index] <= MAX_RELAY_BUTTON1) { if (WifiState() > WIFI_RESTART) { // Wifimanager active
ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally restart_flag = 1;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: Relay%d found on GPIO%d"), Button.press_counter[button_index], pin[GPIO_REL1 + Button.press_counter[button_index]-1]); }
} if (!Settings.flag3.mqtt_buttons) {
} if (Button.press_counter[button_index] == 1) { // By default first press always send a TOGGLE (2)
} ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON);
} } else {
} else { // 6 - 8 press are used to send commands SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9); // 2,3,4 and 5 press send just the key value (11,12,13 and 14) for rules
GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -6, kCommands); if (0 == button_index) { // First button can toggle up to 4 relays if present
ExecuteCommand(scmnd, SRC_BUTTON); if ((Button.press_counter[button_index] > 1 && pin[GPIO_REL1 + Button.press_counter[button_index]-1] < 99) && Button.press_counter[button_index] <= MAX_RELAY_BUTTON1) {
} ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: Relay%d found on GPIO%d"), Button.press_counter[button_index], pin[GPIO_REL1 + Button.press_counter[button_index]-1]);
if (Button.press_counter[button_index] >= 1 && Button.press_counter[button_index] <= 5) { }
char mqttstate[7]; }
}
GetTextIndexed(mqttstate, sizeof(mqttstate), Button.press_counter[button_index], kMultiPress); }
SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9); } else { // 6 - 8 press are used to send commands
snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_index +1); GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -6, kCommands);
GetTopic_P(stopic, STAT, mqtt_topic, scommand); ExecuteCommand(scmnd, SRC_BUTTON);
Response_P(S_JSON_COMMAND_SVALUE, "ACTION", mqttstate); }
MqttPublish(stopic); if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
if (Button.press_counter[button_index] >= 1 && Button.press_counter[button_index] <= 5) {
} char mqttstate[7];
}
} GetTextIndexed(mqttstate, sizeof(mqttstate), Button.press_counter[button_index], kMultiPress);
#if defined(USE_LIGHT) && defined(ROTARY_V1) SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9);
} snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_index +1);
#endif GetTopic_P(stopic, STAT, mqtt_topic, scommand);
Button.press_counter[button_index] = 0; Response_P(S_JSON_COMMAND_SVALUE, "ACTION", mqttstate);
} MqttPublish(stopic);
}
} }
} }
} }
Button.last_state[button_index] = button; #if defined(USE_LIGHT) && defined(ROTARY_V1)
} }
} #endif
Button.press_counter[button_index] = 0;
void ButtonLoop(void) }
{ }
if (Button.present) { }
if (TimeReached(Button.debounce)) { }
SetNextTimeInterval(Button.debounce, Settings.button_debounce); // ButtonDebounce (50) }
ButtonHandler(); Button.last_state[button_index] = button;
} }
} }
}
void ButtonLoop(void)
{
if (Button.present) {
if (TimeReached(Button.debounce)) {
SetNextTimeInterval(Button.debounce, Settings.button_debounce); // ButtonDebounce (50)
ButtonHandler();
}
}
}
#endif // BUTTON_V2 #endif // BUTTON_V2