Files
ESPEasy/src/_P001_Switch.ino
T

252 lines
7.8 KiB
Arduino

#include "_Plugin_Helper.h"
#ifdef USES_P001
# include "src/DataStructs/PinMode.h"
# include "src/ESPEasyCore/Controller.h"
# include "src/ESPEasyCore/ESPEasyGPIO.h"
# include "src/Helpers/PortStatus.h"
# include "src/Helpers/Scheduler.h"
# include "src/Helpers/_Plugin_Helper_webform.h"
# include "src/PluginStructs/P001_data_struct.h"
// #######################################################################################################
// #################################### Plugin 001: Input Switch #########################################
// #######################################################################################################
# define PLUGIN_001
# define PLUGIN_ID_001 1
# define PLUGIN_NAME_001 "Switch input - Switch"
# define PLUGIN_VALUENAME1_001 "State"
boolean Plugin_001(uint8_t function, struct EventStruct *event, String& string)
{
boolean success = false;
// static uint8_t switchstate[TASKS_MAX];
// static uint8_t outputstate[TASKS_MAX];
// static int8_t PinMonitor[GPIO_MAX];
// static int8_t PinMonitorState[GPIO_MAX];
switch (function)
{
case PLUGIN_DEVICE_ADD:
{
auto& dev = Device[++deviceCount];
dev.Number = PLUGIN_ID_001;
dev.Type = DEVICE_TYPE_SINGLE;
dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH;
dev.PullUpOption = true;
dev.InverseLogicOption = true;
dev.ValueCount = 1;
dev.SendDataOption = true;
dev.TimerOption = true;
dev.TimerOptional = true;
break;
}
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_001);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_001));
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
// FIXME TD-er: Split functionality of this plugin into 2 new ones:
// - switch/dimmer input
// - switch output (relays) and pwm output (led) - show the duty cycle as a value
// [ https://github.com/letscontrolit/ESPEasy/issues/4400 ]
event->String1 = formatGpioName_bidirectional(F(""));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
// @giig1967g: set current task value for taking actions after changes in the task gpio
const uint32_t key = createKey(PLUGIN_GPIO, CONFIG_PIN1);
auto it = globalMapPortStatus.find(key);
if (it != globalMapPortStatus.end())
{
it->second.previousTask = event->TaskIndex;
}
const uint8_t switchtype = P001_data_struct::P001_getSwitchType(event);
{
const __FlashStringHelper *options[] = { F("Switch"), F("Dimmer") };
const int optionValues[] = { PLUGIN_001_TYPE_SWITCH, PLUGIN_001_TYPE_DIMMER };
constexpr size_t optionCount = NR_ELEMENTS(optionValues);
const FormSelectorOptions selector(optionCount, options, optionValues);
selector.addFormSelector(F("Switch Type"), F("type"), switchtype);
if (switchtype == PLUGIN_001_TYPE_DIMMER)
{
addFormNumericBox(F("Dim value"), F("dimvalue"), P001_DIMMER_VALUE, 0, 255);
}
}
{
const __FlashStringHelper *buttonOptions[] = {
F("Normal Switch"),
F("Push Button Active Low"),
F("Push Button Active High") };
/*
const int buttonOptionValues[] = {
SWITCH_TYPE_NORMAL_SWITCH,
SWITCH_TYPE_PUSH_ACTIVE_LOW,
SWITCH_TYPE_PUSH_ACTIVE_HIGH };
*/
const FormSelectorOptions selector(
NR_ELEMENTS(buttonOptions),
buttonOptions); // buttonOptionValues);
selector.addFormSelector(
F("Switch Button Type"),
F("button"),
P001_BUTTON_TYPE);
}
SwitchWebformLoad(
P001_BOOTSTATE,
P001_DEBOUNCE,
P001_DOUBLECLICK,
P001_DC_MAX_INT,
P001_LONGPRESS,
P001_LP_MIN_INT,
P001_SAFE_BTN);
# if FEATURE_MQTT_DISCOVER && FEATURE_MQTT_DEVICECLASS
if (switchtype != PLUGIN_001_TYPE_DIMMER) {
addFormSelector_binarySensorDeviceClass(F("MQTT Device class"),
F("devcls"),
P001_MQTT_DEVICECLASS);
}
# endif // if FEATURE_MQTT_DISCOVER && FEATURE_MQTT_DEVICECLASS
success = true;
break;
}
case PLUGIN_WEBFORM_SAVE:
{
P001_SWITCH_OR_DIMMER = getFormItemInt(F("type"));
if (P001_SWITCH_OR_DIMMER == PLUGIN_001_TYPE_DIMMER)
{
P001_DIMMER_VALUE = getFormItemInt(F("dimvalue"));
}
P001_BUTTON_TYPE = getFormItemInt(F("button"));
SwitchWebformSave(
event->TaskIndex,
PLUGIN_GPIO,
P001_BOOTSTATE,
P001_DEBOUNCE,
P001_DOUBLECLICK,
P001_DC_MAX_INT,
P001_LONGPRESS,
P001_LP_MIN_INT,
P001_SAFE_BTN);
# if FEATURE_MQTT_DISCOVER && FEATURE_MQTT_DEVICECLASS
P001_MQTT_DEVICECLASS = getFormItemInt(F("devcls"));
# endif // if FEATURE_MQTT_DISCOVER && FEATURE_MQTT_DEVICECLASS
success = true;
break;
}
# if FEATURE_MQTT_DISCOVER
case PLUGIN_GET_DISCOVERY_VTYPES:
if (P001_SWITCH_OR_DIMMER == PLUGIN_001_TYPE_DIMMER) {
constexpr uint8_t _par = NR_ELEMENTS(event->ParN) - 1;
for (uint8_t i = 0; i < event->Par5 && i < _par; ++i) {
event->ParN[i] = static_cast<int>(Sensor_VType::SENSOR_TYPE_DIMMER) | Sensor_VType_CAN_SET;
}
success = true;
} else {
success = getDiscoveryVType(event, Settings.TaskDevicePin1Inversed[event->TaskIndex]
? Plugin_QueryVType_BinarySensorInv
: Plugin_QueryVType_BinarySensor, 255, event->Par5);
# if FEATURE_MQTT_DEVICECLASS
string = MQTT_binary_deviceClassName(P001_MQTT_DEVICECLASS); // User selected device_cLass/dev_cls value
# endif // if FEATURE_MQTT_DEVICECLASS
}
break;
# endif // if FEATURE_MQTT_DISCOVER
case PLUGIN_INIT:
{
// apply INIT only if PORT is in range. Do not start INIT if port not set in the device page.
if (validGpio(CONFIG_PIN1))
{
success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P001_data_struct(event));
}
break;
}
case PLUGIN_TEN_PER_SECOND:
{
P001_data_struct *P001_data =
static_cast<P001_data_struct *>(getPluginTaskData(event->TaskIndex));
if (nullptr != P001_data)
{
P001_data->tenPerSecond(event);
success = true;
}
break;
}
case PLUGIN_READ:
{
// We do not actually read the pin state as this is already done 10x/second
// Instead we just send the last known state stored in Uservar
# ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_INFO))
{
addLogMove(LOG_LEVEL_INFO, concat(F("SW : State "), static_cast<int>(UserVar[event->BaseVarIndex])));
}
# endif // ifndef BUILD_NO_DEBUG
success = true;
break;
}
case PLUGIN_TASKTIMER_IN:
{
digitalWrite(event->Par1, event->Par2);
// setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
// WARNING: operator [] creates an entry in the map if key does not exist
const uint32_t key = createKey(PLUGIN_GPIO, event->Par1);
portStatusStruct tempStatus = globalMapPortStatus[key];
tempStatus.state = event->Par2;
tempStatus.mode = PIN_MODE_OUTPUT;
// sp (tempStatus.monitor) ? tempStatus.forceMonitor = 1 : tempStatus.forceMonitor = 0;
tempStatus.forceMonitor = 1; // added to send event for longpulse command
savePortStatus(key, tempStatus);
break;
}
}
return success;
}
#endif // USES_P001