Add virtual Buttons & Switches in Digtian driver (#18223)

* add support for virtual buttons or switches

* remove DINGTIAN key from SENSOR when using buttons-switches
This commit is contained in:
Barbudor 2023-03-19 20:19:48 +01:00 committed by GitHub
parent 115105bf7c
commit 948a82d75e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 92 additions and 24 deletions

View File

@ -978,6 +978,11 @@
//#define USE_HX711 // Add support for HX711 load cell (+1k5 code)
// #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code)
//#define USE_DINGTIAN_RELAY // Add support for the Dingian board using 74'595 et 74'165 shift registers
// #define DINGTIAN_INPUTS_INVERTED // Invert input states (Hi => OFF, Low => ON)
// #define DINGTIAN_USE_AS_BUTTON // Inputs as Tasmota's virtual Buttons
// #define DINGTIAN_USE_AS_SWITCH // Inputs as Tasmota's virtual Switches
// Select none or only one of the below defines
//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k6/0k8 code)
//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+2k7/1k code)

View File

@ -22,6 +22,14 @@
#define XDRV_90 90
/********************************************************************************************************
* Check defines
*/
#if defined(DINGTIAN_USE_AS_BUTTON) && defined(DINGTIAN_USE_AS_SWITCH)
#error DINGTIAN - Only one of DINGTIAN_USE_AS_BUTTON or DINGTIAN_USE_AS_SWITCH should be defined
#endif
/********************************************************************************************************
* Global private data
*/
@ -31,6 +39,7 @@ struct DINGTIAN_DATA {
uint32_t last_inputs; // previous inputs state
uint8_t count; // number of relay and input (8 * numver of shift registers)
uint8_t first; // index of 1st Tasmota relay assigned to 1st Dingtian relays
int8_t key_offset; // index of virtual key
// pins
uint8_t pin_clk, pin_sdi, pin_q7, pin_pl, pin_rck;
} *Dingtian = nullptr;
@ -63,7 +72,11 @@ uint32_t DingtianReadWrite(uint32_t outputs)
digitalWrite(Dingtian->pin_rck, 1); // rclk pulse to load '595 into output registers
digitalWrite(Dingtian->pin_pl, 0); // re-enable '595 ouputs
#ifdef DINGTIAN_INPUTS_INVERTED
return ~inputs;
#else
return inputs;
#endif
}
/********************************************************************************************************
@ -98,16 +111,51 @@ void DingtianInit(void) {
DINGTIAN_SET_OUTPUT(Dingtian->pin_rck, 0);
Dingtian->first = TasmotaGlobal.devices_present;
Dingtian->key_offset = -1;
UpdateDevicesPresent(Dingtian->count);
AddLog(LOG_LEVEL_DEBUG, PSTR("DNGT: Dingtian relays: POWER%d to POWER%d"), Dingtian->first + 1, TasmotaGlobal.devices_present);
}
}
}
#if defined(DINGTIAN_USE_AS_BUTTON) || defined(DINGTIAN_USE_AS_SWITCH)
bool DingtianAddKey(void) {
if (Dingtian->key_offset < 0) {
Dingtian->key_offset = XdrvMailbox.index;
#ifdef DINGTIAN_USE_AS_BUTTON
AddLog(LOG_LEVEL_DEBUG, PSTR("DNGT: Dingtian inputs: Button%d to Button%d"), Dingtian->key_offset + 1, Dingtian->key_offset + Dingtian->count);
#else
AddLog(LOG_LEVEL_DEBUG, PSTR("DNGT: Dingtian inputs: Switch%d to Switch%d"), Dingtian->key_offset + 1, Dingtian->key_offset + Dingtian->count);
#endif
}
uint32_t index = XdrvMailbox.index - Dingtian->key_offset;
if (index >= Dingtian->count) {
return false;
}
XdrvMailbox.index = 0; // Default is 0 - Button will also set invert
return true;
}
#endif
/********************************************************************************************************
* Driver operations
*/
#if defined(DINGTIAN_USE_AS_BUTTON) || defined(DINGTIAN_USE_AS_SWITCH)
void DingtianLoop()
{
uint32_t inputs = DingtianReadWrite(Dingtian->outputs);
Dingtian->last_inputs = inputs;
for (int i = 0 ; i < Dingtian->count ; i++, inputs>>=1) {
#ifdef DINGTIAN_USE_AS_BUTTON
ButtonSetVirtualPinState(Dingtian->key_offset +i, inputs &1);
#else
SwitchSetVirtualPinState(Dingtian->key_offset +i, inputs &1);
#endif
}
}
#else
void DingtianLoop()
{
uint32_t inputs = DingtianReadWrite(Dingtian->outputs);
@ -131,6 +179,7 @@ void DingtianLoop()
}
}
}
#endif
void DingtianSetPower(void)
{
@ -146,30 +195,32 @@ void DingtianSetPower(void)
const char HTTP_DINGTIAN_INPUTS[] PROGMEM = "{s}DINGTIAN " D_SENSOR_INPUT "%d.." D_SENSOR_INPUT "%d{m}%s{e}";
void DingtianShow(bool json)
#if !defined(DINGTIAN_USE_AS_BUTTON) && !defined(DINGTIAN_USE_AS_SWITCH)
void DingtianJsonAppend(void)
{
if (json) {
bool first_done = false;
ResponseAppend_P(PSTR(",\"DINGTIAN\":{"));
for (int i = 0 ; i < Dingtian->count ; i++) {
if (first_done) ResponseAppend_P(PSTR(","));
ResponseAppend_P(PSTR("\"IN%d\":%d"), i +1, bitRead(Dingtian->last_inputs, i));
first_done = true;
}
ResponseAppend_P(PSTR("}"));
bool first_done = false;
ResponseAppend_P(PSTR(",\"DINGTIAN\":{"));
for (int i = 0 ; i < Dingtian->count ; i++) {
if (first_done) ResponseAppend_P(PSTR(","));
ResponseAppend_P(PSTR("\"IN%d\":%d"), i +1, bitRead(Dingtian->last_inputs, i));
first_done = true;
}
#ifdef USE_WEBSERVER
else {
char input_str[9];
for (int block_input = 0 ; block_input < Dingtian->count ; block_input += 8 ) {
for (int i = 0 ; i < 8 ; i++ )
input_str[i] = '0' + bitRead(Dingtian->last_inputs, block_input +i);
input_str[8] = '\0';
WSContentSend_P(HTTP_DINGTIAN_INPUTS, block_input, block_input +7, input_str);
}
}
#endif
ResponseAppend_P(PSTR("}"));
}
#endif
#ifdef USE_WEBSERVER
void DingtianWebSensor(void)
{
char input_str[9];
for (int block_input = 0 ; block_input < Dingtian->count ; block_input += 8 ) {
for (int i = 0 ; i < 8 ; i++ )
input_str[i] = '0' + bitRead(Dingtian->last_inputs, block_input +i);
input_str[8] = '\0';
WSContentSend_P(HTTP_DINGTIAN_INPUTS, block_input, block_input +7, input_str);
}
}
#endif
/*********************************************************************************************\
@ -179,7 +230,7 @@ void DingtianShow(bool json)
bool Xdrv90(uint32_t function) {
bool result = false;
if (FUNC_PRE_INIT == function) {
if (FUNC_SETUP_RING2 == function) {
DingtianInit();
} else if (Dingtian) {
switch (function) {
@ -190,14 +241,26 @@ bool Xdrv90(uint32_t function) {
//case FUNC_EVERY_250_MSECOND:
DingtianLoop();
break;
#if !defined(DINGTIAN_USE_AS_BUTTON) && !defined(DINGTIAN_USE_AS_SWITCH)
case FUNC_JSON_APPEND:
DingtianShow(1);
DingtianJsonAppend();
break;
#endif
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
DingtianShow(0);
DingtianWebSensor();
break;
#endif // USE_WEBSERVER
#ifdef DINGTIAN_USE_AS_BUTTON
case FUNC_ADD_BUTTON:
result = DingtianAddKey();
break;
#endif
#ifdef DINGTIAN_USE_AS_SWITCH
case FUNC_ADD_SWITCH:
result = DingtianAddKey();
break;
#endif
}
}
return result;