From 6164a51cdafbd99af84cd338ab2ee15f263635e5 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Fri, 3 Jan 2025 23:51:54 +0100 Subject: [PATCH 1/9] [Build] Reduce code size to allow for some bugfixes in limited builds --- src/_P001_Switch.ino | 6 +- src/_P002_ADC.ino | 24 +- src/_P003_Pulse.ino | 28 +- src/_P004_Dallas.ino | 38 +- src/_P005_DHT.ino | 130 +- src/_P006_BMP085.ino | 20 +- src/_P007_PCF8591.ino | 32 +- src/_P008_RFID.ino | 21 +- src/_P009_MCP.ino | 4 - src/_P010_BH1750.ino | 23 +- src/_P011_PME.ino | 21 +- src/_P012_LCD.ino | 39 +- src/_P013_HCSR04.ino | 39 +- src/_P014_SI70xx.ino | 42 +- src/_P015_TSL2561.ino | 39 +- src/_P016_IR.ino | 6 +- src/_P017_PN532.ino | 40 +- src/_P018_Dust.ino | 127 +- src/_P019_PCF8574.ino | 4 - src/_P020_Ser2Net.ino | 23 +- src/_P021_Level.ino | 37 +- src/_P022_PCA9685.ino | 5 - src/_P023_OLED.ino | 9 +- src/_P024_MLX90614.ino | 26 +- src/_P025_ADS1115.ino | 22 +- src/_P027_INA219.ino | 20 +- src/_P028_BME280.ino | 43 +- src/_P031_SHT1X.ino | 36 +- src/_P032_MS5611.ino | 20 +- src/_P033_Dummy.ino | 25 +- src/_P034_DHT12.ino | 276 +- src/_P036_FrameOLED.ino | 19 +- src/_P037_MQTTImport.ino | 158 +- src/_P039_Thermosensors.ino | 4184 ++++++++++---------- src/_P040_ID12.ino | 258 +- src/_P041_NeoClock.ino | 8 +- src/_P042_Candle.ino | 11 +- src/_P043_ClkOutput.ino | 1 - src/_P047_i2c-soil-moisture-sensor.ino | 22 +- src/_P048_Motorshield_v2.ino | 15 +- src/_P049_MHZ19.ino | 23 +- src/_P050_TCS34725.ino | 1034 ++--- src/_P051_AM2320.ino | 234 +- src/_P052_SenseAir.ino | 978 +++-- src/src/PluginStructs/P016_data_struct.h | 10 +- src/src/PluginStructs/P050_data_struct.cpp | 30 +- src/src/PluginStructs/P050_data_struct.h | 36 +- src/src/PluginStructs/P110_data_struct.cpp | 2 +- 48 files changed, 3986 insertions(+), 4262 deletions(-) diff --git a/src/_P001_Switch.ino b/src/_P001_Switch.ino index 4e7890dc00..e3fdd4893a 100644 --- a/src/_P001_Switch.ino +++ b/src/_P001_Switch.ino @@ -37,15 +37,12 @@ boolean Plugin_001(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_001; Device[deviceCount].Type = DEVICE_TYPE_SINGLE; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].Ports = 0; Device[deviceCount].PullUpOption = true; Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].FormulaOption = false; Device[deviceCount].ValueCount = 1; Device[deviceCount].SendDataOption = true; Device[deviceCount].TimerOption = true; Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; break; } @@ -87,7 +84,8 @@ boolean Plugin_001(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *options[] = { F("Switch"), F("Dimmer") }; const int optionValues[] = { PLUGIN_001_TYPE_SWITCH, PLUGIN_001_TYPE_DIMMER }; const uint8_t switchtype = P001_data_struct::P001_getSwitchType(event); - addFormSelector(F("Switch Type"), F("type"), NR_ELEMENTS(optionValues), options, optionValues, switchtype); + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Switch Type"), F("type"), optionCount, options, optionValues, switchtype); if (switchtype == PLUGIN_001_TYPE_DIMMER) { diff --git a/src/_P002_ADC.ino b/src/_P002_ADC.ino index 2b5d810a63..e76fb7bb6a 100644 --- a/src/_P002_ADC.ino +++ b/src/_P002_ADC.ino @@ -23,19 +23,15 @@ boolean Plugin_002(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_002; - Device[deviceCount].Type = DEVICE_TYPE_ANALOG; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].TaskLogsOwnPeaks = true; + Device[++deviceCount].Number = PLUGIN_ID_002; + Device[deviceCount].Type = DEVICE_TYPE_ANALOG; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].TaskLogsOwnPeaks = true; break; } @@ -133,7 +129,7 @@ boolean Plugin_002(uint8_t function, struct EventStruct *event, String& string) if (loglevelActiveFor(LOG_LEVEL_INFO)) { String log = strformat( - F("ADC : Analog value: %d = %s"), + F("ADC : Analog value: %d = %s"), raw_value, formatUserVarNoCheck(event, 0).c_str()); diff --git a/src/_P003_Pulse.ino b/src/_P003_Pulse.ino index a3f0d6ac7e..b7bace50b4 100644 --- a/src/_P003_Pulse.ino +++ b/src/_P003_Pulse.ino @@ -53,20 +53,17 @@ boolean Plugin_003(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_003; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = true; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = PLUGIN_NR_VALUENAMES_003; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].TaskLogsOwnPeaks = true; + Device[++deviceCount].Number = PLUGIN_ID_003; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].PullUpOption = true; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = PLUGIN_NR_VALUENAMES_003; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].TaskLogsOwnPeaks = true; break; } @@ -165,7 +162,8 @@ boolean Plugin_003(uint8_t function, struct EventStruct *event, String& string) F("Time/Delta"), # endif // if P003_USE_EXTRA_COUNTERTYPES }; - addFormSelector(F("Counter Type"), F("countertype"), NR_ELEMENTS(options), options, nullptr, choice); + constexpr size_t optionCount = NR_ELEMENTS(options); + addFormSelector(F("Counter Type"), F("countertype"), optionCount, options, nullptr, choice); if (choice != 0) { addHtml(F("Total count is not persistent!")); diff --git a/src/_P004_Dallas.ino b/src/_P004_Dallas.ino index 72aac9325e..e1cbc8c133 100644 --- a/src/_P004_Dallas.ino +++ b/src/_P004_Dallas.ino @@ -51,17 +51,15 @@ boolean Plugin_004(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_004; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_004; + Device[deviceCount].Type = DEVICE_TYPE_DUAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].PluginStats = true; Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); break; } @@ -139,18 +137,20 @@ boolean Plugin_004(uint8_t function, struct EventStruct *event, String& string) int resolutionChoice = P004_RESOLUTION; if ((resolutionChoice < 9) || (resolutionChoice > 12)) { resolutionChoice = activeRes; } - const __FlashStringHelper *resultsOptions[4] = { F("9"), F("10"), F("11"), F("12") }; - int resultsOptionValues[4] = { 9, 10, 11, 12 }; - addFormSelector(F("Device Resolution"), F("res"), 4, resultsOptions, resultsOptionValues, resolutionChoice); + const __FlashStringHelper *resultsOptions[] = { F("9"), F("10"), F("11"), F("12") }; + const int resultsOptionValues[] = { 9, 10, 11, 12 }; + constexpr size_t optionCount = NR_ELEMENTS(resultsOptionValues); + addFormSelector(F("Device Resolution"), F("res"), optionCount, resultsOptions, resultsOptionValues, resolutionChoice); addHtml(F(" Bit")); } { // Value in case of Error - const __FlashStringHelper *resultsOptions[5] = { F("NaN"), F("-127"), F("0"), F("125"), F("Ignore") }; - int resultsOptionValues[5] = + const __FlashStringHelper *resultsOptions[] = { F("NaN"), F("-127"), F("0"), F("125"), F("Ignore") }; + int resultsOptionValues[] = { P004_ERROR_NAN, P004_ERROR_MIN_RANGE, P004_ERROR_ZERO, P004_ERROR_MAX_RANGE, P004_ERROR_IGNORE }; - addFormSelector(F("Error State Value"), F("err"), 5, resultsOptions, resultsOptionValues, P004_ERROR_STATE_OUTPUT); + constexpr size_t optionCount = NR_ELEMENTS(resultsOptionValues); + addFormSelector(F("Error State Value"), F("err"), optionCount, resultsOptions, resultsOptionValues, P004_ERROR_STATE_OUTPUT); } addFormNote(F("External pull up resistor is needed, see docs!")); @@ -338,9 +338,7 @@ boolean Plugin_004(uint8_t function, struct EventStruct *event, String& string) } else { log += F("Error!"); } - log += F(" ("); - log += P004_data->get_formatted_address(i); - log += ')'; + log += strformat(F(" (%s)"), P004_data->get_formatted_address(i).c_str()); addLogMove(LOG_LEVEL_INFO, log); } } diff --git a/src/_P005_DHT.ino b/src/_P005_DHT.ino index 78f5fc8c27..ecc321ec48 100644 --- a/src/_P005_DHT.ino +++ b/src/_P005_DHT.ino @@ -1,18 +1,18 @@ #include "_Plugin_Helper.h" #ifdef USES_P005 -//####################################################################################################### -//######################## Plugin 005: Temperature and Humidity sensor DHT 11/22 ######################## -//####################################################################################################### -#include "src/PluginStructs/P005_data_struct.h" +// ####################################################################################################### +// ######################## Plugin 005: Temperature and Humidity sensor DHT 11/22 ######################## +// ####################################################################################################### -#define PLUGIN_005 -#define PLUGIN_ID_005 5 -#define PLUGIN_NAME_005 "Environment - DHT11/12/22 SONOFF2301/7021/MS01" -#define PLUGIN_VALUENAME1_005 "Temperature" -#define PLUGIN_VALUENAME1_005_MS01 "RAW" -#define PLUGIN_VALUENAME2_005 "Humidity" +# include "src/PluginStructs/P005_data_struct.h" +# define PLUGIN_005 +# define PLUGIN_ID_005 5 +# define PLUGIN_NAME_005 "Environment - DHT11/12/22 SONOFF2301/7021/MS01" +# define PLUGIN_VALUENAME1_005 "Temperature" +# define PLUGIN_VALUENAME1_005_MS01 "RAW" +# define PLUGIN_VALUENAME2_005 "Humidity" boolean Plugin_005(uint8_t function, struct EventStruct *event, String& string) @@ -22,85 +22,81 @@ boolean Plugin_005(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_005; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - break; - } + { + Device[++deviceCount].Number = PLUGIN_ID_005; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + break; + } case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_005); - break; - } + { + string = F(PLUGIN_NAME_005); + break; + } case PLUGIN_GET_DEVICEVALUENAMES: - { - if (PCONFIG(0) == P005_MS01) { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_005_MS01)); - } else { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_005)); - } - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_005)); - break; + { + if (PCONFIG(0) == P005_MS01) { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_005_MS01)); + } else { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_005)); } + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_005)); + break; + } case PLUGIN_GET_DEVICEGPIONAMES: - { - event->String1 = formatGpioName_bidirectional(F("Data")); - break; - } + { + event->String1 = formatGpioName_bidirectional(F("Data")); + break; + } case PLUGIN_WEBFORM_LOAD: - { - const __FlashStringHelper * options[] = { F("DHT 11"), F("DHT 22"), F("DHT 12"), F("Sonoff am2301"), F("Sonoff si7021"), F("Sonoff MS01") }; - const int indices[] = { P005_DHT11, P005_DHT22, P005_DHT12, P005_AM2301, P005_SI7021, P005_MS01 }; + { + const __FlashStringHelper *options[] = { F("DHT 11"), F("DHT 22"), F("DHT 12"), F("Sonoff am2301"), F("Sonoff si7021"), + F("Sonoff MS01") }; + const int indices[] = { P005_DHT11, P005_DHT22, P005_DHT12, P005_AM2301, P005_SI7021, P005_MS01 }; - constexpr size_t nrElements = NR_ELEMENTS(indices); + constexpr size_t nrElements = NR_ELEMENTS(indices); - addFormSelector(F("Sensor model"), F("dhttype"), nrElements, options, indices, PCONFIG(0) ); + addFormSelector(F("Sensor model"), F("dhttype"), nrElements, options, indices, PCONFIG(0)); - success = true; - break; - } + success = true; + break; + } case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(0) = getFormItemInt(F("dhttype")); + { + PCONFIG(0) = getFormItemInt(F("dhttype")); - success = true; - break; - } + success = true; + break; + } case PLUGIN_INIT: - { - success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P005_data_struct(event)); - break; - } + { + success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P005_data_struct(event)); + break; + } case PLUGIN_READ: - { - P005_data_struct *P005_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P005_data) { - success = P005_data->readDHT(event); - } - break; + { + P005_data_struct *P005_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P005_data) { + success = P005_data->readDHT(event); } + break; + } } return success; } - #endif // USES_P005 diff --git a/src/_P006_BMP085.ino b/src/_P006_BMP085.ino index 059c3bbdd6..9b8e21f1e0 100644 --- a/src/_P006_BMP085.ino +++ b/src/_P006_BMP085.ino @@ -23,18 +23,14 @@ boolean Plugin_006(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_006; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_006; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } diff --git a/src/_P007_PCF8591.ino b/src/_P007_PCF8591.ino index 5176330572..31951babf1 100644 --- a/src/_P007_PCF8591.ino +++ b/src/_P007_PCF8591.ino @@ -36,19 +36,15 @@ boolean Plugin_007(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_007; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].I2CMax100kHz = true; // Max 100 kHz allowed/supported + Device[++deviceCount].Number = PLUGIN_ID_007; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].I2CMax100kHz = true; // Max 100 kHz allowed/supported break; } @@ -109,7 +105,8 @@ boolean Plugin_007(uint8_t function, struct EventStruct *event, String& string) } addFormSelectorI2C(F("pi2c"), 8, i2cAddressValues, address); addFormSelector(F("Port"), F("pport"), 4, portNames, portValues, port); - addFormNote(F("Selected Port value will be stored in first 'Values' field and consecutively for 'Number Output Values' > Single.")); + addFormNote(F( + "Selected Port value will be stored in first 'Values' field and consecutively for 'Number Output Values' > Single.")); } else { success = intArrayContains(8, i2cAddressValues, event->Par1); } @@ -143,7 +140,8 @@ boolean Plugin_007(uint8_t function, struct EventStruct *event, String& string) 0b00100000, 0b00110000, }; - addFormSelector(F("Input mode"), F("input_mode"), 4, inputModeOptions, inputModeValues, P007_INPUT_MODE); + constexpr size_t optionCount = NR_ELEMENTS(inputModeValues); + addFormSelector(F("Input mode"), F("input_mode"), optionCount, inputModeOptions, inputModeValues, P007_INPUT_MODE); addFormCheckBox(F("Enable Analog output (AOUT)"), F("output_mode"), P007_OUTPUT_MODE == P007_OUTPUT_ENABLED); @@ -209,12 +207,12 @@ boolean Plugin_007(uint8_t function, struct EventStruct *event, String& string) success = true; } } else { - UserVar.setFloat(event->TaskIndex, var, 0); + UserVar.setFloat(event->TaskIndex, var, 0.0f); } } for (; var < VARS_PER_TASK; ++var) { - UserVar.setFloat(event->TaskIndex, var, 0); + UserVar.setFloat(event->TaskIndex, var, 0.0f); } break; } diff --git a/src/_P008_RFID.ino b/src/_P008_RFID.ino index a20aa047cb..69637b8151 100644 --- a/src/_P008_RFID.ino +++ b/src/_P008_RFID.ino @@ -47,13 +47,11 @@ boolean Plugin_008(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_008; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].GlobalSyncOption = true; + Device[++deviceCount].Number = PLUGIN_ID_008; + Device[deviceCount].Type = DEVICE_TYPE_DUAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; break; } @@ -160,15 +158,6 @@ boolean Plugin_008(uint8_t function, struct EventStruct *event, String& string) P008_REMOVE_VALUE = getFormItemInt(F("rmvval")); P008_REMOVE_TIMEOUT = getFormItemInt(F("rmvtime")); - // uint64_t keyMask = 0LL; - // keyMask = (0x1ull << (P008_DATA_BITS - 2)); - // keyMask--; - // String log = F("P008: testing keyMask = 0x"); - // log += ull2String(keyMask, HEX); - // log += F(" bits: "); - // log += P008_DATA_BITS; - // addLog(LOG_LEVEL_INFO, log); - success = true; break; } diff --git a/src/_P009_MCP.ino b/src/_P009_MCP.ino index 36d1d75476..4931e09869 100644 --- a/src/_P009_MCP.ino +++ b/src/_P009_MCP.ino @@ -31,15 +31,11 @@ boolean Plugin_009(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_009; Device[deviceCount].Type = DEVICE_TYPE_I2C; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].FormulaOption = false; Device[deviceCount].ValueCount = 1; Device[deviceCount].SendDataOption = true; Device[deviceCount].TimerOption = true; Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; break; } diff --git a/src/_P010_BH1750.ino b/src/_P010_BH1750.ino index 3f092ffbde..b45ed9b8e7 100644 --- a/src/_P010_BH1750.ino +++ b/src/_P010_BH1750.ino @@ -23,18 +23,14 @@ boolean Plugin_010(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_010; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_010; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -87,7 +83,8 @@ boolean Plugin_010(uint8_t function, struct EventStruct *event, String& string) RESOLUTION_HIGH, RESOLUTION_AUTO_HIGH, }; - addFormSelector(F("Measurement mode"), F("pmode"), 4, optionsMode, optionValuesMode, PCONFIG(1)); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode); + addFormSelector(F("Measurement mode"), F("pmode"), optionCount, optionsMode, optionValuesMode, PCONFIG(1)); addFormCheckBox(F("Send sensor to sleep"), F("psleep"), PCONFIG(2)); diff --git a/src/_P011_PME.ino b/src/_P011_PME.ino index 5e66e21d7d..7222aadcbd 100644 --- a/src/_P011_PME.ino +++ b/src/_P011_PME.ino @@ -40,16 +40,14 @@ boolean Plugin_011(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_011; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].Ports = PLUGIN_011_PORTS; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + Device[++deviceCount].Number = PLUGIN_ID_011; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].Ports = PLUGIN_011_PORTS; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; break; } @@ -84,7 +82,8 @@ boolean Plugin_011(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *options[] = { F("Digital"), F("Analog"), F("Input (switch)") }; const int optionValues[] = { P011_TYPE_DIGITAL, P011_TYPE_ANALOG, P011_TYPE_SWITCH }; - addFormSelector(F("Port Type"), F("p011"), NR_ELEMENTS(options), options, optionValues, P011_PORT_TYPE); + constexpr size_t optionCount = NR_ELEMENTS(options); + addFormSelector(F("Port Type"), F("p011"), optionCount, options, optionValues, P011_PORT_TYPE); success = true; break; diff --git a/src/_P012_LCD.ino b/src/_P012_LCD.ino index bd1841451c..9079b5a3c0 100644 --- a/src/_P012_LCD.ino +++ b/src/_P012_LCD.ino @@ -45,16 +45,10 @@ boolean Plugin_012(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_012; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = true; + Device[++deviceCount].Number = PLUGIN_ID_012; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + Device[deviceCount].TimerOption = true; break; } @@ -74,11 +68,12 @@ boolean Plugin_012(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: { const uint8_t i2cAddressValues[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f }; + constexpr size_t optionCount = NR_ELEMENTS(i2cAddressValues); if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - addFormSelectorI2C(F("i2c_addr"), 16, i2cAddressValues, P012_I2C_ADDR); + addFormSelectorI2C(F("i2c_addr"), optionCount, i2cAddressValues, P012_I2C_ADDR); } else { - success = intArrayContains(16, i2cAddressValues, event->Par1); + success = intArrayContains(optionCount, i2cAddressValues, event->Par1); } break; } @@ -99,8 +94,9 @@ boolean Plugin_012(uint8_t function, struct EventStruct *event, String& string) F("2 x 16"), F("4 x 20"), }; - const int optionValues2[2] = { 1, 2 }; - addFormSelector(F("Display Size"), F("psize"), 2, options2, optionValues2, P012_SIZE); + const int optionValues2[2] = { 1, 2 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues2); + addFormSelector(F("Display Size"), F("psize"), optionCount, options2, optionValues2, P012_SIZE); } { @@ -126,8 +122,9 @@ boolean Plugin_012(uint8_t function, struct EventStruct *event, String& string) F("Truncate exceeding message"), F("Clear then truncate exceeding message"), }; - const int optionValues3[] = { 0, 1, 2 }; - addFormSelector(F("LCD command Mode"), F("pmode"), 3, options3, optionValues3, P012_MODE); + const int optionValues3[] = { 0, 1, 2 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues3); + addFormSelector(F("LCD command Mode"), F("pmode"), optionCount, options3, optionValues3, P012_MODE); } success = true; @@ -253,23 +250,23 @@ boolean Plugin_012(uint8_t function, struct EventStruct *event, String& string) if (nullptr != P012_data) { String cmd = parseString(string, 1); - if (cmd.equalsIgnoreCase(F("LCDCMD"))) + if (equals(cmd, F("lcdcmd"))) { success = true; String arg1 = parseString(string, 2); - if (arg1.equalsIgnoreCase(F("Off"))) { + if (equals(arg1, F("off"))) { P012_data->lcd.noBacklight(); } - else if (arg1.equalsIgnoreCase(F("On"))) { + else if (equals(arg1, F("on"))) { P012_data->lcd.backlight(); } - else if (arg1.equalsIgnoreCase(F("Clear"))) { + else if (equals(arg1, F("clear"))) { P012_data->lcd.clear(); P012_data->splashState = P012_splashState_e::SplashCleared; } } - else if (cmd.equalsIgnoreCase(F("LCD"))) + else if (equals(cmd, F("lcd"))) { success = true; int colPos = event->Par2 - 1; diff --git a/src/_P013_HCSR04.ino b/src/_P013_HCSR04.ino index e6f151a73b..473de0b87a 100644 --- a/src/_P013_HCSR04.ino +++ b/src/_P013_HCSR04.ino @@ -47,17 +47,15 @@ boolean Plugin_013(uint8_t function, struct EventStruct *even { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_013; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_013; + Device[deviceCount].Type = DEVICE_TYPE_DUAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + Device[deviceCount].PluginStats = true; Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); break; @@ -131,13 +129,8 @@ boolean Plugin_013(uint8_t function, struct EventStruct *even F("Combined"), # endif // if P013_FEATURE_COMBINED_MODE }; - addFormSelector(F("Mode"), F("pmode"), - # if P013_FEATURE_COMBINED_MODE - 3 - # else // if P013_FEATURE_COMBINED_MODE - 2 - # endif // if P013_FEATURE_COMBINED_MODE - , optionsOpMode, optionValuesOpMode, P013_OPERATINGMODE); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesOpMode); + addFormSelector(F("Mode"), F("pmode"), optionCount, optionsOpMode, optionValuesOpMode, P013_OPERATINGMODE); } if ((P013_OPERATINGMODE == OPMODE_STATE) @@ -155,21 +148,23 @@ boolean Plugin_013(uint8_t function, struct EventStruct *even addUnit(strUnit); { - const int optionValuesUnit[2] = { UNIT_CM, UNIT_INCH }; + const int optionValuesUnit[] = { UNIT_CM, UNIT_INCH }; const __FlashStringHelper *optionsUnit[] { F("Metric"), F("Imperial"), }; - addFormSelector(F("Unit"), F("pUnit"), 2, optionsUnit, optionValuesUnit, P013_MEASURINGUNIT); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesUnit); + addFormSelector(F("Unit"), F("pUnit"), optionCount, optionsUnit, optionValuesUnit, P013_MEASURINGUNIT); } { - const int optionValuesFilter[2] = { FILTER_NONE, FILTER_MEDIAN }; + const int optionValuesFilter[] = { FILTER_NONE, FILTER_MEDIAN }; const __FlashStringHelper *optionsFilter[] { F("None"), F("Median"), }; - addFormSelector(F("Filter"), F("fltr"), 2, optionsFilter, optionValuesFilter, P013_FILTERTYPE); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesFilter); + addFormSelector(F("Filter"), F("fltr"), optionCount, optionsFilter, optionValuesFilter, P013_FILTERTYPE); } // enable filtersize option if filter is used, diff --git a/src/_P014_SI70xx.ino b/src/_P014_SI70xx.ino index 51c9805d07..588bfb24d2 100644 --- a/src/_P014_SI70xx.ino +++ b/src/_P014_SI70xx.ino @@ -44,21 +44,16 @@ boolean Plugin_014(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_014; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].I2CNoDeviceCheck = true; - - // Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::All; + Device[++deviceCount].Number = PLUGIN_ID_014; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 3; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].I2CNoDeviceCheck = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].OutputDataType = Output_Data_type_t::All; break; } @@ -108,26 +103,23 @@ boolean Plugin_014(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { - # define P014_RESOLUTION_OPTIONS 4 - - const __FlashStringHelper *options[P014_RESOLUTION_OPTIONS] = { + const __FlashStringHelper *options[] = { F("Temp 14 bits / RH 12 bits"), F("Temp 13 bits / RH 10 bits"), F("Temp 12 bits / RH 8 bits"), F("Temp 11 bits / RH 11 bits"), }; - const int optionValues[P014_RESOLUTION_OPTIONS] = { + const int optionValues[] = { SI70xx_RESOLUTION_14T_12RH, SI70xx_RESOLUTION_13T_10RH, SI70xx_RESOLUTION_12T_08RH, SI70xx_RESOLUTION_11T_11RH, }; - addFormSelector(F("Resolution"), F("pres"), P014_RESOLUTION_OPTIONS, options, optionValues, P014_RESOLUTION); + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Resolution"), F("pres"), optionCount, options, optionValues, P014_RESOLUTION); addFormNumericBox("ADC Filter Power", F("pfilter"), P014_FILTER_POWER, 0, 4); - // addUnit(F("bits")); - success = true; break; } @@ -138,12 +130,6 @@ boolean Plugin_014(uint8_t function, struct EventStruct *event, String& string) P014_RESOLUTION = getFormItemInt(F("pres")); P014_FILTER_POWER = getFormItemInt(F("pfilter")); - // Force device setup next time - // P014_data_struct *P014_data = static_cast(getPluginTaskData(event->TaskIndex)); - // if (nullptr != P014_data) { - // P014_data->state = P014_state::Uninitialized; - // } - success = true; break; } diff --git a/src/_P015_TSL2561.ino b/src/_P015_TSL2561.ino index 49b06d36b0..a413538432 100644 --- a/src/_P015_TSL2561.ino +++ b/src/_P015_TSL2561.ino @@ -36,18 +36,14 @@ boolean Plugin_015(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_015; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_015; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 3; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -99,38 +95,33 @@ boolean Plugin_015(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { { - # define TSL2561_INTEGRATION_OPTION 3 - const __FlashStringHelper * options[TSL2561_INTEGRATION_OPTION] = { + const __FlashStringHelper *options[] = { F("13.7 ms"), F("101 ms"), F("402 ms"), }; - const int optionValues[TSL2561_INTEGRATION_OPTION] = { - 0x00, - 0x01, - 0x02, - }; - addFormSelector(F("Integration time"), F("pintegration"), TSL2561_INTEGRATION_OPTION, options, optionValues, P015_INTEGRATION); + constexpr size_t optionCount = NR_ELEMENTS(options); + addFormSelector(F("Integration time"), F("pintegration"), optionCount, options, nullptr, P015_INTEGRATION); } addFormCheckBox(F("Send sensor to sleep:"), F("psleep"), P015_SLEEP); { - # define TSL2561_GAIN_OPTION 4 - const __FlashStringHelper *options[TSL2561_GAIN_OPTION] = { + const __FlashStringHelper *options[] = { F("No Gain"), F("16x Gain"), F("Auto Gain"), F("Extended Auto Gain"), }; - const int optionValues[TSL2561_GAIN_OPTION] = { + const int optionValues[] = { P015_NO_GAIN, P015_16X_GAIN, P015_AUTO_GAIN, P015_EXT_AUTO_GAIN, }; - addFormSelector(F("Gain"), F("pgain"), TSL2561_GAIN_OPTION, options, optionValues, P015_GAIN); + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Gain"), F("pgain"), optionCount, options, optionValues, P015_GAIN); } success = true; diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index 8b897bd708..ad7a2c4c16 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -206,13 +206,11 @@ boolean Plugin_016(uint8_t function, struct EventStruct *event, String& string) # else // if P016_SEND_IR_TO_CONTROLLER Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; # endif // if P016_SEND_IR_TO_CONTROLLER - Device[deviceCount].Ports = 0; Device[deviceCount].PullUpOption = true; Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].FormulaOption = false; Device[deviceCount].ValueCount = 1; Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = false; + Device[deviceCount].TimerOption = true; Device[deviceCount].TimerOptional = true; break; } @@ -378,7 +376,7 @@ boolean Plugin_016(uint8_t function, struct EventStruct *event, String& string) int protocolCount = 0; for (int i = static_cast(decode_type_t::UNKNOWN); i < size; i++) { - const String protocol = typeToString(static_cast(i), false); + const String protocol = typeToString(static_cast(i), false); if ((!bAcceptUnknownType) && (static_cast(i) == UNKNOWN)) { continue; diff --git a/src/_P017_PN532.ino b/src/_P017_PN532.ino index 5db94bbd47..b9a29b1ebd 100644 --- a/src/_P017_PN532.ino +++ b/src/_P017_PN532.ino @@ -84,17 +84,12 @@ boolean Plugin_017(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_017; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = false; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; + Device[++deviceCount].Number = PLUGIN_ID_017; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOptional = true; break; } @@ -149,15 +144,9 @@ boolean Plugin_017(uint8_t function, struct EventStruct *event, String& string) addFormNumericBox(F("Automatic Tag removal after"), F("removetime"), P017_REMOVAL_TIMEOUT, 250, 60000); addUnit(F("mSec.")); - addFormNumericBox(F("Value to set on Tag removal"), F("removevalue"), P017_NO_TAG_DETECTED_VALUE, 0, 2147483647); - // Max allowed is int - // = - // 0x7FFFFFFF ... - - const bool eventOnRemoval = P017_EVENT_ON_TAG_REMOVAL == 1; // Normal state! - addFormCheckBox(F("Event on Tag removal"), F("eventremove"), eventOnRemoval); + addFormCheckBox(F("Event on Tag removal"), F("eventremove"), P017_EVENT_ON_TAG_REMOVAL == 1); success = true; break; @@ -339,17 +328,10 @@ bool P017_handle_timer_in(struct EventStruct *event) tempcounter++; if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("PN532: "); - - if (new_key) { - log += F("New Tag: "); - } else { - log += F("Old Tag: "); - } - log += key; - log += ' '; - log += tempcounter; - addLogMove(LOG_LEVEL_INFO, log); + addLog(LOG_LEVEL_INFO, strformat(F("PN532: %s Tag: %d %u"), + FsP(new_key ? F("New") : F("Old")), + key, + tempcounter)); } if (new_key) { sendData(event); } diff --git a/src/_P018_Dust.ino b/src/_P018_Dust.ino index 173f0be65f..968371e0d4 100644 --- a/src/_P018_Dust.ino +++ b/src/_P018_Dust.ino @@ -1,17 +1,21 @@ #include "_Plugin_Helper.h" #ifdef USES_P018 -#include "src/Helpers/Hardware.h" +# include "src/Helpers/Hardware.h" # include -//####################################################################################################### -//#################################### Plugin 018: GP2Y10 ############################################### -//####################################################################################################### +// ####################################################################################################### +// #################################### Plugin 018: GP2Y10 ############################################### +// ####################################################################################################### -#define PLUGIN_018 -#define PLUGIN_ID_018 18 -#define PLUGIN_NAME_018 "Dust - Sharp GP2Y10" -#define PLUGIN_VALUENAME1_018 "Dust" +/** Changelog: + * 2025-01-03 tonhuisman: Small code size improvements, source formatted using Uncrustify + */ + +# define PLUGIN_018 +# define PLUGIN_ID_018 18 +# define PLUGIN_NAME_018 "Dust - Sharp GP2Y10" +# define PLUGIN_VALUENAME1_018 "Dust" boolean Plugin_018_init = false; @@ -22,73 +26,72 @@ boolean Plugin_018(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_018; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); - break; - } + { + Device[++deviceCount].Number = PLUGIN_ID_018; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + break; + } case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_018); - break; - } + { + string = F(PLUGIN_NAME_018); + break; + } case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_018)); - break; - } + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_018)); + break; + } case PLUGIN_GET_DEVICEGPIONAMES: - { - event->String1 = formatGpioName_output(F("LED")); - break; - } + { + event->String1 = formatGpioName_output(F("LED")); + break; + } case PLUGIN_INIT: - { - Plugin_018_init = true; - pinMode(CONFIG_PIN1, OUTPUT); - DIRECT_pinWrite(CONFIG_PIN1, HIGH); - success = true; - break; - } + { + Plugin_018_init = true; + pinMode(CONFIG_PIN1, OUTPUT); + DIRECT_pinWrite(CONFIG_PIN1, HIGH); + success = true; + break; + } case PLUGIN_READ: - { - ISR_noInterrupts(); - int value = 0; - - for (uint8_t x = 0; x < 25; x++) { - DIRECT_pinWrite(CONFIG_PIN1, LOW); - delayMicroseconds(280); - value = value + espeasy_analogRead(A0); - delayMicroseconds(40); - DIRECT_pinWrite(CONFIG_PIN1, HIGH); - delayMicroseconds(9680); - } - ISR_interrupts(); - UserVar.setFloat(event->TaskIndex, 0, value); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, concat(F("GPY : Dust value: "), value)); - } - - success = true; - break; + { + ISR_noInterrupts(); + int value = 0; + + for (uint8_t x = 0; x < 25; ++x) { + DIRECT_pinWrite(CONFIG_PIN1, LOW); + delayMicroseconds(280); + value = value + espeasy_analogRead(A0); + delayMicroseconds(40); + DIRECT_pinWrite(CONFIG_PIN1, HIGH); + delayMicroseconds(9680); + } + ISR_interrupts(); + UserVar.setFloat(event->TaskIndex, 0, value); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, concat(F("GPY : Dust value: "), value)); } + + success = true; + break; + } } return success; } + #endif // USES_P018 diff --git a/src/_P019_PCF8574.ino b/src/_P019_PCF8574.ino index ad00f3c673..bbc242b87a 100644 --- a/src/_P019_PCF8574.ino +++ b/src/_P019_PCF8574.ino @@ -29,15 +29,11 @@ boolean Plugin_019(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_019; Device[deviceCount].Type = DEVICE_TYPE_I2C; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].FormulaOption = false; Device[deviceCount].ValueCount = 1; Device[deviceCount].SendDataOption = true; Device[deviceCount].TimerOption = true; Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; break; } diff --git a/src/_P020_Ser2Net.ino b/src/_P020_Ser2Net.ino index a3a254ee35..017b62db73 100644 --- a/src/_P020_Ser2Net.ino +++ b/src/_P020_Ser2Net.ino @@ -93,15 +93,8 @@ boolean Plugin_020(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_020; Device[deviceCount].SendDataOption = true; } - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].TimerOption = false; - Device[deviceCount].GlobalSyncOption = false; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; break; } case PLUGIN_GET_DEVICENAME: @@ -388,8 +381,8 @@ boolean Plugin_020(uint8_t function, struct EventStruct *event, String& string) if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { addLogMove(LOG_LEVEL_DEBUG, strformat( - F("Ser2net : P020_RESET_TARGET_PIN : %d"), - P020_RESET_TARGET_PIN)); + F("Ser2net : P020_RESET_TARGET_PIN : %d"), + P020_RESET_TARGET_PIN)); } # endif // ifndef BUILD_NO_DEBUG pinMode(P020_RESET_TARGET_PIN, OUTPUT); @@ -408,10 +401,10 @@ boolean Plugin_020(uint8_t function, struct EventStruct *event, String& string) task->_CRCcheck = P020_GET_BAUDRATE == 115200; # ifndef BUILD_NO_DEBUG - if (task->_CRCcheck) { - addLog(LOG_LEVEL_DEBUG, F("P1 : DSMR version 5 meter, CRC on")); - } else { - addLog(LOG_LEVEL_DEBUG, F("P1 : DSMR version 4 meter, CRC off")); + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLog(LOG_LEVEL_DEBUG, strformat(F("P1 : DSMR version %d meter, CRC %s"), + task->_CRCcheck ? 5 : 4, + FsP(task->_CRCcheck ? F("on") : F("off")))); } # endif // ifndef BUILD_NO_DEBUG } diff --git a/src/_P021_Level.ino b/src/_P021_Level.ino index b6903c355a..2fc077dea4 100644 --- a/src/_P021_Level.ino +++ b/src/_P021_Level.ino @@ -113,7 +113,6 @@ boolean Plugin_021(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_021; Device[deviceCount].Type = DEVICE_TYPE_SINGLE; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].Ports = 0; Device[deviceCount].ValueCount = 1; Device[deviceCount].SendDataOption = true; Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); @@ -236,7 +235,8 @@ boolean Plugin_021(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *options[] = { F("Classic"), F("Off"), F("Standby"), F("On"), F("Local"), F("Remote") }; const int optionValues[] = { P021_OPMODE_CLASSIC, P021_OPMODE_OFF, P021_OPMODE_STANDBY, P021_OPMODE_ON, P021_OPMODE_TEMP, P021_OPMODE_REMOTE }; - addFormSelector(F("Control mode"), F(P021_GUID_OPMODE), NR_ELEMENTS(optionValues), options, optionValues, P021_OPMODE); + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Control mode"), F(P021_GUID_OPMODE), optionCount, options, optionValues, P021_OPMODE); // Add timer values depending on build size // - minimum build size: units are always in seconds; drop the units on the form @@ -487,24 +487,13 @@ boolean Plugin_021(uint8_t function, struct EventStruct *event, String& string) if (equals(command, F("levelcontrol"))) { - if (equals(subcmd, F("remote")) && hasValue) + if (equals(subcmd, F("remote")) && hasValue && ((event->Par2 == 0) || (event->Par2 == 1))) { - if (event->Par2 == 1) - { - P021_remote[event->TaskIndex] = true; - # ifndef P021_MIN_BUILD_SIZE - addLogMove(LOG_LEVEL_INFO, F("P021 write: levelcontrol remote=on")); - # endif // ifndef P021_MIN_BUILD_SIZE - success = true; - } - else if (event->Par2 == 0) - { - P021_remote[event->TaskIndex] = false; - # ifndef P021_MIN_BUILD_SIZE - addLogMove(LOG_LEVEL_INFO, F("P021 write: levelcontrol remote=off")); - # endif // ifndef P021_MIN_BUILD_SIZE - success = true; - } + P021_remote[event->TaskIndex] = event->Par2 != 0; + # ifndef P021_MIN_BUILD_SIZE + addLogMove(LOG_LEVEL_INFO, concat(F("P021 write: levelcontrol remote="), P021_remote[event->TaskIndex] ? F("on") : F("off"))); + # endif // ifndef P021_MIN_BUILD_SIZE + success = true; } // If not successful rely upon ESPeasy framework to report the issue @@ -552,11 +541,11 @@ const __FlashStringHelper* P021_printControlState(int state) { switch (state) { - case P021_STATE_IDLE: return F("Idle"); - case P021_STATE_ACTIVE: return F("Active"); - case P021_STATE_EXTEND: return F("Extend"); - case P021_STATE_FORCE: return F("Force"); - default: return F("***ERROR***"); + case P021_STATE_IDLE: return F("Idle"); + case P021_STATE_ACTIVE: return F("Active"); + case P021_STATE_EXTEND: return F("Extend"); + case P021_STATE_FORCE: return F("Force"); + default: return F("***ERROR***"); } } diff --git a/src/_P022_PCA9685.ino b/src/_P022_PCA9685.ino index a967139d05..4048769e93 100644 --- a/src/_P022_PCA9685.ino +++ b/src/_P022_PCA9685.ino @@ -58,12 +58,7 @@ boolean Plugin_022(uint8_t function, struct EventStruct *event, String& string) Device[deviceCount].Type = DEVICE_TYPE_I2C; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; Device[deviceCount].Ports = 1; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; Device[deviceCount].Custom = true; - Device[deviceCount].TimerOption = false; Device[deviceCount].ExitTaskBeforeSave = false; break; } diff --git a/src/_P023_OLED.ino b/src/_P023_OLED.ino index f2ae1b0fd0..8ad2b3541d 100644 --- a/src/_P023_OLED.ino +++ b/src/_P023_OLED.ino @@ -43,8 +43,6 @@ boolean Plugin_023(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_023; Device[deviceCount].Type = DEVICE_TYPE_I2C; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 0; Device[deviceCount].TimerOption = true; Device[deviceCount].TimerOptional = true; break; @@ -104,9 +102,10 @@ boolean Plugin_023(uint8_t function, struct EventStruct *event, String& string) OLedFormSizes(F("size"), optionValues3, PCONFIG(3)); } { - const __FlashStringHelper *options4[2] = { F("Normal"), F("Optimized") }; - const int optionValues4[2] = { 1, 2 }; - addFormSelector(F("Font Width"), F("font_spacing"), 2, options4, optionValues4, PCONFIG(4)); + const __FlashStringHelper *options4[] = { F("Normal"), F("Optimized") }; + const int optionValues4[] = { 1, 2 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues4); + addFormSelector(F("Font Width"), F("font_spacing"), optionCount, options4, optionValues4, PCONFIG(4)); } { String strings[P23_Nlines]; diff --git a/src/_P024_MLX90614.ino b/src/_P024_MLX90614.ino index 7e09f2f372..76f8606ef7 100644 --- a/src/_P024_MLX90614.ino +++ b/src/_P024_MLX90614.ino @@ -29,17 +29,16 @@ boolean Plugin_024(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_024; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 16; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CMax100kHz = true; // Max 100 kHz allowed/supported + Device[++deviceCount].Number = PLUGIN_ID_024; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].Ports = 16; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].I2CMax100kHz = true; // Max 100 kHz allowed/supported break; } @@ -80,7 +79,8 @@ boolean Plugin_024(uint8_t function, struct EventStruct *event, String& string) (0x07), (0x06) }; - addFormSelector(F("Option"), F("option"), NR_ELEMENTS(optionValues), options, optionValues, PCONFIG(0)); + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Option"), F("option"), optionCount, options, optionValues, PCONFIG(0)); success = true; break; @@ -110,7 +110,7 @@ boolean Plugin_024(uint8_t function, struct EventStruct *event, String& string) UserVar.setFloat(event->TaskIndex, 0, P024_data->readTemperature(PCONFIG(0))); if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, concat(F("MLX90614 : Temperature: "), formatUserVarNoCheck(event, 0))); + addLog(LOG_LEVEL_INFO, concat(F("MLX90614 : Temperature: "), formatUserVarNoCheck(event, 0))); } // send(msgObjTemp024->set(UserVar[event->BaseVarIndex], 1)); // Mysensors diff --git a/src/_P025_ADS1115.ino b/src/_P025_ADS1115.ino index aa7cd3864a..6b9ee509dd 100644 --- a/src/_P025_ADS1115.ino +++ b/src/_P025_ADS1115.ino @@ -23,19 +23,15 @@ boolean Plugin_025(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_025; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_025; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].PluginStats = true; break; } diff --git a/src/_P027_INA219.ino b/src/_P027_INA219.ino index 4ce3d298ca..72d3418b40 100644 --- a/src/_P027_INA219.ino +++ b/src/_P027_INA219.ino @@ -53,18 +53,14 @@ boolean Plugin_027(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_027; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_027; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 3; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } diff --git a/src/_P028_BME280.ino b/src/_P028_BME280.ino index 58113e26bb..9c40d41b64 100644 --- a/src/_P028_BME280.ino +++ b/src/_P028_BME280.ino @@ -33,19 +33,15 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_028; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM_BARO; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].ErrorStateValues = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_028; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM_BARO; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 3; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].ErrorStateValues = true; + Device[deviceCount].PluginStats = true; break; } @@ -209,7 +205,7 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string) if (nullptr != P028_data) { if ((P028_data_struct::BMx_DetectMode::BMP280 != static_cast(P028_DETECTION_MODE)) && - P028_data->hasHumidity()) + P028_data->hasHumidity()) { P028_data->plot_ChartJS_scatter( 0, @@ -221,10 +217,11 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string) 500); } } + // Do not set success = true, since we're not actually adding stats, but just plotting a scatter plot break; } -#endif +# endif // if FEATURE_PLUGIN_STATS && FEATURE_CHART_JS case PLUGIN_WEBFORM_SHOW_ERRORSTATE_OPT: @@ -350,17 +347,17 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string) if (loglevelActiveFor(LOG_LEVEL_INFO)) { String hum; + if (P028_data->hasHumidity()) { hum = formatUserVarNoCheck(event, 1); } - addLogMove(LOG_LEVEL_INFO, concat( - P028_data_struct::getDeviceName(P028_data->sensorID), - strformat( - F(": Addr: %s T: %s H: %s P: %s"), - formatToHex(P028_I2C_ADDRESS, 2).c_str(), - formatUserVarNoCheck(event, 0).c_str(), - hum.c_str(), - formatUserVarNoCheck(event, 2).c_str()))); + addLogMove(LOG_LEVEL_INFO, + strformat(F("%s: Addr: %s T: %s H: %s P: %s"), + FsP(P028_data_struct::getDeviceName(P028_data->sensorID)), + formatToHex(P028_I2C_ADDRESS, 2).c_str(), + formatUserVarNoCheck(event, 0).c_str(), + hum.c_str(), + formatUserVarNoCheck(event, 2).c_str())); } # endif // ifndef LIMIT_BUILD_SIZE success = true; diff --git a/src/_P031_SHT1X.ino b/src/_P031_SHT1X.ino index 0ed34f2791..f4aa9f537b 100644 --- a/src/_P031_SHT1X.ino +++ b/src/_P031_SHT1X.ino @@ -22,16 +22,14 @@ boolean Plugin_031(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_031; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = true; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_031; + Device[deviceCount].Type = DEVICE_TYPE_DUAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + Device[deviceCount].PullUpOption = true; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); break; } @@ -88,20 +86,16 @@ boolean Plugin_031(uint8_t function, struct EventStruct *event, String& string) CONFIG_PIN1, CONFIG_PIN2, Settings.TaskDevicePin1PullUp[event->TaskIndex], PCONFIG(0)); - # ifndef BUILD_NO_DEBUG + # ifndef BUILD_NO_DEBUG if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - String log = F("SHT1x : Status uint8_t: "); - log += String(status, HEX); - log += F(" - resolution: "); - log += ((status & 1) ? F("low") : F("high")); - log += F(" reload from OTP: "); - log += (((status >> 1) & 1) ? F("yes") : F("no")); - log += F(", heater: "); - log += (((status >> 2) & 1) ? F("on") : F("off")); - addLogMove(LOG_LEVEL_DEBUG, log); + addLog(LOG_LEVEL_DEBUG, strformat(F("SHT1x : Status uint8_t: %x - resolution: %s reload from OTP: %s, heater: %s"), + status, + FsP((status & 1) ? F("low") : F("high")), + FsP(((status >> 1) & 1) ? F("yes") : F("no")), + FsP(((status >> 2) & 1) ? F("on") : F("off")))); } - # endif // ifndef BUILD_NO_DEBUG + # endif // ifndef BUILD_NO_DEBUG success = true; break; } diff --git a/src/_P032_MS5611.ino b/src/_P032_MS5611.ino index 372cecd791..a613721a1b 100644 --- a/src/_P032_MS5611.ino +++ b/src/_P032_MS5611.ino @@ -23,18 +23,14 @@ boolean Plugin_032(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_032; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_032; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } diff --git a/src/_P033_Dummy.ino b/src/_P033_Dummy.ino index a5f7562b7d..b313f804fe 100644 --- a/src/_P033_Dummy.ino +++ b/src/_P033_Dummy.ino @@ -17,21 +17,16 @@ boolean Plugin_033(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_033; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::All; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_033; + Device[deviceCount].Type = DEVICE_TYPE_DUMMY; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].DecimalsOnly = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + Device[deviceCount].OutputDataType = Output_Data_type_t::All; + Device[deviceCount].PluginStats = true; break; } diff --git a/src/_P034_DHT12.ino b/src/_P034_DHT12.ino index 35c0a57e11..0401fb35fc 100644 --- a/src/_P034_DHT12.ino +++ b/src/_P034_DHT12.ino @@ -1,140 +1,136 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P034 - -// ####################################################################################################### -// ######################## Plugin 034: Temperature and Humidity sensor DHT 12 (I2C) ##################### -// ####################################################################################################### - - -# define PLUGIN_034 -# define PLUGIN_ID_034 34 -# define PLUGIN_NAME_034 "Environment - DHT12 (I2C)" -# define PLUGIN_VALUENAME1_034 "Temperature" -# define PLUGIN_VALUENAME2_034 "Humidity" - -# define DHT12_I2C_ADDRESS 0x5C // I2C address for the sensor - -boolean Plugin_034(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_034; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_034); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_034)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_034)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - { - success = (event->Par1 == DHT12_I2C_ADDRESS); - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = DHT12_I2C_ADDRESS; - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_INIT: - { - success = true; - break; - } - - case PLUGIN_READ: - { - uint8_t dht_dat[5]; - bool error = false; - - Wire.beginTransmission(DHT12_I2C_ADDRESS); // start transmission to device - Wire.write(0); // sends register address to read from - Wire.endTransmission(); // end transmission - - if (Wire.requestFrom(DHT12_I2C_ADDRESS, 5) == 5) { // send data n-bytes read - for (uint8_t i = 0; i < 5; ++i) - { - dht_dat[i] = Wire.read(); // receive DATA - } - } else { - error = true; - } - - if (!error) - { - // Checksum calculation is a Rollover Checksum by design! - const uint8_t dht_check_sum = dht_dat[0] + dht_dat[1] + dht_dat[2] + dht_dat[3]; // check check_sum - - if (dht_dat[4] == dht_check_sum) - { - const float temperature = static_cast( - (dht_dat[2] * 10 + (dht_dat[3] & 0x7f)) * (dht_dat[3] & 0x80 ? -1 : 1)) / 10.0f; // Temperature - - const float humidity = float(dht_dat[0] * 10 + dht_dat[1]) / 10.0f; // Humidity - - UserVar.setFloat(event->TaskIndex, 0, temperature); - UserVar.setFloat(event->TaskIndex, 1, humidity); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, - concat(F("DHT12: Temperature: "), - formatUserVarNoCheck(event, 0))); - addLogMove(LOG_LEVEL_INFO, - concat(F("DHT12: Humidity: "), - formatUserVarNoCheck(event, 1))); - - /* - log = F("DHT12: Data: "); - for (int i=0; i < 5; i++) - { - log += dht_dat[i]; - log += ", "; - } - addLog(LOG_LEVEL_INFO, log); - */ - } - success = true; - } // checksum - } // error - - if (!success) - { - addLog(LOG_LEVEL_INFO, F("DHT12: No reading!")); - UserVar.setFloat(event->TaskIndex, 0, NAN); - UserVar.setFloat(event->TaskIndex, 1, NAN); - } - break; - } - } - return success; -} - -#endif // USES_P034 +#include "_Plugin_Helper.h" +#ifdef USES_P034 + +// ####################################################################################################### +// ######################## Plugin 034: Temperature and Humidity sensor DHT 12 (I2C) ##################### +// ####################################################################################################### + + +# define PLUGIN_034 +# define PLUGIN_ID_034 34 +# define PLUGIN_NAME_034 "Environment - DHT12 (I2C)" +# define PLUGIN_VALUENAME1_034 "Temperature" +# define PLUGIN_VALUENAME2_034 "Humidity" + +# define DHT12_I2C_ADDRESS 0x5C // I2C address for the sensor + +boolean Plugin_034(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_034; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_034); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_034)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_034)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + { + success = (event->Par1 == DHT12_I2C_ADDRESS); + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = DHT12_I2C_ADDRESS; + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_INIT: + { + success = true; + break; + } + + case PLUGIN_READ: + { + uint8_t dht_dat[5]; + bool error = false; + + Wire.beginTransmission(DHT12_I2C_ADDRESS); // start transmission to device + Wire.write(0); // sends register address to read from + Wire.endTransmission(); // end transmission + + if (Wire.requestFrom(DHT12_I2C_ADDRESS, 5) == 5) { // send data n-bytes read + for (uint8_t i = 0; i < 5; ++i) + { + dht_dat[i] = Wire.read(); // receive DATA + } + } else { + error = true; + } + + if (!error) + { + // Checksum calculation is a Rollover Checksum by design! + const uint8_t dht_check_sum = dht_dat[0] + dht_dat[1] + dht_dat[2] + dht_dat[3]; // check check_sum + + if (dht_dat[4] == dht_check_sum) + { + const float temperature = static_cast( + (dht_dat[2] * 10 + (dht_dat[3] & 0x7f)) * (dht_dat[3] & 0x80 ? -1 : 1)) / 10.0f; // Temperature + + const float humidity = float(dht_dat[0] * 10 + dht_dat[1]) / 10.0f; // Humidity + + UserVar.setFloat(event->TaskIndex, 0, temperature); + UserVar.setFloat(event->TaskIndex, 1, humidity); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, + concat(F("DHT12: Temperature: "), + formatUserVarNoCheck(event, 0))); + addLogMove(LOG_LEVEL_INFO, + concat(F("DHT12: Humidity: "), + formatUserVarNoCheck(event, 1))); + + /* + log = F("DHT12: Data: "); + for (int i=0; i < 5; i++) + { + log += dht_dat[i]; + log += ", "; + } + addLog(LOG_LEVEL_INFO, log); + */ + } + success = true; + } // checksum + } // error + + if (!success) + { + addLog(LOG_LEVEL_INFO, F("DHT12: No reading!")); + UserVar.setFloat(event->TaskIndex, 0, NAN); + UserVar.setFloat(event->TaskIndex, 1, NAN); + } + break; + } + } + return success; +} + +#endif // USES_P034 diff --git a/src/_P036_FrameOLED.ino b/src/_P036_FrameOLED.ino index 03c9d8ec8e..ca86d782a4 100644 --- a/src/_P036_FrameOLED.ino +++ b/src/_P036_FrameOLED.ino @@ -15,7 +15,8 @@ // As long as the device is not enabled, no RAM is wasted. // // @uwekaditz: 2024-08-06 -// ADD: Using template notations with escaped character (\%, \[ and \]) within oledframedcmd,, to reinterpreted each time before the line is displayed, +// ADD: Using template notations with escaped character (\%, \[ and \]) within oledframedcmd,, to reinterpreted each time +// before the line is displayed, // not only once while issuing the command and creating the new line content // @tonhuisman: 2024-07-14 // ADD: Selectable Header Time format, HH:MM:SS (default), HH:MM, HH:MM:SS AM/PM, HH:MM AM/PM, not enabled in LIMIT_BUILD_SIZE builds @@ -241,17 +242,11 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_036; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + Device[++deviceCount].Number = PLUGIN_ID_036; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; break; } diff --git a/src/_P037_MQTTImport.ino b/src/_P037_MQTTImport.ino index 69ca168072..dc05181ff6 100644 --- a/src/_P037_MQTTImport.ino +++ b/src/_P037_MQTTImport.ino @@ -11,6 +11,7 @@ // This task reads data from the MQTT Import input stream and saves the value /** + * 2025-01-03, tonhuisman: Small code cleanup * 2023-06-17, tonhuisman: Replace Device[].FormulaOption by Device[].DecimalsOnly option, as no (successful) PLUGIN_READ is done * 2023-03-06, tonhuisman: Fix PLUGIN_INIT behavior to now always return success = true * 2022-12-13, tonhuisman: Implement separator character input selector @@ -61,7 +62,7 @@ String P037_getMQTTLastTopicPart(const String& topic) { const int16_t lastSlash = topic.lastIndexOf('/'); if (lastSlash >= static_cast(topic.length() - 1)) { - return F(""); + return EMPTY_STRING; } String result = topic.substring(lastSlash + 1); // Take last part of the topic @@ -80,8 +81,8 @@ bool P037_addEventToQueue(struct EventStruct *event, String& newEvent) { # if P037_REPLACE_BY_COMMA_SUPPORT if (P037_REPLACE_BY_COMMA != 0x0) { - const String character = String(static_cast(P037_REPLACE_BY_COMMA)); - newEvent.replace(character, F(",")); + const char character = static_cast(P037_REPLACE_BY_COMMA); + newEvent.replace(character, ','); } # endif // if P037_REPLACE_BY_COMMA_SUPPORT eventQueue.add(newEvent, P037_DEDUPLICATE_EVENTS); @@ -112,16 +113,11 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_037; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; // This means it has a single pin - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].DecimalsOnly = true; // We only want to have the decimals option - Device[deviceCount].ValueCount = VARS_PER_TASK; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; + Device[++deviceCount].Number = PLUGIN_ID_037; + Device[deviceCount].Type = DEVICE_TYPE_DUMMY; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; // This means it has a single pin + Device[deviceCount].DecimalsOnly = true; // We only want to have the decimals option + Device[deviceCount].ValueCount = VARS_PER_TASK; break; } @@ -166,7 +162,7 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) addFormSubHeader(F("Options")); addFormCheckBox(F("Generate events for accepted topics"), - F("p037_send_events"), P037_SEND_EVENTS); + F("psend_events"), P037_SEND_EVENTS); # if !defined(P037_LIMIT_BUILD_SIZE) addFormNote(F("Event: <TaskName>#<topic>=<payload>")); # if P037_JSON_SUPPORT @@ -248,7 +244,7 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) # if P037_FILTER_SUPPORT P037_APPLY_FILTERS = getFormItemInt(F("pfilters")); # endif // if P037_FILTER_SUPPORT - P037_SEND_EVENTS = isFormItemChecked(F("p037_send_events")) ? 1 : 0; + P037_SEND_EVENTS = isFormItemChecked(F("psend_events")) ? 1 : 0; P037_DEDUPLICATE_EVENTS = isFormItemChecked(F("pdedupe")) ? 1 : 0; P037_QUEUEDEPTH_EVENTS = getFormItemInt(F("pquedepth")); @@ -331,11 +327,9 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) # ifdef PLUGIN_037_DEBUG if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String info = F("P037 : topic: "); - info += event->String1; - info += F(" value: "); - info += Payload; - addLog(LOG_LEVEL_INFO, info); + addLog(LOG_LEVEL_INFO, strformat(F("P037 : topic: %s value: %s"), + event->String1.c_str(), + Payload.c_str())); } # endif // ifdef PLUGIN_037_DEBUG @@ -379,7 +373,7 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) if (matchedTopic && P037_PARSE_JSON && - Payload.startsWith(F("{"))) { // With JSON enabled and rudimentary check for JSon content + Payload.startsWith(F("{"))) { // With JSON enabled a rudimentary check for JSon content # ifdef PLUGIN_037_DEBUG addLog(LOG_LEVEL_INFO, F("IMPT : MQTT JSON data detected.")); # endif // ifdef PLUGIN_037_DEBUG @@ -459,9 +453,7 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) if (matchedTopic && P037_data->hasFilters() && // Single log statement loglevelActiveFor(LOG_LEVEL_DEBUG)) { // Reduce standard logging - String log = F("IMPT : MQTT filter result: "); - log += processData ? F("true") : F("false"); - addLogMove(LOG_LEVEL_DEBUG, log); + addLog(LOG_LEVEL_DEBUG, concat(F("IMPT : MQTT filter result: "), boolToString(processData))); } # endif // ifndef BUILD_NO_DEBUG # endif // if P037_FILTER_SUPPORT @@ -540,11 +532,9 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) # if !defined(P037_LIMIT_BUILD_SIZE) || defined(P037_OVERRIDE) if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("IMPT : MQTT fetched json attribute: "); - log.reserve(48); - log += key; - log += F(" payload: "); - log += Payload; + String log = strformat(F("IMPT : MQTT fetched json attribute: %s payload: "), + key.c_str(), + Payload.c_str()); if (!jsonIndex.isEmpty()) { log += F(" index: "); @@ -562,16 +552,14 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) # ifdef PLUGIN_037_DEBUG if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("P037 json key: "); - log.reserve(48); - log += key; - log += F(" payload: "); - # if P037_MAPPING_SUPPORT - log += (P037_APPLY_MAPPINGS ? P037_data->mapValue(Payload, key) : Payload); - # else // if P037_MAPPING_SUPPORT - log += Payload; - # endif // if P037_MAPPING_SUPPORT - addLogMove(LOG_LEVEL_INFO, log); + addLog(LOG_LEVEL_INFO, strformat(F("P037 json key: %s payload: %s"), + key.c_str(), + # if P037_MAPPING_SUPPORT + P037_APPLY_MAPPINGS ? P037_data->mapValue(Payload, key).c_str() : Payload.c_str() + # else // if P037_MAPPING_SUPPORT + Payload.c_str() + # endif // if P037_MAPPING_SUPPORT + )); } # endif // ifdef PLUGIN_037_DEBUG ++P037_data->iter; @@ -590,19 +578,13 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) if (!validDoubleFromString(Payload, doublePayload)) { if (!checkJson && (P037_SEND_EVENTS == 0)) { // If we want all values as events, then no error logged and don't stop here - String log = F("IMPT : Bad Import MQTT Command "); - log.reserve(64); - log += event->String1; - addLog(LOG_LEVEL_ERROR, log); + addLog(LOG_LEVEL_ERROR, concat(F("IMPT : Bad Import MQTT Command "), event->String1)); # if !defined(P037_LIMIT_BUILD_SIZE) || defined(P037_OVERRIDE) if (loglevelActiveFor(LOG_LEVEL_INFO)) { - log.clear(); - log += F("ERR : Illegal Payload "); - log += Payload; - log += ' '; - log += getTaskDeviceName(event->TaskIndex); - addLogMove(LOG_LEVEL_INFO, log); + addLog(LOG_LEVEL_INFO, strformat(F("ERR : Illegal Payload %s %s"), + Payload.c_str(), + getTaskDeviceName(event->TaskIndex).c_str())); } # endif // if !defined(P037_LIMIT_BUILD_SIZE) || defined(P037_OVERRIDE) success = false; @@ -611,16 +593,13 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) numericPayload = false; // No, it isn't numeric doublePayload = NAN; // Invalid value } - UserVar.setFloat(event->TaskIndex, x, doublePayload); // Save the new value + UserVar.setFloat(event->TaskIndex, x, doublePayload); // Save the new value if (!checkJson && P037_SEND_EVENTS && Settings.UseRules) { // Generate event of all non-json topic/payloads - String RuleEvent; - RuleEvent.reserve(64); - RuleEvent += getTaskDeviceName(event->TaskIndex); - RuleEvent += '#'; - RuleEvent += event->String1; - RuleEvent += '='; - RuleEvent += wrapWithQuotesIfContainsParameterSeparatorChar(unparsedPayload); + String RuleEvent = strformat(F("%s#%s=%s"), + getTaskDeviceName(event->TaskIndex).c_str(), + event->String1.c_str(), + wrapWithQuotesIfContainsParameterSeparatorChar(unparsedPayload).c_str()); P037_addEventToQueue(event, RuleEvent); } @@ -628,18 +607,10 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) # if !defined(P037_LIMIT_BUILD_SIZE) || defined(P037_OVERRIDE) if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("IMPT : ["); - log += getTaskDeviceName(event->TaskIndex); - log += '#'; - - if (checkJson) { - log += key; - } else { - log += getTaskValueName(event->TaskIndex, x); - } - log += F("] : "); - log += doublePayload; - addLogMove(LOG_LEVEL_INFO, log); + addLog(LOG_LEVEL_INFO, strformat(F("IMPT : [%s#%s] : %.3f"), + getTaskDeviceName(event->TaskIndex), + checkJson ? key.c_str() : getTaskValueName(event->TaskIndex, x).c_str(), + doublePayload)); } # endif // if !defined(P037_LIMIT_BUILD_SIZE) || defined(P037_OVERRIDE) @@ -738,7 +709,8 @@ bool MQTT_unsubscribe_037(struct EventStruct *event) for (taskIndex_t task = 0; task < INVALID_TASK_INDEX && canUnsubscribe; ++task) { if (task != event->TaskIndex) { - constexpr pluginID_t P037_PLUGIN_ID{PLUGIN_ID_037}; + constexpr pluginID_t P037_PLUGIN_ID{ PLUGIN_ID_037 }; + if (Settings.TaskDeviceEnabled[task] && (Settings.getPluginID_for_task(task) == P037_PLUGIN_ID)) { P037_data_struct *P037_data_other = static_cast(getPluginTaskData(task)); @@ -748,15 +720,11 @@ bool MQTT_unsubscribe_037(struct EventStruct *event) canUnsubscribe = false; if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("IMPT : Cannot unsubscribe topic: "); - log += topic; - log += F(" used by: ["); - log += getTaskDeviceName(event->TaskIndex); - log += '#'; - log += getTaskValueName(event->TaskIndex, x); - log += ']'; - log += topic; - addLogMove(LOG_LEVEL_INFO, log); + addLog(LOG_LEVEL_INFO, strformat(F("IMPT : Cannot unsubscribe topic: %s used by: [%s#%s]%s"), + topic.c_str(), + getTaskDeviceName(event->TaskIndex).c_str(), + getTaskValueName(event->TaskIndex, x).c_str(), + topic.c_str())); } } } @@ -766,13 +734,10 @@ bool MQTT_unsubscribe_037(struct EventStruct *event) if (canUnsubscribe && (topic.length() > 0) && MQTTclient.unsubscribe(topic.c_str())) { if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("IMPT : ["); - log += getTaskDeviceName(event->TaskIndex); - log += '#'; - log += getTaskValueName(event->TaskIndex, x); - log += F("] : Unsubscribe topic: "); - log += topic; - addLogMove(LOG_LEVEL_INFO, log); + addLog(LOG_LEVEL_INFO, strformat(F("IMPT : [%s#%s] : Unsubscribe topic: %s"), + getTaskDeviceName(event->TaskIndex).c_str(), + getTaskValueName(event->TaskIndex, x).c_str(), + topic.c_str())); } } } @@ -800,19 +765,14 @@ bool MQTTSubscribe_037(struct EventStruct *event) if (MQTTclient.subscribe(subscribeTo.c_str())) { if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("IMPT : ["); - log += getTaskDeviceName(event->TaskIndex); - log += F("#"); - log += getTaskValueName(event->TaskIndex, x); - log += F("] subscribed to "); - log += subscribeTo; - addLogMove(LOG_LEVEL_INFO, log); + addLog(LOG_LEVEL_INFO, strformat(F("IMPT : [%s#%s] subscribed to %s"), + getTaskDeviceName(event->TaskIndex).c_str(), + getTaskValueName(event->TaskIndex, x).c_str(), + subscribeTo.c_str())); } } else { if (loglevelActiveFor(LOG_LEVEL_ERROR)) { - String log = F("IMPT : Error subscribing to "); - log += subscribeTo; - addLogMove(LOG_LEVEL_ERROR, log); + addLog(LOG_LEVEL_ERROR, concat(F("IMPT : Error subscribing to "), subscribeTo)); } return false; } @@ -846,7 +806,7 @@ bool MQTTCheckSubscription_037(const String& Topic, const String& Subscription) if (equals(tmpSub, '#')) { return true; } // If the subscription is for '#' then all topics are accepted if (tmpSub.endsWith(F("/#"))) { // A valid MQTT multi-level wildcard is a # at the end of the topic that's preceded by a / - bool multiLevelWildcard = tmpTopic.startsWith(tmpSub.substring(0, tmpSub.length() - 1)); + const bool multiLevelWildcard = tmpTopic.startsWith(tmpSub.substring(0, tmpSub.length() - 1)); if (tmpSub.indexOf('+') == -1) { return multiLevelWildcard; // It matched, or not @@ -858,11 +818,11 @@ bool MQTTCheckSubscription_037(const String& Topic, const String& Subscription) // Add trailing / if required - int lenTopic = tmpTopic.length(); + const int lenTopic = tmpTopic.length(); if (tmpTopic.substring(lenTopic - 1, lenTopic) != "/") { tmpTopic += '/'; } - int lenSub = tmpSub.length(); + const int lenSub = tmpSub.length(); if (tmpSub.substring(lenSub - 1, lenSub) != "/") { tmpSub += '/'; } diff --git a/src/_P039_Thermosensors.ino b/src/_P039_Thermosensors.ino index 096d141089..131b59c0b9 100644 --- a/src/_P039_Thermosensors.ino +++ b/src/_P039_Thermosensors.ino @@ -1,2139 +1,2045 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P039 - -// ####################################################################################################### -// ######################## Plugin 039: Thermocouple (MAX6675 / MAX31855) ################################ -// ####################################################################################################### - -// Original work by Dominik - -// Plugin Description -// This Plugin reads the data from Thermocouples. You have to use an Adapter Board with a -// MAX6675 or MAX31855 in order to read the values. Take a look at ebay to find such boards :-) -// You can only use ESP8266 boards which expose the SPI Interface. This Plugin uses only the Hardware -// SPI Interface - no software SPI at the moment. -// But nevertheless you need at least 3 Pins to use SPI. So using an very simple ESP-01 is no option - Sorry. -// The Wiring is straight forward ... -// -// If you like to send suggestions feel free to send me an email : dominik@logview.info -// Have fun ... Dominik - -/** Changelog: - * 2024-01-04 tonhuisman: Minor corrections, formatted source using Uncrustify - * 2023-01-08 tonhuisman: Add Low temperature threshold setting (default 0 K/-273.15 C) to ignore temperatures below that value - * 2023-01-02 tonhuisman: Cleanup and uncrustify source - * 2022-10-22 tonhuisman: Correct CS pin check to allow GPIO0 - * 2022-10: Older changelog not recorded - */ - -// Wiring -// https://de.wikipedia.org/wiki/Serial_Peripheral_Interface -// You need an ESP8266 device with accessible SPI Pins. These are: -// Name Description GPIO NodeMCU Notes -// MOSI Master Output GPIO13 D7 Not used (No Data sending to MAX) -// MISO Master Input GPIO12 D6 Hardware SPI -// SCK Clock Output GPIO14 D5 Hardware SPI -// CS Chip Select GPIO15 D8 Hardware SPI (CS is configurable through the web interface) - -// Thermocouple Infos -// http://www.bristolwatch.com/ele2/therc.htm - -// Resistor Temperature Detector Infos -// https://en.wikipedia.org/wiki/Resistance_thermometer - -// Chips -// MAX6675 - Cold-Junction-Compensated K-Thermocouple-to-Digital Converter ( 0°C to +1024°C) -// https://cdn-shop.adafruit.com/datasheets/MAX6675.pdf (only -// MAX31855 - Cold-Junction Compensated Thermocouple-to-Digital Converter (-270°C to +1800°C) -// https://cdn-shop.adafruit.com/datasheets/MAX31855.pdf -// MAX31856 - Precision Thermocouple to Digital Converter with Linearization (-210°C to +1800°C) -// https://datasheets.maximintegrated.com/en/ds/MAX31856.pdf -// MAX31865 - Precision Resistor Temperature Detector to Digital Converter with Linearization (PT100 / PT1000) -// https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf -// TI Digital Temperature sensors with SPI interface -// https://www.ti.com/sensors/temperature-sensors/digital/products.html#p1918=SPI,%20Microwire -// TI LM7x - Digital temperature sensor with SPI interface -// https://www.ti.com/lit/gpn/LM70 -// https://www.ti.com/lit/gpn/LM71 -// https://www.ti.com/lit/gpn/LM70 -// https://www.ti.com/lit/gpn/LM74 -// TI TMP12x Digital temperature sensor with SPI interface -// https://www.ti.com/lit/gpn/TMP121 -// https://www.ti.com/lit/gpn/TMP122 -// https://www.ti.com/lit/gpn/TMP123 -// https://www.ti.com/lit/gpn/TMP124 - -# include - -// #include -# include "src/PluginStructs/P039_data_struct.h" - - -// // plugin-local quick activation of debug messages -// #ifdef BUILD_NO_DEBUG -// #undef BUILD_NO_DEBUG -// #endif - - -# define MAX31865_RD_ADDRESS(n) (MAX31865_READ_ADDR_BASE + (n)) -# define MAX31865_WR_ADDRESS(n) (MAX31865_WRITE_ADDR_BASE + (n)) - -# define PLUGIN_039 -# define PLUGIN_ID_039 39 -# define PLUGIN_NAME_039 "Environment - Thermosensors" -# define PLUGIN_VALUENAME1_039 "Temperature" - -# define P039_SET true -# define P039_RESET false - -// typically 500ns of wating on positive/negative edge of CS should be enough ( -> datasheet); to make sure we cover a lot of devices we -// spend 1ms -// FIX 2021-05-05: review of all covered device datasheets showed 2µs is more than enough; review with every newly added device -# define P039_CS_Delay() delayMicroseconds(2u) - -# define P039_MAX_TYPE PCONFIG(0) -# define P039_TC_TYPE PCONFIG(1) -# define P039_FAM_TYPE PCONFIG(2) -# define P039_RTD_TYPE PCONFIG(3) -# define P039_CONFIG_4 PCONFIG(4) -# define P039_RTD_FILT_TYPE PCONFIG(5) -# define P039_RTD_LM_TYPE PCONFIG(6) -# define P039_RTD_LM_SHTDWN PCONFIG(7) -# define P039_RTD_RES PCONFIG_LONG(0) -# define P039_FLAGS PCONFIG_ULONG(3) -# define P039_TEMP_THRESHOLD_FLAG 0 -# define P039_RTD_OFFSET PCONFIG_FLOAT(0) -# define P039_TEMP_THRESHOLD PCONFIG_FLOAT(1) - -# define P039_TEMP_THRESHOLD_DEFAULT (-273.15f) // Default and minimum value -# define P039_TEMP_THRESHOLD_MIN P039_TEMP_THRESHOLD_DEFAULT -# define P039_TEMP_THRESHOLD_MAX (1000.0f) // Max value -# define P039_TC 0u -# define P039_RTD 1u - -# define P039_MAX6675 1 -# define P039_MAX31855 2 -# define P039_MAX31856 3 -# define P039_MAX31865 4 -# define P039_LM7x 5 - -// MAX 6675 related defines - -// bit masks to identify failures for MAX 6675 -# define MAX6675_TC_DEVID 0x0002u -# define MAX6675_TC_OC 0x0004u - -// MAX 31855 related defines - -// bit masks to identify failures for MAX 31855 -# define MAX31855_TC_OC 0x00000001u -# define MAX31855_TC_SC 0x00000002u -# define MAX31855_TC_SCVCC 0x00000004u -# define MAX31855_TC_GENFLT 0x00010000u - - -// MAX 31856 related defines - -// base address for read/write acces to MAX 31856 -# define MAX31856_READ_ADDR_BASE 0x00u -# define MAX31856_WRITE_ADDR_BASE 0x80u - -// register offset values for MAX 31856 -# define MAX31856_CR0 0u -# define MAX31856_CR1 1u -# define MAX31856_MASK 2u -# define MAX31856_CJHF 3u -# define MAX31856_CJLF 4u -# define MAX31856_LTHFTH 5u -# define MAX31856_LTHFTL 6u -# define MAX31856_LTLFTH 7u -# define MAX31856_LTLFTL 8u -# define MAX31856_CJTO 9u -# define MAX31856_CJTH 10u -# define MAX31856_CJTL 11u -# define MAX31856_LTCBH 12u -# define MAX31856_LTCBM 13u -# define MAX31856_LTCBL 14u -# define MAX31856_SR 15u - -# define MAX31856_NO_REG 16u - -// bit masks to identify failures for MAX 31856 -# define MAX31856_TC_OC 0x01u -# define MAX31856_TC_OVUV 0x02u -# define MAX31856_TC_TCLOW 0x04u -# define MAX31856_TC_TCLHIGH 0x08u -# define MAX31856_TC_CJLOW 0x10u -# define MAX31856_TC_CJHIGH 0x20u -# define MAX31856_TC_TCRANGE 0x40u -# define MAX31856_TC_CJRANGE 0x80u - -// bit masks for access of configuration bits -# define MAX31856_SET_50HZ 0x01u -# define MAX31856_CLEAR_FAULTS 0x02u -# define MAX31856_FLT_ISR_MODE 0x04u -# define MAX31856_CJ_SENS_DISABLE 0x08u -# define MAX31856_FAULT_CTRL_MASK 0x30u -# define MAX31856_SET_ONE_SHOT 0x40u -# define MAX31856_SET_CONV_AUTO 0x80u - - -// RTD related defines - -// MAX 31865 related defines - -// waiting time until "in sequence" conversion is ready (-> used in case device is set to shutdown in between call cycles) -// typically 70ms should be fine, according to datasheet maximum -> 66ms - give a little adder to "be sure" conversion is done -// alternatively ONE SHOT bit could be polled (system/SPI bus load !) -# define MAX31865_CONVERSION_TIME 70ul -# define MAX31865_BIAS_WAIT_TIME 10ul - -// MAX 31865 Main States -# define MAX31865_INIT_STATE 0u -# define MAX31865_BIAS_ON_STATE 1u -# define MAX31865_RD_STATE 2u -# define MAX31865_RDY_STATE 3u - -// sensor type -# define MAX31865_PT100 0u -# define MAX31865_PT1000 1u - -// base address for read/write acces to MAX 31865 -# define MAX31865_READ_ADDR_BASE 0x00u -# define MAX31865_WRITE_ADDR_BASE 0x80u - -// register offset values for MAX 31865 -# define MAX31865_CONFIG 0u -# define MAX31865_RTD_MSB 1u -# define MAX31865_RTD_LSB 2u -# define MAX31865_HFT_MSB 3u -# define MAX31865_HFT_LSB 4u -# define MAX31865_LFT_MSB 5u -# define MAX31865_LFT_LSB 6u -# define MAX31865_FAULT 7u - -// total number of registers in MAX 31865 -# define MAX31865_NO_REG 8u - -// bit masks to identify failures for MAX 31865 -# define MAX31865_FAULT_HIGHTHRESH 0x80u -# define MAX31865_FAULT_LOWTHRESH 0x40u -# define MAX31865_FAULT_REFINLOW 0x20u -# define MAX31865_FAULT_REFINHIGH 0x10u -# define MAX31865_FAULT_RTDINLOW 0x08u -# define MAX31865_FAULT_OVUV 0x04u - -// bit masks for access of configuration bits -# define MAX31865_SET_50HZ 0x01u -# define MAX31865_CLEAR_FAULTS 0x02u -# define MAX31865_FAULT_CTRL_MASK 0x0Cu -# define MAX31865_SET_3WIRE 0x10u -# define MAX31865_SET_ONE_SHOT 0x20u -# define MAX31865_SET_CONV_AUTO 0x40u -# define MAX31865_SET_VBIAS_ON 0x80u - -// LM7x related defines - -// LM7x subtype defines -# define LM7x_SD70 0x00u -# define LM7x_SD71 0x01u -# define LM7x_SD74 0x04u -# define LM7x_SD121 0x05u -# define LM7x_SD122 0x06u -# define LM7x_SD123 0x07u -# define LM7x_SD124 0x08u -# define LM7x_SD125 0x09u - -// bit masks for access of configuration bits -# define LM7x_CONV_RDY 0x02u - - -void P039_AddMainsFrequencyFilterSelection(struct EventStruct *event); - -boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_039; - Device[deviceCount].Type = DEVICE_TYPE_SPI; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_039); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_039)); - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: - { - event->String1 = formatGpioName_output(F("CS")); - break; - } - - case PLUGIN_SET_DEFAULTS: - { - P039_TEMP_THRESHOLD = P039_TEMP_THRESHOLD_DEFAULT; // 0 K - bitSet(P039_FLAGS, P039_TEMP_THRESHOLD_FLAG); - break; - } - - case PLUGIN_INIT: - { - if (!bitRead(P039_FLAGS, P039_TEMP_THRESHOLD_FLAG)) { - P039_TEMP_THRESHOLD = P039_TEMP_THRESHOLD_DEFAULT; // 0 K - } - - if ((P039_MAX_TYPE < P039_MAX6675) || (P039_MAX_TYPE > P039_LM7x)) { - break; - } - - - initPluginTaskData(event->TaskIndex, new (std::nothrow) P039_data_struct()); - P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); - - int8_t CS_pin_no = get_SPI_CS_Pin(event); - - // set the slaveSelectPin as an output: - init_SPI_CS_Pin(CS_pin_no); - - // initialize SPI: - SPI.setHwCs(false); - SPI.begin(); - - // ensure MODE3 access to SPI device - SPI.setDataMode(SPI_MODE3); - - /* - if (P039_MAX_TYPE == P039_MAX6675) { - - // SPI.setBitOrder(MSBFIRST); - } - */ - if (P039_MAX_TYPE == P039_MAX31855) { - // SPI.setBitOrder(MSBFIRST); - - if (nullptr != P039_data) { - // FIXED: c.k.i. : moved static fault flag to instance data structure - P039_data->sensorFault = false; - } - } - - - if (P039_MAX_TYPE == P039_MAX31856) { - // init string - content accoring to inital implementation of P039 - MAX31856 read function - // write to Adress 0x80 - // activate 50Hz filter in CR0, choose averaging and TC type from configuration in CR1, activate OV/UV/OC faults, write defaults to - // CJHF, CJLF, LTHFTH, LTHFTL, LTLFTH, LTLFTL, CJTO - uint8_t sendBuffer[11] = - { 0x80, static_cast(P039_RTD_FILT_TYPE), static_cast((P039_CONFIG_4 << 4) | P039_TC_TYPE), 0xFC, 0x7F, 0xC0, 0x7F, - 0xFF, 0x80, 0x00, 0x00 }; - - transfer_n_ByteSPI(CS_pin_no, 11, &sendBuffer[0]); - - if (nullptr != P039_data) { - // FIXED: c.k.i. : moved static fault flag to instance data structure - P039_data->sensorFault = false; - } - - // start on shot conversion for upcoming read cycle - change8BitRegister(CS_pin_no, - (MAX31856_READ_ADDR_BASE + MAX31856_CR0), - (MAX31856_WRITE_ADDR_BASE + MAX31856_CR0), - MAX31856_SET_ONE_SHOT, - P039_SET); - } - - - if (P039_MAX_TYPE == P039_MAX31865) { - // two step initialization buffer - uint8_t initSendBufferHFTH[3] = { (MAX31865_WRITE_ADDR_BASE + MAX31865_HFT_MSB), 0xFF, 0xFF }; - uint8_t initSendBufferLFTH[3] = { (MAX31865_WRITE_ADDR_BASE + MAX31865_HFT_MSB), 0xFF, 0xFF }; - - // write intially 0x00 to CONFIG register - write8BitRegister(CS_pin_no, (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), 0x00u); - - // activate 50Hz filter, clear all faults, no auto conversion, no conversion started - change8BitRegister(CS_pin_no, - MAX31865_RD_ADDRESS(MAX31865_CONFIG), - MAX31865_WR_ADDRESS(MAX31865_CONFIG), - MAX31865_SET_50HZ, - static_cast(P039_RTD_FILT_TYPE)); - - // configure 2/4-wire sensor connection as default - MAX31865_setConType(CS_pin_no, P039_CONFIG_4); - - // set HighFault Threshold - transfer_n_ByteSPI(CS_pin_no, 3, &initSendBufferHFTH[0]); - - // set LowFault Threshold - transfer_n_ByteSPI(CS_pin_no, 3, &initSendBufferLFTH[0]); - - // clear all faults - MAX31865_clearFaults(CS_pin_no); - - // activate BIAS short before read, to reduce power consumption - change8BitRegister(CS_pin_no, - (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), - (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), - MAX31865_SET_VBIAS_ON, - P039_SET); - - if (nullptr != P039_data) { - // save current timer for next calculation - P039_data->timer = millis(); - - // start time to follow up on BIAS activation before starting the conversion - // and start conversion sequence via TIMER API - - Scheduler.setPluginTaskTimer(MAX31865_BIAS_WAIT_TIME, event->TaskIndex, MAX31865_BIAS_ON_STATE); - } - } - - /* - if (P039_MAX_TYPE == P039_LM7x) - { - // TODO: c.k.i.: more detailed inits depending on the sub devices expected , e.g. TMP 122/124 - } - */ - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, strformat(F("P039 : %s : SPI Init - DONE"), getTaskDeviceName(event->TaskIndex).c_str())); - } - # endif // ifndef BUILD_NO_DEBUG - - success = true; - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - addFormSubHeader(F("Sensor Family Selection")); - - const uint8_t family = P039_FAM_TYPE; - { - const __FlashStringHelper *Foptions[2] = { F("Thermocouple"), F("RTD") }; - const int FoptionValues[2] = { P039_TC, P039_RTD }; - addFormSelector(F("Sensor Family Type"), F("famtype"), 2, Foptions, FoptionValues, family, true); // auto reload activated - } - - const uint8_t choice = P039_MAX_TYPE; - - addFormSubHeader(F("Device Type Settings")); - - if (family == P039_TC) { - { - const __FlashStringHelper *options[3] = { F("MAX 6675"), F("MAX 31855"), F("MAX 31856") }; - const int optionValues[3] = { P039_MAX6675, P039_MAX31855, P039_MAX31856 }; - addFormSelector(F("Adapter IC"), F("maxtype"), 3, options, optionValues, choice, true); // auto reload activated - } - - if (choice == P039_MAX31856) { - addFormSubHeader(F("Device Settings")); - { - const __FlashStringHelper *Toptions[10] = { F("B"), F("E"), F("J"), F("K"), F("N"), F("R"), F("S"), F("T"), F("VM8"), F("VM32") }; - - // 2021-05-17: c.k.i.: values are directly written to device register for configuration, therefore no linear values are used - // here - // MAX 31856 datasheet (page 20): - // Thermocouple Type - // 0000 = B Type - // 0001 = E Type - // 0010 = J Type - // 0011 = K Type (default) - // 0100 = N Type - // 0101 = R Type - // 0110 = S Type - // 0111 = T Type - // 10xx = Voltage Mode, Gain = 8. Code = 8 x 1.6 x 217 x VIN - // 11xx = Voltage Mode, Gain = 32. Code = 32 x 1.6 x 217 x VIN - // Where Code is 19 bit signed number from TC registers and VIN is thermocouple input voltage - - const int ToptionValues[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12 }; - addFormSelector(F("Thermocouple type"), F("tctype"), 10, Toptions, ToptionValues, P039_TC_TYPE); - } - { - const __FlashStringHelper *Coptions[5] = { F("1"), F("2"), F("4"), F("8"), F("16") }; - const int CoptionValues[5] = { 0, 1, 2, 3, 4 }; - addFormSelector(F("Averaging"), F("contype"), 5, Coptions, CoptionValues, P039_CONFIG_4); - addUnit(F("sample(s)")); - } - P039_AddMainsFrequencyFilterSelection(event); - } - } - else { - { - const __FlashStringHelper *TPoptions[2] = { F("MAX 31865"), F("LM7x") }; - const int TPoptionValues[2] = { P039_MAX31865, P039_LM7x }; - addFormSelector(F("Adapter IC"), F("maxtype"), 2, TPoptions, TPoptionValues, choice, true); // auto reload activated - addFormNote(F("LM7x support is experimental.")); - } - - - if (choice == P039_MAX31865) - { - { - addFormSubHeader(F("Device Settings")); - } - { - const __FlashStringHelper *PToptions[2] = { F("PT100"), F("PT1000") }; - const int PToptionValues[2] = { MAX31865_PT100, MAX31865_PT1000 }; - addFormSelector(F("Resistor Type"), F("rtdtype"), 2, PToptions, PToptionValues, P039_RTD_TYPE); - } - { - const __FlashStringHelper *Coptions[2] = { F("2-/4"), F("3") }; - const int CoptionValues[2] = { 0, 1 }; - addFormSelector(F("Connection Type"), F("contype"), 2, Coptions, CoptionValues, P039_CONFIG_4); - addUnit(F("wire")); - } - - P039_AddMainsFrequencyFilterSelection(event); - - { - addFormNumericBox(F("Reference Resistor"), F("res"), P039_RTD_RES, 0); - addUnit(F("Ohm")); - addFormNote(F("PT100: typically 430 [OHM]; PT1000: typically 4300 [OHM]")); - } - { - addFormFloatNumberBox(F("Temperature Offset"), F("offset"), P039_RTD_OFFSET, -50.0f, 50.0f, 2, 0.01f); - addUnit('K'); - # ifndef BUILD_NO_DEBUG - addFormNote(F("Valid values: [-50.0...50.0 K], min. stepsize: [0.01]")); - # endif // ifndef BUILD_NO_DEBUG - } - } - - if (choice == P039_LM7x) - { - { - addFormSubHeader(F("Device Settings")); - } - - { - const __FlashStringHelper *PToptions[8] = - { F("LM70"), F("LM71"), F("LM74"), F("TMP121"), F("TMP122"), F("TMP123"), F("TMP124"), F("TMP125") }; - const int PToptionValues[8] = { LM7x_SD70, LM7x_SD71, LM7x_SD74, LM7x_SD121, LM7x_SD122, LM7x_SD123, LM7x_SD124, LM7x_SD125 }; - addFormSelector(F("LM7x device details"), F("rtd_lm_type"), 8, PToptions, PToptionValues, P039_RTD_LM_TYPE); - addFormNote(F("TMP122/124 Limited support -> fixed 12 Bit res, no advanced options")); - } - { - addFormCheckBox(F("Enable Shutdown Mode"), F("rtd_lm_shtdwn"), P039_RTD_LM_SHTDWN); - # ifndef BUILD_NO_DEBUG - addFormNote(F("Device is set to shutdown between sample cycles. Useful for very long call cycles, to save power.
" - "Without LM7x device conversion happens in between call cycles. Call Cylces should therefore not become lower than 350ms.")); - # endif // ifndef BUILD_NO_DEBUG - } - } - } - - addFormSubHeader(F("Value validation")); - - if (!bitRead(P039_FLAGS, P039_TEMP_THRESHOLD_FLAG)) { - P039_TEMP_THRESHOLD = P039_TEMP_THRESHOLD_DEFAULT; // 0 K - } - addFormFloatNumberBox(F("Low temperature threshold"), - F("temp_thres"), - P039_TEMP_THRESHOLD, - P039_TEMP_THRESHOLD_MIN, - P039_TEMP_THRESHOLD_MAX, - 2u); - addUnit(F("°C")); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - P039_FAM_TYPE = getFormItemInt(F("famtype")); - P039_MAX_TYPE = getFormItemInt(F("maxtype")); - P039_TC_TYPE = getFormItemInt(F("tctype")); - P039_RTD_TYPE = getFormItemInt(F("rtdtype")); - P039_CONFIG_4 = getFormItemInt(F("contype")); - P039_RTD_FILT_TYPE = getFormItemInt(F("filttype")); - P039_RTD_RES = getFormItemInt(F("res")); - P039_RTD_OFFSET = getFormItemFloat(F("offset")); - P039_RTD_LM_TYPE = getFormItemInt(F("rtd_lm_type")); - P039_RTD_LM_SHTDWN = isFormItemChecked(F("rtd_lm_shtdwn")); - P039_TEMP_THRESHOLD = getFormItemFloat(F("temp_thres")); - bitSet(P039_FLAGS, P039_TEMP_THRESHOLD_FLAG); // We've set a value, don't replace by default - - success = true; - break; - } - - case PLUGIN_READ: - { - // Get the MAX Type (6675 / 31855 / 31856) - uint8_t MaxType = P039_MAX_TYPE; - - float Plugin_039_Celsius = NAN; - - switch (MaxType) { - case P039_MAX6675: - Plugin_039_Celsius = readMax6675(event); - break; - case P039_MAX31855: - Plugin_039_Celsius = readMax31855(event); - break; - case P039_MAX31856: - Plugin_039_Celsius = readMax31856(event); - break; - case P039_MAX31865: - Plugin_039_Celsius = readMax31865(event); - break; - case P039_LM7x: - Plugin_039_Celsius = readLM7x(event); - break; - } - - if (isValidFloat(Plugin_039_Celsius)) - { - UserVar.setFloat(event->TaskIndex, 0, Plugin_039_Celsius); - -# ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = strformat(F("P039 : %s :"), getTaskDeviceName(event->TaskIndex).c_str()); - - const uint8_t valueCount = getValueCountForTask(event->TaskIndex); - - for (uint8_t i = 0; i < valueCount; ++i) - { - log += strformat( - F(" %s: %s"), - Cache.getTaskDeviceValueName(event->TaskIndex, i).c_str(), - formatUserVarNoCheck(event, i).c_str()); - } - addLogMove(LOG_LEVEL_INFO, log); - } -# endif // ifndef BUILD_NO_DEBUG - - if (definitelyGreaterThan(Plugin_039_Celsius, P039_TEMP_THRESHOLD)) { - success = true; - } - } - else - { - UserVar.setFloat(event->TaskIndex, 0, NAN); - UserVar.setFloat(event->TaskIndex, 1, NAN); - - if (loglevelActiveFor(LOG_LEVEL_ERROR)) { - addLog(LOG_LEVEL_ERROR, strformat(F("P039 : %s : No Sensor attached!"), getTaskDeviceName(event->TaskIndex).c_str())); - } - success = false; - } - - break; - } - - case PLUGIN_TASKTIMER_IN: - { - P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); - - int8_t CS_pin_no = get_SPI_CS_Pin(event); - - // Get the MAX Type (6675 / 31855 / 31856) - uint8_t MaxType = P039_MAX_TYPE; - - switch (MaxType) - { - case P039_MAX31865: - { - if ((nullptr != P039_data)) { - switch (event->Par1) - { - case MAX31865_BIAS_ON_STATE: - { - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - addLog(LOG_LEVEL_DEBUG, strformat( - F("P039 : %s : current state: MAX31865_BIAS_ON_STATE; delta: %d ms"), - getTaskDeviceName(event->TaskIndex).c_str(), - timePassedSince(P039_data->timer))); // calc delta since last call - } - # endif // ifndef BUILD_NO_DEBUG - - // save current timer for next calculation - P039_data->timer = millis(); - - // activate one shot conversion - change8BitRegister(CS_pin_no, - (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), - (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), - MAX31865_SET_ONE_SHOT, - P039_SET); - - // set next state in sequence -> READ STATE - // start time to follow up on conversion and read the conversion result - P039_data->convReady = false; - Scheduler.setPluginTaskTimer(MAX31865_CONVERSION_TIME, event->TaskIndex, MAX31865_RD_STATE); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - addLog(LOG_LEVEL_DEBUG, strformat( - F("P039 : %s : Next State: %d"), - getTaskDeviceName(event->TaskIndex).c_str(), - event->Par1)); - } - # endif // ifndef BUILD_NO_DEBUG - - break; - } - case MAX31865_RD_STATE: - { - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - addLog(LOG_LEVEL_DEBUG, strformat( - F("P039 : %s : current state: MAX31865_RD_STATE; delta: %d ms"), - getTaskDeviceName(event->TaskIndex).c_str(), - timePassedSince(P039_data->timer))); // calc delta since last call - } - # endif // ifndef BUILD_NO_DEBUG - - // save current timer for next calculation - P039_data->timer = millis(); - - // read conversion result - P039_data->conversionResult = read16BitRegister(CS_pin_no, (MAX31865_READ_ADDR_BASE + MAX31865_RTD_MSB)); - - // deactivate BIAS short after read, to reduce power consumption - change8BitRegister(CS_pin_no, - (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), - (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), - MAX31865_SET_VBIAS_ON, - P039_RESET); - - // read fault register to get a full picture - P039_data->deviceFaults = read8BitRegister(CS_pin_no, (MAX31865_READ_ADDR_BASE + MAX31865_FAULT)); - - // mark conversion as ready - P039_data->convReady = true; - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - String log; - - if ((log.reserve(170u))) { // reserve value derived from example log file - log = F("P039 : "); // 7 char - log += getTaskDeviceName(event->TaskIndex); // 41 char ( max length of task device name + 1) - log += F(" : conversionResult: "); // 21 char - log += formatToHex_decimal(P039_data->conversionResult); // 11 char - log += F("; deviceFaults: "); // 16 char - log += formatToHex_decimal(P039_data->deviceFaults); // 9 char - log += F("; Next State: "); // 13 char - log += event->Par1; // 4 char - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - # endif // ifndef BUILD_NO_DEBUG - - - break; - } - case MAX31865_INIT_STATE: - default: - { - // clear all faults - MAX31865_clearFaults(CS_pin_no); - - // activate BIAS short before read, to reduce power consumption - change8BitRegister(CS_pin_no, - (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), - (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), - MAX31865_SET_VBIAS_ON, - P039_SET); - - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - String log; - - if ((log.reserve(140u))) { // reserve value derived from example log file - log = F("P039 : "); // 7 char - log += getTaskDeviceName(event->TaskIndex); // 41 char - log += F(" : "); // 3 char - log += F("current state: MAX31865_INIT_STATE, default;"); // many char - 44 - log += F(" next state: MAX31865_BIAS_ON_STATE"); // a little less char - 35 - addLogMove(LOG_LEVEL_DEBUG, log); - } - - // save current timer for next calculation - P039_data->timer = millis(); - } - # endif // ifndef BUILD_NO_DEBUG - - // start time to follow up on BIAS activation before starting the conversion - // and start conversion sequence via TIMER API - // set next state in sequence -> BIAS ON STATE - - Scheduler.setPluginTaskTimer(MAX31865_BIAS_WAIT_TIME, event->TaskIndex, MAX31865_BIAS_ON_STATE); - - - break; - } - } - } - break; - } - default: - { - break; - } - } - - success = true; - break; - } - } - return success; -} - -void P039_AddMainsFrequencyFilterSelection(struct EventStruct *event) -{ - const __FlashStringHelper *FToptions[2] = { F("60"), F("50") }; - const int FToptionValues[2] = { 0, 1 }; - - addFormSelector(F("Supply Frequency Filter"), F("filttype"), 2, FToptions, FToptionValues, P039_RTD_FILT_TYPE); - addUnit(F("Hz")); - addFormNote(F("Filter power net frequency (50/60 Hz)")); -} - -float readMax6675(struct EventStruct *event) -{ - int8_t CS_pin_no = get_SPI_CS_Pin(event); - - uint8_t messageBuffer[2] = { 0 }; - uint16_t rawvalue = 0u; - - - // "transfer" 2 bytes to SPI to get 16 Bit return value - transfer_n_ByteSPI(CS_pin_no, 2, &messageBuffer[0]); - - // merge 16Bit return value from messageBuffer - rawvalue = ((messageBuffer[0] << 8) | messageBuffer[1]); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) - { - String log; - - if ((log.reserve(130u))) { // reserve value derived from example log file - log = F("P039 : MAX6675 : RAW - BIN: "); // 27 char - log += String(rawvalue, BIN); // 18 char - log += F(" HEX: "); // 5 char - log += formatToHex(rawvalue); // 4 char - log += F(" DEC: "); // 5 char - log += String(rawvalue); // 5 char - log += F(" MSB: "); // 5 char - log += formatToHex_decimal(messageBuffer[0]); // 9 char - log += F(" LSB: "); // 5 char - log += formatToHex_decimal(messageBuffer[1]); // 9 char - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - // Open Thermocouple - // Bit D2 is normally low and goes high if the thermocouple input is open. In order to allow the operation of the - // open thermocouple detector, T- must be grounded. Make the ground connection as close to the GND pin - // as possible. - // 2021-05-11: FIXED: c.k.i.: OC Flag already checked; migrated to #define for improved maintenance - const bool Plugin_039_SensorAttached = !(rawvalue & MAX6675_TC_OC); - - if (Plugin_039_SensorAttached) - { - // shift RAW value 3 Bits to the right to get the data - rawvalue >>= 3; - - // calculate Celsius with device resolution 0.25 K/bit - return rawvalue * 0.25f; - } - else - { - return NAN; - } -} - -float readMax31855(struct EventStruct *event) -{ - P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); - - uint8_t messageBuffer[4] = { 0 }; - - int8_t CS_pin_no = get_SPI_CS_Pin(event); - - // "transfer" 0x0 and read the 32 Bit conversion register from the Chip - transfer_n_ByteSPI(CS_pin_no, 4, &messageBuffer[0]); - - // merge rawvalue from 4 bytes of messageBuffer - uint32_t rawvalue = - ((static_cast(messageBuffer[0]) << - 24) | - (static_cast(messageBuffer[1]) << - 16) | (static_cast(messageBuffer[2]) << 8) | static_cast(messageBuffer[3])); - - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) - { - String log; - - if ((log.reserve(200u))) { // reserve value derived from example log file - log = F("P039 : MAX31855 : RAW - BIN: "); // 35 char - log += String(rawvalue, BIN); // 16 char - log += F(" rawvalue,HEX: "); // 15 char - log += formatToHex(rawvalue); // 4 char - log += F(" rawvalue,DEC: "); // 15 char - log += rawvalue; // 5 char - log += F(" messageBuffer[],HEX:"); // 21 char - - for (size_t i = 0u; i < 4; ++i) - { - log += ' '; // 1 char - log += formatToHex_decimal(messageBuffer[i]); // 9 char - } - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - if (nullptr != P039_data) { - // FIXED: c.k.i. : moved static fault flag to instance data structure - - // check for fault flags in LSB of 32 Bit messageBuffer - if (P039_data->sensorFault != ((rawvalue & (MAX31855_TC_SCVCC | MAX31855_TC_SC | MAX31855_TC_OC)) == 0)) { - // Fault code changed, log them - P039_data->sensorFault = ((rawvalue & (MAX31855_TC_SCVCC | MAX31855_TC_SC | MAX31855_TC_OC)) == 0); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(120u))) { // reserve value derived from example log file - log = F("P039 : MAX31855 : "); - - if ((P039_data->sensorFault)) { - log += F("Fault resolved"); - } else { - log += F("Fault code :"); - - if (rawvalue & MAX31855_TC_OC) { - log += F(" Open (no connection)"); - } - - if (rawvalue & MAX31855_TC_SC) { - log += F(" Short-circuit to GND"); - } - - if (rawvalue & MAX31855_TC_SCVCC) { - log += F(" Short-circuit to Vcc"); - } - } - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - # endif // ifndef BUILD_NO_DEBUG - } - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) - { - String log; - - if ((log.reserve(120u))) { // reserve value derived from example log file - log = F("P039 : MAX31855 : "); - log += F("rawvalue: "); - log += formatToHex_decimal(rawvalue); - log += F(" P039_data->sensorFault: "); - log += formatToHex_decimal(P039_data->sensorFault); - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - } - - // D16 - This bit reads at 1 when any of the SCV, SCG, or OC faults are active. Default value is 0. - // 2020-05-11: FIXED: c.k.i.: migrated plain flag mask to #defines to enhance maintainability; added all fault flags for safety reasons - const bool Plugin_039_SensorAttached = !(rawvalue & (MAX31855_TC_GENFLT | MAX31855_TC_SCVCC | MAX31855_TC_SC | MAX31855_TC_OC)); - - if (Plugin_039_SensorAttached) - { - // Data is D[31:18] - // Shift RAW value 18 Bits to the right to get the data - rawvalue >>= 18; - - // Check for negative Values - // +25.00 0000 0001 1001 00 - // 0.00 0000 0000 0000 00 - // -0.25 1111 1111 1111 11 - // -1.00 1111 1111 1111 00 - // -250.00 1111 0000 0110 00 - // We're left with (32 - 18 =) 14 bits - int temperature = Plugin_039_convert_two_complement(rawvalue, 14); - - // Calculate Celsius - return temperature * 0.25f; - } - else - { - // Fault state, thus output no value. - return NAN; - } -} - -float readMax31856(struct EventStruct *event) -{ - P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); - - int8_t CS_pin_no = get_SPI_CS_Pin(event); - - - uint8_t registers[MAX31856_NO_REG] = { 0 }; - uint8_t messageBuffer[MAX31856_NO_REG + 1] = { 0 }; - - messageBuffer[0] = MAX31856_READ_ADDR_BASE; - - // "transfer" 0x0 starting at address 0x00 and read the all registers from the Chip - transfer_n_ByteSPI(CS_pin_no, (MAX31856_NO_REG + 1), &messageBuffer[0]); - - // transfer data from messageBuffer and get rid of initial address uint8_t - for (uint8_t i = 0u; i < MAX31856_NO_REG; ++i) { - registers[i] = messageBuffer[i + 1]; - } - - // configure device for next conversion - // activate frequency filter according to configuration - change8BitRegister(CS_pin_no, - (MAX31856_READ_ADDR_BASE + MAX31856_CR0), - (MAX31856_WRITE_ADDR_BASE + MAX31856_CR0), - MAX31856_SET_50HZ, - static_cast(P039_RTD_FILT_TYPE)); - - // set averaging and TC type - write8BitRegister(CS_pin_no, (MAX31856_WRITE_ADDR_BASE + MAX31856_CR1), static_cast((P039_CONFIG_4 << 4) | P039_TC_TYPE)); - - - // start on shot conversion for next read cycle - change8BitRegister(CS_pin_no, - (MAX31856_READ_ADDR_BASE + MAX31856_CR0), - (MAX31856_WRITE_ADDR_BASE + MAX31856_CR0), - MAX31856_SET_ONE_SHOT, - P039_SET); - - - // now derive raw value from respective registers - uint32_t rawvalue = static_cast(registers[MAX31856_LTCBH]); - - rawvalue = (rawvalue << 8) | static_cast(registers[MAX31856_LTCBM]); - rawvalue = (rawvalue << 8) | static_cast(registers[MAX31856_LTCBL]); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) - { - String log; - - if ((log.reserve(210u))) { // reserve value derived from example log file - log = F("P039 : MAX31856 :"); - - for (uint8_t i = 0; i < MAX31856_NO_REG; ++i) { - log += ' '; - log += formatToHex_decimal(registers[i]); - } - log += F(" rawvalue: "); - log += formatToHex_decimal(rawvalue); - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - - // ignore TC Range Bit in case Voltage Modes are used - // datasheet: - // Thermocouple Out-of-Range fault. - // 0 = The Thermocouple Hot Junction temperature is within the normal operating range (see Table 1). - // 1 = The Thermocouple Hot Junction temperature is outside of the normal operating range. - // Note: The TC Range bit should be ignored in voltage mode. - uint8_t sr = registers[MAX31856_SR]; - - if ((8u == P039_TC_TYPE) || (12u == P039_TC_TYPE)) { - sr &= ~MAX31856_TC_TCRANGE; - } - - - // FIXED: c.k.i. : moved static fault flag to instance data structure - if ((nullptr != P039_data)) { - // P039_data->sensorFault = false; - - P039_data->sensorFault = (sr != 0); // Set new state - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - // FIXME TD-er: Part of expression is always false (sr == 0) - const bool faultResolved = (P039_data->sensorFault) && (sr == 0); - - if ((P039_data->sensorFault) || faultResolved) { - String log; - - if ((log.reserve(140u))) { // reserve value derived from example log file - log = F("P039 : MAX31856 : "); - - if ((P039_data->sensorFault) == 0) { - log += F("Fault resolved"); - } else { - log += F("Fault :"); - - if (sr & MAX31856_TC_OC) { - log += F(" Open (no connection)"); - } - - if (sr & MAX31856_TC_OVUV) { - log += F(" Over/Under Voltage"); - } - - if (sr & MAX31856_TC_TCLOW) { - log += F(" TC Low"); - } - - if (sr & MAX31856_TC_TCLHIGH) { - log += F(" TC High"); - } - - if (sr & MAX31856_TC_CJLOW) { - log += F(" CJ Low"); - } - - if (sr & MAX31856_TC_CJHIGH) { - log += F(" CJ High"); - } - - if (sr & MAX31856_TC_TCRANGE) { - log += F(" TC Range"); - } - - if (sr & MAX31856_TC_CJRANGE) { - log += F(" CJ Range"); - } - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - } - } - # endif // ifndef BUILD_NO_DEBUG - } - - - const bool Plugin_039_SensorAttached = (sr == 0); - - if (Plugin_039_SensorAttached) - { - rawvalue >>= 5; // bottom 5 bits are unused - // We're left with (24 - 5 =) 19 bits - - { - float temperature = 0; - - switch (P039_TC_TYPE) - { - case 8: - { - temperature = rawvalue / 1677721.6f; // datasheet: rawvalue = 8 x 1.6 x 2^17 x VIN -> VIN = rawvalue / (8 x 1.6 x 2^17) - break; - } - case 12: - { - temperature = rawvalue / 6710886.4f; // datasheet: rawvalue = 32 x 1.6 x 2^17 x VIN -> VIN = rawvalue / (32 x 1.6 x 2^17) - break; - } - default: - { - temperature = Plugin_039_convert_two_complement(rawvalue, 19); - - // Calculate Celsius - temperature /= 128.0f; - break; - } - } - - return temperature; - } - } - else - { - // Fault state, thus output no value. - return NAN; - } -} - -float readMax31865(struct EventStruct *event) -{ - P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (P039_data == nullptr) { - return NAN; - } - - uint8_t registers[MAX31865_NO_REG] = { 0 }; - uint16_t rawValue = 0u; - - int8_t CS_pin_no = get_SPI_CS_Pin(event); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) - { - String log; - - if ((log.reserve(80u))) { // reserve value derived from example log file - log = F("P039 : MAX31865 :"); - log += F(" P039_data->convReady: "); - log += boolToString(P039_data->convReady); - - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - - // read conversion result and faults from plugin data structure - // if pointer exists and conversion has been finished - if (P039_data->convReady) { - rawValue = P039_data->conversionResult; - registers[MAX31865_FAULT] = P039_data->deviceFaults; - } - - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(160u))) { // reserve value derived from example log file - for (uint8_t i = 0u; i < MAX31865_NO_REG; ++i) - { - registers[i] = read8BitRegister(CS_pin_no, (MAX31865_READ_ADDR_BASE + i)); - } - - log = F("P039 : MAX31865 :"); - - for (uint8_t i = 0u; i < MAX31865_NO_REG; ++i) - { - log += ' '; - log += formatToHex_decimal(registers[i]); - } - - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - // Prepare and start next conversion, before handling faults and rawValue - // clear all faults - MAX31865_clearFaults(CS_pin_no); - - // set frequency filter - change8BitRegister(CS_pin_no, - (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), - (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), - MAX31865_SET_50HZ, - static_cast(P039_RTD_FILT_TYPE)); - - - // configure read access with configuration from web interface - MAX31865_setConType(CS_pin_no, P039_CONFIG_4); - - // activate BIAS short before read, to reduce power consumption - change8BitRegister(CS_pin_no, - (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), - (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), - MAX31865_SET_VBIAS_ON, - P039_SET); - - // start time to follow up on BIAS activation before starting the conversion - // and start conversion sequence via TIMER API - // save current timer for next calculation - P039_data->timer = millis(); - - // set next state to MAX31865_BIAS_ON_STATE - - Scheduler.setPluginTaskTimer(MAX31865_BIAS_WAIT_TIME, event->TaskIndex, MAX31865_BIAS_ON_STATE); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - if (registers[MAX31865_FAULT]) - { - String log; - - if ((log.reserve(210u))) { // reserve value derived from example log file - log = F("P039 : MAX31865 : "); - - log += F("Fault : "); - log += formatToHex_decimal(registers[MAX31865_FAULT]); - log += F(" :"); - - if (registers[MAX31865_FAULT] & MAX31865_FAULT_OVUV) - { - log += F(" Under/Over voltage"); - } - - if (registers[MAX31865_FAULT] & MAX31865_FAULT_RTDINLOW) - { - log += F(" RTDIN- < 0.85 x Bias - FORCE- open"); - } - - if (registers[MAX31865_FAULT] & MAX31865_FAULT_REFINHIGH) - { - log += F(" REFIN- < 0.85 x Bias - FORCE- open"); - } - - if (registers[MAX31865_FAULT] & MAX31865_FAULT_REFINLOW) - { - log += F(" REFIN- > 0.85 x Bias"); - } - - if (registers[MAX31865_FAULT] & MAX31865_FAULT_LOWTHRESH) - { - log += F(" RTD Low Threshold"); - } - - if (registers[MAX31865_FAULT] & MAX31865_FAULT_HIGHTHRESH) - { - log += F(" RTD High Threshold"); - } - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - } - # endif // ifndef BUILD_NO_DEBUG - - - bool ValueValid = false; - - if (registers[MAX31865_FAULT] == 0x00u) { - ValueValid = true; - } - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) - { - String log; - - if ((log.reserve(85u))) { // reserve value derived from example log file - log = F("P039 : Temperature :"); // 20 char - log += F(" registers[MAX31865_FAULT]: "); // 33 char - log += formatToHex_decimal(registers[MAX31865_FAULT]); // 7 char - log += F(" ValueValid: "); // 13 char - log += boolToString(ValueValid); // 5 char - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - if (ValueValid) - { - rawValue >>= 1; // bottom fault bits is unused - - float temperature = Plugin_039_convert_to_temperature(rawValue, getNomResistor(P039_RTD_TYPE), P039_RTD_RES); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) - { - String log; - - if ((log.reserve(110u))) { // reserve value derived from example log file - log = F("P039 : Temperature :"); // 20 char - log += F(" rawValue: "); // 11 char - log += formatToHex_decimal(rawValue); // 9 char - log += F(" temperature: "); // 14 char - log += temperature; // 11 char - log += F(" P039_RTD_TYPE: "); // 16 char - log += P039_RTD_TYPE; // 1 char - log += F(" P039_RTD_RES: "); // 15 char - log += P039_RTD_RES; // 4 char - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - // add offset handling from configuration webpage - temperature += P039_RTD_OFFSET; - - // Calculate Celsius - return temperature; - } - else - { - // Fault state, thus output no value. - return NAN; - } -} - -void MAX31865_clearFaults(int8_t l_CS_pin_no) -{ - uint8_t l_reg = 0u; - - // read in config register - l_reg = read8BitRegister(l_CS_pin_no, (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG)); - - - // clear all faults ( write "0" to D2, D3, D5; write "1" to D2) - l_reg &= ~(MAX31865_SET_ONE_SHOT | MAX31865_FAULT_CTRL_MASK); - l_reg |= MAX31865_CLEAR_FAULTS; - - // write configuration - write8BitRegister(l_CS_pin_no, (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), l_reg); -} - -void MAX31865_setConType(int8_t l_CS_pin_no, uint8_t l_conType) -{ - bool l_set_reset = false; - - // configure if 3 WIRE bit will be set/reset - switch (l_conType) - { - case 0: - l_set_reset = P039_RESET; - break; - case 1: - l_set_reset = P039_SET; - break; - default: - l_set_reset = P039_RESET; - break; - } - - // change to configuration register - change8BitRegister(l_CS_pin_no, - (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), - (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), - MAX31865_SET_3WIRE, - l_set_reset); -} - -/**************************************************************************/ - -/*! - @brief Read the temperature in C from the RTD through calculation of the - resistance. Uses - http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf - technique - @param RTDnominal The 'nominal' resistance of the RTD sensor, usually 100 - or 1000 - @param refResistor The value of the matching reference resistor, usually - 430 or 4300 - @returns Temperature in C - */ - -/**************************************************************************/ -float Plugin_039_convert_to_temperature(uint32_t l_rawvalue, float RTDnominal, float refResistor) -{ - # define RTD_A 3.9083e-3f - # define RTD_B -5.775e-7f - - float Z1, Z2, Z3, Z4, Rt, temp; - - Rt = l_rawvalue; - Rt /= 32768u; - Rt *= refResistor; - - Z1 = -RTD_A; - Z2 = RTD_A * RTD_A - (4 * RTD_B); - Z3 = (4 * RTD_B) / RTDnominal; - Z4 = 2 * RTD_B; - - temp = Z2 + (Z3 * Rt); - temp = (sqrtf(temp) + Z1) / Z4; - - if (temp >= 0) { - return temp; - } - - Rt /= RTDnominal; - Rt *= 100; // normalize to 100 ohm - - float rpoly = Rt; - - temp = -242.02f; - temp += 2.2228f * rpoly; - rpoly *= Rt; // square - temp += 2.5859e-3f * rpoly; - rpoly *= Rt; // ^3 - temp -= 4.8260e-6f * rpoly; - rpoly *= Rt; // ^4 - temp -= 2.8183e-8f * rpoly; - rpoly *= Rt; // ^5 - temp += 1.5243e-10f * rpoly; - - return temp; -} - -uint16_t getNomResistor(uint8_t l_RType) -{ - uint16_t l_returnValue = 100u; - - switch (l_RType) - { - case MAX31865_PT100: - l_returnValue = 100u; - break; - case MAX31865_PT1000: - l_returnValue = 1000u; - break; - default: - l_returnValue = 100u; - break; - } - return l_returnValue; -} - -int Plugin_039_convert_two_complement(uint32_t value, int nr_bits) { - const bool negative = (value & (1 << (nr_bits - 1))) != 0; - int nativeInt; - - if (negative) { - // Add zeroes to the left to create the proper negative native-sized integer. - nativeInt = value | ~((1 << nr_bits) - 1); - } else { - nativeInt = value; - } - return nativeInt; -} - -float readLM7x(struct EventStruct *event) -{ - float temperature = 0.0f; - uint16_t device_id = 0u; - uint16_t rawValue = 0u; - - int8_t CS_pin_no = get_SPI_CS_Pin(event); - - // operate LM7x devices in polling mode, assuming conversion is ready with every call of this read function ( >=210ms call cycle) - // this allows usage of multiples generations of LM7x devices, that doe not provde conversion ready information in temperature register - - rawValue = readLM7xRegisters(CS_pin_no, P039_RTD_LM_TYPE, P039_RTD_LM_SHTDWN, &device_id); - - temperature = convertLM7xTemp(rawValue, P039_RTD_LM_TYPE); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) - { - String log; - - if ((log.reserve(130u))) { // reserve value derived from example log file - log = F("P039 : LM7x : readLM7x : "); - log += F(" rawValue: "); - log += formatToHex_decimal(rawValue); - log += F(" device_id: "); - log += formatToHex(device_id); - log += F(" temperature: "); - log += temperature; - addLogMove(LOG_LEVEL_DEBUG, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - return temperature; -} - -float convertLM7xTemp(uint16_t l_rawValue, uint16_t l_LM7xsubtype) -{ - float l_returnValue = 0.0f; - float l_lsbvalue = 0.0f; - uint8_t l_noBits = 0u; - int l_intTemperature = 0; - - switch (l_LM7xsubtype) - { - case LM7x_SD70: - l_rawValue >>= 5; - l_lsbvalue = 0.25f; - l_noBits = 11u; - break; - case LM7x_SD71: - l_rawValue >>= 2; - l_lsbvalue = 0.03125f; - l_noBits = 14u; - break; - case LM7x_SD74: - l_rawValue >>= 3; - l_lsbvalue = 0.0625f; - l_noBits = 13u; - break; - case LM7x_SD121: - case LM7x_SD122: - case LM7x_SD123: - case LM7x_SD124: - l_rawValue >>= 4; - l_lsbvalue = 0.0625f; - l_noBits = 12u; - break; - case LM7x_SD125: - l_rawValue >>= 5; - l_lsbvalue = 0.25f; - l_noBits = 10u; - break; - default: // use lowest resolution as fallback if no device has been configured - l_rawValue >>= 5; - l_lsbvalue = 0.25f; - l_noBits = 11u; - break; - } - - l_intTemperature = Plugin_039_convert_two_complement(l_rawValue, l_noBits); - - l_returnValue = l_intTemperature * l_lsbvalue; - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(185u))) { // reserve value derived from example log file - log = F("P039 : LM7x : convertLM7xTemp : "); - log += F(" l_returnValue: "); - log += formatToHex_decimal(l_returnValue); - log += F(" l_LM7xsubtype: "); - log += formatToHex_decimal(l_LM7xsubtype); - log += F(" l_rawValue: "); - log += formatToHex_decimal(l_rawValue); - log += F(" l_noBits: "); - log += l_noBits; - log += F(" l_lsbvalue: "); - log += l_lsbvalue; - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - return l_returnValue; -} - -uint16_t readLM7xRegisters(int8_t l_CS_pin_no, uint8_t l_LM7xsubType, uint8_t l_runMode, uint16_t *l_device_id) -{ - uint16_t l_returnValue = 0u; - uint16_t l_mswaitTime = 0u; - - - switch (l_LM7xsubType) - { - case LM7x_SD70: - case LM7x_SD71: - case LM7x_SD74: - l_mswaitTime = 300; - break; - case LM7x_SD121: - case LM7x_SD122: - case LM7x_SD123: - case LM7x_SD124: - l_mswaitTime = 320; - break; - case LM7x_SD125: - l_mswaitTime = 100; - break; - default: - l_mswaitTime = 500; - break; - } - - // // activate communication -> CS low - // handle_SPI_CS_Pin(l_CS_pin_no, LOW); - - if (l_runMode) - { - // shutdown mode active -> conversion when called - uint8_t messageBuffer[12] = { 0xFF, 0xFF, 0xFF, 0X00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF }; - - // send inital 4 bytes to wake the device and start the conversion - transfer_n_ByteSPI(l_CS_pin_no, 4, &messageBuffer[0]); - - // wait specific ms for conversion to be ready (TI datasheet per devices) - delay(l_mswaitTime); - - // send remaining 8 bytes to read the device ID and shutdown the device - transfer_n_ByteSPI(l_CS_pin_no, 8, &messageBuffer[4]); - - // read temperature value (16 Bit) - l_returnValue = ((messageBuffer[4] << 8) | messageBuffer[5]); - - // read Manufatures/Device ID (16 Bit) - *(l_device_id) = ((messageBuffer[8] << 8) | messageBuffer[9]); - - // // wakeup device and start conversion - // // initial read of conversion result is obsolete - // SPI.transfer16(0xFFFF); - - // // (wakeup device with "all zero2 message in the last 8 bits - // SPI.transfer16(0xFF00); - - // //wait specific ms for conversion to be ready (TI datasheet per devices) - // delay(l_mswaitTime); - - // //read temperature value (16 Bit) - // l_returnValue = SPI.transfer16(0x0000); - // // l_returnValue <<= 8; - // // l_returnValue = SPI.transfer(0x00); - - // // set device to shutdown with "all one" message in the last 8 bits - // SPI.transfer16(0xFFFF); - - // // read Manufatures/Device ID (16 Bit) - // *(l_device_id) = SPI.transfer16(0x0000); - // // *(l_device_id) <<= 8; - // // *(l_device_id) = SPI.transfer(0x00); - - // // set device to shutdown with "all one" message in the last 8 bits ( maybe redundant, check with test) - // SPI.transfer16(0xFFFF); - } - else - { - // shutdown mode inactive -> normal background conversion during call cycle - uint8_t messageBuffer[8] = { 0x00, 0x00, 0xFF, 0XFF, 0x00, 0x00, 0x00, 0x00 }; - - transfer_n_ByteSPI(l_CS_pin_no, 8, &messageBuffer[0]); - - // read temperature value (16 Bit) - l_returnValue = ((messageBuffer[0] << 8) | messageBuffer[1]); - - // read Manufatures/Device ID (16 Bit) - *(l_device_id) = ((messageBuffer[4] << 8) | messageBuffer[5]); - - - // l_returnValue = SPI.transfer16(0x0000); //read temperature value (16 Bit) - // // l_returnValue <<= 8; - // // l_returnValue = SPI.transfer(0x00); - - // // set device to shutdown - // SPI.transfer16(0xFFFF); - - // // read Manufatures/Device ID (16 Bit) - // *(l_device_id) = SPI.transfer16(0x0000); - // // *(l_device_id) <<= 8; - // // *(l_device_id) = SPI.transfer(0x00); - - // // start conversion until next read (8 Bit sufficient) - // // 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F allowed - else device goes to test mode (not desirable here) - // SPI.transfer(0x00); - // // SPI.transfer16(0x0000); - } - - // // stop communication -> CS high - // handle_SPI_CS_Pin(l_CS_pin_no, HIGH); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(115u))) { // reserve value derived from example log file - log = F("P039 : LM7x : readLM7xRegisters : "); - log += F(" l_returnValue: "); - log += formatToHex_decimal(l_returnValue); - log += F(" l_device_id: "); - log += formatToHex(*(l_device_id)); - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - return l_returnValue; -} - -// POSSIBLE START OF GENERIC SPI HIGH LEVEL FUNCTIONS WITH POTENTIAL OF SYSTEM WIDE RE-USE - -/**************************************************************************/ - -/*! - @brief generic high level library to access SPI interface from plugins - with GPIO pin handled as CS - chri.kai.in 2021 - - Initial Revision - chri.kai.in 2021 - - TODO: c.k.i.: make it generic and carve out to generic _SPI_helper.c library - - - /**************************************************************************/ - - -/**************************************************************************/ - -/*! - - @brief Identifying the CS pin from the event basic data structure - @param event pointer to the event structure; default GPIO is chosen as GPIO 15 - - @returns - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -int get_SPI_CS_Pin(struct EventStruct *event) { // If no Pin is in Config we use 15 as default -> Hardware Chip Select on ESP8266 - if (CONFIG_PIN1 != -1) { - return CONFIG_PIN1; - } - return 15; // D8 -} - -/**************************************************************************/ - -/*! - @brief Initializing GPIO as OUTPUT for CS for SPI communication - @param l_CS_pin_no the GPIO pin number used as CS - - @returns - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -void init_SPI_CS_Pin(int8_t l_CS_pin_no) { - // set the slaveSelectPin as an output: - pinMode(l_CS_pin_no, OUTPUT); -} - -/**************************************************************************/ - -/*! - @brief Handling GPIO as CS for SPI communication - @param l_CS_pin_no the GPIO pin number used as CS - @param l_state the state of the CS pin: "HIGH/LOW" reflecting the physical level - - @returns - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -void handle_SPI_CS_Pin(int8_t l_CS_pin_no, bool l_state) { - P039_CS_Delay(); // tCWH (min) >= x00ns - digitalWrite(l_CS_pin_no, l_state); - P039_CS_Delay(); // tCC (min) >= x00ns -} - -/**************************************************************************/ - -/*! - @brief write 8 bits to adress l_address on the SPI interface, handling a GPIO CS - @param l_CS_pin_no the GPIO pin number used as CS - @param l_address the register addess of the connected SPI device - @param value the unsigned 8 Bit message to be transferred - - @returns - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -void write8BitRegister(int8_t l_CS_pin_no, uint8_t l_address, uint8_t value) -{ - uint8_t l_messageBuffer[2] = { l_address, value }; - - transfer_n_ByteSPI(l_CS_pin_no, 2, l_messageBuffer); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(100u))) { // reserve value derived from example log file - log = F("P039 : SPI : write8BitRegister : "); - log += F("l_address: "); - log += formatToHex(l_address); - log += F(" value: "); - log += formatToHex_decimal(value); - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG -} - -/**************************************************************************/ - -/*! - @brief write 16 bits to adress l_address on the SPI interface, handling a GPIO CS - @param l_CS_pin_no the GPIO pin number used as CS - @param l_address the register addess of the connected SPI device - @param value the unsigned 16 Bit message to be transferred - - @returns - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -void write16BitRegister(int8_t l_CS_pin_no, uint8_t l_address, uint16_t value) -{ - uint8_t l_messageBuffer[3] = { l_address, static_cast((value >> 8) & 0xFF), static_cast(value & 0xFF) }; - - transfer_n_ByteSPI(l_CS_pin_no, 3, l_messageBuffer); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(110u))) { // reserve value derived from example log file - log = F("P039 : SPI : write16BitRegister : "); - log += F("l_address: "); - log += formatToHex(l_address); - log += F(" value: "); - log += formatToHex_decimal(value); - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG -} - -/**************************************************************************/ - -/*! - @brief read 8 bits from adress l_address on the SPI interface, handling a GPIO CS - @param l_CS_pin_no the GPIO pin number used as CS - @param l_address the register addess of the connected SPI device - - @returns the unsigned 8 Bit message read from l_address - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -uint8_t read8BitRegister(int8_t l_CS_pin_no, uint8_t l_address) -{ - uint8_t l_messageBuffer[2] = { l_address, 0x00 }; - - transfer_n_ByteSPI(l_CS_pin_no, 2, l_messageBuffer); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(100u))) { // reserve value derived from example log file - log = F("P039 : SPI : read8BitRegister : "); - log += F("l_address: "); - log += formatToHex(l_address); - log += F(" returnvalue: "); - log += formatToHex_decimal(l_messageBuffer[1]); - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - return l_messageBuffer[1]; -} - -/**************************************************************************/ - -/*! - @brief write 16 bits to adress l_address on the SPI interface, handling a GPIO CS - @param l_CS_pin_no the GPIO pin number used as CS - @param l_address the register addess of the connected SPI device - - @returns the unsigned 16 Bit message read from l_address - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -uint16_t read16BitRegister(int8_t l_CS_pin_no, uint8_t l_address) -{ - uint8_t l_messageBuffer[3] = { l_address, 0x00, 0x00 }; - uint16_t l_returnValue; - - transfer_n_ByteSPI(l_CS_pin_no, 3, l_messageBuffer); - l_returnValue = ((l_messageBuffer[1] << 8) | l_messageBuffer[2]); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(110u))) { // reserve value derived from example log file - log = F("P039 : SPI : read16BitRegister : "); - log += F("l_address: "); - log += formatToHex(l_address); - log += F(" l_returnValue: "); - log += formatToHex_decimal(l_returnValue); - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG - - return l_returnValue; -} - -/**************************************************************************/ - -/*! - @brief read from/write to dedicated number of bytes from/to SPI, handling a GPIO CS - @param l_CS_pin_no the GPIO pin number used as CS - @param l_noBytesToSend number of bytes to read/write from/to SPI - @param l_inoutMessageBuffer pointer to the messsage buffer to provide bytes to send - and provide read bytes from the SPI bus after the call - - @returns - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -void transfer_n_ByteSPI(int8_t l_CS_pin_no, uint8_t l_noBytesToSend, uint8_t *l_inoutMessageBuffer) -{ - // activate communication -> CS low - handle_SPI_CS_Pin(l_CS_pin_no, LOW); - - for (size_t i = 0u; i < l_noBytesToSend; i++) - { - l_inoutMessageBuffer[i] = SPI.transfer(l_inoutMessageBuffer[i]); - } - - // stop communication -> CS high - handle_SPI_CS_Pin(l_CS_pin_no, HIGH); - - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) - { - String log; - - if ((log.reserve(120u))) { // reserve value derived from example log file - log = F("P039 : SPI : transfer_n_ByteSPI : "); // 34 char - - for (uint8_t i = 0; i < l_noBytesToSend; ++i) - { - log += ' '; // 1 char - log += formatToHex_decimal(l_inoutMessageBuffer[i]); // 9 char - } - addLogMove(LOG_LEVEL_DEBUG_MORE, log); - } - } - - # endif // ifndef BUILD_NO_DEBUG -} - -/**************************************************************************/ - -/*! - @brief read a 16Bit register and change a flag, writing it back, handling a GPIO CS - @param l_CS_pin_no the GPIO pin number used as CS - @param l_readaddress SPI read address of the device register - @param l_writeaddress SPI write address of the device register - @param l_flagmask mask set to apply on the read register - @param l_set_reset controls if flag mask will be set (-> true) or reset ( -> false) - - - @returns - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -void change16BitRegister(int8_t l_CS_pin_no, uint8_t l_readaddress, uint8_t l_writeaddress, uint16_t l_flagmask, bool l_set_reset) -{ - uint16_t l_reg = 0u; - - // read in config register - l_reg = read16BitRegister(l_CS_pin_no, l_readaddress); - - if (l_set_reset) { - l_reg |= l_flagmask; - } - else - { - l_reg &= ~(l_flagmask); - } - - // write to configuration register - write16BitRegister(l_CS_pin_no, l_writeaddress, l_reg); -} - -/**************************************************************************/ - -/*! - @brief read a 8 Bit register and change a flag, writing it back, handling a GPIO CS - @param l_CS_pin_no the GPIO pin number used as CS - @param l_readaddress SPI read address of the device register - @param l_writeaddress SPI write address of the device register - @param l_flagmask mask set to apply on the read register - @param l_set_reset controls if flag mask will be set (-> true) or reset ( -> false) - - - @returns - - Initial Revision - chri.kai.in 2021 - - /**************************************************************************/ -void change8BitRegister(int8_t l_CS_pin_no, uint8_t l_readaddress, uint8_t l_writeaddress, uint8_t l_flagmask, bool l_set_reset) -{ - uint8_t l_reg = 0u; - - // read in config register - l_reg = read8BitRegister(l_CS_pin_no, l_readaddress); - - - // TODO: c.k.i.: analyze opportunity to use arduino bitSet/Clear macros instead - if (l_set_reset) { - l_reg |= l_flagmask; - } - else - { - l_reg &= ~(l_flagmask); - } - - // write to configuration register - write8BitRegister(l_CS_pin_no, l_writeaddress, l_reg); -} - -#endif // USES_P039 +#include "_Plugin_Helper.h" +#ifdef USES_P039 + +// ####################################################################################################### +// ######################## Plugin 039: Thermocouple (MAX6675 / MAX31855) ################################ +// ####################################################################################################### + +// Original work by Dominik + +// Plugin Description +// This Plugin reads the data from Thermocouples. You have to use an Adapter Board with a +// MAX6675 or MAX31855 in order to read the values. Take a look at ebay to find such boards :-) +// You can only use ESP8266 boards which expose the SPI Interface. This Plugin uses only the Hardware +// SPI Interface - no software SPI at the moment. +// But nevertheless you need at least 3 Pins to use SPI. So using an very simple ESP-01 is no option - Sorry. +// The Wiring is straight forward ... +// +// If you like to send suggestions feel free to send me an email : dominik@logview.info +// Have fun ... Dominik + +/** Changelog: + * 2025-01-03 tonhuisman: Small code size reductions, cleanup of DEBUG level logging + * 2024-01-04 tonhuisman: Minor corrections, formatted source using Uncrustify + * 2023-01-08 tonhuisman: Add Low temperature threshold setting (default 0 K/-273.15 C) to ignore temperatures below that value + * 2023-01-02 tonhuisman: Cleanup and uncrustify source + * 2022-10-22 tonhuisman: Correct CS pin check to allow GPIO0 + * 2022-10: Older changelog not recorded + */ + +// Wiring +// https://de.wikipedia.org/wiki/Serial_Peripheral_Interface +// You need an ESP8266 device with accessible SPI Pins. These are: +// Name Description GPIO NodeMCU Notes +// MOSI Master Output GPIO13 D7 Not used (No Data sending to MAX) +// MISO Master Input GPIO12 D6 Hardware SPI +// SCK Clock Output GPIO14 D5 Hardware SPI +// CS Chip Select GPIO15 D8 Hardware SPI (CS is configurable through the web interface) + +// Thermocouple Infos +// http://www.bristolwatch.com/ele2/therc.htm + +// Resistor Temperature Detector Infos +// https://en.wikipedia.org/wiki/Resistance_thermometer + +// Chips +// MAX6675 - Cold-Junction-Compensated K-Thermocouple-to-Digital Converter ( 0°C to +1024°C) +// https://cdn-shop.adafruit.com/datasheets/MAX6675.pdf (only +// MAX31855 - Cold-Junction Compensated Thermocouple-to-Digital Converter (-270°C to +1800°C) +// https://cdn-shop.adafruit.com/datasheets/MAX31855.pdf +// MAX31856 - Precision Thermocouple to Digital Converter with Linearization (-210°C to +1800°C) +// https://datasheets.maximintegrated.com/en/ds/MAX31856.pdf +// MAX31865 - Precision Resistor Temperature Detector to Digital Converter with Linearization (PT100 / PT1000) +// https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf +// TI Digital Temperature sensors with SPI interface +// https://www.ti.com/sensors/temperature-sensors/digital/products.html#p1918=SPI,%20Microwire +// TI LM7x - Digital temperature sensor with SPI interface +// https://www.ti.com/lit/gpn/LM70 +// https://www.ti.com/lit/gpn/LM71 +// https://www.ti.com/lit/gpn/LM70 +// https://www.ti.com/lit/gpn/LM74 +// TI TMP12x Digital temperature sensor with SPI interface +// https://www.ti.com/lit/gpn/TMP121 +// https://www.ti.com/lit/gpn/TMP122 +// https://www.ti.com/lit/gpn/TMP123 +// https://www.ti.com/lit/gpn/TMP124 + +# include + +// #include +# include "src/PluginStructs/P039_data_struct.h" + + +// // plugin-local quick activation of debug messages +// #ifdef BUILD_NO_DEBUG +// #undef BUILD_NO_DEBUG +// #endif + + +# define MAX31865_RD_ADDRESS(n) (MAX31865_READ_ADDR_BASE + (n)) +# define MAX31865_WR_ADDRESS(n) (MAX31865_WRITE_ADDR_BASE + (n)) + +# define PLUGIN_039 +# define PLUGIN_ID_039 39 +# define PLUGIN_NAME_039 "Environment - Thermosensors" +# define PLUGIN_VALUENAME1_039 "Temperature" + +# define P039_SET true +# define P039_RESET false + +// typically 500ns of wating on positive/negative edge of CS should be enough ( -> datasheet); to make sure we cover a lot of devices we +// spend 1ms +// FIX 2021-05-05: review of all covered device datasheets showed 2µs is more than enough; review with every newly added device +# define P039_CS_Delay() delayMicroseconds(2u) + +# define P039_MAX_TYPE PCONFIG(0) +# define P039_TC_TYPE PCONFIG(1) +# define P039_FAM_TYPE PCONFIG(2) +# define P039_RTD_TYPE PCONFIG(3) +# define P039_CONFIG_4 PCONFIG(4) +# define P039_RTD_FILT_TYPE PCONFIG(5) +# define P039_RTD_LM_TYPE PCONFIG(6) +# define P039_RTD_LM_SHTDWN PCONFIG(7) +# define P039_RTD_RES PCONFIG_LONG(0) +# define P039_FLAGS PCONFIG_ULONG(3) +# define P039_TEMP_THRESHOLD_FLAG 0 +# define P039_RTD_OFFSET PCONFIG_FLOAT(0) +# define P039_TEMP_THRESHOLD PCONFIG_FLOAT(1) + +# define P039_TEMP_THRESHOLD_DEFAULT (-273.15f) // Default and minimum value +# define P039_TEMP_THRESHOLD_MIN P039_TEMP_THRESHOLD_DEFAULT +# define P039_TEMP_THRESHOLD_MAX (1000.0f) // Max value +# define P039_TC 0u +# define P039_RTD 1u + +# define P039_MAX6675 1 +# define P039_MAX31855 2 +# define P039_MAX31856 3 +# define P039_MAX31865 4 +# define P039_LM7x 5 + +// MAX 6675 related defines + +// bit masks to identify failures for MAX 6675 +# define MAX6675_TC_DEVID 0x0002u +# define MAX6675_TC_OC 0x0004u + +// MAX 31855 related defines + +// bit masks to identify failures for MAX 31855 +# define MAX31855_TC_OC 0x00000001u +# define MAX31855_TC_SC 0x00000002u +# define MAX31855_TC_SCVCC 0x00000004u +# define MAX31855_TC_GENFLT 0x00010000u + + +// MAX 31856 related defines + +// base address for read/write acces to MAX 31856 +# define MAX31856_READ_ADDR_BASE 0x00u +# define MAX31856_WRITE_ADDR_BASE 0x80u + +// register offset values for MAX 31856 +# define MAX31856_CR0 0u +# define MAX31856_CR1 1u +# define MAX31856_MASK 2u +# define MAX31856_CJHF 3u +# define MAX31856_CJLF 4u +# define MAX31856_LTHFTH 5u +# define MAX31856_LTHFTL 6u +# define MAX31856_LTLFTH 7u +# define MAX31856_LTLFTL 8u +# define MAX31856_CJTO 9u +# define MAX31856_CJTH 10u +# define MAX31856_CJTL 11u +# define MAX31856_LTCBH 12u +# define MAX31856_LTCBM 13u +# define MAX31856_LTCBL 14u +# define MAX31856_SR 15u + +# define MAX31856_NO_REG 16u + +// bit masks to identify failures for MAX 31856 +# define MAX31856_TC_OC 0x01u +# define MAX31856_TC_OVUV 0x02u +# define MAX31856_TC_TCLOW 0x04u +# define MAX31856_TC_TCLHIGH 0x08u +# define MAX31856_TC_CJLOW 0x10u +# define MAX31856_TC_CJHIGH 0x20u +# define MAX31856_TC_TCRANGE 0x40u +# define MAX31856_TC_CJRANGE 0x80u + +// bit masks for access of configuration bits +# define MAX31856_SET_50HZ 0x01u +# define MAX31856_CLEAR_FAULTS 0x02u +# define MAX31856_FLT_ISR_MODE 0x04u +# define MAX31856_CJ_SENS_DISABLE 0x08u +# define MAX31856_FAULT_CTRL_MASK 0x30u +# define MAX31856_SET_ONE_SHOT 0x40u +# define MAX31856_SET_CONV_AUTO 0x80u + + +// RTD related defines + +// MAX 31865 related defines + +// waiting time until "in sequence" conversion is ready (-> used in case device is set to shutdown in between call cycles) +// typically 70ms should be fine, according to datasheet maximum -> 66ms - give a little adder to "be sure" conversion is done +// alternatively ONE SHOT bit could be polled (system/SPI bus load !) +# define MAX31865_CONVERSION_TIME 70ul +# define MAX31865_BIAS_WAIT_TIME 10ul + +// MAX 31865 Main States +# define MAX31865_INIT_STATE 0u +# define MAX31865_BIAS_ON_STATE 1u +# define MAX31865_RD_STATE 2u +# define MAX31865_RDY_STATE 3u + +// sensor type +# define MAX31865_PT100 0u +# define MAX31865_PT1000 1u + +// base address for read/write acces to MAX 31865 +# define MAX31865_READ_ADDR_BASE 0x00u +# define MAX31865_WRITE_ADDR_BASE 0x80u + +// register offset values for MAX 31865 +# define MAX31865_CONFIG 0u +# define MAX31865_RTD_MSB 1u +# define MAX31865_RTD_LSB 2u +# define MAX31865_HFT_MSB 3u +# define MAX31865_HFT_LSB 4u +# define MAX31865_LFT_MSB 5u +# define MAX31865_LFT_LSB 6u +# define MAX31865_FAULT 7u + +// total number of registers in MAX 31865 +# define MAX31865_NO_REG 8u + +// bit masks to identify failures for MAX 31865 +# define MAX31865_FAULT_HIGHTHRESH 0x80u +# define MAX31865_FAULT_LOWTHRESH 0x40u +# define MAX31865_FAULT_REFINLOW 0x20u +# define MAX31865_FAULT_REFINHIGH 0x10u +# define MAX31865_FAULT_RTDINLOW 0x08u +# define MAX31865_FAULT_OVUV 0x04u + +// bit masks for access of configuration bits +# define MAX31865_SET_50HZ 0x01u +# define MAX31865_CLEAR_FAULTS 0x02u +# define MAX31865_FAULT_CTRL_MASK 0x0Cu +# define MAX31865_SET_3WIRE 0x10u +# define MAX31865_SET_ONE_SHOT 0x20u +# define MAX31865_SET_CONV_AUTO 0x40u +# define MAX31865_SET_VBIAS_ON 0x80u + +// LM7x related defines + +// LM7x subtype defines +# define LM7x_SD70 0x00u +# define LM7x_SD71 0x01u +# define LM7x_SD74 0x04u +# define LM7x_SD121 0x05u +# define LM7x_SD122 0x06u +# define LM7x_SD123 0x07u +# define LM7x_SD124 0x08u +# define LM7x_SD125 0x09u + +// bit masks for access of configuration bits +# define LM7x_CONV_RDY 0x02u + + +void P039_AddMainsFrequencyFilterSelection(struct EventStruct *event); + +boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_039; + Device[deviceCount].Type = DEVICE_TYPE_SPI; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_039); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_039)); + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: + { + event->String1 = formatGpioName_output(F("CS")); + break; + } + + case PLUGIN_SET_DEFAULTS: + { + P039_TEMP_THRESHOLD = P039_TEMP_THRESHOLD_DEFAULT; // 0 K + bitSet(P039_FLAGS, P039_TEMP_THRESHOLD_FLAG); + break; + } + + case PLUGIN_INIT: + { + if (!bitRead(P039_FLAGS, P039_TEMP_THRESHOLD_FLAG)) { + P039_TEMP_THRESHOLD = P039_TEMP_THRESHOLD_DEFAULT; // 0 K + } + + if ((P039_MAX_TYPE < P039_MAX6675) || (P039_MAX_TYPE > P039_LM7x)) { + break; + } + + + initPluginTaskData(event->TaskIndex, new (std::nothrow) P039_data_struct()); + P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); + + int8_t CS_pin_no = get_SPI_CS_Pin(event); + + // set the slaveSelectPin as an output: + init_SPI_CS_Pin(CS_pin_no); + + // initialize SPI: + SPI.setHwCs(false); + SPI.begin(); + + // ensure MODE3 access to SPI device + SPI.setDataMode(SPI_MODE3); + + /* + if (P039_MAX_TYPE == P039_MAX6675) { + + // SPI.setBitOrder(MSBFIRST); + } + */ + if (P039_MAX_TYPE == P039_MAX31855) { + // SPI.setBitOrder(MSBFIRST); + + if (nullptr != P039_data) { + // FIXED: c.k.i. : moved static fault flag to instance data structure + P039_data->sensorFault = false; + } + } + + + if (P039_MAX_TYPE == P039_MAX31856) { + // init string - content accoring to inital implementation of P039 - MAX31856 read function + // write to Adress 0x80 + // activate 50Hz filter in CR0, choose averaging and TC type from configuration in CR1, activate OV/UV/OC faults, write defaults to + // CJHF, CJLF, LTHFTH, LTHFTL, LTLFTH, LTLFTL, CJTO + uint8_t sendBuffer[11] = + { 0x80, static_cast(P039_RTD_FILT_TYPE), static_cast((P039_CONFIG_4 << 4) | P039_TC_TYPE), 0xFC, 0x7F, 0xC0, 0x7F, + 0xFF, 0x80, 0x00, 0x00 }; + + transfer_n_ByteSPI(CS_pin_no, 11, &sendBuffer[0]); + + if (nullptr != P039_data) { + // FIXED: c.k.i. : moved static fault flag to instance data structure + P039_data->sensorFault = false; + } + + // start on shot conversion for upcoming read cycle + change8BitRegister(CS_pin_no, + (MAX31856_READ_ADDR_BASE + MAX31856_CR0), + (MAX31856_WRITE_ADDR_BASE + MAX31856_CR0), + MAX31856_SET_ONE_SHOT, + P039_SET); + } + + + if (P039_MAX_TYPE == P039_MAX31865) { + // two step initialization buffer + uint8_t initSendBufferHFTH[3] = { (MAX31865_WRITE_ADDR_BASE + MAX31865_HFT_MSB), 0xFF, 0xFF }; + uint8_t initSendBufferLFTH[3] = { (MAX31865_WRITE_ADDR_BASE + MAX31865_HFT_MSB), 0xFF, 0xFF }; + + // write intially 0x00 to CONFIG register + write8BitRegister(CS_pin_no, (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), 0x00u); + + // activate 50Hz filter, clear all faults, no auto conversion, no conversion started + change8BitRegister(CS_pin_no, + MAX31865_RD_ADDRESS(MAX31865_CONFIG), + MAX31865_WR_ADDRESS(MAX31865_CONFIG), + MAX31865_SET_50HZ, + static_cast(P039_RTD_FILT_TYPE)); + + // configure 2/4-wire sensor connection as default + MAX31865_setConType(CS_pin_no, P039_CONFIG_4); + + // set HighFault Threshold + transfer_n_ByteSPI(CS_pin_no, 3, &initSendBufferHFTH[0]); + + // set LowFault Threshold + transfer_n_ByteSPI(CS_pin_no, 3, &initSendBufferLFTH[0]); + + // clear all faults + MAX31865_clearFaults(CS_pin_no); + + // activate BIAS short before read, to reduce power consumption + change8BitRegister(CS_pin_no, + (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), + (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), + MAX31865_SET_VBIAS_ON, + P039_SET); + + if (nullptr != P039_data) { + // save current timer for next calculation + P039_data->timer = millis(); + + // start time to follow up on BIAS activation before starting the conversion + // and start conversion sequence via TIMER API + + Scheduler.setPluginTaskTimer(MAX31865_BIAS_WAIT_TIME, event->TaskIndex, MAX31865_BIAS_ON_STATE); + } + } + + /* + if (P039_MAX_TYPE == P039_LM7x) + { + // TODO: c.k.i.: more detailed inits depending on the sub devices expected , e.g. TMP 122/124 + } + */ + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, strformat(F("P039 : %s : SPI Init - DONE"), getTaskDeviceName(event->TaskIndex).c_str())); + } + # endif // ifndef BUILD_NO_DEBUG + + success = true; + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + addFormSubHeader(F("Sensor Family Selection")); + + const uint8_t family = P039_FAM_TYPE; + { + const __FlashStringHelper *Foptions[] = { F("Thermocouple"), F("RTD") }; + const int FoptionValues[] = { P039_TC, P039_RTD }; + constexpr size_t optionCount = NR_ELEMENTS(FoptionValues); + addFormSelector(F("Sensor Family Type"), F("famtype"), optionCount, Foptions, FoptionValues, family, true); // auto reload activated + } + + const uint8_t choice = P039_MAX_TYPE; + + addFormSubHeader(F("Device Type Settings")); + + if (family == P039_TC) { + { + const __FlashStringHelper *options[] = { F("MAX 6675"), F("MAX 31855"), F("MAX 31856") }; + const int optionValues[] = { P039_MAX6675, P039_MAX31855, P039_MAX31856 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Adapter IC"), F("maxtype"), optionCount, options, optionValues, choice, true); // auto reload activated + } + + if (choice == P039_MAX31856) { + addFormSubHeader(F("Device Settings")); + { + const __FlashStringHelper *Toptions[] = { F("B"), F("E"), F("J"), F("K"), F("N"), F("R"), F("S"), F("T"), F("VM8"), F("VM32") }; + + // 2021-05-17: c.k.i.: values are directly written to device register for configuration, therefore no linear values are used + // here + // MAX 31856 datasheet (page 20): + // Thermocouple Type + // 0000 = B Type + // 0001 = E Type + // 0010 = J Type + // 0011 = K Type (default) + // 0100 = N Type + // 0101 = R Type + // 0110 = S Type + // 0111 = T Type + // 10xx = Voltage Mode, Gain = 8. Code = 8 x 1.6 x 217 x VIN + // 11xx = Voltage Mode, Gain = 32. Code = 32 x 1.6 x 217 x VIN + // Where Code is 19 bit signed number from TC registers and VIN is thermocouple input voltage + + const int ToptionValues[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12 }; + constexpr size_t optionCount = NR_ELEMENTS(ToptionValues); + addFormSelector(F("Thermocouple type"), F("tctype"), optionCount, Toptions, ToptionValues, P039_TC_TYPE); + } + { + const __FlashStringHelper *Coptions[] = { F("1"), F("2"), F("4"), F("8"), F("16") }; + const int CoptionValues[] = { 0, 1, 2, 3, 4 }; + constexpr size_t optionCount = NR_ELEMENTS(CoptionValues); + addFormSelector(F("Averaging"), F("contype"), optionCount, Coptions, CoptionValues, P039_CONFIG_4); + addUnit(F("sample(s)")); + } + P039_AddMainsFrequencyFilterSelection(event); + } + } + else { + { + const __FlashStringHelper *TPoptions[] = { F("MAX 31865"), F("LM7x") }; + const int TPoptionValues[] = { P039_MAX31865, P039_LM7x }; + constexpr size_t optionCount = NR_ELEMENTS(TPoptionValues); + addFormSelector(F("Adapter IC"), F("maxtype"), optionCount, TPoptions, TPoptionValues, choice, true); // auto reload activated + addFormNote(F("LM7x support is experimental.")); + } + + + if (choice == P039_MAX31865) + { + { + addFormSubHeader(F("Device Settings")); + } + { + const __FlashStringHelper *PToptions[] = { F("PT100"), F("PT1000") }; + const int PToptionValues[] = { MAX31865_PT100, MAX31865_PT1000 }; + constexpr size_t optionCount = NR_ELEMENTS(PToptionValues); + addFormSelector(F("Resistor Type"), F("rtdtype"), optionCount, PToptions, PToptionValues, P039_RTD_TYPE); + } + { + const __FlashStringHelper *Coptions[] = { F("2-/4"), F("3") }; + constexpr size_t optionCount = NR_ELEMENTS(Coptions); + addFormSelector(F("Connection Type"), F("contype"), optionCount, Coptions, nullptr, P039_CONFIG_4); + addUnit(F("wire")); + } + + P039_AddMainsFrequencyFilterSelection(event); + + { + addFormNumericBox(F("Reference Resistor"), F("res"), P039_RTD_RES, 0); + addUnit(F("Ohm")); + addFormNote(F("PT100: typically 430 [OHM]; PT1000: typically 4300 [OHM]")); + } + { + addFormFloatNumberBox(F("Temperature Offset"), F("offset"), P039_RTD_OFFSET, -50.0f, 50.0f, 2, 0.01f); + addUnit('K'); + # ifndef BUILD_NO_DEBUG + addFormNote(F("Valid values: [-50.0...50.0 K], min. stepsize: [0.01]")); + # endif // ifndef BUILD_NO_DEBUG + } + } + + if (choice == P039_LM7x) + { + { + addFormSubHeader(F("Device Settings")); + } + + { + const __FlashStringHelper *PToptions[] = + { F("LM70"), F("LM71"), F("LM74"), F("TMP121"), F("TMP122"), F("TMP123"), F("TMP124"), F("TMP125") }; + const int PToptionValues[] = { LM7x_SD70, LM7x_SD71, LM7x_SD74, LM7x_SD121, LM7x_SD122, LM7x_SD123, LM7x_SD124, LM7x_SD125 }; + constexpr size_t optionCount = NR_ELEMENTS(PToptionValues); + addFormSelector(F("LM7x device details"), F("rtd_lm_type"), optionCount, PToptions, PToptionValues, P039_RTD_LM_TYPE); + addFormNote(F("TMP122/124 Limited support -> fixed 12 Bit res, no advanced options")); + } + { + addFormCheckBox(F("Enable Shutdown Mode"), F("rtd_lm_shtdwn"), P039_RTD_LM_SHTDWN); + # ifndef BUILD_NO_DEBUG + addFormNote(F("Device is set to shutdown between sample cycles. Useful for very long call cycles, to save power.
" + "Without LM7x device conversion happens in between call cycles. Call Cylces should therefore not become lower than 350ms.")); + # endif // ifndef BUILD_NO_DEBUG + } + } + } + + addFormSubHeader(F("Value validation")); + + if (!bitRead(P039_FLAGS, P039_TEMP_THRESHOLD_FLAG)) { + P039_TEMP_THRESHOLD = P039_TEMP_THRESHOLD_DEFAULT; // 0 K + } + addFormFloatNumberBox(F("Low temperature threshold"), + F("temp_thres"), + P039_TEMP_THRESHOLD, + P039_TEMP_THRESHOLD_MIN, + P039_TEMP_THRESHOLD_MAX, + 2u); + addUnit(F("°C")); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + P039_FAM_TYPE = getFormItemInt(F("famtype")); + P039_MAX_TYPE = getFormItemInt(F("maxtype")); + P039_TC_TYPE = getFormItemInt(F("tctype")); + P039_RTD_TYPE = getFormItemInt(F("rtdtype")); + P039_CONFIG_4 = getFormItemInt(F("contype")); + P039_RTD_FILT_TYPE = getFormItemInt(F("filttype")); + P039_RTD_RES = getFormItemInt(F("res")); + P039_RTD_OFFSET = getFormItemFloat(F("offset")); + P039_RTD_LM_TYPE = getFormItemInt(F("rtd_lm_type")); + P039_RTD_LM_SHTDWN = isFormItemChecked(F("rtd_lm_shtdwn")); + P039_TEMP_THRESHOLD = getFormItemFloat(F("temp_thres")); + bitSet(P039_FLAGS, P039_TEMP_THRESHOLD_FLAG); // We've set a value, don't replace by default + + success = true; + break; + } + + case PLUGIN_READ: + { + // Get the MAX Type (6675 / 31855 / 31856) + uint8_t MaxType = P039_MAX_TYPE; + + float Plugin_039_Celsius = NAN; + + switch (MaxType) { + case P039_MAX6675: + Plugin_039_Celsius = readMax6675(event); + break; + case P039_MAX31855: + Plugin_039_Celsius = readMax31855(event); + break; + case P039_MAX31856: + Plugin_039_Celsius = readMax31856(event); + break; + case P039_MAX31865: + Plugin_039_Celsius = readMax31865(event); + break; + case P039_LM7x: + Plugin_039_Celsius = readLM7x(event); + break; + } + + if (isValidFloat(Plugin_039_Celsius)) + { + UserVar.setFloat(event->TaskIndex, 0, Plugin_039_Celsius); + +# ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = strformat(F("P039 : %s :"), getTaskDeviceName(event->TaskIndex).c_str()); + + const uint8_t valueCount = getValueCountForTask(event->TaskIndex); + + for (uint8_t i = 0; i < valueCount; ++i) + { + log += strformat( + F(" %s: %s"), + Cache.getTaskDeviceValueName(event->TaskIndex, i).c_str(), + formatUserVarNoCheck(event, i).c_str()); + } + addLogMove(LOG_LEVEL_INFO, log); + } +# endif // ifndef BUILD_NO_DEBUG + + if (definitelyGreaterThan(Plugin_039_Celsius, P039_TEMP_THRESHOLD)) { + success = true; + } + } + else + { + UserVar.setFloat(event->TaskIndex, 0, NAN); + UserVar.setFloat(event->TaskIndex, 1, NAN); + + if (loglevelActiveFor(LOG_LEVEL_ERROR)) { + addLog(LOG_LEVEL_ERROR, strformat(F("P039 : %s : No Sensor attached!"), getTaskDeviceName(event->TaskIndex).c_str())); + } + success = false; + } + + break; + } + + case PLUGIN_TASKTIMER_IN: + { + P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); + + int8_t CS_pin_no = get_SPI_CS_Pin(event); + + // Get the MAX Type (6675 / 31855 / 31856) + uint8_t MaxType = P039_MAX_TYPE; + + switch (MaxType) + { + case P039_MAX31865: + { + if ((nullptr != P039_data)) { + switch (event->Par1) + { + case MAX31865_BIAS_ON_STATE: + { + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLog(LOG_LEVEL_DEBUG, strformat( + F("P039 : %s : current state: MAX31865_BIAS_ON_STATE; delta: %d ms"), + getTaskDeviceName(event->TaskIndex).c_str(), + timePassedSince(P039_data->timer))); // calc delta since last call + } + # endif // ifndef BUILD_NO_DEBUG + + // save current timer for next calculation + P039_data->timer = millis(); + + // activate one shot conversion + change8BitRegister(CS_pin_no, + (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), + (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), + MAX31865_SET_ONE_SHOT, + P039_SET); + + // set next state in sequence -> READ STATE + // start time to follow up on conversion and read the conversion result + P039_data->convReady = false; + Scheduler.setPluginTaskTimer(MAX31865_CONVERSION_TIME, event->TaskIndex, MAX31865_RD_STATE); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLog(LOG_LEVEL_DEBUG, strformat( + F("P039 : %s : Next State: %d"), + getTaskDeviceName(event->TaskIndex).c_str(), + event->Par1)); + } + # endif // ifndef BUILD_NO_DEBUG + + break; + } + case MAX31865_RD_STATE: + { + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLog(LOG_LEVEL_DEBUG, strformat( + F("P039 : %s : current state: MAX31865_RD_STATE; delta: %d ms"), + getTaskDeviceName(event->TaskIndex).c_str(), + timePassedSince(P039_data->timer))); // calc delta since last call + } + # endif // ifndef BUILD_NO_DEBUG + + // save current timer for next calculation + P039_data->timer = millis(); + + // read conversion result + P039_data->conversionResult = read16BitRegister(CS_pin_no, (MAX31865_READ_ADDR_BASE + MAX31865_RTD_MSB)); + + // deactivate BIAS short after read, to reduce power consumption + change8BitRegister(CS_pin_no, + (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), + (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), + MAX31865_SET_VBIAS_ON, + P039_RESET); + + // read fault register to get a full picture + P039_data->deviceFaults = read8BitRegister(CS_pin_no, (MAX31865_READ_ADDR_BASE + MAX31865_FAULT)); + + // mark conversion as ready + P039_data->convReady = true; + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLog(LOG_LEVEL_DEBUG, + strformat(F("P039 : %s : conversionResult: %s; deviceFaults: %s; Next State: %d"), + getTaskDeviceName(event->TaskIndex).c_str(), + formatToHex_decimal(P039_data->conversionResult).c_str(), + formatToHex_decimal(P039_data->deviceFaults).c_str(), + event->Par1)); + } + # endif // ifndef BUILD_NO_DEBUG + + + break; + } + case MAX31865_INIT_STATE: + default: + { + // clear all faults + MAX31865_clearFaults(CS_pin_no); + + // activate BIAS short before read, to reduce power consumption + change8BitRegister(CS_pin_no, + (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), + (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), + MAX31865_SET_VBIAS_ON, + P039_SET); + + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLog(LOG_LEVEL_DEBUG, strformat(F("P039 : %s : current state: MAX31865_INIT_STATE, " + "default; next state: MAX31865_BIAS_ON_STATE"), + getTaskDeviceName(event->TaskIndex).c_str())); + + // FIXME: Shouldn't this be in active code? // save current timer for next calculation + P039_data->timer = millis(); + } + # endif // ifndef BUILD_NO_DEBUG + + // start time to follow up on BIAS activation before starting the conversion + // and start conversion sequence via TIMER API + // set next state in sequence -> BIAS ON STATE + + Scheduler.setPluginTaskTimer(MAX31865_BIAS_WAIT_TIME, event->TaskIndex, MAX31865_BIAS_ON_STATE); + + + break; + } + } + } + break; + } + default: + { + break; + } + } + + success = true; + break; + } + } + return success; +} + +void P039_AddMainsFrequencyFilterSelection(struct EventStruct *event) +{ + const __FlashStringHelper *FToptions[2] = { F("60"), F("50") }; + const int FToptionValues[2] = { 0, 1 }; + + addFormSelector(F("Supply Frequency Filter"), F("filttype"), 2, FToptions, FToptionValues, P039_RTD_FILT_TYPE); + addUnit(F("Hz")); + # ifndef LIMIT_BUILD_SIZE + addFormNote(F("Filter power net frequency (50/60 Hz)")); + # else // ifndef LIMIT_BUILD_SIZE + addUnit(F("net frequency")); + # endif // ifndef LIMIT_BUILD_SIZE +} + +float readMax6675(struct EventStruct *event) +{ + int8_t CS_pin_no = get_SPI_CS_Pin(event); + + uint8_t messageBuffer[2] = { 0 }; + uint16_t rawvalue = 0u; + + + // "transfer" 2 bytes to SPI to get 16 Bit return value + transfer_n_ByteSPI(CS_pin_no, 2, &messageBuffer[0]); + + // merge 16Bit return value from messageBuffer + rawvalue = ((messageBuffer[0] << 8) | messageBuffer[1]); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) + { + addLog(LOG_LEVEL_DEBUG, strformat(F("P039 : MAX6675 : RAW - BIN: %s HEX: %s DEC: %d MSB: %s LSB: %s"), + String(rawvalue, BIN).c_str(), + formatToHex(rawvalue).c_str(), + rawvalue, + formatToHex_decimal(messageBuffer[0]).c_str(), + formatToHex_decimal(messageBuffer[1]).c_str())); + } + + # endif // ifndef BUILD_NO_DEBUG + + // Open Thermocouple + // Bit D2 is normally low and goes high if the thermocouple input is open. In order to allow the operation of the + // open thermocouple detector, T- must be grounded. Make the ground connection as close to the GND pin + // as possible. + // 2021-05-11: FIXED: c.k.i.: OC Flag already checked; migrated to #define for improved maintenance + const bool Plugin_039_SensorAttached = !(rawvalue & MAX6675_TC_OC); + + if (Plugin_039_SensorAttached) + { + // shift RAW value 3 Bits to the right to get the data + rawvalue >>= 3; + + // calculate Celsius with device resolution 0.25 K/bit + return rawvalue * 0.25f; + } + else + { + return NAN; + } +} + +float readMax31855(struct EventStruct *event) +{ + P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); + + uint8_t messageBuffer[4] = { 0 }; + + int8_t CS_pin_no = get_SPI_CS_Pin(event); + + // "transfer" 0x0 and read the 32 Bit conversion register from the Chip + transfer_n_ByteSPI(CS_pin_no, 4, &messageBuffer[0]); + + // merge rawvalue from 4 bytes of messageBuffer + uint32_t rawvalue = + ((static_cast(messageBuffer[0]) << + 24) | + (static_cast(messageBuffer[1]) << + 16) | (static_cast(messageBuffer[2]) << 8) | static_cast(messageBuffer[3])); + + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) + { + String log; + + if ((log.reserve(200u))) { // reserve value derived from example log file + log = strformat(F("P039 : MAX31855 : RAW - BIN: %s rawvalue,HEX: %s rawvalue,DEC: %d messageBuffer[],HEX:"), + String(rawvalue, BIN).c_str(), + formatToHex(rawvalue).c_str(), + rawvalue); + + for (size_t i = 0u; i < 4; ++i) + { + log += ' '; // 1 char + log += formatToHex_decimal(messageBuffer[i]); // 9 char + } + addLogMove(LOG_LEVEL_DEBUG, log); + } + } + + # endif // ifndef BUILD_NO_DEBUG + + if (nullptr != P039_data) { + // FIXED: c.k.i. : moved static fault flag to instance data structure + + // check for fault flags in LSB of 32 Bit messageBuffer + if (P039_data->sensorFault != ((rawvalue & (MAX31855_TC_SCVCC | MAX31855_TC_SC | MAX31855_TC_OC)) == 0)) { + // Fault code changed, log them + P039_data->sensorFault = ((rawvalue & (MAX31855_TC_SCVCC | MAX31855_TC_SC | MAX31855_TC_OC)) == 0); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + String log; + + if ((log.reserve(120u))) { // reserve value derived from example log file + log = F("P039 : MAX31855 : "); + + if ((P039_data->sensorFault)) { + log += F("Fault resolved"); + } else { + log += F("Fault code :"); + + if (rawvalue & MAX31855_TC_OC) { + log += F(" Open (no connection)"); + } + + if (rawvalue & MAX31855_TC_SC) { + log += F(" Short-circuit to GND"); + } + + if (rawvalue & MAX31855_TC_SCVCC) { + log += F(" Short-circuit to Vcc"); + } + } + addLogMove(LOG_LEVEL_DEBUG_MORE, log); + } + } + # endif // ifndef BUILD_NO_DEBUG + } + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) + { + addLog(LOG_LEVEL_DEBUG, strformat(F("P039 : MAX31855 : rawvalue: %s P039_data->sensorFault: "), + formatToHex_decimal(rawvalue).c_str(), + formatToHex_decimal(P039_data->sensorFault).c_str())); + } + + # endif // ifndef BUILD_NO_DEBUG + } + + // D16 - This bit reads at 1 when any of the SCV, SCG, or OC faults are active. Default value is 0. + // 2020-05-11: FIXED: c.k.i.: migrated plain flag mask to #defines to enhance maintainability; added all fault flags for safety reasons + const bool Plugin_039_SensorAttached = !(rawvalue & (MAX31855_TC_GENFLT | MAX31855_TC_SCVCC | MAX31855_TC_SC | MAX31855_TC_OC)); + + if (Plugin_039_SensorAttached) + { + // Data is D[31:18] + // Shift RAW value 18 Bits to the right to get the data + rawvalue >>= 18; + + // Check for negative Values + // +25.00 0000 0001 1001 00 + // 0.00 0000 0000 0000 00 + // -0.25 1111 1111 1111 11 + // -1.00 1111 1111 1111 00 + // -250.00 1111 0000 0110 00 + // We're left with (32 - 18 =) 14 bits + int temperature = Plugin_039_convert_two_complement(rawvalue, 14); + + // Calculate Celsius + return temperature * 0.25f; + } + else + { + // Fault state, thus output no value. + return NAN; + } +} + +float readMax31856(struct EventStruct *event) +{ + P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); + + int8_t CS_pin_no = get_SPI_CS_Pin(event); + + + uint8_t registers[MAX31856_NO_REG] = { 0 }; + uint8_t messageBuffer[MAX31856_NO_REG + 1] = { 0 }; + + messageBuffer[0] = MAX31856_READ_ADDR_BASE; + + // "transfer" 0x0 starting at address 0x00 and read the all registers from the Chip + transfer_n_ByteSPI(CS_pin_no, (MAX31856_NO_REG + 1), &messageBuffer[0]); + + // transfer data from messageBuffer and get rid of initial address uint8_t + for (uint8_t i = 0u; i < MAX31856_NO_REG; ++i) { + registers[i] = messageBuffer[i + 1]; + } + + // configure device for next conversion + // activate frequency filter according to configuration + change8BitRegister(CS_pin_no, + (MAX31856_READ_ADDR_BASE + MAX31856_CR0), + (MAX31856_WRITE_ADDR_BASE + MAX31856_CR0), + MAX31856_SET_50HZ, + static_cast(P039_RTD_FILT_TYPE)); + + // set averaging and TC type + write8BitRegister(CS_pin_no, (MAX31856_WRITE_ADDR_BASE + MAX31856_CR1), static_cast((P039_CONFIG_4 << 4) | P039_TC_TYPE)); + + + // start on shot conversion for next read cycle + change8BitRegister(CS_pin_no, + (MAX31856_READ_ADDR_BASE + MAX31856_CR0), + (MAX31856_WRITE_ADDR_BASE + MAX31856_CR0), + MAX31856_SET_ONE_SHOT, + P039_SET); + + + // now derive raw value from respective registers + uint32_t rawvalue = static_cast(registers[MAX31856_LTCBH]); + + rawvalue = (rawvalue << 8) | static_cast(registers[MAX31856_LTCBM]); + rawvalue = (rawvalue << 8) | static_cast(registers[MAX31856_LTCBL]); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) + { + String log; + + if ((log.reserve(210u))) { // reserve value derived from example log file + log = F("P039 : MAX31856 :"); + + for (uint8_t i = 0; i < MAX31856_NO_REG; ++i) { + log += ' '; + log += formatToHex_decimal(registers[i]); + } + log += F(" rawvalue: "); + log += formatToHex_decimal(rawvalue); + addLogMove(LOG_LEVEL_DEBUG, log); + } + } + + # endif // ifndef BUILD_NO_DEBUG + + + // ignore TC Range Bit in case Voltage Modes are used + // datasheet: + // Thermocouple Out-of-Range fault. + // 0 = The Thermocouple Hot Junction temperature is within the normal operating range (see Table 1). + // 1 = The Thermocouple Hot Junction temperature is outside of the normal operating range. + // Note: The TC Range bit should be ignored in voltage mode. + uint8_t sr = registers[MAX31856_SR]; + + if ((8u == P039_TC_TYPE) || (12u == P039_TC_TYPE)) { + sr &= ~MAX31856_TC_TCRANGE; + } + + + // FIXED: c.k.i. : moved static fault flag to instance data structure + if ((nullptr != P039_data)) { + // P039_data->sensorFault = false; + + P039_data->sensorFault = (sr != 0); // Set new state + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + // FIXME TD-er: Part of expression is always false (sr == 0) + const bool faultResolved = (P039_data->sensorFault) && (sr == 0); + + if ((P039_data->sensorFault) || faultResolved) { + String log; + + if ((log.reserve(140u))) { // reserve value derived from example log file + log = F("P039 : MAX31856 : "); + + if ((P039_data->sensorFault) == 0) { + log += F("Fault resolved"); + } else { + log += F("Fault :"); + + if (sr & MAX31856_TC_OC) { + log += F(" Open (no connection)"); + } + + if (sr & MAX31856_TC_OVUV) { + log += F(" Over/Under Voltage"); + } + + if (sr & MAX31856_TC_TCLOW) { + log += F(" TC Low"); + } + + if (sr & MAX31856_TC_TCLHIGH) { + log += F(" TC High"); + } + + if (sr & MAX31856_TC_CJLOW) { + log += F(" CJ Low"); + } + + if (sr & MAX31856_TC_CJHIGH) { + log += F(" CJ High"); + } + + if (sr & MAX31856_TC_TCRANGE) { + log += F(" TC Range"); + } + + if (sr & MAX31856_TC_CJRANGE) { + log += F(" CJ Range"); + } + addLogMove(LOG_LEVEL_DEBUG_MORE, log); + } + } + } + } + # endif // ifndef BUILD_NO_DEBUG + } + + + const bool Plugin_039_SensorAttached = (sr == 0); + + if (Plugin_039_SensorAttached) + { + rawvalue >>= 5; // bottom 5 bits are unused + // We're left with (24 - 5 =) 19 bits + + { + float temperature = 0; + + switch (P039_TC_TYPE) + { + case 8: + { + temperature = rawvalue / 1677721.6f; // datasheet: rawvalue = 8 x 1.6 x 2^17 x VIN -> VIN = rawvalue / (8 x 1.6 x 2^17) + break; + } + case 12: + { + temperature = rawvalue / 6710886.4f; // datasheet: rawvalue = 32 x 1.6 x 2^17 x VIN -> VIN = rawvalue / (32 x 1.6 x 2^17) + break; + } + default: + { + temperature = Plugin_039_convert_two_complement(rawvalue, 19); + + // Calculate Celsius + temperature /= 128.0f; + break; + } + } + + return temperature; + } + } + else + { + // Fault state, thus output no value. + return NAN; + } +} + +float readMax31865(struct EventStruct *event) +{ + P039_data_struct *P039_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (P039_data == nullptr) { + return NAN; + } + + uint8_t registers[MAX31865_NO_REG] = { 0 }; + uint16_t rawValue = 0u; + + int8_t CS_pin_no = get_SPI_CS_Pin(event); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) + { + String log; + + if ((log.reserve(80u))) { // reserve value derived from example log file + log = F("P039 : MAX31865 :"); + log += F(" P039_data->convReady: "); + log += boolToString(P039_data->convReady); + + addLogMove(LOG_LEVEL_DEBUG, log); + } + } + + # endif // ifndef BUILD_NO_DEBUG + + + // read conversion result and faults from plugin data structure + // if pointer exists and conversion has been finished + if (P039_data->convReady) { + rawValue = P039_data->conversionResult; + registers[MAX31865_FAULT] = P039_data->deviceFaults; + } + + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + String log; + + if ((log.reserve(160u))) { // reserve value derived from example log file + for (uint8_t i = 0u; i < MAX31865_NO_REG; ++i) + { + registers[i] = read8BitRegister(CS_pin_no, (MAX31865_READ_ADDR_BASE + i)); + } + + log = F("P039 : MAX31865 :"); + + for (uint8_t i = 0u; i < MAX31865_NO_REG; ++i) + { + log += ' '; + log += formatToHex_decimal(registers[i]); + } + + addLogMove(LOG_LEVEL_DEBUG_MORE, log); + } + } + + # endif // ifndef BUILD_NO_DEBUG + + // Prepare and start next conversion, before handling faults and rawValue + // clear all faults + MAX31865_clearFaults(CS_pin_no); + + // set frequency filter + change8BitRegister(CS_pin_no, + (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), + (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), + MAX31865_SET_50HZ, + static_cast(P039_RTD_FILT_TYPE)); + + + // configure read access with configuration from web interface + MAX31865_setConType(CS_pin_no, P039_CONFIG_4); + + // activate BIAS short before read, to reduce power consumption + change8BitRegister(CS_pin_no, + (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), + (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), + MAX31865_SET_VBIAS_ON, + P039_SET); + + // start time to follow up on BIAS activation before starting the conversion + // and start conversion sequence via TIMER API + // save current timer for next calculation + P039_data->timer = millis(); + + // set next state to MAX31865_BIAS_ON_STATE + + Scheduler.setPluginTaskTimer(MAX31865_BIAS_WAIT_TIME, event->TaskIndex, MAX31865_BIAS_ON_STATE); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + if (registers[MAX31865_FAULT]) + { + String log; + + if ((log.reserve(210u))) { // reserve value derived from example log file + log = F("P039 : MAX31865 : "); + + log += F("Fault : "); + log += formatToHex_decimal(registers[MAX31865_FAULT]); + log += F(" :"); + + if (registers[MAX31865_FAULT] & MAX31865_FAULT_OVUV) + { + log += F(" Under/Over voltage"); + } + + if (registers[MAX31865_FAULT] & MAX31865_FAULT_RTDINLOW) + { + log += F(" RTDIN- < 0.85 x Bias - FORCE- open"); + } + + if (registers[MAX31865_FAULT] & MAX31865_FAULT_REFINHIGH) + { + log += F(" REFIN- < 0.85 x Bias - FORCE- open"); + } + + if (registers[MAX31865_FAULT] & MAX31865_FAULT_REFINLOW) + { + log += F(" REFIN- > 0.85 x Bias"); + } + + if (registers[MAX31865_FAULT] & MAX31865_FAULT_LOWTHRESH) + { + log += F(" RTD Low Threshold"); + } + + if (registers[MAX31865_FAULT] & MAX31865_FAULT_HIGHTHRESH) + { + log += F(" RTD High Threshold"); + } + addLogMove(LOG_LEVEL_DEBUG_MORE, log); + } + } + } + # endif // ifndef BUILD_NO_DEBUG + + + bool ValueValid = false; + + if (registers[MAX31865_FAULT] == 0x00u) { + ValueValid = true; + } + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) + { + addLog(LOG_LEVEL_DEBUG, strformat(F("P039 : Temperature : registers[MAX31865_FAULT]: %s ValueValid: %s"), + formatToHex_decimal(registers[MAX31865_FAULT]).c_str(), + FsP(boolToString(ValueValid)))); + } + + # endif // ifndef BUILD_NO_DEBUG + + if (ValueValid) + { + rawValue >>= 1; // bottom fault bits is unused + + float temperature = Plugin_039_convert_to_temperature(rawValue, getNomResistor(P039_RTD_TYPE), P039_RTD_RES); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) + { + addLog(LOG_LEVEL_DEBUG, strformat(F("P039 : Temperature : rawValue: %s temperature: %.3f P039_RTD_TYPE: %d P039_RTD_RES: %d"), + formatToHex_decimal(rawValue).c_str(), + temperature, + P039_RTD_TYPE, + P039_RTD_RES)); + } + + # endif // ifndef BUILD_NO_DEBUG + + // add offset handling from configuration webpage + temperature += P039_RTD_OFFSET; + + // Calculate Celsius + return temperature; + } + else + { + // Fault state, thus output no value. + return NAN; + } +} + +void MAX31865_clearFaults(int8_t l_CS_pin_no) +{ + uint8_t l_reg = 0u; + + // read in config register + l_reg = read8BitRegister(l_CS_pin_no, (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG)); + + + // clear all faults ( write "0" to D2, D3, D5; write "1" to D2) + l_reg &= ~(MAX31865_SET_ONE_SHOT | MAX31865_FAULT_CTRL_MASK); + l_reg |= MAX31865_CLEAR_FAULTS; + + // write configuration + write8BitRegister(l_CS_pin_no, (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), l_reg); +} + +void MAX31865_setConType(int8_t l_CS_pin_no, uint8_t l_conType) +{ + bool l_set_reset = false; + + // configure if 3 WIRE bit will be set/reset + switch (l_conType) + { + case 0: + l_set_reset = P039_RESET; + break; + case 1: + l_set_reset = P039_SET; + break; + default: + l_set_reset = P039_RESET; + break; + } + + // change to configuration register + change8BitRegister(l_CS_pin_no, + (MAX31865_READ_ADDR_BASE + MAX31865_CONFIG), + (MAX31865_WRITE_ADDR_BASE + MAX31865_CONFIG), + MAX31865_SET_3WIRE, + l_set_reset); +} + +/**************************************************************************/ + +/*! + @brief Read the temperature in C from the RTD through calculation of the + resistance. Uses + http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf + technique + @param RTDnominal The 'nominal' resistance of the RTD sensor, usually 100 + or 1000 + @param refResistor The value of the matching reference resistor, usually + 430 or 4300 + @returns Temperature in C + */ + +/**************************************************************************/ +float Plugin_039_convert_to_temperature(uint32_t l_rawvalue, float RTDnominal, float refResistor) +{ + # define RTD_A 3.9083e-3f + # define RTD_B -5.775e-7f + + float Z1, Z2, Z3, Z4, Rt, temp; + + Rt = l_rawvalue; + Rt /= 32768u; + Rt *= refResistor; + + Z1 = -RTD_A; + Z2 = RTD_A * RTD_A - (4 * RTD_B); + Z3 = (4 * RTD_B) / RTDnominal; + Z4 = 2 * RTD_B; + + temp = Z2 + (Z3 * Rt); + temp = (sqrtf(temp) + Z1) / Z4; + + if (temp >= 0) { + return temp; + } + + Rt /= RTDnominal; + Rt *= 100; // normalize to 100 ohm + + float rpoly = Rt; + + temp = -242.02f; + temp += 2.2228f * rpoly; + rpoly *= Rt; // square + temp += 2.5859e-3f * rpoly; + rpoly *= Rt; // ^3 + temp -= 4.8260e-6f * rpoly; + rpoly *= Rt; // ^4 + temp -= 2.8183e-8f * rpoly; + rpoly *= Rt; // ^5 + temp += 1.5243e-10f * rpoly; + + return temp; +} + +uint16_t getNomResistor(uint8_t l_RType) +{ + uint16_t l_returnValue = 100u; + + switch (l_RType) + { + case MAX31865_PT100: + l_returnValue = 100u; + break; + case MAX31865_PT1000: + l_returnValue = 1000u; + break; + default: + l_returnValue = 100u; + break; + } + return l_returnValue; +} + +int Plugin_039_convert_two_complement(uint32_t value, int nr_bits) { + const bool negative = (value & (1 << (nr_bits - 1))) != 0; + int nativeInt; + + if (negative) { + // Add zeroes to the left to create the proper negative native-sized integer. + nativeInt = value | ~((1 << nr_bits) - 1); + } else { + nativeInt = value; + } + return nativeInt; +} + +float readLM7x(struct EventStruct *event) +{ + float temperature = 0.0f; + uint16_t device_id = 0u; + uint16_t rawValue = 0u; + + int8_t CS_pin_no = get_SPI_CS_Pin(event); + + // operate LM7x devices in polling mode, assuming conversion is ready with every call of this read function ( >=210ms call cycle) + // this allows usage of multiples generations of LM7x devices, that doe not provde conversion ready information in temperature register + + rawValue = readLM7xRegisters(CS_pin_no, P039_RTD_LM_TYPE, P039_RTD_LM_SHTDWN, &device_id); + + temperature = convertLM7xTemp(rawValue, P039_RTD_LM_TYPE); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) + { + addLog(LOG_LEVEL_DEBUG, strformat(F("P039 : LM7x : readLM7x : rawValue: %s device_id: %s temperature: %.3f"), + formatToHex_decimal(rawValue).c_str(), + formatToHex(device_id).c_str(), + temperature)); + } + # endif // ifndef BUILD_NO_DEBUG + + return temperature; +} + +float convertLM7xTemp(uint16_t l_rawValue, uint16_t l_LM7xsubtype) +{ + float l_returnValue = 0.0f; + float l_lsbvalue = 0.0f; + uint8_t l_noBits = 0u; + int l_intTemperature = 0; + + switch (l_LM7xsubtype) + { + case LM7x_SD70: + l_rawValue >>= 5; + l_lsbvalue = 0.25f; + l_noBits = 11u; + break; + case LM7x_SD71: + l_rawValue >>= 2; + l_lsbvalue = 0.03125f; + l_noBits = 14u; + break; + case LM7x_SD74: + l_rawValue >>= 3; + l_lsbvalue = 0.0625f; + l_noBits = 13u; + break; + case LM7x_SD121: + case LM7x_SD122: + case LM7x_SD123: + case LM7x_SD124: + l_rawValue >>= 4; + l_lsbvalue = 0.0625f; + l_noBits = 12u; + break; + case LM7x_SD125: + l_rawValue >>= 5; + l_lsbvalue = 0.25f; + l_noBits = 10u; + break; + default: // use lowest resolution as fallback if no device has been configured + l_rawValue >>= 5; + l_lsbvalue = 0.25f; + l_noBits = 11u; + break; + } + + l_intTemperature = Plugin_039_convert_two_complement(l_rawValue, l_noBits); + + l_returnValue = l_intTemperature * l_lsbvalue; + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + addLog(LOG_LEVEL_DEBUG_MORE, + strformat(F("P039 : LM7x : convertLM7xTemp : l_returnValue: %s l_LM7xsubtype: %s l_rawValue: %s l_noBits: %d l_lsbvalue: %.3f"), + formatToHex_decimal(l_returnValue).c_str(), + formatToHex_decimal(l_LM7xsubtype).c_str(), + formatToHex_decimal(l_rawValue).c_str(), + l_noBits, + l_lsbvalue)); + } + + # endif // ifndef BUILD_NO_DEBUG + + return l_returnValue; +} + +uint16_t readLM7xRegisters(int8_t l_CS_pin_no, uint8_t l_LM7xsubType, uint8_t l_runMode, uint16_t *l_device_id) +{ + uint16_t l_returnValue = 0u; + uint16_t l_mswaitTime = 0u; + + + switch (l_LM7xsubType) + { + case LM7x_SD70: + case LM7x_SD71: + case LM7x_SD74: + l_mswaitTime = 300; + break; + case LM7x_SD121: + case LM7x_SD122: + case LM7x_SD123: + case LM7x_SD124: + l_mswaitTime = 320; + break; + case LM7x_SD125: + l_mswaitTime = 100; + break; + default: + l_mswaitTime = 500; + break; + } + + // // activate communication -> CS low + // handle_SPI_CS_Pin(l_CS_pin_no, LOW); + + if (l_runMode) + { + // shutdown mode active -> conversion when called + uint8_t messageBuffer[12] = { 0xFF, 0xFF, 0xFF, 0X00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF }; + + // send inital 4 bytes to wake the device and start the conversion + transfer_n_ByteSPI(l_CS_pin_no, 4, &messageBuffer[0]); + + // wait specific ms for conversion to be ready (TI datasheet per devices) + delay(l_mswaitTime); + + // send remaining 8 bytes to read the device ID and shutdown the device + transfer_n_ByteSPI(l_CS_pin_no, 8, &messageBuffer[4]); + + // read temperature value (16 Bit) + l_returnValue = ((messageBuffer[4] << 8) | messageBuffer[5]); + + // read Manufatures/Device ID (16 Bit) + *(l_device_id) = ((messageBuffer[8] << 8) | messageBuffer[9]); + + // // wakeup device and start conversion + // // initial read of conversion result is obsolete + // SPI.transfer16(0xFFFF); + + // // (wakeup device with "all zero2 message in the last 8 bits + // SPI.transfer16(0xFF00); + + // //wait specific ms for conversion to be ready (TI datasheet per devices) + // delay(l_mswaitTime); + + // //read temperature value (16 Bit) + // l_returnValue = SPI.transfer16(0x0000); + // // l_returnValue <<= 8; + // // l_returnValue = SPI.transfer(0x00); + + // // set device to shutdown with "all one" message in the last 8 bits + // SPI.transfer16(0xFFFF); + + // // read Manufatures/Device ID (16 Bit) + // *(l_device_id) = SPI.transfer16(0x0000); + // // *(l_device_id) <<= 8; + // // *(l_device_id) = SPI.transfer(0x00); + + // // set device to shutdown with "all one" message in the last 8 bits ( maybe redundant, check with test) + // SPI.transfer16(0xFFFF); + } + else + { + // shutdown mode inactive -> normal background conversion during call cycle + uint8_t messageBuffer[8] = { 0x00, 0x00, 0xFF, 0XFF, 0x00, 0x00, 0x00, 0x00 }; + + transfer_n_ByteSPI(l_CS_pin_no, 8, &messageBuffer[0]); + + // read temperature value (16 Bit) + l_returnValue = ((messageBuffer[0] << 8) | messageBuffer[1]); + + // read Manufatures/Device ID (16 Bit) + *(l_device_id) = ((messageBuffer[4] << 8) | messageBuffer[5]); + + + // l_returnValue = SPI.transfer16(0x0000); //read temperature value (16 Bit) + // // l_returnValue <<= 8; + // // l_returnValue = SPI.transfer(0x00); + + // // set device to shutdown + // SPI.transfer16(0xFFFF); + + // // read Manufatures/Device ID (16 Bit) + // *(l_device_id) = SPI.transfer16(0x0000); + // // *(l_device_id) <<= 8; + // // *(l_device_id) = SPI.transfer(0x00); + + // // start conversion until next read (8 Bit sufficient) + // // 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F allowed - else device goes to test mode (not desirable here) + // SPI.transfer(0x00); + // // SPI.transfer16(0x0000); + } + + // // stop communication -> CS high + // handle_SPI_CS_Pin(l_CS_pin_no, HIGH); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + addLog(LOG_LEVEL_DEBUG_MORE, strformat(F("P039 : LM7x : readLM7xRegisters : l_returnValue: %s l_device_id: %s"), + formatToHex_decimal(l_returnValue).c_str(), + formatToHex(*(l_device_id)).c_str())); + } + + # endif // ifndef BUILD_NO_DEBUG + + return l_returnValue; +} + +// POSSIBLE START OF GENERIC SPI HIGH LEVEL FUNCTIONS WITH POTENTIAL OF SYSTEM WIDE RE-USE + +/**************************************************************************/ + +/*! + @brief generic high level library to access SPI interface from plugins + with GPIO pin handled as CS - chri.kai.in 2021 + + Initial Revision - chri.kai.in 2021 + + TODO: c.k.i.: make it generic and carve out to generic _SPI_helper.c library + + + /**************************************************************************/ + + +/**************************************************************************/ + +/*! + + @brief Identifying the CS pin from the event basic data structure + @param event pointer to the event structure; default GPIO is chosen as GPIO 15 + + @returns + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +int get_SPI_CS_Pin(struct EventStruct *event) { // If no Pin is in Config we use 15 as default -> Hardware Chip Select on ESP8266 + if (CONFIG_PIN1 != -1) { + return CONFIG_PIN1; + } + return 15; // D8 +} + +/**************************************************************************/ + +/*! + @brief Initializing GPIO as OUTPUT for CS for SPI communication + @param l_CS_pin_no the GPIO pin number used as CS + + @returns + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +void init_SPI_CS_Pin(int8_t l_CS_pin_no) { + // set the slaveSelectPin as an output: + pinMode(l_CS_pin_no, OUTPUT); +} + +/**************************************************************************/ + +/*! + @brief Handling GPIO as CS for SPI communication + @param l_CS_pin_no the GPIO pin number used as CS + @param l_state the state of the CS pin: "HIGH/LOW" reflecting the physical level + + @returns + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +void handle_SPI_CS_Pin(int8_t l_CS_pin_no, bool l_state) { + P039_CS_Delay(); // tCWH (min) >= x00ns + digitalWrite(l_CS_pin_no, l_state); + P039_CS_Delay(); // tCC (min) >= x00ns +} + +/**************************************************************************/ + +/*! + @brief write 8 bits to adress l_address on the SPI interface, handling a GPIO CS + @param l_CS_pin_no the GPIO pin number used as CS + @param l_address the register addess of the connected SPI device + @param value the unsigned 8 Bit message to be transferred + + @returns + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +void write8BitRegister(int8_t l_CS_pin_no, uint8_t l_address, uint8_t value) +{ + uint8_t l_messageBuffer[2] = { l_address, value }; + + transfer_n_ByteSPI(l_CS_pin_no, 2, l_messageBuffer); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + addLog(LOG_LEVEL_DEBUG_MORE, strformat(F("P039 : SPI : write8BitRegister : l_address: %s value: %s"), + formatToHex(l_address).c_str(), + formatToHex_decimal(value).c_str())); + } + + # endif // ifndef BUILD_NO_DEBUG +} + +/**************************************************************************/ + +/*! + @brief write 16 bits to adress l_address on the SPI interface, handling a GPIO CS + @param l_CS_pin_no the GPIO pin number used as CS + @param l_address the register addess of the connected SPI device + @param value the unsigned 16 Bit message to be transferred + + @returns + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +void write16BitRegister(int8_t l_CS_pin_no, uint8_t l_address, uint16_t value) +{ + uint8_t l_messageBuffer[3] = { l_address, static_cast((value >> 8) & 0xFF), static_cast(value & 0xFF) }; + + transfer_n_ByteSPI(l_CS_pin_no, 3, l_messageBuffer); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + addLog(LOG_LEVEL_DEBUG_MORE, strformat(F("P039 : SPI : write16BitRegister : l_address: %s value: %s"), + formatToHex(l_address).c_str(), + formatToHex_decimal(value).c_str())); + } + + # endif // ifndef BUILD_NO_DEBUG +} + +/**************************************************************************/ + +/*! + @brief read 8 bits from adress l_address on the SPI interface, handling a GPIO CS + @param l_CS_pin_no the GPIO pin number used as CS + @param l_address the register addess of the connected SPI device + + @returns the unsigned 8 Bit message read from l_address + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +uint8_t read8BitRegister(int8_t l_CS_pin_no, uint8_t l_address) +{ + uint8_t l_messageBuffer[2] = { l_address, 0x00 }; + + transfer_n_ByteSPI(l_CS_pin_no, 2, l_messageBuffer); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + addLog(LOG_LEVEL_DEBUG_MORE, strformat(F("P039 : SPI : read8BitRegister : l_address: %s returnvalue: %s"), + formatToHex(l_address).c_str(), + formatToHex_decimal(l_messageBuffer[1]).c_str())); + } + + # endif // ifndef BUILD_NO_DEBUG + + return l_messageBuffer[1]; +} + +/**************************************************************************/ + +/*! + @brief write 16 bits to adress l_address on the SPI interface, handling a GPIO CS + @param l_CS_pin_no the GPIO pin number used as CS + @param l_address the register addess of the connected SPI device + + @returns the unsigned 16 Bit message read from l_address + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +uint16_t read16BitRegister(int8_t l_CS_pin_no, uint8_t l_address) +{ + uint8_t l_messageBuffer[3] = { l_address, 0x00, 0x00 }; + uint16_t l_returnValue; + + transfer_n_ByteSPI(l_CS_pin_no, 3, l_messageBuffer); + l_returnValue = ((l_messageBuffer[1] << 8) | l_messageBuffer[2]); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + addLog(LOG_LEVEL_DEBUG_MORE, strformat(F("P039 : SPI : read16BitRegister : l_address: %s l_returnValue: %s"), + formatToHex(l_address).c_str(), + formatToHex_decimal(l_returnValue).c_str())); + } + + # endif // ifndef BUILD_NO_DEBUG + + return l_returnValue; +} + +/**************************************************************************/ + +/*! + @brief read from/write to dedicated number of bytes from/to SPI, handling a GPIO CS + @param l_CS_pin_no the GPIO pin number used as CS + @param l_noBytesToSend number of bytes to read/write from/to SPI + @param l_inoutMessageBuffer pointer to the messsage buffer to provide bytes to send + and provide read bytes from the SPI bus after the call + + @returns + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +void transfer_n_ByteSPI(int8_t l_CS_pin_no, uint8_t l_noBytesToSend, uint8_t *l_inoutMessageBuffer) +{ + // activate communication -> CS low + handle_SPI_CS_Pin(l_CS_pin_no, LOW); + + for (size_t i = 0u; i < l_noBytesToSend; i++) + { + l_inoutMessageBuffer[i] = SPI.transfer(l_inoutMessageBuffer[i]); + } + + // stop communication -> CS high + handle_SPI_CS_Pin(l_CS_pin_no, HIGH); + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) + { + String log; + + if ((log.reserve(120u))) { // reserve value derived from example log file + log = F("P039 : SPI : transfer_n_ByteSPI : "); // 34 char + + for (uint8_t i = 0; i < l_noBytesToSend; ++i) + { + log += ' '; // 1 char + log += formatToHex_decimal(l_inoutMessageBuffer[i]); // 9 char + } + addLogMove(LOG_LEVEL_DEBUG_MORE, log); + } + } + + # endif // ifndef BUILD_NO_DEBUG +} + +/**************************************************************************/ + +/*! + @brief read a 16Bit register and change a flag, writing it back, handling a GPIO CS + @param l_CS_pin_no the GPIO pin number used as CS + @param l_readaddress SPI read address of the device register + @param l_writeaddress SPI write address of the device register + @param l_flagmask mask set to apply on the read register + @param l_set_reset controls if flag mask will be set (-> true) or reset ( -> false) + + + @returns + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +void change16BitRegister(int8_t l_CS_pin_no, uint8_t l_readaddress, uint8_t l_writeaddress, uint16_t l_flagmask, bool l_set_reset) +{ + uint16_t l_reg = 0u; + + // read in config register + l_reg = read16BitRegister(l_CS_pin_no, l_readaddress); + + if (l_set_reset) { + l_reg |= l_flagmask; + } + else + { + l_reg &= ~(l_flagmask); + } + + // write to configuration register + write16BitRegister(l_CS_pin_no, l_writeaddress, l_reg); +} + +/**************************************************************************/ + +/*! + @brief read a 8 Bit register and change a flag, writing it back, handling a GPIO CS + @param l_CS_pin_no the GPIO pin number used as CS + @param l_readaddress SPI read address of the device register + @param l_writeaddress SPI write address of the device register + @param l_flagmask mask set to apply on the read register + @param l_set_reset controls if flag mask will be set (-> true) or reset ( -> false) + + + @returns + + Initial Revision - chri.kai.in 2021 + + /**************************************************************************/ +void change8BitRegister(int8_t l_CS_pin_no, uint8_t l_readaddress, uint8_t l_writeaddress, uint8_t l_flagmask, bool l_set_reset) +{ + uint8_t l_reg = 0u; + + // read in config register + l_reg = read8BitRegister(l_CS_pin_no, l_readaddress); + + + // TODO: c.k.i.: analyze opportunity to use arduino bitSet/Clear macros instead + if (l_set_reset) { + l_reg |= l_flagmask; + } + else + { + l_reg &= ~(l_flagmask); + } + + // write to configuration register + write8BitRegister(l_CS_pin_no, l_writeaddress, l_reg); +} + +#endif // USES_P039 diff --git a/src/_P040_ID12.ino b/src/_P040_ID12.ino index e797352270..22ad32ab70 100644 --- a/src/_P040_ID12.ino +++ b/src/_P040_ID12.ino @@ -2,14 +2,18 @@ #ifdef USES_P040 -//####################################################################################################### -//#################################### Plugin 040: Serial RFID ID-12 #################################### -//####################################################################################################### - -#define PLUGIN_040 -#define PLUGIN_ID_040 40 -#define PLUGIN_NAME_040 "RFID - ID12LA/RDM6300" -#define PLUGIN_VALUENAME1_040 "Tag" +// ####################################################################################################### +// #################################### Plugin 040: Serial RFID ID-12 #################################### +// ####################################################################################################### + +/** Changelog: + * 2025-01-03 tonhuisman: Format source code and small code size reductions + * TODO: Implement ESPEasySerial + */ +# define PLUGIN_040 +# define PLUGIN_ID_040 40 +# define PLUGIN_NAME_040 "RFID - ID12LA/RDM6300" +# define PLUGIN_VALUENAME1_040 "Tag" boolean Plugin_040_init = false; @@ -19,154 +23,156 @@ boolean Plugin_040(uint8_t function, struct EventStruct *event, String& string) switch (function) { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_040; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = false; - Device[deviceCount].GlobalSyncOption = true; - break; - } + { + Device[++deviceCount].Number = PLUGIN_ID_040; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + break; + } case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_040); - break; - } + { + string = F(PLUGIN_NAME_040); + break; + } case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_040)); - break; - } + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_040)); + break; + } case PLUGIN_INIT: - { - Plugin_040_init = true; - ESPEASY_SERIAL_0.begin(9600); - success = true; - break; - } + { + Plugin_040_init = true; + ESPEASY_SERIAL_0.begin(9600); + success = true; + break; + } case PLUGIN_TASKTIMER_IN: - { - if (Plugin_040_init) { - // Reset card id on timeout - UserVar.setSensorTypeLong(event->TaskIndex, 0); - addLog(LOG_LEVEL_INFO, F("RFID : Removed Tag")); - sendData(event); - success = true; - } - break; + { + if (Plugin_040_init) { + // Reset card id on timeout + UserVar.setSensorTypeLong(event->TaskIndex, 0); + addLog(LOG_LEVEL_INFO, F("RFID : Removed Tag")); + sendData(event); + success = true; } + break; + } case PLUGIN_SERIAL_IN: + { + if (Plugin_040_init) { - if (Plugin_040_init) - { - uint8_t val = 0; - uint8_t code[6]; - uint8_t checksum = 0; - uint8_t bytesread = 0; - uint8_t tempbyte = 0; - - if ((val = ESPEASY_SERIAL_0.read()) == 2) - { // check for header - bytesread = 0; - while (bytesread < 12) { // read 10 digit code + 2 digit checksum - if ( ESPEASY_SERIAL_0.available() > 0) { - val = ESPEASY_SERIAL_0.read(); - if ((val == 0x0D) || (val == 0x0A) || (val == 0x03) || (val == 0x02)) { - // if header or stop bytes before the 10 digit reading - break; - } + uint8_t val = 0; + uint8_t code[6]; + uint8_t checksum = 0; + uint8_t bytesread = 0; + uint8_t tempbyte = 0; + + if ((val = ESPEASY_SERIAL_0.read()) == 2) + { // check for header + bytesread = 0; + + while (bytesread < 12) { // read 10 digit code + 2 digit checksum + if (ESPEASY_SERIAL_0.available() > 0) { + val = ESPEASY_SERIAL_0.read(); + + if ((val == 0x0D) || (val == 0x0A) || (val == 0x03) || (val == 0x02)) { + // if header or stop bytes before the 10 digit reading + break; + } - // Do Ascii/Hex conversion: - if (isDigit(val)) { - val = val - '0'; - } - else if ((val >= 'A') && (val <= 'F')) { - val = 10 + val - 'A'; - } + // Do Ascii/Hex conversion: + if (isDigit(val)) { + val = val - '0'; + } + else if ((val >= 'A') && (val <= 'F')) { + val = 10 + val - 'A'; + } - // Every two hex-digits, add uint8_t to code: - if ( (bytesread & 1) == 1) { - // make some space for this hex-digit by - // shifting the previous hex-digit with 4 bits to the left: - code[bytesread >> 1] = (val | (tempbyte << 4)); + // Every two hex-digits, add uint8_t to code: + if ((bytesread & 1) == 1) { + // make some space for this hex-digit by + // shifting the previous hex-digit with 4 bits to the left: + code[bytesread >> 1] = (val | (tempbyte << 4)); - if (bytesread >> 1 != 5) { // If we're at the checksum uint8_t, - checksum ^= code[bytesread >> 1]; // Calculate the checksum... (XOR) - }; + if (bytesread >> 1 != 5) { // If we're at the checksum uint8_t, + checksum ^= code[bytesread >> 1]; // Calculate the checksum... (XOR) } - else { - tempbyte = val; // Store the first hex digit first... - }; - bytesread++; // ready to read next digit } + else { + tempbyte = val; // Store the first hex digit first... + } + bytesread++; // ready to read next digit } } + } - if (bytesread == 12) + if (bytesread == 12) + { + if (code[5] == checksum) { - if (code[5] == checksum) - { - // temp woraround, ESP Easy framework does not currently prepare this... - taskIndex_t index = INVALID_TASK_INDEX; - constexpr pluginID_t PLUGIN_ID_P040_ID12(PLUGIN_ID_040); - - for (taskIndex_t y = 0; y < TASKS_MAX; ++y) { - if (Settings.getPluginID_for_task(y) == PLUGIN_ID_P040_ID12) { - index = y; - } - } - const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(index); - if (!validDeviceIndex(DeviceIndex)) { - break; - } - event->setTaskIndex(index); - if (!validUserVarIndex(event->BaseVarIndex)) { - break; - } - checkDeviceVTypeForTask(event); - // endof workaround - - unsigned long key = 0, old_key = 0; - old_key = UserVar.getSensorTypeLong(event->TaskIndex); - for (uint8_t i = 1; i < 5; ++i) { key = key | (((unsigned long) code[i] << ((4 - i) * 8))); } - bool new_key = false; - if (old_key != key) { - UserVar.setSensorTypeLong(event->TaskIndex, key); - new_key = true; + // temp woraround, ESP Easy framework does not currently prepare this... + taskIndex_t index = INVALID_TASK_INDEX; + constexpr pluginID_t PLUGIN_ID_P040_ID12(PLUGIN_ID_040); + + for (taskIndex_t y = 0; y < TASKS_MAX; ++y) { + if (Settings.getPluginID_for_task(y) == PLUGIN_ID_P040_ID12) { + index = y; } + } + const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(index); - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("RFID : "); - if (new_key) { - log += F("New Tag: "); - } else { - log += F("Old Tag: "); - } - log += key; - addLogMove(LOG_LEVEL_INFO, log); + if (!validDeviceIndex(DeviceIndex)) { + break; + } + event->setTaskIndex(index); + + if (!validUserVarIndex(event->BaseVarIndex)) { + break; + } + checkDeviceVTypeForTask(event); + + // endof workaround + + unsigned long key = 0, old_key = 0; + old_key = UserVar.getSensorTypeLong(event->TaskIndex); + + for (uint8_t i = 1; i < 5; ++i) { key = key | (((unsigned long)code[i] << ((4 - i) * 8))); } + bool new_key = false; + + if (old_key != key) { + UserVar.setSensorTypeLong(event->TaskIndex, key); + new_key = true; + } + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("RFID : "); + + if (new_key) { + log += F("New Tag: "); + } else { + log += F("Old Tag: "); } - - if (new_key) sendData(event); - Scheduler.setPluginTaskTimer(500, event->TaskIndex, event->Par1); + log += key; + addLogMove(LOG_LEVEL_INFO, log); } + + if (new_key) { sendData(event); } + Scheduler.setPluginTaskTimer(500, event->TaskIndex, event->Par1); } - success = true; } - break; + success = true; } + break; + } } return success; } + #endif // USES_P040 diff --git a/src/_P041_NeoClock.ino b/src/_P041_NeoClock.ino index 2813907fc4..7751795ab9 100644 --- a/src/_P041_NeoClock.ino +++ b/src/_P041_NeoClock.ino @@ -36,11 +36,9 @@ boolean Plugin_041(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_041; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 0; + Device[++deviceCount].Number = PLUGIN_ID_041; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P042_Candle.ino b/src/_P042_Candle.ino index 6c0d4083a7..6e5305c37a 100644 --- a/src/_P042_Candle.ino +++ b/src/_P042_Candle.ino @@ -95,7 +95,6 @@ boolean Plugin_042(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_042; Device[deviceCount].Type = DEVICE_TYPE_SINGLE; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; Device[deviceCount].ValueCount = 3; Device[deviceCount].SendDataOption = true; Device[deviceCount].TimerOption = true; @@ -164,18 +163,16 @@ boolean Plugin_042(uint8_t function, struct EventStruct *event, String& string) addHtml(F("")); - } else { - addHtml('>'); + addHtml(F(" checked")); } + addHtml('>'); addHtml(F("
")); addHtml(F("")); - } else { - addHtml('>'); + addHtml(F(" checked")); } + addHtml('>'); addHtml(F("
")); // http://jscolor.com/examples/ diff --git a/src/_P043_ClkOutput.ino b/src/_P043_ClkOutput.ino index 44ee37e40e..6a7f897818 100644 --- a/src/_P043_ClkOutput.ino +++ b/src/_P043_ClkOutput.ino @@ -71,7 +71,6 @@ boolean Plugin_043(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_043; Device[deviceCount].Type = DEVICE_TYPE_SINGLE; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].Ports = 0; Device[deviceCount].ValueCount = 2; Device[deviceCount].SendDataOption = true; Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; diff --git a/src/_P047_i2c-soil-moisture-sensor.ino b/src/_P047_i2c-soil-moisture-sensor.ino index 10fb3df924..514c7aa3da 100644 --- a/src/_P047_i2c-soil-moisture-sensor.ino +++ b/src/_P047_i2c-soil-moisture-sensor.ino @@ -46,18 +46,14 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_047; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_047; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 3; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -170,7 +166,7 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string) # if P047_FEATURE_BEFLE_V3 if (P047_MODEL_CATNIP == static_cast(P047_MODEL)) - # endif // if !P047_FEATURE_BEFLE_V3 + # endif // if P047_FEATURE_BEFLE_V3 { addFormCheckBox(F("Check sensor version"), F("version"), P047_CHECK_VERSION); } diff --git a/src/_P048_Motorshield_v2.ino b/src/_P048_Motorshield_v2.ino index abee192acc..b8954a299a 100644 --- a/src/_P048_Motorshield_v2.ino +++ b/src/_P048_Motorshield_v2.ino @@ -32,17 +32,10 @@ boolean Plugin_048(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_048; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; - Device[deviceCount].I2CNoDeviceCheck = true; + Device[++deviceCount].Number = PLUGIN_ID_048; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + Device[deviceCount].I2CNoDeviceCheck = true; break; } diff --git a/src/_P049_MHZ19.ino b/src/_P049_MHZ19.ino index 69239e368d..09bbc97562 100644 --- a/src/_P049_MHZ19.ino +++ b/src/_P049_MHZ19.ino @@ -4,7 +4,8 @@ # include "src/PluginStructs/P049_data_struct.h" /** Changelog: - * 2024-01-04 tonhuisman: Add Device[].ExitBeforeSeve = false so ABD can be enabled during settings save + * 2025-01-03 tonhuisman: Small code size reductions + * 2024-01-04 tonhuisman: Add Device[].ExitBeforeSeve = false so ABC can be enabled during settings save * 2024-01-04 tonhuisman: Start changelog, most recent change on top */ @@ -50,14 +51,10 @@ boolean Plugin_049(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_049; Device[deviceCount].Type = DEVICE_TYPE_SERIAL; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; Device[deviceCount].FormulaOption = true; Device[deviceCount].ValueCount = 3; Device[deviceCount].SendDataOption = true; Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; Device[deviceCount].PluginStats = true; Device[deviceCount].ExitTaskBeforeSave = false; break; @@ -160,15 +157,15 @@ boolean Plugin_049(uint8_t function, struct EventStruct *event, String& string) if (nullptr == P049_data) { return success; } - bool expectReset = false; - unsigned int ppm = 0; - signed int temp = 0; - unsigned int s = 0; - float u = 0; + bool expectReset = false; + unsigned int ppm = 0; + signed int temp = 0; + unsigned int s = 0; + float u = 0; + const bool mustLog = loglevelActiveFor(LOG_LEVEL_INFO); if (P049_data->read_ppm(ppm, temp, s, u)) { - const bool mustLog = loglevelActiveFor(LOG_LEVEL_INFO); - String log; + String log; if (mustLog) { log = F("MHZ19: "); @@ -247,7 +244,7 @@ boolean Plugin_049(uint8_t function, struct EventStruct *event, String& string) // log verbosely anything else that the sensor reports } else { - if (loglevelActiveFor(LOG_LEVEL_INFO)) { + if (mustLog) { addLog(LOG_LEVEL_INFO, concat(F("MHZ19: Unknown response:"), P049_data->getBufferHexDump())); } diff --git a/src/_P050_TCS34725.ino b/src/_P050_TCS34725.ino index 972dcb5960..0b0829f9a5 100644 --- a/src/_P050_TCS34725.ino +++ b/src/_P050_TCS34725.ino @@ -1,507 +1,527 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P050 - -// ####################################################################################################### -// #################### Plugin 050 I2C TCS34725 RGB Color Sensor with IR filter and White LED ############ -// ####################################################################################################### -// -// RGB Color Sensor with IR filter and White LED -// like this one: https://www.adafruit.com/products/1334 -// based on this library: https://github.com/adafruit/Adafruit_TCS34725 -// this code is based on 20170331 date version of the above library -// this code is UNTESTED, because my TCS34725 sensor is still not shipped :( -// -// 2021-01-20 tonhuisman: Renamed Calibration to Transformation, fix some textual issues -// 2021-01-20 tonhuisman: Added optional events for not selected RGB outputs, compile-time optional -// 2021-01-19 tonhuisman: (Re)Added additional transformation & calculation options -// 2021-01-16 tonhuisman: Move stuff to PluginStructs, add 3x3 matrix calibration -// 2021-01-09 tonhuisman: Add R/G/B calibration factors, improved/corrected normalization -// 2021-01-03 tonhuisman: Merged most of the changes in the library, for adding the getRGB() and calculateColorTemperature_dn40(0 functions) -// - -# include "src/PluginStructs/P050_data_struct.h" - - -# define PLUGIN_050 -# define PLUGIN_ID_050 50 -# define PLUGIN_NAME_050 "Color - TCS34725" -# define PLUGIN_VALUENAME1_050 "Red" -# define PLUGIN_VALUENAME2_050 "Green" -# define PLUGIN_VALUENAME3_050 "Blue" -# define PLUGIN_VALUENAME4_050 "ColorTemperature" - -// #ifndef LIMIT_BUILD_SIZE -# define P050_OPTION_RGB_EVENTS - -// #endif - -boolean Plugin_050(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_050; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_050); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_050)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_050)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_050)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[3], PSTR(PLUGIN_VALUENAME4_050)); - break; - } - - case PLUGIN_SET_DEFAULTS: - { - PCONFIG(2) = 1; // RGB values: Calibrated RGB - PCONFIG(3) = 1; // Value #4: Color Temperature (DN40) - - # if FEATURE_I2C_DEVICE_CHECK - - if (!I2C_deviceCheck(0x29)) { - break; // Will return the default false for success - } - # endif // if FEATURE_I2C_DEVICE_CHECK - P050_data_struct *P050_data = new (std::nothrow) P050_data_struct(PCONFIG(0), PCONFIG(1)); - - if (nullptr != P050_data) { - P050_data->resetTransformation(); // Explicit reset - P050_data->saveSettings(event->TaskIndex); - delete P050_data; - } - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - { - success = (event->Par1 == 0x29); - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = 0x29; - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_WEBFORM_LOAD: - { - { - const __FlashStringHelper *optionsMode[] = { - F("2.4 ms"), - F("24 ms"), - F("50 ms"), - F("101 ms"), - F("154 ms"), - F("700 ms"), - }; - const int optionValuesMode[] = { - TCS34725_INTEGRATIONTIME_2_4MS, - TCS34725_INTEGRATIONTIME_24MS, - TCS34725_INTEGRATIONTIME_50MS, - TCS34725_INTEGRATIONTIME_101MS, - TCS34725_INTEGRATIONTIME_154MS, - TCS34725_INTEGRATIONTIME_700MS, - }; - addFormSelector(F("Integration Time"), F("inttime"), 6, optionsMode, optionValuesMode, PCONFIG(0)); - } - - { - const __FlashStringHelper *optionsMode2[] = { - F("1x"), - F("4x"), - F("16x"), - F("60x"), - }; - const int optionValuesMode2[] = { - TCS34725_GAIN_1X, - TCS34725_GAIN_4X, - TCS34725_GAIN_16X, - TCS34725_GAIN_60X, - }; - addFormSelector(F("Gain"), F("gain"), 4, optionsMode2, optionValuesMode2, PCONFIG(1)); - } - - addFormSubHeader(F("Output settings")); - - { - # define P050_RGB_OPTIONS 6 - const __FlashStringHelper *optionsRGB[P050_RGB_OPTIONS] = { - F("Raw RGB"), - F("Raw RGB transformed (3x3 matrix, below)"), - F("Normalized RGB (0..255)"), - F("Normalized RGB transformed (3x3 matrix, below)"), - F("Normalized RGB (0.0000..1.0000)"), - F("Normalized RGB (0.0000..1.0000) transformed (3x3 matrix, below)"), - }; - const int optionValuesRGB[P050_RGB_OPTIONS] = { 0, 1, 2, 3, 4, 5 }; - addFormSelector(F("Output RGB Values"), F("outputrgb"), P050_RGB_OPTIONS, optionsRGB, optionValuesRGB, PCONFIG(2)); - addFormNote(F("For 'normalized' or 'transformed' options, the Red/Green/Blue Decimals should best be increased.")); - -# ifdef P050_OPTION_RGB_EVENTS - addFormCheckBox(F("Generate RGB events"), F("rgbevents"), PCONFIG(5) == 1); - addFormNote(F("Eventnames: taskname + #RawRGB, #RawRGBtransformed, #NormRGB, #NormRGBtransformed, #NormSRGB, #NormSRGBtransformed")); - addFormNote(F("Only generated for not selected outputs, 3 values per event, =<r>,<g>,<b>")); -# endif // ifdef P050_OPTION_RGB_EVENTS - } - - { - # define P050_VALUE4_OPTIONS 4 - const __FlashStringHelper *optionsOutput[P050_VALUE4_OPTIONS] = { - F("Color Temperature (deprecated) [K]"), - F("Color Temperature (DN40) [K]"), - F("Ambient Light [Lux]"), - F("Clear Channel"), - }; - const int optionValuesOutput[P050_VALUE4_OPTIONS] = { 0, 1, 2, 3 }; - addFormSelector(F("Output at Values #4"), F("output4"), P050_VALUE4_OPTIONS, optionsOutput, optionValuesOutput, PCONFIG(3)); - addFormNote(F("Optionally adjust Values #4 name accordingly.")); - - addFormCheckBox(F("Generate all as events"), F("allevents"), PCONFIG(4) == 1); - addFormNote(F("Eventnames: taskname + #CCT, #CCT_DN40, #Lux, #Clear")); - } - - { - P050_data_struct *P050_data = new (std::nothrow) P050_data_struct(PCONFIG(0), PCONFIG(1)); - - if (nullptr != P050_data) { - addFormSubHeader(F("Transformation matrix")); - - P050_data->resetTransformation(); - P050_data->loadSettings(event->TaskIndex); - - // Display current settings - const String RGB = F("RGB"); - - for (int i = 0; i < 3; ++i) { - addRowLabel(RGB.substring(i, i + 1)); - for (int j = 0; j < 3; ++j) { - addHtml(strformat(F("%c%d:"), static_cast('a' + i), j + 1)); - addFloatNumberBox(P050_data_struct::generate_cal_id(i, j), - P050_data->TransformationSettings.matrix[i][j], - -255.999f, - 255.999f); - } - } - addFormNote(F("Check plugin documentation (i) on how to calibrate and how to calculate transformation matrix.")); - - addFormCheckBox(F("Reset transformation matrix"), F("resettrans"), false); - addFormNote(F("Select then Submit to confirm. Reset transformation matrix can't be un-done!")); - - // Need to delete the allocated object here - delete P050_data; - } - } - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(0) = getFormItemInt(F("inttime")); - PCONFIG(1) = getFormItemInt(F("gain")); - PCONFIG(2) = getFormItemInt(F("outputrgb")); - PCONFIG(3) = getFormItemInt(F("output4")); - PCONFIG(4) = isFormItemChecked(F("allevents")) ? 1 : 0; -# ifdef P050_OPTION_RGB_EVENTS - PCONFIG(5) = isFormItemChecked(F("rgbevents")) ? 1 : 0; -# endif // ifdef P050_OPTION_RGB_EVENTS - bool resetTransformation = isFormItemChecked(F("resettrans")); - { - P050_data_struct *P050_data = new (std::nothrow) P050_data_struct(PCONFIG(0), PCONFIG(1)); - - if (nullptr != P050_data) { - P050_data->resetTransformation(); - P050_data->loadSettings(event->TaskIndex); - - if (resetTransformation) { - // Clear Transformation settings - P050_data->resetTransformation(); - } else { - // Save new settings - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - P050_data->TransformationSettings.matrix[i][j] = - getFormItemFloat(P050_data_struct::generate_cal_id(i, j)); - } - } - } - P050_data->saveSettings(event->TaskIndex); - - // Need to delete the allocated object here - delete P050_data; - } - } - success = true; - break; - } - - case PLUGIN_INIT: - { - /* Initialise with specific int time and gain values */ - initPluginTaskData(event->TaskIndex, new (std::nothrow) P050_data_struct(PCONFIG(0), PCONFIG(1))); - P050_data_struct *P050_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P050_data) { - P050_data->resetTransformation(); - success = true; - } - break; - } - - case PLUGIN_READ: - { - P050_data_struct *P050_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P050_data) { - return success; - } - - if (P050_data->tcs.begin()) { -# ifndef BUILD_NO_DEBUG - addLog(LOG_LEVEL_DEBUG, F("Found TCS34725 sensor")); -# endif // ifndef BUILD_NO_DEBUG - - uint16_t r, g, b, c; - float value4 = 0.0f; - - P050_data->loadSettings(event->TaskIndex); - - P050_data->tcs.getRawData(&r, &g, &b, &c, true); - - switch (PCONFIG(3)) { - case 0: - value4 = P050_data->tcs.calculateColorTemperature(r, g, b); // Deprecated because of deemed inaccurate calculation, kept for - // backward compatibility - break; - case 1: - value4 = P050_data->tcs.calculateColorTemperature_dn40(r, g, b, c); - break; - case 2: - value4 = P050_data->tcs.calculateLux(r, g, b); - break; - case 3: - value4 = c; - break; - } - - float sRGBFactor = 1.0f; // (s)RGB factor 1.0 or 255.0 - uint32_t t = r + g + b; // Normalization factor - - if (t == 0) { - UserVar.setFloat(event->TaskIndex, 0, 0.0f); - UserVar.setFloat(event->TaskIndex, 1, 0.0f); - UserVar.setFloat(event->TaskIndex, 2, 0.0f); - } - - switch (PCONFIG(2)) { - case 0: - UserVar.setFloat(event->TaskIndex, 0, r); - UserVar.setFloat(event->TaskIndex, 1, g); - UserVar.setFloat(event->TaskIndex, 2, b); - break; - case 1: - - if (t != 0) { // R/G/B transformed - float r_f, g_f, b_f{}; - P050_data->applyTransformation( - r, g, b, - &r_f, &g_f, &b_f); - UserVar.setFloat(event->TaskIndex, 0, r_f); - UserVar.setFloat(event->TaskIndex, 1, g_f); - UserVar.setFloat(event->TaskIndex, 2, b_f); - - } - break; - case 2: - sRGBFactor = 255.0f; - - // Fall through - case 4: - - if (t != 0) { // r/g/b (normalized to 0.00..255.00 (but avoid divide by 0) - UserVar.setFloat(event->TaskIndex, 0, static_cast(r) / t * sRGBFactor); - UserVar.setFloat(event->TaskIndex, 1, static_cast(g) / t * sRGBFactor); - UserVar.setFloat(event->TaskIndex, 2, static_cast(b) / t * sRGBFactor); - } - break; - case 3: - sRGBFactor = 255.0f; - - // Fall through - case 5: - - if (t != 0) { // R/G/B normalized & transformed - const float nr = static_cast(r) / t * sRGBFactor; - const float ng = static_cast(g) / t * sRGBFactor; - const float nb = static_cast(b) / t * sRGBFactor; - - float r_f, g_f, b_f{}; - P050_data->applyTransformation( - nr, ng, nb, - &r_f, &g_f, &b_f); - UserVar.setFloat(event->TaskIndex, 0, r_f); - UserVar.setFloat(event->TaskIndex, 1, g_f); - UserVar.setFloat(event->TaskIndex, 2, b_f); - } - break; - } - UserVar.setFloat(event->TaskIndex, 3, value4); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("TCS34725: "); - - switch (PCONFIG(3)) { - case 0: - case 1: - log += F("Color Temp (K): "); - break; - case 2: - log += F("Lux : "); - break; - case 3: - log += F("Clear : "); - break; - } - log += strformat( - F(" %s R: %s G: %s B: %s "), - formatUserVarNoCheck(event, 3).c_str(), - formatUserVarNoCheck(event, 0).c_str(), - formatUserVarNoCheck(event, 1).c_str(), - formatUserVarNoCheck(event, 2).c_str()); - addLogMove(LOG_LEVEL_INFO, log); - } - -# ifdef P050_OPTION_RGB_EVENTS - - // First RGB events - if ((PCONFIG(5) == 1) && (t != 0)) { // Not if invalid read/data - float tr, tg, tb, nr, ng, nb; - - for (int i = 0; i < 6; ++i) { - if (i != PCONFIG(2)) { // Skip currently selected RGB output to keep nr. of events a bit limited - const __FlashStringHelper* varName = F(""); - String eventValues; - sRGBFactor = 1.0f; - - switch (i) { - case 0: - varName = F("RawRGB"); - eventValues += strformat(F("%u,%u,%u"), r, g, b); - break; - case 3: - sRGBFactor = 255.0f; - - // Fall through - case 1: - case 5: - - if (i == 1) { - varName = F("RawRGBtransformed"); - P050_data->applyTransformation(r, g, b, &tr, &tg, &tb); - } else { - if (i == 3) { - varName = F("NormRGBtransformed"); - } else { - varName = F("NormSRGBtransformed"); - } - nr = static_cast(r) / t * sRGBFactor; - ng = static_cast(g) / t * sRGBFactor; - nb = static_cast(b) / t * sRGBFactor; - P050_data->applyTransformation(nr, ng, nb, &tr, &tg, &tb); - } - - eventValues += strformat(F("%.4f,%.4f,%.4f"), tr, tg, tb); - break; - case 2: - sRGBFactor = 255.0f; - - // Fall through - case 4: - - if (i == 2) { - varName = F("NormRGB"); - } else { - varName = F("NormSRGB"); - } - eventValues += strformat( - F("%.4f,%.4f,%.4f"), - static_cast(r) / t * sRGBFactor, - static_cast(g) / t * sRGBFactor, - static_cast(b) / t * sRGBFactor); - break; - default: - eventValues.clear(); - break; - } - - if (!eventValues.isEmpty()) { - eventQueue.add(event->TaskIndex, varName, eventValues); - } - } - } - } -# endif // ifdef P050_OPTION_RGB_EVENTS - - // Then Values #4 events - if (PCONFIG(4) == 1) { - for (int i = 0; i < 4; ++i) { - switch (i) { - case 0: - eventQueue.add(event->TaskIndex, F("CCT"), P050_data->tcs.calculateColorTemperature(r, g, b)); - break; - case 1: - eventQueue.add(event->TaskIndex, F("CCT_DN40"), P050_data->tcs.calculateColorTemperature_dn40(r, g, b, c)); - break; - case 2: - eventQueue.add(event->TaskIndex, F("Lux"), P050_data->tcs.calculateLux(r, g, b)); - break; - case 3: - eventQueue.add(event->TaskIndex, F("Clear"), String(c)); - break; - default: - break; - } - } - } - - success = true; - } else { -# ifndef BUILD_NO_DEBUG - addLog(LOG_LEVEL_DEBUG, F("No TCS34725 found")); -# endif // ifndef BUILD_NO_DEBUG - success = false; - } - - break; - } - } - return success; -} - -#endif // USES_P050 +#include "_Plugin_Helper.h" +#ifdef USES_P050 + +// ####################################################################################################### +// #################### Plugin 050 I2C TCS34725 RGB Color Sensor with IR filter and White LED ############ +// ####################################################################################################### +// +// RGB Color Sensor with IR filter and White LED +// like this one: https://www.adafruit.com/products/1334 +// based on this library: https://github.com/adafruit/Adafruit_TCS34725 +// this code is based on 20170331 date version of the above library +// this code is UNTESTED, because my TCS34725 sensor is still not shipped :( +// + +/** Changelog + * 2025-01-03 tonhuisman: Small code cleanup and reformatting + * 2021-01-20 tonhuisman: Renamed Calibration to Transformation, fix some textual issues + * 2021-01-20 tonhuisman: Added optional events for not selected RGB outputs, compile-time optional + * 2021-01-19 tonhuisman: (Re)Added additional transformation & calculation options + * 2021-01-16 tonhuisman: Move stuff to PluginStructs, add 3x3 matrix calibration + * 2021-01-09 tonhuisman: Add R/G/B calibration factors, improved/corrected normalization + * 2021-01-03 tonhuisman: Merged most of the changes in the library, for adding the getRGB() and calculateColorTemperature_dn40(0 functions) + * + */ + +# include "src/PluginStructs/P050_data_struct.h" + + +# define PLUGIN_050 +# define PLUGIN_ID_050 50 +# define PLUGIN_NAME_050 "Color - TCS34725" +# define PLUGIN_VALUENAME1_050 "Red" +# define PLUGIN_VALUENAME2_050 "Green" +# define PLUGIN_VALUENAME3_050 "Blue" +# define PLUGIN_VALUENAME4_050 "ColorTemperature" + +// #ifndef LIMIT_BUILD_SIZE +# define P050_OPTION_RGB_EVENTS + +// #endif + +boolean Plugin_050(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_050; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_050); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_050)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_050)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_050)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[3], PSTR(PLUGIN_VALUENAME4_050)); + break; + } + + case PLUGIN_SET_DEFAULTS: + { + PCONFIG(2) = 1; // RGB values: Calibrated RGB + PCONFIG(3) = 1; // Value #4: Color Temperature (DN40) + + # if FEATURE_I2C_DEVICE_CHECK + + if (!I2C_deviceCheck(0x29)) { + break; // Will return the default false for success + } + # endif // if FEATURE_I2C_DEVICE_CHECK + P050_data_struct *P050_data = new (std::nothrow) P050_data_struct(PCONFIG(0), PCONFIG(1)); + + if (nullptr != P050_data) { + P050_data->resetTransformation(); // Explicit reset + P050_data->saveSettings(event->TaskIndex); + delete P050_data; + } + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + { + success = (event->Par1 == 0x29); + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = 0x29; + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_WEBFORM_LOAD: + { + { + const __FlashStringHelper *optionsMode[] = { + F("2.4 ms"), + F("24 ms"), + F("50 ms"), + F("101 ms"), + F("154 ms"), + F("700 ms"), + }; + const int optionValuesMode[] = { + TCS34725_INTEGRATIONTIME_2_4MS, + TCS34725_INTEGRATIONTIME_24MS, + TCS34725_INTEGRATIONTIME_50MS, + TCS34725_INTEGRATIONTIME_101MS, + TCS34725_INTEGRATIONTIME_154MS, + TCS34725_INTEGRATIONTIME_700MS, + }; + addFormSelector(F("Integration Time"), F("inttime"), 6, optionsMode, optionValuesMode, PCONFIG(0)); + } + + { + const __FlashStringHelper *optionsMode2[] = { + F("1x"), + F("4x"), + F("16x"), + F("60x"), + }; + const int optionValuesMode2[] = { + TCS34725_GAIN_1X, + TCS34725_GAIN_4X, + TCS34725_GAIN_16X, + TCS34725_GAIN_60X, + }; + addFormSelector(F("Gain"), F("gain"), 4, optionsMode2, optionValuesMode2, PCONFIG(1)); + } + + addFormSubHeader(F("Output settings")); + + { + // # define P050_RGB_OPTIONS 6 + const __FlashStringHelper *optionsRGB[] = { + F("Raw RGB"), + F("Raw RGB transformed (3x3 matrix, below)"), + F("Normalized RGB (0..255)"), + F("Normalized RGB transformed (3x3 matrix, below)"), + F("Normalized RGB (0.0000..1.0000)"), + F("Normalized RGB (0.0000..1.0000) transformed (3x3 matrix, below)"), + }; + + // const int optionValuesRGB[P050_RGB_OPTIONS] = { 0, 1, 2, 3, 4, 5 }; + constexpr size_t valueCount = NR_ELEMENTS(optionsRGB); + addFormSelector(F("Output RGB Values"), F("outputrgb"), valueCount, optionsRGB, nullptr, PCONFIG(2)); + # ifndef LIMIT_BUILD_SIZE + addFormNote(F("For 'normalized' or 'transformed' options, the Red/Green/Blue Decimals should best be increased.")); + # endif // ifndef LIMIT_BUILD_SIZE + + # ifdef P050_OPTION_RGB_EVENTS + addFormCheckBox(F("Generate RGB events"), F("rgbevents"), PCONFIG(5) == 1); + addFormNote(F("Eventnames: taskname + #RawRGB, #RawRGBtransformed, #NormRGB, #NormRGBtransformed, #NormSRGB, #NormSRGBtransformed")); + addFormNote(F( + # ifndef LIMIT_BUILD_SIZE + "Only generated for not selected outputs, " + # endif // ifndef LIMIT_BUILD_SIZE + "3 values per event, =<r>,<g>,<b>")); + # endif // ifdef P050_OPTION_RGB_EVENTS + } + + { + // # define P050_VALUE4_OPTIONS 4 + const __FlashStringHelper *optionsOutput[] = { + F("Color Temperature (deprecated) [K]"), + F("Color Temperature (DN40) [K]"), + F("Ambient Light [Lux]"), + F("Clear Channel"), + }; + + // const int optionValuesOutput[P050_VALUE4_OPTIONS] = { 0, 1, 2, 3 }; + constexpr size_t valueCount = NR_ELEMENTS(optionsOutput); + addFormSelector(F("Output at Values #4"), F("output4"), valueCount, optionsOutput, nullptr, PCONFIG(3)); + # ifndef LIMIT_BUILD_SIZE + addFormNote(F("Optionally adjust Values #4 name accordingly.")); + # endif // ifndef LIMIT_BUILD_SIZE + + addFormCheckBox(F("Generate all as events"), F("allevents"), PCONFIG(4) == 1); + addFormNote(F("Eventnames: taskname + #CCT, #CCT_DN40, #Lux, #Clear")); + } + + { + P050_data_struct *P050_data = new (std::nothrow) P050_data_struct(PCONFIG(0), PCONFIG(1)); + + if (nullptr != P050_data) { + addFormSubHeader(F("Transformation matrix")); + + P050_data->resetTransformation(); + P050_data->loadSettings(event->TaskIndex); + + // Display current settings + const String RGB = F("RGB"); + + for (int i = 0; i < 3; ++i) { + addRowLabel(RGB.substring(i, i + 1)); + + for (int j = 0; j < 3; ++j) { + addHtml(strformat(F("%c%d:"), static_cast('a' + i), j + 1)); + addFloatNumberBox(P050_data_struct::generate_cal_id(i, j), + P050_data->TransformationSettings.matrix[i][j], + -255.999f, + 255.999f); + } + } + addFormNote(F("Check plugin documentation (i)" + # ifndef LIMIT_BUILD_SIZE + " on how to calibrate and how to calculate transformation matrix" + # endif // ifndef LIMIT_BUILD_SIZE + "." + )); + + addFormCheckBox(F("Reset transformation matrix"), F("resettrans"), false); + addFormNote(F( + # ifndef LIMIT_BUILD_SIZE + "Select then Submit to confirm. " + # endif // ifndef LIMIT_BUILD_SIZE + "Reset transformation matrix can't be un-done!")); + + // Need to delete the allocated object here + delete P050_data; + } + } + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(0) = getFormItemInt(F("inttime")); + PCONFIG(1) = getFormItemInt(F("gain")); + PCONFIG(2) = getFormItemInt(F("outputrgb")); + PCONFIG(3) = getFormItemInt(F("output4")); + PCONFIG(4) = isFormItemChecked(F("allevents")) ? 1 : 0; + # ifdef P050_OPTION_RGB_EVENTS + PCONFIG(5) = isFormItemChecked(F("rgbevents")) ? 1 : 0; + # endif // ifdef P050_OPTION_RGB_EVENTS + bool resetTransformation = isFormItemChecked(F("resettrans")); + { + P050_data_struct *P050_data = new (std::nothrow) P050_data_struct(PCONFIG(0), PCONFIG(1)); + + if (nullptr != P050_data) { + P050_data->resetTransformation(); + P050_data->loadSettings(event->TaskIndex); + + if (resetTransformation) { + // Clear Transformation settings + P050_data->resetTransformation(); + } else { + // Save new settings + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + P050_data->TransformationSettings.matrix[i][j] = + getFormItemFloat(P050_data_struct::generate_cal_id(i, j)); + } + } + } + P050_data->saveSettings(event->TaskIndex); + + // Need to delete the allocated object here + delete P050_data; + } + } + success = true; + break; + } + + case PLUGIN_INIT: + { + /* Initialise with specific int time and gain values */ + initPluginTaskData(event->TaskIndex, new (std::nothrow) P050_data_struct(PCONFIG(0), PCONFIG(1))); + P050_data_struct *P050_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P050_data) { + P050_data->resetTransformation(); + P050_data->loadSettings(event->TaskIndex); // Loading once should be enough + success = true; + } + break; + } + + case PLUGIN_READ: + { + P050_data_struct *P050_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P050_data) { + return success; + } + + if (P050_data->tcs.begin()) { +# ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG, F("Found TCS34725 sensor")); +# endif // ifndef BUILD_NO_DEBUG + + uint16_t r, g, b, c; + float value4 = 0.0f; + + P050_data->tcs.getRawData(&r, &g, &b, &c, true); + + switch (PCONFIG(3)) { + case 0: + value4 = P050_data->tcs.calculateColorTemperature(r, g, b); // Deprecated because of deemed inaccurate calculation, kept for + // backward compatibility + break; + case 1: + value4 = P050_data->tcs.calculateColorTemperature_dn40(r, g, b, c); + break; + case 2: + value4 = P050_data->tcs.calculateLux(r, g, b); + break; + case 3: + value4 = c; + break; + } + + float sRGBFactor = 1.0f; // (s)RGB factor 1.0 or 255.0 + uint32_t t = r + g + b; // Normalization factor + + if (t == 0) { + UserVar.setFloat(event->TaskIndex, 0, 0.0f); + UserVar.setFloat(event->TaskIndex, 1, 0.0f); + UserVar.setFloat(event->TaskIndex, 2, 0.0f); + } + + switch (PCONFIG(2)) { + case 0: + UserVar.setFloat(event->TaskIndex, 0, r); + UserVar.setFloat(event->TaskIndex, 1, g); + UserVar.setFloat(event->TaskIndex, 2, b); + break; + case 1: + + if (t != 0) { // R/G/B transformed + float r_f, g_f, b_f{}; + P050_data->applyTransformation( + r, g, b, + &r_f, &g_f, &b_f); + UserVar.setFloat(event->TaskIndex, 0, r_f); + UserVar.setFloat(event->TaskIndex, 1, g_f); + UserVar.setFloat(event->TaskIndex, 2, b_f); + } + break; + case 2: + sRGBFactor = 255.0f; + + // Fall through + case 4: + + if (t != 0) { // r/g/b (normalized to 0.00..255.00 (but avoid divide by 0) + UserVar.setFloat(event->TaskIndex, 0, static_cast(r) / t * sRGBFactor); + UserVar.setFloat(event->TaskIndex, 1, static_cast(g) / t * sRGBFactor); + UserVar.setFloat(event->TaskIndex, 2, static_cast(b) / t * sRGBFactor); + } + break; + case 3: + sRGBFactor = 255.0f; + + // Fall through + case 5: + + if (t != 0) { // R/G/B normalized & transformed + const float nr = static_cast(r) / t * sRGBFactor; + const float ng = static_cast(g) / t * sRGBFactor; + const float nb = static_cast(b) / t * sRGBFactor; + + float r_f, g_f, b_f{}; + P050_data->applyTransformation( + nr, ng, nb, + &r_f, &g_f, &b_f); + UserVar.setFloat(event->TaskIndex, 0, r_f); + UserVar.setFloat(event->TaskIndex, 1, g_f); + UserVar.setFloat(event->TaskIndex, 2, b_f); + } + break; + } + UserVar.setFloat(event->TaskIndex, 3, value4); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("TCS34725: "); + + switch (PCONFIG(3)) { + case 0: + case 1: + log += F("Color Temp (K): "); + break; + case 2: + log += F("Lux : "); + break; + case 3: + log += F("Clear : "); + break; + } + log += strformat( + F(" %s R: %s G: %s B: %s "), + formatUserVarNoCheck(event, 3).c_str(), + formatUserVarNoCheck(event, 0).c_str(), + formatUserVarNoCheck(event, 1).c_str(), + formatUserVarNoCheck(event, 2).c_str()); + addLogMove(LOG_LEVEL_INFO, log); + } + + # ifdef P050_OPTION_RGB_EVENTS + + // First RGB events + if ((PCONFIG(5) == 1) && (t != 0)) { // Not if invalid read/data + float tr, tg, tb, nr, ng, nb; + + for (int i = 0; i < 6; ++i) { + if (i != PCONFIG(2)) { // Skip currently selected RGB output to keep nr. of events a bit limited + const __FlashStringHelper*varName = F(""); + String eventValues; + sRGBFactor = 1.0f; + + switch (i) { + case 0: + varName = F("RawRGB"); + eventValues += strformat(F("%u,%u,%u"), r, g, b); + break; + case 3: + sRGBFactor = 255.0f; + + // Fall through + case 1: + case 5: + + if (i == 1) { + varName = F("RawRGBtransformed"); + P050_data->applyTransformation(r, g, b, &tr, &tg, &tb); + } else { + if (i == 3) { + varName = F("NormRGBtransformed"); + } else { + varName = F("NormSRGBtransformed"); + } + nr = static_cast(r) / t * sRGBFactor; + ng = static_cast(g) / t * sRGBFactor; + nb = static_cast(b) / t * sRGBFactor; + P050_data->applyTransformation(nr, ng, nb, &tr, &tg, &tb); + } + + eventValues += strformat(F("%.4f,%.4f,%.4f"), tr, tg, tb); + break; + case 2: + sRGBFactor = 255.0f; + + // Fall through + case 4: + + if (i == 2) { + varName = F("NormRGB"); + } else { + varName = F("NormSRGB"); + } + eventValues += strformat( + F("%.4f,%.4f,%.4f"), + static_cast(r) / t * sRGBFactor, + static_cast(g) / t * sRGBFactor, + static_cast(b) / t * sRGBFactor); + break; + default: + eventValues.clear(); + break; + } + + if (!eventValues.isEmpty()) { + eventQueue.add(event->TaskIndex, varName, eventValues); + } + } + } + } + # endif // ifdef P050_OPTION_RGB_EVENTS + + // Then Values #4 events + if (PCONFIG(4) == 1) { + for (int i = 0; i < 4; ++i) { + switch (i) { + case 0: + eventQueue.add(event->TaskIndex, F("CCT"), P050_data->tcs.calculateColorTemperature(r, g, b)); + break; + case 1: + eventQueue.add(event->TaskIndex, F("CCT_DN40"), P050_data->tcs.calculateColorTemperature_dn40(r, g, b, c)); + break; + case 2: + eventQueue.add(event->TaskIndex, F("Lux"), P050_data->tcs.calculateLux(r, g, b)); + break; + case 3: + eventQueue.add(event->TaskIndex, F("Clear"), String(c)); + break; + default: + break; + } + } + } + + success = true; + } else { + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG, F("No TCS34725 found")); + # endif // ifndef BUILD_NO_DEBUG + success = false; + } + + break; + } + } + return success; +} + +#endif // USES_P050 diff --git a/src/_P051_AM2320.ino b/src/_P051_AM2320.ino index c9ef5ca6c7..1d50c60c9b 100644 --- a/src/_P051_AM2320.ino +++ b/src/_P051_AM2320.ino @@ -1,119 +1,115 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P051 - -// ####################################################################################################### -// #################### Plugin 051 Temperature and Humidity Sensor AM2320 ############## -// ####################################################################################################### -// -// Temperature and Humidity Sensor AM2320 -// written by https://github.com/krikk -// based on this library: https://github.com/thakshak/AM2320 -// this code is based on git-version https://github.com/thakshak/AM2320/commit/ddaabaf37952d4c74f3ea70af20e5a95cfdfcadb -// of the above library -// - -/** Changelog: - * 2023-09-05 tonhuisman: Disable I2C device-check during read, as the sensor seems a bit 'itchy' about that - * 2023-09-05 tonhuisman: Add changelog - */ - - -# include - -# define PLUGIN_051 -# define PLUGIN_ID_051 51 -# define PLUGIN_NAME_051 "Environment - AM2320" -# define PLUGIN_VALUENAME1_051 "Temperature" -# define PLUGIN_VALUENAME2_051 "Humidity" - - -boolean Plugin_051(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_051; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CNoDeviceCheck = true; // Avoid device check - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_051); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_051)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_051)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - { - success = (event->Par1 == 0x5c); - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = 0x5c; - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_WEBFORM_LOAD: - case PLUGIN_WEBFORM_SAVE: - case PLUGIN_INIT: - { - success = true; - break; - } - - case PLUGIN_READ: - { - AM2320 th; - - switch (th.Read()) { - case 2: - addLog(LOG_LEVEL_ERROR, F("AM2320: CRC failed")); - break; - case 1: - addLog(LOG_LEVEL_ERROR, F("AM2320: Sensor offline")); - break; - case 0: - { - UserVar.setFloat(event->TaskIndex, 0, th.t); - UserVar.setFloat(event->TaskIndex, 1, th.h); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, concat(F("AM2320: Temperature: "), formatUserVarNoCheck(event, 0))); - addLogMove(LOG_LEVEL_INFO, concat(F("AM2320: Humidity: "), formatUserVarNoCheck(event, 1))); - } - success = true; - break; - } - } - } - } - return success; -} - -#endif // USES_P051 +#include "_Plugin_Helper.h" +#ifdef USES_P051 + +// ####################################################################################################### +// #################### Plugin 051 Temperature and Humidity Sensor AM2320 ############## +// ####################################################################################################### +// +// Temperature and Humidity Sensor AM2320 +// written by https://github.com/krikk +// based on this library: https://github.com/thakshak/AM2320 +// this code is based on git-version https://github.com/thakshak/AM2320/commit/ddaabaf37952d4c74f3ea70af20e5a95cfdfcadb +// of the above library +// + +/** Changelog: + * 2023-09-05 tonhuisman: Disable I2C device-check during read, as the sensor seems a bit 'itchy' about that + * 2023-09-05 tonhuisman: Add changelog + */ + + +# include + +# define PLUGIN_051 +# define PLUGIN_ID_051 51 +# define PLUGIN_NAME_051 "Environment - AM2320" +# define PLUGIN_VALUENAME1_051 "Temperature" +# define PLUGIN_VALUENAME2_051 "Humidity" + + +boolean Plugin_051(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_051; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].I2CNoDeviceCheck = true; // Avoid device check + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_051); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_051)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_051)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + { + success = (event->Par1 == 0x5c); + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = 0x5c; + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_WEBFORM_LOAD: + case PLUGIN_WEBFORM_SAVE: + case PLUGIN_INIT: + { + success = true; + break; + } + + case PLUGIN_READ: + { + AM2320 th; + + switch (th.Read()) { + case 2: + addLog(LOG_LEVEL_ERROR, F("AM2320: CRC failed")); + break; + case 1: + addLog(LOG_LEVEL_ERROR, F("AM2320: Sensor offline")); + break; + case 0: + { + UserVar.setFloat(event->TaskIndex, 0, th.t); + UserVar.setFloat(event->TaskIndex, 1, th.h); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, concat(F("AM2320: Temperature: "), formatUserVarNoCheck(event, 0))); + addLogMove(LOG_LEVEL_INFO, concat(F("AM2320: Humidity: "), formatUserVarNoCheck(event, 1))); + } + success = true; + break; + } + } + } + } + return success; +} + +#endif // USES_P051 diff --git a/src/_P052_SenseAir.ino b/src/_P052_SenseAir.ino index b210c6c2a6..7abfb07880 100644 --- a/src/_P052_SenseAir.ino +++ b/src/_P052_SenseAir.ino @@ -1,492 +1,486 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P052 - -# include "src/PluginStructs/P052_data_struct.h" - -// ####################################################################################################### -// ############################# Plugin 052: Senseair CO2 Sensors ######################################## -// ####################################################################################################### - -/* - Plugin originally written by: Daniel Tedenljung - info__AT__tedenljungconsulting.com - Rewritten by: Mikael Trieb mikael__AT__triebconsulting.se - - This plugin reads available values of Senseair Co2 Sensors. - Datasheet can be found here: - S8: http://www.senseair.com/products/oem-modules/senseair-s8/ - K30: http://www.senseair.com/products/oem-modules/k30/ - K70/tSENSE: http://www.senseair.com/products/wall-mount/tsense/ - - Circuit wiring - GPIO Setting 1 -> RX - GPIO Setting 2 -> TX - Use 1kOhm in serie on datapins! - */ - -# define PLUGIN_052 -# define PLUGIN_ID_052 52 -# define PLUGIN_NAME_052 "Gases - CO2 Senseair" - - -boolean Plugin_052(uint8_t function, struct EventStruct *event, String& string) { - boolean success = false; - - switch (function) { - case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_052; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].ExitTaskBeforeSave = false; - Device[deviceCount].PluginStats = true; - break; - } - - case PLUGIN_GET_DEVICENAME: { - string = F(PLUGIN_NAME_052); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: { - for (uint8_t i = 0; i < VARS_PER_TASK; ++i) { - if (i < P052_NR_OUTPUT_VALUES) { - const uint8_t pconfigIndex = i + P052_QUERY1_CONFIG_POS; - uint8_t choice = PCONFIG(pconfigIndex); - ExtraTaskSettings.setTaskDeviceValueName(i, P052_data_struct::Plugin_052_valuename(choice, false)); - } else { - ExtraTaskSettings.clearTaskDeviceValueName(i); - } - } - break; - } - - case PLUGIN_GET_DEVICEVALUECOUNT: - { - event->Par1 = P052_NR_OUTPUT_VALUES; - success = true; - break; - } - - case PLUGIN_GET_DEVICEVTYPE: - { - event->sensorType = static_cast(PCONFIG(P052_SENSOR_TYPE_INDEX)); - event->idx = P052_SENSOR_TYPE_INDEX; - success = true; - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: { - serialHelper_getGpioNames(event); - break; - } - - case PLUGIN_WEBFORM_SHOW_CONFIG: - { - string += serialHelper_getSerialTypeLabel(event); - success = true; - break; - } - - case PLUGIN_SET_DEFAULTS: - { - PCONFIG(P052_SENSOR_TYPE_INDEX) = static_cast(Sensor_VType::SENSOR_TYPE_SINGLE); - PCONFIG(0) = 1; // "CO2" - - for (uint8_t i = 1; i < VARS_PER_TASK; ++i) { - PCONFIG(i) = 0; // "Empty" - } - - success = true; - break; - } - - case PLUGIN_WEBFORM_LOAD_OUTPUT_SELECTOR: - { - const __FlashStringHelper *options[P052_NR_OUTPUT_OPTIONS]; - - for (uint8_t i = 0; i < P052_NR_OUTPUT_OPTIONS; ++i) { - options[i] = P052_data_struct::Plugin_052_valuename(i, true); - } - - for (uint8_t i = 0; i < P052_NR_OUTPUT_VALUES; ++i) { - const uint8_t pconfigIndex = i + P052_QUERY1_CONFIG_POS; - sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P052_NR_OUTPUT_OPTIONS, options); - } - break; - } - - case PLUGIN_WEBFORM_LOAD: { - P052_data_struct *P052_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if ((nullptr != P052_data) && P052_data->isInitialized()) { - addFormSubHeader(F("Device Information")); - { - int value = 0; - - if (P052_data->modbus.detected_device_description.length() > 0) { - addRowLabel(F("Detected Device")); - addHtml(P052_data->modbus.detected_device_description); - } - - if (P052_data->readInputRegister(P052_IR29_FW_REV, value)) { - addRowLabel(F("FW rev.")); - addHtmlInt(value); - } - - addRowLabel(F("Sensor ID")); - addHtml(formatToHex_decimal(P052_data->getSensorID())); - - - addRowLabel(F("Checksum (pass/fail/nodata)")); - { - uint32_t reads_pass, reads_crc_failed, reads_nodata; - P052_data->modbus.getStatistics(reads_pass, reads_crc_failed, reads_nodata); - String chksumStats; - chksumStats = reads_pass; - chksumStats += '/'; - chksumStats += reads_crc_failed; - chksumStats += '/'; - chksumStats += reads_nodata; - addHtml(chksumStats); - } - - bool hasFactorySettings = false; - bool enabledABC = false; - - if (P052_data->readHoldingRegister(P052_HR19_METER_CONTROL, value)) { - hasFactorySettings = value == 255; - enabledABC = bitRead(value, 1) == 0; - addRowLabel(F("Using Factory Settings")); - addEnabled(hasFactorySettings); - - if (!hasFactorySettings) { - // addRowLabel(F("HR19")); - // addHtmlInt(value); - addRowLabel(F("nRDY")); - addEnabled(bitRead(value, 0) == 0); - addRowLabel(F("ABC")); - addEnabled(enabledABC); - addRowLabel(F("Static IIR filter")); - addEnabled(bitRead(value, 2) == 0); - addRowLabel(F("Dynamic IIR filter")); - addEnabled(bitRead(value, 3) == 0); - addRowLabel(F("Pressure Compensation")); - addEnabled(bitRead(value, 4) == 0); - } - } - - if (P052_data->readInputRegister(P052_IR7_MEASUREMENT_COUNT, value)) { - addRowLabel(F("Measurement Count")); - addHtmlInt(value); - } - - if (P052_data->readInputRegister(P052_IR8_MEASUREMENT_CYCLE_TIME, value)) { - addRowLabel(F("Measurement Cycle time")); - addHtmlInt(value * 2); - addUnit('s'); - } - - if (P052_data->readInputRegister(P052_IR9_MEASURED_UNFILTERED_CO2, value)) { - addRowLabel(F("Unfiltered CO2")); - addHtmlInt(value); - } - - if (P052_data->readHoldingRegister(P052_HR11_MEASUREMENT_MODE, value)) { - addRowLabel(F("Measurement Mode")); - addHtml(value == 0 ? F("Continuous") : F("Single Measurement")); - } - - if (enabledABC) { - if (P052_data->readHoldingRegister(P052_HR14_ABC_PERIOD, value)) { - addRowLabel(F("ABC Period")); - addHtmlInt(value); - addUnit('h'); - } - - if (P052_data->readHoldingRegister(P052_HR5_ABC_TIME, value)) { - addRowLabel(F("Time Since ABC")); - addHtmlInt(value); - addUnit('h'); - } - } - } - - { - int value = 0; - - /* - if (P052_data->readHoldingRegister(P052_HR11_MEASUREMENT_MODE, value)) { - // Disable selector for now, since single measurement not yet supported. - - const __FlashStringHelper *options[2] = { F("Continuous"), F("Single Measurement") }; - addFormSelector(F("Measurement Mode"), F("mode"), 2, options, nullptr, value); - } - */ - - if (P052_data->readHoldingRegister(P052_HR12_MEASUREMENT_PERIOD, value)) { - addFormNumericBox(F("Measurement Period"), F("period"), value, 2, 65534); - addUnit('s'); - } - - if (P052_data->readHoldingRegister(P052_HR13_NR_OF_SAMPLES, value)) { - addFormNumericBox(F("Samples per measurement"), F("samp_meas"), value, 1, 1024); - } - } - { - // P052_ABC_PERIOD - } - } - - /* - // ABC functionality disabled for now, due to a bug in the firmware. - // See https://github.com/letscontrolit/ESPEasy/issues/759 - uint8_t choiceABCperiod = PCONFIG(4); - const __FlashStringHelper * optionsABCperiod[9] = { F("disable"), F("1 h"), F("12 h"), F("1 - day"), F("2 days"), F("4 days"), F("7 days"), F("14 days"), F("30 days") }; - addFormSelector(F("ABC period"), F("ABC_period"), 9, optionsABCperiod, - nullptr, choiceABCperiod); - */ - - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: { - // Save output selector parameters. - for (uint8_t i = 0; i < P052_NR_OUTPUT_VALUES; ++i) { - const uint8_t pconfigIndex = i + P052_QUERY1_CONFIG_POS; - const uint8_t choice = PCONFIG(pconfigIndex); - sensorTypeHelper_saveOutputSelector(event, pconfigIndex, i, P052_data_struct::Plugin_052_valuename(choice, false)); - } - - P052_data_struct *P052_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if ((nullptr != P052_data) && P052_data->isInitialized()) { - bool changed = false; - uint16_t mode = getFormItemInt(F("mode"), 65535); - - if (((mode == 0) || (mode == 1))) { - uint8_t errorcode; - int readVal = P052_data->modbus.readHoldingRegister(0x0A, errorcode); - - if ((errorcode == 0) && (readVal != mode)) { - P052_data->modbus.writeMultipleRegisters(0x0A, mode); - delay(0); - changed = true; - } - } - uint16_t period = getFormItemInt(F("period"), 0); - - if (period > 1) { - uint8_t errorcode; - int readVal = P052_data->modbus.readHoldingRegister(0x0B, errorcode); - - if ((errorcode == 0) && (readVal != period)) { - P052_data->modbus.writeMultipleRegisters(0x0B, period); - delay(0); - changed = true; - } - } - uint16_t samp_meas = getFormItemInt(F("samp_meas"), 0); - - if ((samp_meas > 0) && (samp_meas <= 1024)) { - uint8_t errorcode; - int readVal = P052_data->modbus.readHoldingRegister(0x0C, errorcode); - - if ((errorcode == 0) && (readVal != samp_meas)) { - P052_data->modbus.writeMultipleRegisters(0x0C, samp_meas); - delay(0); - changed = true; - } - } - - if (changed) { - // Restart sensor. - P052_data->modbus.writeMultipleRegisters(0x11, 0xFF); - - // FIXME TD-er: Must leave the sensor to boot for a while. - delay(35); - } - } - - - /* - // ABC functionality disabled for now, due to a bug in the firmware. - // See https://github.com/letscontrolit/ESPEasy/issues/759 - PCONFIG(4) = getFormItemInt(F("ABC_period")); - */ - - success = true; - break; - } - - case PLUGIN_INIT: { - const int16_t serial_rx = CONFIG_PIN1; - const int16_t serial_tx = CONFIG_PIN2; - const ESPEasySerialPort port = static_cast(CONFIG_PORT); - - initPluginTaskData(event->TaskIndex, new (std::nothrow) P052_data_struct()); - P052_data_struct *P052_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P052_data) { - return success; - } - - - if (P052_data->init(port, serial_rx, serial_tx)) { - /* - // ABC functionality disabled for now, due to a bug in the firmware. - // See https://github.com/letscontrolit/ESPEasy/issues/759 - const int periodInHours[9] = {0, 1, 12, (24*1), (24*2), (24*4), (24*7), - (24*14), (24*30) }; - uint8_t choiceABCperiod = PCONFIG(1); - - Plugin_052_setABCperiod(periodInHours[choiceABCperiod]); - */ - P052_data->modbus.setModbusTimeout(P052_MODBUS_TIMEOUT); - - // P052_data->modbus.writeMultipleRegisters(0x09, 1); // Start Single Measurement - // P052_data->modbus.writeMultipleRegisters(0x0B, 16); // Measurement Period - // P052_data->modbus.writeMultipleRegisters(0x0C, 8); // Number of samples - - success = true; - } else { - clearPluginTaskData(event->TaskIndex); - } - break; - } - - case PLUGIN_EXIT: { - success = true; - break; - } - - case PLUGIN_READ: { - P052_data_struct *P052_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if ((nullptr != P052_data) && P052_data->isInitialized()) { - event->sensorType = static_cast(PCONFIG(P052_SENSOR_TYPE_INDEX)); - String log = F("Senseair: "); - String logPrefix; - - for (int varnr = 0; varnr < P052_NR_OUTPUT_VALUES; ++varnr) { - uint8_t errorcode = 0; - float value = 0; - - switch (PCONFIG(varnr)) { - case 1: { - value = P052_data->modbus.readInputRegister(P052_IR4_MEASURED_FILTERED_CO2, errorcode); - logPrefix = F("co2="); - break; - } - case 2: { - int temperatureX100 = P052_data->modbus.readInputRegister(P052_IR5_TEMPERATURE, errorcode); - - if (errorcode == 2) { - // Exception code: Illegal Data Address - // SenseAir S8, not for other modules. - temperatureX100 = P052_data->modbus.read_RAM_EEPROM( - P052_CMD_READ_RAM, P052_RAM_ADDR_DET_TEMPERATURE, 2, errorcode); - } - - if (temperatureX100 >= 32768) { - // 2-complement value. - temperatureX100 -= 65536; - } - value = static_cast(temperatureX100) / 100.0f; - logPrefix = F("temp="); - break; - } - case 3: { - int rhX100 = P052_data->modbus.readInputRegister(P052_IR6_SPACE_HUMIDITY, errorcode); - value = static_cast(rhX100) / 100.0f; - logPrefix = F("hum="); - break; - } - case 4: { - int status = P052_data->modbus.readInputRegister(P052_IR29_FW_REV, errorcode); - - if (errorcode == 0) { - int relayStatus = (status >> 8) & 0x1; - UserVar.setFloat(event->TaskIndex, varnr, relayStatus); - log += F("relay status="); - log += relayStatus; - } - break; - } - case 5: { - int temperatureAdjustment = P052_data->modbus.readInputRegister(P052_IR11_MEASURED_CONCENTRATION_UNFILTERED, errorcode); - value = static_cast(temperatureAdjustment); - logPrefix = F("temp adj="); - break; - } - - case 7: { - const int errorWord = P052_data->modbus.readInputRegister(P052_IR_ERRORSTATUS, errorcode); - - if (errorcode == 0) { - value = errorWord; - - for (size_t i = 0; i < 9; i++) { - if (bitRead(errorWord, i)) { - log += F("err="); - log += i; - break; - } - } - } else { - value = -1; - log += F("err="); - log += -1; - } - break; - } - case 0: - default: { - UserVar.setFloat(event->TaskIndex, varnr, 0); - break; - } - } - - if ((errorcode == 0) && (P052_data->modbus.getLastError() == 0)) { - success = true; - UserVar.setFloat(event->TaskIndex, varnr, value); - log += logPrefix; - log += value; - } - } - addLogMove(LOG_LEVEL_INFO, log); - break; - } - break; - } - - case PLUGIN_WRITE: - { - P052_data_struct *P052_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if ((nullptr != P052_data) && P052_data->plugin_write(event, string)) { - success = true; - } - break; - } - } - return success; -} - -#endif // USES_P052 \ No newline at end of file +#include "_Plugin_Helper.h" +#ifdef USES_P052 + +# include "src/PluginStructs/P052_data_struct.h" + +// ####################################################################################################### +// ############################# Plugin 052: Senseair CO2 Sensors ######################################## +// ####################################################################################################### + +/** Changelog: + * 25025-01-03 tonhuisman: Small code size reduction + */ + +/* + Plugin originally written by: Daniel Tedenljung + info__AT__tedenljungconsulting.com + Rewritten by: Mikael Trieb mikael__AT__triebconsulting.se + + This plugin reads available values of Senseair Co2 Sensors. + Datasheet can be found here: + S8: http://www.senseair.com/products/oem-modules/senseair-s8/ + K30: http://www.senseair.com/products/oem-modules/k30/ + K70/tSENSE: http://www.senseair.com/products/wall-mount/tsense/ + + Circuit wiring + GPIO Setting 1 -> RX + GPIO Setting 2 -> TX + Use 1kOhm in serie on datapins! + */ + +# define PLUGIN_052 +# define PLUGIN_ID_052 52 +# define PLUGIN_NAME_052 "Gases - CO2 Senseair" + + +boolean Plugin_052(uint8_t function, struct EventStruct *event, String& string) { + boolean success = false; + + switch (function) { + case PLUGIN_DEVICE_ADD: { + Device[++deviceCount].Number = PLUGIN_ID_052; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].ExitTaskBeforeSave = false; + Device[deviceCount].PluginStats = true; + break; + } + + case PLUGIN_GET_DEVICENAME: { + string = F(PLUGIN_NAME_052); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: { + for (uint8_t i = 0; i < VARS_PER_TASK; ++i) { + if (i < P052_NR_OUTPUT_VALUES) { + const uint8_t pconfigIndex = i + P052_QUERY1_CONFIG_POS; + uint8_t choice = PCONFIG(pconfigIndex); + ExtraTaskSettings.setTaskDeviceValueName(i, P052_data_struct::Plugin_052_valuename(choice, false)); + } else { + ExtraTaskSettings.clearTaskDeviceValueName(i); + } + } + break; + } + + case PLUGIN_GET_DEVICEVALUECOUNT: + { + event->Par1 = P052_NR_OUTPUT_VALUES; + success = true; + break; + } + + case PLUGIN_GET_DEVICEVTYPE: + { + event->sensorType = static_cast(PCONFIG(P052_SENSOR_TYPE_INDEX)); + event->idx = P052_SENSOR_TYPE_INDEX; + success = true; + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: { + serialHelper_getGpioNames(event); + break; + } + + case PLUGIN_WEBFORM_SHOW_CONFIG: + { + string += serialHelper_getSerialTypeLabel(event); + success = true; + break; + } + + case PLUGIN_SET_DEFAULTS: + { + PCONFIG(P052_SENSOR_TYPE_INDEX) = static_cast(Sensor_VType::SENSOR_TYPE_SINGLE); + PCONFIG(0) = 1; // "CO2" + + for (uint8_t i = 1; i < VARS_PER_TASK; ++i) { + PCONFIG(i) = 0; // "Empty" + } + + success = true; + break; + } + + case PLUGIN_WEBFORM_LOAD_OUTPUT_SELECTOR: + { + const __FlashStringHelper *options[P052_NR_OUTPUT_OPTIONS]; + + for (uint8_t i = 0; i < P052_NR_OUTPUT_OPTIONS; ++i) { + options[i] = P052_data_struct::Plugin_052_valuename(i, true); + } + + for (uint8_t i = 0; i < P052_NR_OUTPUT_VALUES; ++i) { + const uint8_t pconfigIndex = i + P052_QUERY1_CONFIG_POS; + sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P052_NR_OUTPUT_OPTIONS, options); + } + break; + } + + case PLUGIN_WEBFORM_LOAD: { + P052_data_struct *P052_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if ((nullptr != P052_data) && P052_data->isInitialized()) { + addFormSubHeader(F("Device Information")); + { + int value = 0; + + if (P052_data->modbus.detected_device_description.length() > 0) { + addRowLabel(F("Detected Device")); + addHtml(P052_data->modbus.detected_device_description); + } + + if (P052_data->readInputRegister(P052_IR29_FW_REV, value)) { + addRowLabel(F("FW rev.")); + addHtmlInt(value); + } + + addRowLabel(F("Sensor ID")); + addHtml(formatToHex_decimal(P052_data->getSensorID())); + + + addRowLabel(F("Checksum (pass/fail/nodata)")); + { + uint32_t reads_pass, reads_crc_failed, reads_nodata; + P052_data->modbus.getStatistics(reads_pass, reads_crc_failed, reads_nodata); + addHtml(strformat(F("%d/%d/%d"), reads_pass, reads_crc_failed, reads_nodata)); + } + + bool hasFactorySettings = false; + bool enabledABC = false; + + if (P052_data->readHoldingRegister(P052_HR19_METER_CONTROL, value)) { + hasFactorySettings = value == 255; + enabledABC = bitRead(value, 1) == 0; + addRowLabel(F("Using Factory Settings")); + addEnabled(hasFactorySettings); + + if (!hasFactorySettings) { + // addRowLabel(F("HR19")); + // addHtmlInt(value); + addRowLabel(F("nRDY")); + addEnabled(bitRead(value, 0) == 0); + addRowLabel(F("ABC")); + addEnabled(enabledABC); + addRowLabel(F("Static IIR filter")); + addEnabled(bitRead(value, 2) == 0); + addRowLabel(F("Dynamic IIR filter")); + addEnabled(bitRead(value, 3) == 0); + addRowLabel(F("Pressure Compensation")); + addEnabled(bitRead(value, 4) == 0); + } + } + + if (P052_data->readInputRegister(P052_IR7_MEASUREMENT_COUNT, value)) { + addRowLabel(F("Measurement Count")); + addHtmlInt(value); + } + + if (P052_data->readInputRegister(P052_IR8_MEASUREMENT_CYCLE_TIME, value)) { + addRowLabel(F("Measurement Cycle time")); + addHtmlInt(value * 2); + addUnit('s'); + } + + if (P052_data->readInputRegister(P052_IR9_MEASURED_UNFILTERED_CO2, value)) { + addRowLabel(F("Unfiltered CO2")); + addHtmlInt(value); + } + + if (P052_data->readHoldingRegister(P052_HR11_MEASUREMENT_MODE, value)) { + addRowLabel(F("Measurement Mode")); + addHtml(value == 0 ? F("Continuous") : F("Single Measurement")); + } + + if (enabledABC) { + if (P052_data->readHoldingRegister(P052_HR14_ABC_PERIOD, value)) { + addRowLabel(F("ABC Period")); + addHtmlInt(value); + addUnit('h'); + } + + if (P052_data->readHoldingRegister(P052_HR5_ABC_TIME, value)) { + addRowLabel(F("Time Since ABC")); + addHtmlInt(value); + addUnit('h'); + } + } + } + + { + int value = 0; + + /* + if (P052_data->readHoldingRegister(P052_HR11_MEASUREMENT_MODE, value)) { + // Disable selector for now, since single measurement not yet supported. + + const __FlashStringHelper *options[2] = { F("Continuous"), F("Single Measurement") }; + addFormSelector(F("Measurement Mode"), F("mode"), 2, options, nullptr, value); + } + */ + + if (P052_data->readHoldingRegister(P052_HR12_MEASUREMENT_PERIOD, value)) { + addFormNumericBox(F("Measurement Period"), F("period"), value, 2, 65534); + addUnit('s'); + } + + if (P052_data->readHoldingRegister(P052_HR13_NR_OF_SAMPLES, value)) { + addFormNumericBox(F("Samples per measurement"), F("samp_meas"), value, 1, 1024); + } + } + { + // P052_ABC_PERIOD + } + } + + /* + // ABC functionality disabled for now, due to a bug in the firmware. + // See https://github.com/letscontrolit/ESPEasy/issues/759 + uint8_t choiceABCperiod = PCONFIG(4); + const __FlashStringHelper * optionsABCperiod[9] = { F("disable"), F("1 h"), F("12 h"), F("1 + day"), F("2 days"), F("4 days"), F("7 days"), F("14 days"), F("30 days") }; + addFormSelector(F("ABC period"), F("ABC_period"), 9, optionsABCperiod, + nullptr, choiceABCperiod); + */ + + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: { + // Save output selector parameters. + for (uint8_t i = 0; i < P052_NR_OUTPUT_VALUES; ++i) { + const uint8_t pconfigIndex = i + P052_QUERY1_CONFIG_POS; + const uint8_t choice = PCONFIG(pconfigIndex); + sensorTypeHelper_saveOutputSelector(event, pconfigIndex, i, P052_data_struct::Plugin_052_valuename(choice, false)); + } + + P052_data_struct *P052_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if ((nullptr != P052_data) && P052_data->isInitialized()) { + bool changed = false; + uint16_t mode = getFormItemInt(F("mode"), 65535); + + if (((mode == 0) || (mode == 1))) { + uint8_t errorcode; + int readVal = P052_data->modbus.readHoldingRegister(0x0A, errorcode); + + if ((errorcode == 0) && (readVal != mode)) { + P052_data->modbus.writeMultipleRegisters(0x0A, mode); + delay(0); + changed = true; + } + } + uint16_t period = getFormItemInt(F("period"), 0); + + if (period > 1) { + uint8_t errorcode; + int readVal = P052_data->modbus.readHoldingRegister(0x0B, errorcode); + + if ((errorcode == 0) && (readVal != period)) { + P052_data->modbus.writeMultipleRegisters(0x0B, period); + delay(0); + changed = true; + } + } + uint16_t samp_meas = getFormItemInt(F("samp_meas"), 0); + + if ((samp_meas > 0) && (samp_meas <= 1024)) { + uint8_t errorcode; + int readVal = P052_data->modbus.readHoldingRegister(0x0C, errorcode); + + if ((errorcode == 0) && (readVal != samp_meas)) { + P052_data->modbus.writeMultipleRegisters(0x0C, samp_meas); + delay(0); + changed = true; + } + } + + if (changed) { + // Restart sensor. + P052_data->modbus.writeMultipleRegisters(0x11, 0xFF); + + // FIXME TD-er: Must leave the sensor to boot for a while. + delay(35); + } + } + + + /* + // ABC functionality disabled for now, due to a bug in the firmware. + // See https://github.com/letscontrolit/ESPEasy/issues/759 + PCONFIG(4) = getFormItemInt(F("ABC_period")); + */ + + success = true; + break; + } + + case PLUGIN_INIT: { + const int16_t serial_rx = CONFIG_PIN1; + const int16_t serial_tx = CONFIG_PIN2; + const ESPEasySerialPort port = static_cast(CONFIG_PORT); + + initPluginTaskData(event->TaskIndex, new (std::nothrow) P052_data_struct()); + P052_data_struct *P052_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P052_data) { + return success; + } + + + if (P052_data->init(port, serial_rx, serial_tx)) { + /* + // ABC functionality disabled for now, due to a bug in the firmware. + // See https://github.com/letscontrolit/ESPEasy/issues/759 + const int periodInHours[9] = {0, 1, 12, (24*1), (24*2), (24*4), (24*7), + (24*14), (24*30) }; + uint8_t choiceABCperiod = PCONFIG(1); + + Plugin_052_setABCperiod(periodInHours[choiceABCperiod]); + */ + P052_data->modbus.setModbusTimeout(P052_MODBUS_TIMEOUT); + + // P052_data->modbus.writeMultipleRegisters(0x09, 1); // Start Single Measurement + // P052_data->modbus.writeMultipleRegisters(0x0B, 16); // Measurement Period + // P052_data->modbus.writeMultipleRegisters(0x0C, 8); // Number of samples + + success = true; + } else { + clearPluginTaskData(event->TaskIndex); + } + break; + } + + case PLUGIN_EXIT: { + success = true; + break; + } + + case PLUGIN_READ: { + P052_data_struct *P052_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if ((nullptr != P052_data) && P052_data->isInitialized()) { + event->sensorType = static_cast(PCONFIG(P052_SENSOR_TYPE_INDEX)); + String log = F("Senseair: "); + String logPrefix; + + for (int varnr = 0; varnr < P052_NR_OUTPUT_VALUES; ++varnr) { + uint8_t errorcode = 0; + float value = 0; + + switch (PCONFIG(varnr)) { + case 1: { + value = P052_data->modbus.readInputRegister(P052_IR4_MEASURED_FILTERED_CO2, errorcode); + logPrefix = F("co2="); + break; + } + case 2: { + int temperatureX100 = P052_data->modbus.readInputRegister(P052_IR5_TEMPERATURE, errorcode); + + if (errorcode == 2) { + // Exception code: Illegal Data Address + // SenseAir S8, not for other modules. + temperatureX100 = P052_data->modbus.read_RAM_EEPROM( + P052_CMD_READ_RAM, P052_RAM_ADDR_DET_TEMPERATURE, 2, errorcode); + } + + if (temperatureX100 >= 32768) { + // 2-complement value. + temperatureX100 -= 65536; + } + value = static_cast(temperatureX100) / 100.0f; + logPrefix = F("temp="); + break; + } + case 3: { + int rhX100 = P052_data->modbus.readInputRegister(P052_IR6_SPACE_HUMIDITY, errorcode); + value = static_cast(rhX100) / 100.0f; + logPrefix = F("hum="); + break; + } + case 4: { + int status = P052_data->modbus.readInputRegister(P052_IR29_FW_REV, errorcode); + + if (errorcode == 0) { + int relayStatus = (status >> 8) & 0x1; + UserVar.setFloat(event->TaskIndex, varnr, relayStatus); + log += F("relay status="); + log += relayStatus; + } + break; + } + case 5: { + int temperatureAdjustment = P052_data->modbus.readInputRegister(P052_IR11_MEASURED_CONCENTRATION_UNFILTERED, errorcode); + value = static_cast(temperatureAdjustment); + logPrefix = F("temp adj="); + break; + } + + case 7: { + const int errorWord = P052_data->modbus.readInputRegister(P052_IR_ERRORSTATUS, errorcode); + + if (errorcode == 0) { + value = errorWord; + + for (size_t i = 0; i < 9; i++) { + if (bitRead(errorWord, i)) { + log += F("err="); + log += i; + break; + } + } + } else { + value = -1; + log += F("err="); + log += -1; + } + break; + } + case 0: + default: { + UserVar.setFloat(event->TaskIndex, varnr, 0); + break; + } + } + + if ((errorcode == 0) && (P052_data->modbus.getLastError() == 0)) { + success = true; + UserVar.setFloat(event->TaskIndex, varnr, value); + log += logPrefix; + log += value; + } + } + addLogMove(LOG_LEVEL_INFO, log); + break; + } + break; + } + + case PLUGIN_WRITE: + { + P052_data_struct *P052_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if ((nullptr != P052_data) && P052_data->plugin_write(event, string)) { + success = true; + } + break; + } + } + return success; +} + +#endif // USES_P052 diff --git a/src/src/PluginStructs/P016_data_struct.h b/src/src/PluginStructs/P016_data_struct.h index 450527c36c..10f84acc3e 100644 --- a/src/src/PluginStructs/P016_data_struct.h +++ b/src/src/PluginStructs/P016_data_struct.h @@ -123,11 +123,11 @@ struct P016_data_struct : public PluginTaskData_base { decode_type_t DecodeType, uint16_t CodeFlags); - uint64_t iLastCmd = 0; // last command send - uint32_t iLastCmdTime = 0; // time while last command was send - decode_type_t iLastDecodeType = decode_type_t::UNUSED; // last decode_type sent - uint16_t iCmdInhibitTime = 0; // inhibit time for sending the same command again - uint16_t iLastCodeFlags = 0; // last flags sent + uint64_t iLastCmd = 0; // last command send + uint32_t iLastCmdTime = 0; // time while last command was send + decode_type_t iLastDecodeType = decode_type_t::UNUSED; // last decode_type sent + uint16_t iCmdInhibitTime = 0; // inhibit time for sending the same command again + uint16_t iLastCodeFlags = 0; // last flags sent # endif // if P016_FEATURE_COMMAND_HANDLING # ifdef P016_CHECK_HEAP void CheckHeap(String dbgtxt); diff --git a/src/src/PluginStructs/P050_data_struct.cpp b/src/src/PluginStructs/P050_data_struct.cpp index 5cb01c1369..38e440361a 100644 --- a/src/src/PluginStructs/P050_data_struct.cpp +++ b/src/src/PluginStructs/P050_data_struct.cpp @@ -1,4 +1,4 @@ -// Needed also here for PlatformIO's library finder as the .h file +// Needed also here for PlatformIO's library finder as the .h file // is in a directory which is excluded in the src_filter #include "../PluginStructs/P050_data_struct.h" @@ -6,12 +6,9 @@ #ifdef USES_P050 -# include "../Helpers/ESPEasy_Storage.h" - # include P050_data_struct::P050_data_struct(uint16_t integrationSetting, uint16_t gainSetting) { - // Map integration time setting (uint16_t to enum) _integrationTime = static_cast(integrationSetting); @@ -30,12 +27,12 @@ P050_data_struct::P050_data_struct(uint16_t integrationSetting, uint16_t gainSet /** * resetTransformation - * Effectgively sets matrix[0][0], matrix[1][1] and matrix[2][2] to 1.0f, all other fields to 0.0f + * Effectgively sets matrix[0][0], matrix[1][1] and matrix[2][2] to 1.0f, all other fields to 0.0f */ void P050_data_struct::resetTransformation() { // Initialize Transformationn defaults - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { TransformationSettings.matrix[i][j] = i == j ? 1.0f : 0.0f; } } @@ -45,23 +42,27 @@ void P050_data_struct::resetTransformation() { * applyTransformation : calibrate r/g/b inputs (uint16_t) to rc/gc/bc outputs (float, by reference) */ void P050_data_struct::applyTransformation(uint16_t r, uint16_t g, uint16_t b, float *rc, float *gc, float *bc) { - *rc = TransformationSettings.matrix[0][0] * static_cast(r) + TransformationSettings.matrix[0][1] * static_cast(g) + TransformationSettings.matrix[0][2] * static_cast(b); - *gc = TransformationSettings.matrix[1][0] * static_cast(r) + TransformationSettings.matrix[1][1] * static_cast(g) + TransformationSettings.matrix[1][2] * static_cast(b); - *bc = TransformationSettings.matrix[2][0] * static_cast(r) + TransformationSettings.matrix[2][1] * static_cast(g) + TransformationSettings.matrix[2][2] * static_cast(b); + applyTransformation(static_cast(r), static_cast(g), static_cast(b), rc, gc, bc); } /** * applyTransformation : calibrate normalized r/g/b inputs (float) to rc/gc/bc outputs (float, by reference) */ void P050_data_struct::applyTransformation(float nr, float ng, float nb, float *rc, float *gc, float *bc) { - *rc = TransformationSettings.matrix[0][0] * static_cast(nr) + TransformationSettings.matrix[0][1] * static_cast(ng) + TransformationSettings.matrix[0][2] * static_cast(nb); - *gc = TransformationSettings.matrix[1][0] * static_cast(nr) + TransformationSettings.matrix[1][1] * static_cast(ng) + TransformationSettings.matrix[1][2] * static_cast(nb); - *bc = TransformationSettings.matrix[2][0] * static_cast(nr) + TransformationSettings.matrix[2][1] * static_cast(ng) + TransformationSettings.matrix[2][2] * static_cast(nb); + *rc = TransformationSettings.matrix[0][0] * nr + + TransformationSettings.matrix[0][1] * ng + + TransformationSettings.matrix[0][2] * nb; + *gc = TransformationSettings.matrix[1][0] * nr + + TransformationSettings.matrix[1][1] * ng + + TransformationSettings.matrix[1][2] * nb; + *bc = TransformationSettings.matrix[2][0] * nr + + TransformationSettings.matrix[2][1] * ng + + TransformationSettings.matrix[2][2] * nb; } bool P050_data_struct::loadSettings(taskIndex_t taskIndex) { LoadCustomTaskSettings(taskIndex, reinterpret_cast(&TransformationSettings), sizeof(TransformationSettings)); - return true; + return true; } bool P050_data_struct::saveSettings(taskIndex_t taskIndex) { @@ -73,5 +74,4 @@ String P050_data_struct::generate_cal_id(int i, int j) { return strformat(F("cal_%c_%d"), static_cast('a' + i), j); } - #endif // ifdef USES_P050 diff --git a/src/src/PluginStructs/P050_data_struct.h b/src/src/PluginStructs/P050_data_struct.h index 07d770158c..6b6fe247c8 100644 --- a/src/src/PluginStructs/P050_data_struct.h +++ b/src/src/PluginStructs/P050_data_struct.h @@ -7,32 +7,44 @@ # include typedef struct { - float matrix[3][3]={}; + float matrix[3][3] = {}; } tcsTransformationSettings_t; struct P050_data_struct : public PluginTaskData_base { - public: - P050_data_struct(uint16_t integrationSetting, uint16_t gainSetting); - P050_data_struct() = delete; + P050_data_struct(uint16_t integrationSetting, + uint16_t gainSetting); + P050_data_struct() = delete; virtual ~P050_data_struct() = default; bool loadSettings(taskIndex_t taskIndex); bool saveSettings(taskIndex_t taskIndex); void resetTransformation(); - void applyTransformation(uint16_t r, uint16_t g, uint16_t b, float *rc, float *gc, float *bc); - void applyTransformation(float nr, float ng, float nb, float *rc, float *gc, float *bc); - - static String generate_cal_id(int i, int j); - - Adafruit_TCS34725 tcs; + void applyTransformation(uint16_t r, + uint16_t g, + uint16_t b, + float *rc, + float *gc, + float *bc); + void applyTransformation(float nr, + float ng, + float nb, + float *rc, + float *gc, + float *bc); + + static String generate_cal_id(int i, + int j); + + Adafruit_TCS34725 tcs; tcsTransformationSettings_t TransformationSettings; private: - tcs34725IntegrationTime_t _integrationTime; - tcs34725Gain_t _gain; + + tcs34725IntegrationTime_t _integrationTime; + tcs34725Gain_t _gain; }; #endif // ifdef USES_P050 diff --git a/src/src/PluginStructs/P110_data_struct.cpp b/src/src/PluginStructs/P110_data_struct.cpp index 7b908aeecf..0a9b3ffaa6 100644 --- a/src/src/PluginStructs/P110_data_struct.cpp +++ b/src/src/PluginStructs/P110_data_struct.cpp @@ -162,7 +162,7 @@ int16_t P110_data_struct::readDistance() { addLog(LOG_LEVEL_DEBUG, F("VL53L0X: TIMEOUT")); # endif // P110_DEBUG_LOG return P110_DISTANCE_READ_TIMEOUT; - } else if (dist >= 8190u) { + } else if (dist >= 8190) { # ifdef P110_DEBUG_LOG addLog(LOG_LEVEL_DEBUG, concat(F("VL53L0X: NO MEASUREMENT: "), dist)); # endif // P110_DEBUG_LOG From 9c66fb52544b5b86e94f7c2ec3bc7c6c670ce441 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sat, 4 Jan 2025 10:44:51 +0100 Subject: [PATCH 2/9] [Build] Fix typo --- src/_P037_MQTTImport.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_P037_MQTTImport.ino b/src/_P037_MQTTImport.ino index dc05181ff6..1b3bd33f8a 100644 --- a/src/_P037_MQTTImport.ino +++ b/src/_P037_MQTTImport.ino @@ -608,7 +608,7 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) if (loglevelActiveFor(LOG_LEVEL_INFO)) { addLog(LOG_LEVEL_INFO, strformat(F("IMPT : [%s#%s] : %.3f"), - getTaskDeviceName(event->TaskIndex), + getTaskDeviceName(event->TaskIndex).c_str(), checkJson ? key.c_str() : getTaskValueName(event->TaskIndex, x).c_str(), doublePayload)); } From 2d8011843276444d709f572ce2b30a8fcbee559a Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sat, 4 Jan 2025 22:19:17 +0100 Subject: [PATCH 3/9] [Build] More code reductions in .ino files [P054] .. [P091] --- src/_P054_DMX512.ino | 688 ++++++++++++----------- src/_P055_Chiming.ino | 12 +- src/_P056_SDS011-Dust.ino | 445 ++++++++------- src/_P057_HT16K33_LED.ino | 817 ++++++++++++++------------- src/_P058_HT16K33_KeyPad.ino | 297 +++++----- src/_P059_Encoder.ino | 421 +++++++------- src/_P060_MCP3221.ino | 355 ++++++------ src/_P061_KeyPad.ino | 426 +++++++------- src/_P062_MPR121_KeyPad.ino | 739 ++++++++++++------------- src/_P063_TTP229_KeyPad.ino | 457 +++++++-------- src/_P064_APDS9960.ino | 797 ++++++++++++++------------- src/_P065_DRF0299_MP3.ino | 14 +- src/_P066_VEML6040.ino | 43 +- src/_P067_HX711_Load_Cell.ino | 477 ++++++++-------- src/_P068_SHT3x.ino | 288 +++++----- src/_P069_LM75A.ino | 33 +- src/_P070_NeoPixel_Clock.ino | 9 +- src/_P071_Kamstrup401.ino | 430 ++++++++------- src/_P072_HDC1080.ino | 249 ++++----- src/_P073_7DGT.ino | 25 +- src/_P074_TSL2591.ino | 31 +- src/_P075_Nextion.ino | 947 ++++++++++++++++---------------- src/_P076_HLW8012.ino | 7 +- src/_P077_CSE7766.ino | 28 +- src/_P078_Eastron.ino | 29 +- src/_P079_Wemos_Motorshield.ino | 16 +- src/_P080_DallasIButton.ino | 19 +- src/_P081_Cron.ino | 17 +- src/_P082_GPS.ino | 101 ++-- src/_P083_SGP30.ino | 20 +- src/_P084_VEML6070.ino | 29 +- src/_P085_AcuDC243.ino | 11 +- src/_P086_Homie.ino | 1 - src/_P087_SerialProxy.ino | 19 +- src/_P088_HeatpumpIR.ino | 10 +- src/_P089_Ping.ino | 22 +- src/_P090_CCS811.ino | 70 ++- src/_P091_SerSwitch.ino | 83 ++- 38 files changed, 4167 insertions(+), 4315 deletions(-) diff --git a/src/_P054_DMX512.ino b/src/_P054_DMX512.ino index 09d4483c96..3d61af844f 100644 --- a/src/_P054_DMX512.ino +++ b/src/_P054_DMX512.ino @@ -1,345 +1,343 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P054 - -// ####################################################################################################### -// ######################################## Plugin 054: DMX512 TX ######################################## -// ####################################################################################################### - -/** Changelog: - * 2024-09-21 tonhuisman: Use Direct-GPIO for interacting with GPIO pins for speed & timing accuracy - * Use ESPEasySerial for more flexible serial configuration - * 2024-09-20 tonhuisman: Reformat source, allow GPIO selection on ESP32 by _not_ resetting to GPIO 2 when not ESP8266 - * 2024-09-20 Start changelog - */ - -// ESPEasy Plugin to control DMX-512 Devices (DMX 512/1990; DIN 56930-2) like Dimmer-Packs, LED-Bars, Moving-Heads, Event-Lighting -// written by Jochen Krapf (jk@nerd2nerd.org) - -// List of commands: -// (1) DMX, -// (2) DMX,,,, ... - -// List of DMX params: -// (a) -// DMX-value (0...255) to write to the next channel address (1...512) starting with 1 -// (b) = -// DMX-value (0...255) to write to the given channel address (1...512). -// (c) =,,,... -// List of DMX-values (0...255) to write beginning with the given channel address (1...512). -// (d) "OFF" -// Set DMX-values of all channels to 0. -// (e) "ON" -// Set DMX-values of all channels to 255. -// (f) "LOG" -// Print DMX-values of all channels to log output. - -// Examples: -// DMX,123" Set channel 1 to value 123 -// DMX,123,22,33,44" Set channel 1 to value 123, channel 2 to 22, channel 3 to 33, channel 4 to 44 -// DMX,5=123" Set channel 5 to value 123 -// DMX,5=123,22,33,44" Set channel 5 to value 123, channel 6 to 22, channel 7 to 33, channel 8 to 44 -// DMX,5=123,8=44" Set channel 5 to value 123, channel 8 to 44 -// DMX,OFF" Pitch Black - -// Transceiver: -// SN75176 or MAX485 or LT1785 or ... -// Pin 5: GND -// Pin 2, 3, 8: +5V -// Pin 4: to ESP D4 -// Pin 6: DMX+ (hot) -// Pin 7: DMX- (cold) - -// XLR Plug: -// Pin 1: GND, Shield -// Pin 2: DMX- (cold) -// Pin 3: DMX+ (hot) - -// Note: The ESP serial FIFO has size of 128 uint8_t. Therefore it is rcommented to use DMX buffer sizes below 128 - - -// #include <*.h> //no lib needed - -# include -# include - -# define PLUGIN_054 -# define PLUGIN_ID_054 54 -# define PLUGIN_NAME_054 "Communication - DMX512 TX" - -uint8_t *Plugin_054_DMXBuffer = 0; -int16_t Plugin_054_DMXSize = 32; -ESPeasySerial *Plugin_054_Serial = nullptr; - -static inline void PLUGIN_054_Limit(int16_t& value, int16_t min, int16_t max) -{ - if (value < min) { - value = min; - } - - if (value > max) { - value = max; - } -} - -boolean Plugin_054(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_054; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].ValueCount = 0; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_054); - break; - } - - case PLUGIN_SET_DEFAULTS: - { - # ifdef ESP8266 - CONFIG_PORT = static_cast(ESPEasySerialPort::serial1); // Serial1 port - CONFIG_PIN1 = -1; // RX pin - CONFIG_PIN2 = 2; // TX pin - # endif // ifdef ESP8266 - # ifdef ESP32 - CONFIG_PORT = static_cast(ESPEasySerialPort::serial1); // Serial1 port - int rxPin = 0; - int txPin = 0; - const ESPEasySerialPort port = static_cast(CONFIG_PORT); - - ESPeasySerialType::getSerialTypePins(port, rxPin, txPin); - CONFIG_PIN1 = rxPin; - CONFIG_PIN2 = txPin; - # endif // ifdef ESP32 - - PCONFIG(0) = Plugin_054_DMXSize; // Holds default value - break; - } - - case PLUGIN_WEBFORM_PRE_SERIAL_PARAMS: - { - if ((-1 == CONFIG_PIN2) && (2 == CONFIG_PIN1)) { - CONFIG_PIN2 = CONFIG_PIN1; - CONFIG_PIN1 = -1; - } - break; - } - - case PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS: - { - addFormNote(F("An on-chip ESP Serial port" - #if USES_USBCDC - " (not USB CDC)" - #endif // if USES_USBCDC - #if USES_HWCDC - " (not USB HWCDC)" - #endif // if USES_HWCDC - " must be selected!")); - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: - { - serialHelper_getGpioNames(event, true); - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - addFormNumericBox(F("Channels"), F("channels"), PCONFIG(0), 1, 512); - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - # ifdef ESP8266 - - if (static_cast(ESPEasySerialPort::serial1) == CONFIG_PORT) { - CONFIG_PIN2 = 2; - } - # endif // ifdef ESP8266 - - if (Settings.Pin_status_led == CONFIG_PIN2) { // Status LED assigned to TX1? - Settings.Pin_status_led = -1; - } - Plugin_054_DMXSize = getFormItemInt(F("channels")); - PLUGIN_054_Limit(Plugin_054_DMXSize, 1, 512); - PCONFIG(0) = Plugin_054_DMXSize; - success = true; - break; - } - - case PLUGIN_INIT: - { - Plugin_054_DMXSize = PCONFIG(0); - - if (Plugin_054_DMXBuffer) { - delete[] Plugin_054_DMXBuffer; - } - Plugin_054_DMXBuffer = new (std::nothrow) uint8_t[Plugin_054_DMXSize]; - - if (Plugin_054_DMXBuffer != nullptr) { - memset(Plugin_054_DMXBuffer, 0, Plugin_054_DMXSize); - } - - if ((-1 == CONFIG_PIN2) && (2 == CONFIG_PIN1)) { // Convert previous GPIO settings - CONFIG_PIN2 = CONFIG_PIN1; - CONFIG_PIN1 = -1; - } - int rxPin = CONFIG_PIN1; - int txPin = CONFIG_PIN2; - const ESPEasySerialPort port = static_cast(CONFIG_PORT); - - if ((rxPin < 0) && (txPin < 0)) { - ESPeasySerialType::getSerialTypePins(port, rxPin, txPin); - CONFIG_PIN1 = rxPin; - CONFIG_PIN2 = txPin; - } - delete Plugin_054_Serial; - Plugin_054_Serial = new (std::nothrow) ESPeasySerial(port, rxPin, txPin); - - if (nullptr != Plugin_054_Serial) { - # ifdef ESP8266 - Plugin_054_Serial->begin(250000, (SerialConfig)SERIAL_8N2); - # endif // ifdef ESP8266 - # ifdef ESP32 - Plugin_054_Serial->begin(250000, SERIAL_8N2); - # endif // ifdef ESP32 - } - - success = Plugin_054_DMXBuffer != nullptr && Plugin_054_Serial != nullptr && validGpio(CONFIG_PIN2); - break; - } - - case PLUGIN_EXIT: - { - if (Plugin_054_DMXBuffer) { - delete[] Plugin_054_DMXBuffer; - Plugin_054_DMXBuffer = nullptr; - } - delete Plugin_054_Serial; - Plugin_054_Serial = nullptr; - break; - } - - case PLUGIN_WRITE: - { - const String command = parseString(string, 1); - - if (equals(command, F("dmx"))) { - String param; - String paramKey; - String paramVal; - uint8_t paramIdx = 2; - int16_t channel = 1; - int16_t value = 0; - - param = parseString(string, paramIdx++); - - while (param.length()) { - # ifndef BUILD_NO_DEBUG - addLog(LOG_LEVEL_DEBUG_MORE, param); - # endif // ifndef BUILD_NO_DEBUG - - if (equals(param, F("log"))) { - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("DMX : "); - - for (int16_t i = 0; i < Plugin_054_DMXSize; ++i) { - log += concat(Plugin_054_DMXBuffer[i], F(", ")); - } - addLogMove(LOG_LEVEL_INFO, log); - } - success = true; - } - - else if (equals(param, F("test"))) { - for (int16_t i = 0; i < Plugin_054_DMXSize; ++i) { - Plugin_054_DMXBuffer[i] = rand() & 255; - } - success = true; - } - - else if (equals(param, F("on"))) { - memset(Plugin_054_DMXBuffer, 255, Plugin_054_DMXSize); - success = true; - } - - else if (equals(param, F("off"))) { - memset(Plugin_054_DMXBuffer, 0, Plugin_054_DMXSize); - success = true; - } - - else { - int16_t index = param.indexOf('='); - - if (index > 0) { // syntax: "=" - paramKey = param.substring(0, index); - paramVal = param.substring(index + 1); - channel = paramKey.toInt(); - } - else { // syntax: "" - paramVal = param; - } - - value = paramVal.toInt(); - PLUGIN_054_Limit(value, 0, 255); - - if ((channel > 0) && (channel <= Plugin_054_DMXSize)) { - Plugin_054_DMXBuffer[channel - 1] = value; - } - channel++; - success = true; - } - - param = parseString(string, paramIdx++); - } - } - - break; - } - - case PLUGIN_TEN_PER_SECOND: - { - if (Plugin_054_DMXBuffer && Plugin_054_Serial) { - int16_t sendPin = CONFIG_PIN2; // ESP8266: TX1 fixed to GPIO2 (D4) == onboard LED - - // empty serial from prev. transmit - Plugin_054_Serial->flush(); - - // send break - Plugin_054_Serial->end(); - - // DIRECT_PINMODE_OUTPUT(sendPin); // This shouldn't be needed - DIRECT_pinWrite(sendPin, LOW); - delayMicroseconds(120); // 88µs ... inf - DIRECT_pinWrite(sendPin, HIGH); - delayMicroseconds(12); // 8µs ... 1s - - // send DMX data - # ifdef ESP8266 - Plugin_054_Serial->begin(250000, (SerialConfig)SERIAL_8N2); - # endif // ifdef ESP8266 - # ifdef ESP32 - Plugin_054_Serial->begin(250000, SERIAL_8N2); - # endif // ifdef ESP32 - Plugin_054_Serial->write((uint8_t)0); // start uint8_t - Plugin_054_Serial->write(Plugin_054_DMXBuffer, Plugin_054_DMXSize); - } - break; - } - } - return success; -} - -#endif // USES_P054 +#include "_Plugin_Helper.h" +#ifdef USES_P054 + +// ####################################################################################################### +// ######################################## Plugin 054: DMX512 TX ######################################## +// ####################################################################################################### + +/** Changelog: + * 2024-09-21 tonhuisman: Use Direct-GPIO for interacting with GPIO pins for speed & timing accuracy + * Use ESPEasySerial for more flexible serial configuration + * 2024-09-20 tonhuisman: Reformat source, allow GPIO selection on ESP32 by _not_ resetting to GPIO 2 when not ESP8266 + * 2024-09-20 Start changelog + */ + +// ESPEasy Plugin to control DMX-512 Devices (DMX 512/1990; DIN 56930-2) like Dimmer-Packs, LED-Bars, Moving-Heads, Event-Lighting +// written by Jochen Krapf (jk@nerd2nerd.org) + +// List of commands: +// (1) DMX, +// (2) DMX,,,, ... + +// List of DMX params: +// (a) +// DMX-value (0...255) to write to the next channel address (1...512) starting with 1 +// (b) = +// DMX-value (0...255) to write to the given channel address (1...512). +// (c) =,,,... +// List of DMX-values (0...255) to write beginning with the given channel address (1...512). +// (d) "OFF" +// Set DMX-values of all channels to 0. +// (e) "ON" +// Set DMX-values of all channels to 255. +// (f) "LOG" +// Print DMX-values of all channels to log output. + +// Examples: +// DMX,123" Set channel 1 to value 123 +// DMX,123,22,33,44" Set channel 1 to value 123, channel 2 to 22, channel 3 to 33, channel 4 to 44 +// DMX,5=123" Set channel 5 to value 123 +// DMX,5=123,22,33,44" Set channel 5 to value 123, channel 6 to 22, channel 7 to 33, channel 8 to 44 +// DMX,5=123,8=44" Set channel 5 to value 123, channel 8 to 44 +// DMX,OFF" Pitch Black + +// Transceiver: +// SN75176 or MAX485 or LT1785 or ... +// Pin 5: GND +// Pin 2, 3, 8: +5V +// Pin 4: to ESP D4 +// Pin 6: DMX+ (hot) +// Pin 7: DMX- (cold) + +// XLR Plug: +// Pin 1: GND, Shield +// Pin 2: DMX- (cold) +// Pin 3: DMX+ (hot) + +// Note: The ESP serial FIFO has size of 128 uint8_t. Therefore it is rcommented to use DMX buffer sizes below 128 + + +// #include <*.h> //no lib needed + +# include +# include + +# define PLUGIN_054 +# define PLUGIN_ID_054 54 +# define PLUGIN_NAME_054 "Communication - DMX512 TX" + +uint8_t *Plugin_054_DMXBuffer = 0; +int16_t Plugin_054_DMXSize = 32; +ESPeasySerial *Plugin_054_Serial = nullptr; + +static inline void PLUGIN_054_Limit(int16_t& value, int16_t min, int16_t max) +{ + if (value < min) { + value = min; + } + + if (value > max) { + value = max; + } +} + +boolean Plugin_054(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_054; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_054); + break; + } + + case PLUGIN_SET_DEFAULTS: + { + # ifdef ESP8266 + CONFIG_PORT = static_cast(ESPEasySerialPort::serial1); // Serial1 port + CONFIG_PIN1 = -1; // RX pin + CONFIG_PIN2 = 2; // TX pin + # endif // ifdef ESP8266 + # ifdef ESP32 + CONFIG_PORT = static_cast(ESPEasySerialPort::serial1); // Serial1 port + int rxPin = 0; + int txPin = 0; + const ESPEasySerialPort port = static_cast(CONFIG_PORT); + + ESPeasySerialType::getSerialTypePins(port, rxPin, txPin); + CONFIG_PIN1 = rxPin; + CONFIG_PIN2 = txPin; + # endif // ifdef ESP32 + + PCONFIG(0) = Plugin_054_DMXSize; // Holds default value + break; + } + + case PLUGIN_WEBFORM_PRE_SERIAL_PARAMS: + { + if ((-1 == CONFIG_PIN2) && (2 == CONFIG_PIN1)) { + CONFIG_PIN2 = CONFIG_PIN1; + CONFIG_PIN1 = -1; + } + break; + } + + case PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS: + { + addFormNote(F("An on-chip ESP Serial port" + # if USES_USBCDC + " (not USB CDC)" + # endif // if USES_USBCDC + # if USES_HWCDC + " (not USB HWCDC)" + # endif // if USES_HWCDC + " must be selected!")); + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: + { + serialHelper_getGpioNames(event, true); + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + addFormNumericBox(F("Channels"), F("channels"), PCONFIG(0), 1, 512); + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + # ifdef ESP8266 + + if (static_cast(ESPEasySerialPort::serial1) == CONFIG_PORT) { + CONFIG_PIN2 = 2; + } + # endif // ifdef ESP8266 + + if (Settings.Pin_status_led == CONFIG_PIN2) { // Status LED assigned to TX1? + Settings.Pin_status_led = -1; + } + Plugin_054_DMXSize = getFormItemInt(F("channels")); + PLUGIN_054_Limit(Plugin_054_DMXSize, 1, 512); + PCONFIG(0) = Plugin_054_DMXSize; + success = true; + break; + } + + case PLUGIN_INIT: + { + Plugin_054_DMXSize = PCONFIG(0); + + if (Plugin_054_DMXBuffer) { + delete[] Plugin_054_DMXBuffer; + } + Plugin_054_DMXBuffer = new (std::nothrow) uint8_t[Plugin_054_DMXSize]; + + if (Plugin_054_DMXBuffer != nullptr) { + memset(Plugin_054_DMXBuffer, 0, Plugin_054_DMXSize); + } + + if ((-1 == CONFIG_PIN2) && (2 == CONFIG_PIN1)) { // Convert previous GPIO settings + CONFIG_PIN2 = CONFIG_PIN1; + CONFIG_PIN1 = -1; + } + int rxPin = CONFIG_PIN1; + int txPin = CONFIG_PIN2; + const ESPEasySerialPort port = static_cast(CONFIG_PORT); + + if ((rxPin < 0) && (txPin < 0)) { + ESPeasySerialType::getSerialTypePins(port, rxPin, txPin); + CONFIG_PIN1 = rxPin; + CONFIG_PIN2 = txPin; + } + delete Plugin_054_Serial; + Plugin_054_Serial = new (std::nothrow) ESPeasySerial(port, rxPin, txPin); + + if (nullptr != Plugin_054_Serial) { + # ifdef ESP8266 + Plugin_054_Serial->begin(250000, (SerialConfig)SERIAL_8N2); + # endif // ifdef ESP8266 + # ifdef ESP32 + Plugin_054_Serial->begin(250000, SERIAL_8N2); + # endif // ifdef ESP32 + } + + success = Plugin_054_DMXBuffer != nullptr && Plugin_054_Serial != nullptr && validGpio(CONFIG_PIN2); + break; + } + + case PLUGIN_EXIT: + { + if (Plugin_054_DMXBuffer) { + delete[] Plugin_054_DMXBuffer; + Plugin_054_DMXBuffer = nullptr; + } + delete Plugin_054_Serial; + Plugin_054_Serial = nullptr; + break; + } + + case PLUGIN_WRITE: + { + const String command = parseString(string, 1); + + if (equals(command, F("dmx"))) { + String param; + String paramKey; + String paramVal; + uint8_t paramIdx = 2; + int16_t channel = 1; + int16_t value = 0; + + param = parseString(string, paramIdx++); + + while (param.length()) { + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG_MORE, param); + # endif // ifndef BUILD_NO_DEBUG + + if (equals(param, F("log"))) { + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("DMX : "); + + for (int16_t i = 0; i < Plugin_054_DMXSize; ++i) { + log += concat(Plugin_054_DMXBuffer[i], F(", ")); + } + addLogMove(LOG_LEVEL_INFO, log); + } + success = true; + } + + else if (equals(param, F("test"))) { + for (int16_t i = 0; i < Plugin_054_DMXSize; ++i) { + Plugin_054_DMXBuffer[i] = rand() & 255; + } + success = true; + } + + else if (equals(param, F("on"))) { + memset(Plugin_054_DMXBuffer, 255, Plugin_054_DMXSize); + success = true; + } + + else if (equals(param, F("off"))) { + memset(Plugin_054_DMXBuffer, 0, Plugin_054_DMXSize); + success = true; + } + + else { + int16_t index = param.indexOf('='); + + if (index > 0) { // syntax: "=" + paramKey = param.substring(0, index); + paramVal = param.substring(index + 1); + channel = paramKey.toInt(); + } + else { // syntax: "" + paramVal = param; + } + + value = paramVal.toInt(); + PLUGIN_054_Limit(value, 0, 255); + + if ((channel > 0) && (channel <= Plugin_054_DMXSize)) { + Plugin_054_DMXBuffer[channel - 1] = value; + } + channel++; + success = true; + } + + param = parseString(string, paramIdx++); + } + } + + break; + } + + case PLUGIN_TEN_PER_SECOND: + { + if (Plugin_054_DMXBuffer && Plugin_054_Serial) { + int16_t sendPin = CONFIG_PIN2; // ESP8266: TX1 fixed to GPIO2 (D4) == onboard LED + + // empty serial from prev. transmit + Plugin_054_Serial->flush(); + + // send break + Plugin_054_Serial->end(); + + // DIRECT_PINMODE_OUTPUT(sendPin); // This shouldn't be needed + DIRECT_pinWrite(sendPin, LOW); + delayMicroseconds(120); // 88µs ... inf + DIRECT_pinWrite(sendPin, HIGH); + delayMicroseconds(12); // 8µs ... 1s + + // send DMX data + # ifdef ESP8266 + Plugin_054_Serial->begin(250000, (SerialConfig)SERIAL_8N2); + # endif // ifdef ESP8266 + # ifdef ESP32 + Plugin_054_Serial->begin(250000, SERIAL_8N2); + # endif // ifdef ESP32 + Plugin_054_Serial->write((uint8_t)0); // start uint8_t + Plugin_054_Serial->write(Plugin_054_DMXBuffer, Plugin_054_DMXSize); + } + break; + } + } + return success; +} + +#endif // USES_P054 diff --git a/src/_P055_Chiming.ino b/src/_P055_Chiming.ino index b589b065be..eaf6781271 100644 --- a/src/_P055_Chiming.ino +++ b/src/_P055_Chiming.ino @@ -5,6 +5,11 @@ // #################################### Plugin 055: Chiming Mechanism #################################### // ####################################################################################################### +/** Changelog: + * 2025-01-04 tonhuisman: Change check for a timesource to look for more than just NTP, but anything more reliable than 'Restore from RTC' + * Minor code cleanup + */ + // ESPEasy plugin to strike up to 4 physical bells and gongs with chiming sequences. // You also can use an antique door bell as a single strikes (not ringing) notification. // Optional you can use it as hourly chiming clock @@ -91,11 +96,8 @@ boolean Plugin_055(uint8_t function, struct EventStruct *event, String& string) { Device[++deviceCount].Number = PLUGIN_ID_055; Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].GlobalSyncOption = true; Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); @@ -156,8 +158,8 @@ boolean Plugin_055(uint8_t function, struct EventStruct *event, String& string) // addHtml(F("")); addButton(F("'control?cmd=chimeplay,hours'"), F("Test 1…12")); - if (PCONFIG(2) && !(Settings.UseNTP())) { - addFormNote(F("Enable and configure NTP!")); + if (PCONFIG(2) && !(node_time.getTimeSource() < timeSource_t::Restore_RTC_time_source)) { // Somewhat reliable timesource? + addFormNote(F("Configure a timesource! (NTP, P2P, RTC, GPS)")); } success = true; diff --git a/src/_P056_SDS011-Dust.ino b/src/_P056_SDS011-Dust.ino index 67c9aad941..d5b76072b7 100644 --- a/src/_P056_SDS011-Dust.ino +++ b/src/_P056_SDS011-Dust.ino @@ -1,225 +1,220 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P056 - -// ####################################################################################################### -// #################################### Plugin 056: Dust Sensor SDS011 / SDS018 ########################## -// ####################################################################################################### - -/* - Plugin is based upon SDS011 dust sensor PM2.5 and PM10 lib - This plugin and lib was written by Jochen Krapf (jk@nerd2nerd.org) - - This plugin reads the particle concentration from SDS011 Sensor - DevicePin1 - RX on ESP, TX on SDS - */ - -// #ifdef ESP8266 // Needed for precompile issues. - -# define PLUGIN_056 -# define PLUGIN_ID_056 56 -# define PLUGIN_NAME_056 "Dust - SDS011/018/198" -# define PLUGIN_VALUENAME1_056 "PM2.5" // Dust <2.5µm in µg/m³ SDS198:<100µm in µg/m³ -# define PLUGIN_VALUENAME2_056 "PM10" // Dust <10µm in µg/m³ - -# include - -#include "ESPEasy-Globals.h" - - -CjkSDS011 *Plugin_056_SDS = nullptr; - - -boolean Plugin_056(uint8_t function, struct EventStruct *event, String& string) -{ - bool success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_056; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = false; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_056); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_056)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_056)); - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: - { - serialHelper_getGpioNames(event, false, true); // TX optional - break; - } - - case PLUGIN_WEBFORM_SHOW_CONFIG: - { - string += serialHelper_getSerialTypeLabel(event); - success = true; - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - // FIXME TD-er: Whether TX pin is connected should be set somewhere - if (validGpio(CONFIG_PIN2)) { - addFormNumericBox(F("Sleep time"), F("sleeptime"), - PCONFIG(0), - 0, 30); - addUnit(F("Minutes")); - addFormNote(F("0 = continous, 1..30 = Work 30 seconds and sleep n*60-30 seconds")); - } - break; - } - case PLUGIN_WEBFORM_SAVE: - { - if (validGpio(CONFIG_PIN2)) { - // Communications to device should work. - const int newsleeptime = getFormItemInt(F("sleeptime")); - - if (PCONFIG(0) != newsleeptime) { - PCONFIG(0) = newsleeptime; - Plugin_056_setWorkingPeriod(newsleeptime); - } - } - success = true; - break; - } - - case PLUGIN_INIT: - { - if (Plugin_056_SDS) { - delete Plugin_056_SDS; - } - - const ESPEasySerialPort port = static_cast(CONFIG_PORT); - Plugin_056_SDS = new (std::nothrow) CjkSDS011(port, CONFIG_PIN1, CONFIG_PIN2); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, strformat(F("SDS : Init OK ESP GPIO-pin RX:%d TX:%d"), CONFIG_PIN1, CONFIG_PIN2)); - } - - success = true; - break; - } - - case PLUGIN_EXIT: - { - // //FIXME: if this plugin is used more than once at the same time, things go horribly wrong :) - // FIXME TD-er: Must implement plugin_data_struct for this - // - // if (Plugin_056_SDS) - // delete Plugin_056_SDS; - // addLog(LOG_LEVEL_INFO, F("SDS : Exit")); - shouldReboot = true; - break; - } - - case PLUGIN_FIFTY_PER_SECOND: - { - if (!Plugin_056_SDS) { - break; - } - - Plugin_056_SDS->Process(); - - if (Plugin_056_SDS->available()) - { - const float pm2_5 = Plugin_056_SDS->GetPM2_5(); - const float pm10 = Plugin_056_SDS->GetPM10_(); - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - addLog(LOG_LEVEL_DEBUG, strformat(F("SDS : act %.2f %.2f"), pm2_5, pm10)); - } - # endif // ifndef BUILD_NO_DEBUG - - if (Settings.TaskDeviceTimer[event->TaskIndex] == 0) - { - UserVar.setFloat(event->TaskIndex, 0, pm2_5); - UserVar.setFloat(event->TaskIndex, 1, pm10); - event->sensorType = Sensor_VType::SENSOR_TYPE_DUAL; - sendData(event); - } - } - - success = true; - break; - } - - case PLUGIN_READ: - { - if (!Plugin_056_SDS) { - break; - } - - float pm25, pm10; - - if (Plugin_056_SDS->ReadAverage(pm25, pm10)) { - UserVar.setFloat(event->TaskIndex, 0, pm25); - UserVar.setFloat(event->TaskIndex, 1, pm10); - success = true; - } - break; - } - } - - return success; -} - -String Plugin_056_ErrorToString(int error) { - String log; - - if (error < 0) { - log = concat(F("comm error: "), error); - } - return log; -} - -String Plugin_056_WorkingPeriodToString(int workingPeriod) { - if (workingPeriod < 0) { - return Plugin_056_ErrorToString(workingPeriod); - } - String log; - - if (workingPeriod > 0) { - log = strformat(F("%d minutes"), workingPeriod); - } else { - log = F(" continuous"); - } - return log; -} - -void Plugin_056_setWorkingPeriod(int minutes) { - if (!Plugin_056_SDS) { - return; - } - Plugin_056_SDS->SetWorkingPeriod(minutes); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, concat(F("SDS : Working Period set to: "), Plugin_056_WorkingPeriodToString(minutes))); - } -} - -// #endif -#endif // USES_P056 +#include "_Plugin_Helper.h" +#ifdef USES_P056 + +// ####################################################################################################### +// #################################### Plugin 056: Dust Sensor SDS011 / SDS018 ########################## +// ####################################################################################################### + +/* + Plugin is based upon SDS011 dust sensor PM2.5 and PM10 lib + This plugin and lib was written by Jochen Krapf (jk@nerd2nerd.org) + + This plugin reads the particle concentration from SDS011 Sensor + DevicePin1 - RX on ESP, TX on SDS + */ + +// #ifdef ESP8266 // Needed for precompile issues. + +# define PLUGIN_056 +# define PLUGIN_ID_056 56 +# define PLUGIN_NAME_056 "Dust - SDS011/018/198" +# define PLUGIN_VALUENAME1_056 "PM2.5" // Dust <2.5µm in µg/m³ SDS198:<100µm in µg/m³ +# define PLUGIN_VALUENAME2_056 "PM10" // Dust <10µm in µg/m³ + +# include + +# include "ESPEasy-Globals.h" + + +CjkSDS011 *Plugin_056_SDS = nullptr; + + +boolean Plugin_056(uint8_t function, struct EventStruct *event, String& string) +{ + bool success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_056; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_056); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_056)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_056)); + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: + { + serialHelper_getGpioNames(event, false, true); // TX optional + break; + } + + case PLUGIN_WEBFORM_SHOW_CONFIG: + { + string += serialHelper_getSerialTypeLabel(event); + success = true; + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + // FIXME TD-er: Whether TX pin is connected should be set somewhere + if (validGpio(CONFIG_PIN2)) { + addFormNumericBox(F("Sleep time"), F("sleeptime"), + PCONFIG(0), + 0, 30); + addUnit(F("Minutes")); + addFormNote(F("0 = continous, 1..30 = Work 30 seconds and sleep n*60-30 seconds")); + } + break; + } + case PLUGIN_WEBFORM_SAVE: + { + if (validGpio(CONFIG_PIN2)) { + // Communications to device should work. + const int newsleeptime = getFormItemInt(F("sleeptime")); + + if (PCONFIG(0) != newsleeptime) { + PCONFIG(0) = newsleeptime; + Plugin_056_setWorkingPeriod(newsleeptime); + } + } + success = true; + break; + } + + case PLUGIN_INIT: + { + if (Plugin_056_SDS) { + delete Plugin_056_SDS; + } + + const ESPEasySerialPort port = static_cast(CONFIG_PORT); + Plugin_056_SDS = new (std::nothrow) CjkSDS011(port, CONFIG_PIN1, CONFIG_PIN2); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, strformat(F("SDS : Init OK ESP GPIO-pin RX:%d TX:%d"), CONFIG_PIN1, CONFIG_PIN2)); + } + + success = true; + break; + } + + case PLUGIN_EXIT: + { + // //FIXME: if this plugin is used more than once at the same time, things go horribly wrong :) + // FIXME TD-er: Must implement plugin_data_struct for this + // + // if (Plugin_056_SDS) + // delete Plugin_056_SDS; + // addLog(LOG_LEVEL_INFO, F("SDS : Exit")); + shouldReboot = true; + break; + } + + case PLUGIN_FIFTY_PER_SECOND: + { + if (!Plugin_056_SDS) { + break; + } + + Plugin_056_SDS->Process(); + + if (Plugin_056_SDS->available()) + { + const float pm2_5 = Plugin_056_SDS->GetPM2_5(); + const float pm10 = Plugin_056_SDS->GetPM10_(); + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLog(LOG_LEVEL_DEBUG, strformat(F("SDS : act %.2f %.2f"), pm2_5, pm10)); + } + # endif // ifndef BUILD_NO_DEBUG + + if (Settings.TaskDeviceTimer[event->TaskIndex] == 0) + { + UserVar.setFloat(event->TaskIndex, 0, pm2_5); + UserVar.setFloat(event->TaskIndex, 1, pm10); + event->sensorType = Sensor_VType::SENSOR_TYPE_DUAL; + sendData(event); + } + } + + success = true; + break; + } + + case PLUGIN_READ: + { + if (!Plugin_056_SDS) { + break; + } + + float pm25, pm10; + + if (Plugin_056_SDS->ReadAverage(pm25, pm10)) { + UserVar.setFloat(event->TaskIndex, 0, pm25); + UserVar.setFloat(event->TaskIndex, 1, pm10); + success = true; + } + break; + } + } + + return success; +} + +String Plugin_056_ErrorToString(int error) { + String log; + + if (error < 0) { + log = concat(F("comm error: "), error); + } + return log; +} + +String Plugin_056_WorkingPeriodToString(int workingPeriod) { + if (workingPeriod < 0) { + return Plugin_056_ErrorToString(workingPeriod); + } + String log; + + if (workingPeriod > 0) { + log = strformat(F("%d minutes"), workingPeriod); + } else { + log = F(" continuous"); + } + return log; +} + +void Plugin_056_setWorkingPeriod(int minutes) { + if (!Plugin_056_SDS) { + return; + } + Plugin_056_SDS->SetWorkingPeriod(minutes); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, concat(F("SDS : Working Period set to: "), Plugin_056_WorkingPeriodToString(minutes))); + } +} + +// #endif +#endif // USES_P056 diff --git a/src/_P057_HT16K33_LED.ino b/src/_P057_HT16K33_LED.ino index dfc7bca5ff..f0f6eb0afd 100644 --- a/src/_P057_HT16K33_LED.ino +++ b/src/_P057_HT16K33_LED.ino @@ -1,417 +1,400 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P057 - -// ####################################################################################################### -// #################################### Plugin 057: HT16K33 LED ########################################## -// ####################################################################################################### - -// ESPEasy Plugin to control a 16x8 LED matrix or 8 7-segment displays with chip HT16K33 -// written by Jochen Krapf (jk@nerd2nerd.org) - -/** Changelog: - * 2024-12-14 tonhuisman: Fix mprint command to skip the colon segment when printing a non-colon character in that position. - * 2024-12 tonhuisman: Start changelog. - */ - -// List of commands: -// (1) M,,,, ... with decimal values -// (2) MX,,,, ... with hexadecimal values -// (3) MNUM,,,, ... with decimal values for 7-segment displays -// (4) MPRINT, with decimal values for 7-segment displays -// (5) MBR,<0-15> set display brightness, between 0 and 15 - -// List of M* params: -// (a) -// Writes a decimal / hexadecimal (0...0xFFFF) values to actual segment starting with 0 -// (b) = -// Writes a decimal / hexadecimal (0...0xFFFF) values to given segment (0...7) -// (c) "CLEAR" -// Set all LEDs to 0. -// (d) "TEST" -// Set test pattern to LED buffer. -// (e) "LOG" -// Print LED buffer to log output. - -// Examples: -// MX,AA,55,AA,55,AA,55,AA,55 Set chess pattern to LED buffer -// MNUM,CLEAR,1,0 Clear the LED buffer and then set 0x06 to 1st segment and 0x3F to 2nd segment - -// Connecting LEDs to HT16K33-board: -// Cathode for Column 0 = C0 -// Cathode for Column 1 = C1 -// ... -// Cathode for Column 7 = C7 -// -// Anode for bit 0x0001 = A0 -// Anode for bit 0x0002 = A1 -// ... -// Anode for bit 0x0080 = A7 -// ... -// Anode for bit 0x8000 = A15 - -// Note: The HT16K33-LED-plugin and the HT16K33-key-plugin can be used at the same time with the same I2C address - -// Clock Display: -// This plugin also allows a "clock" mode. In clock mode the display will show -// the current system time. The "7-Seg. Clock" needs to be configured for this -// mode to work. Each segment number (0..5) needs to be set based on your -// display. -// -// For my _Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display_ these -// settings are as follows: -// Xx:xx = 0, xX:xx = 1, -// xx:Xx = 3, xx:xX = 4 -// Seg. for Colon is 2 with a value of 2 -// -// Any other data written to the display will show and be replaced at the next -// clock cycle, e.g. when the plugin received 'PLUGIN_CLOCK_IN'. -// -// NOTE: The system time is set via NTP as part of the Core ESPEasy firmware. -// There is no configuration here to set or manipulate the time, only to -// display it. - -# define PLUGIN_057 -# define PLUGIN_ID_057 57 -# define PLUGIN_NAME_057 "Display - HT16K33" - - -# include "src/PluginStructs/P057_data_struct.h" - -boolean Plugin_057(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_057; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; - Device[deviceCount].TimerOptional = false; - Device[deviceCount].GlobalSyncOption = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_057); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: - { - const uint8_t i2cAddressValues[] = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77 }; - - if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - addFormSelectorI2C(F("i2c_addr"), 8, i2cAddressValues, PCONFIG(0)); - } else { - success = intArrayContains(8, i2cAddressValues, event->Par1); - } - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = PCONFIG(0); - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_WEBFORM_LOAD: - { - addFormSubHeader(F("7-Seg. Clock")); - - { - const __FlashStringHelper *options[3] = { F("none"), F("7-Seg. HH:MM (24 hour)"), F("7-Seg. HH:MM (12 hour)") }; - addFormSelector(F("Clock Type"), F("clocktype"), 3, options, nullptr, PCONFIG(1)); - } - - addFormNumericBox(F("Seg. for Xx:xx"), F("csh10"), PCONFIG(2), 0, 7); - addFormNumericBox(F("Seg. for xX:xx"), F("csh1"), PCONFIG(3), 0, 7); - addFormNumericBox(F("Seg. for xx:Xx"), F("csm10"), PCONFIG(4), 0, 7); - addFormNumericBox(F("Seg. for xx:xX"), F("csm1"), PCONFIG(5), 0, 7); - - addFormNumericBox(F("Seg. for Colon"), F("cscol"), PCONFIG(6), -1, 7); - addHtml(F(" Value ")); - addNumericBox(F("cscolval"), PCONFIG(7), 0, 255); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(0) = getFormItemInt(F("i2c_addr")); - - PCONFIG(1) = getFormItemInt(F("clocktype")); - - PCONFIG(2) = getFormItemInt(F("csh10")); - PCONFIG(3) = getFormItemInt(F("csh1")); - PCONFIG(4) = getFormItemInt(F("csm10")); - PCONFIG(5) = getFormItemInt(F("csm1")); - PCONFIG(6) = getFormItemInt(F("cscol")); - PCONFIG(7) = getFormItemInt(F("cscolval")); - - success = true; - break; - } - - case PLUGIN_INIT: - { - success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P057_data_struct(PCONFIG(0))); - break; - } - - case PLUGIN_WRITE: - { - P057_data_struct *P057_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P057_data) { - return false; - } - - String command = parseString(string, 1); - - if (equals(command, F("mprint"))) - { - const String text = parseStringToEnd(string, 2); - - if (!text.isEmpty()) { - uint8_t seg = 0; - uint8_t txt = 0; // Separate indexers for text and segments - bool setDot; - - P057_data->ledMatrix.ClearRowBuffer(); - - while (txt < text.length() && text[txt] && seg < 8) - { - setDot = (txt < text.length() - 1 && text[txt + 1] == '.'); - char c = text[txt]; - - if ((':' != c) && (PCONFIG(6) > -1) && (seg == PCONFIG(6))) { // skip the colon segment when not putting a colon there - seg++; - } - P057_data->ledMatrix.SetDigit(seg, c, setDot); - seg++; - txt++; - - if (setDot) { txt++; } // extra increment to skip past the dot - } - P057_data->ledMatrix.TransmitRowBuffer(); - success = true; - } - } - else if (equals(command, F("mbr"))) { - const String param = parseString(string, 2); - int32_t brightness; - - if (validIntFromString(param, brightness)) { - if ((brightness >= 0) && (brightness <= 255)) { - P057_data->ledMatrix.SetBrightness(brightness); - } - } - success = true; - } - else if ((equals(command, 'm')) || (equals(command, F("mx"))) || (equals(command, F("mnum")))) - { - String param; - String paramKey; - String paramVal; - uint8_t paramIdx = 2; - uint8_t seg = 0; - uint16_t value = 0; - - String lowerString = string; - lowerString.toLowerCase(); - lowerString.replace(F(" "), F(" ")); - lowerString.replace(F(" ="), F("=")); - lowerString.replace(F("= "), F("=")); - - param = parseStringKeepCase(lowerString, paramIdx++); - - if (param.length()) - { - while (param.length()) - { - # ifndef BUILD_NO_DEBUG - addLog(LOG_LEVEL_DEBUG_MORE, param); - # endif // ifndef BUILD_NO_DEBUG - - if (equals(param, F("log"))) - { - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("MX : "); - - for (uint8_t i = 0; i < 8; ++i) - { - log += formatToHex_no_prefix(P057_data->ledMatrix.GetRow(i)); - log += F("h, "); - } - addLogMove(LOG_LEVEL_INFO, log); - } - success = true; - } - - else if (equals(param, F("test"))) - { - for (uint8_t i = 0; i < 8; ++i) { - P057_data->ledMatrix.SetRow(i, 1 << i); - } - success = true; - } - - else if (equals(param, F("clear"))) - { - P057_data->ledMatrix.ClearRowBuffer(); - success = true; - } - - else - { - int index = param.indexOf('='); - - if (index > 0) // syntax: "=" - { - paramKey = param.substring(0, index); - paramVal = param.substring(index + 1); - seg = paramKey.toInt(); - } - else // syntax: "" - { - paramVal = param; - } - - if (equals(command, F("mnum"))) - { - value = paramVal.toInt(); - - if (value < 16) { - P057_data->ledMatrix.SetDigit(seg, value); - } - else { - P057_data->ledMatrix.SetRow(seg, value); - } - } - else if (equals(command, F("mx"))) - { - char *ep; - value = strtol(paramVal.c_str(), &ep, 16); - P057_data->ledMatrix.SetRow(seg, value); - } - else - { - value = paramVal.toInt(); - P057_data->ledMatrix.SetRow(seg, value); - } - - success = true; - seg++; - } - - param = parseStringKeepCase(lowerString, paramIdx++); - } - } - else - { - // ??? no params - } - - if (success) { - P057_data->ledMatrix.TransmitRowBuffer(); - } - success = true; - } - - break; - } - - case PLUGIN_CLOCK_IN: - { - P057_data_struct *P057_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if ((nullptr == P057_data) || (PCONFIG(1) == 0)) { - break; - } - - uint8_t hours = node_time.hour(); - const uint8_t minutes = node_time.minute(); - - // P057_data->ledMatrix.ClearRowBuffer(); - P057_data->ledMatrix.SetDigit(PCONFIG(5), minutes % 10); - P057_data->ledMatrix.SetDigit(PCONFIG(4), minutes / 10); - - if (PCONFIG(1) == 1) { // 24-hour clock - // 24-hour clock shows leading zero - P057_data->ledMatrix.SetDigit(PCONFIG(2), hours / 10); - P057_data->ledMatrix.SetDigit(PCONFIG(3), hours % 10); - } else if (PCONFIG(1) == 2) { // 12-hour clock - if (hours < 12) { - // to set AM marker, get buffer and add decimal to it. - P057_data->ledMatrix.SetRow(PCONFIG(5), (P057_data->ledMatrix.GetRow(PCONFIG(5)) | 0x80)); - } - - hours = hours % 12; - - if (hours == 0) { - hours = 12; - } - - P057_data->ledMatrix.SetDigit(PCONFIG(3), hours % 10); - - if (hours < 10) { - // 12-hour clock will show empty segment when hours < 10 - P057_data->ledMatrix.SetRow(PCONFIG(2), 0); - } else { - P057_data->ledMatrix.SetDigit(PCONFIG(2), hours / 10); - } - } - - // if (PCONFIG(6) >= 0) - // P057_data->ledMatrix.SetRow(PCONFIG(6), PCONFIG(7)); - P057_data->ledMatrix.TransmitRowBuffer(); - - success = true; - - break; - } - - case PLUGIN_TEN_PER_SECOND: - { - P057_data_struct *P057_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if ((nullptr == P057_data) || (PCONFIG(1) == 0)) { // clock enabled? - break; - } - - if (PCONFIG(6) >= 0) // colon used? - { - const uint8_t act = ((uint16_t)millis() >> 9) & 1; // blink with about 2 Hz - static uint8_t last = 0; - - if (act != last) - { - last = act; - P057_data->ledMatrix.SetRow(PCONFIG(6), (act) ? PCONFIG(7) : 0); - P057_data->ledMatrix.TransmitRowBuffer(); - } - } - } - } - return success; -} - -#endif // USES_P057 +#include "_Plugin_Helper.h" +#ifdef USES_P057 + +// ####################################################################################################### +// #################################### Plugin 057: HT16K33 LED ########################################## +// ####################################################################################################### + +// ESPEasy Plugin to control a 16x8 LED matrix or 8 7-segment displays with chip HT16K33 +// written by Jochen Krapf (jk@nerd2nerd.org) + +/** Changelog: + * 2024-12-14 tonhuisman: Fix mprint command to skip the colon segment when printing a non-colon character in that position. + * 2024-12 tonhuisman: Start changelog. + */ + +// List of commands: +// (1) M,,,, ... with decimal values +// (2) MX,,,, ... with hexadecimal values +// (3) MNUM,,,, ... with decimal values for 7-segment displays +// (4) MPRINT, with decimal values for 7-segment displays +// (5) MBR,<0-15> set display brightness, between 0 and 15 + +// List of M* params: +// (a) +// Writes a decimal / hexadecimal (0...0xFFFF) values to actual segment starting with 0 +// (b) = +// Writes a decimal / hexadecimal (0...0xFFFF) values to given segment (0...7) +// (c) "CLEAR" +// Set all LEDs to 0. +// (d) "TEST" +// Set test pattern to LED buffer. +// (e) "LOG" +// Print LED buffer to log output. + +// Examples: +// MX,AA,55,AA,55,AA,55,AA,55 Set chess pattern to LED buffer +// MNUM,CLEAR,1,0 Clear the LED buffer and then set 0x06 to 1st segment and 0x3F to 2nd segment + +// Connecting LEDs to HT16K33-board: +// Cathode for Column 0 = C0 +// Cathode for Column 1 = C1 +// ... +// Cathode for Column 7 = C7 +// +// Anode for bit 0x0001 = A0 +// Anode for bit 0x0002 = A1 +// ... +// Anode for bit 0x0080 = A7 +// ... +// Anode for bit 0x8000 = A15 + +// Note: The HT16K33-LED-plugin and the HT16K33-key-plugin can be used at the same time with the same I2C address + +// Clock Display: +// This plugin also allows a "clock" mode. In clock mode the display will show +// the current system time. The "7-Seg. Clock" needs to be configured for this +// mode to work. Each segment number (0..5) needs to be set based on your +// display. +// +// For my _Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display_ these +// settings are as follows: +// Xx:xx = 0, xX:xx = 1, +// xx:Xx = 3, xx:xX = 4 +// Seg. for Colon is 2 with a value of 2 +// +// Any other data written to the display will show and be replaced at the next +// clock cycle, e.g. when the plugin received 'PLUGIN_CLOCK_IN'. +// +// NOTE: The system time is set via NTP as part of the Core ESPEasy firmware. +// There is no configuration here to set or manipulate the time, only to +// display it. + +# define PLUGIN_057 +# define PLUGIN_ID_057 57 +# define PLUGIN_NAME_057 "Display - HT16K33" + + +# include "src/PluginStructs/P057_data_struct.h" + +boolean Plugin_057(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_057; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_057); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: + { + const uint8_t i2cAddressValues[] = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77 }; + + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { + addFormSelectorI2C(F("i2c_addr"), 8, i2cAddressValues, PCONFIG(0)); + } else { + success = intArrayContains(8, i2cAddressValues, event->Par1); + } + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = PCONFIG(0); + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_WEBFORM_LOAD: + { + addFormSubHeader(F("7-Seg. Clock")); + + { + const __FlashStringHelper *options[3] = { F("none"), F("7-Seg. HH:MM (24 hour)"), F("7-Seg. HH:MM (12 hour)") }; + addFormSelector(F("Clock Type"), F("clocktype"), 3, options, nullptr, PCONFIG(1)); + } + + addFormNumericBox(F("Seg. for Xx:xx"), F("csh10"), PCONFIG(2), 0, 7); + addFormNumericBox(F("Seg. for xX:xx"), F("csh1"), PCONFIG(3), 0, 7); + addFormNumericBox(F("Seg. for xx:Xx"), F("csm10"), PCONFIG(4), 0, 7); + addFormNumericBox(F("Seg. for xx:xX"), F("csm1"), PCONFIG(5), 0, 7); + + addFormNumericBox(F("Seg. for Colon"), F("cscol"), PCONFIG(6), -1, 7); + addHtml(F(" Value ")); + addNumericBox(F("cscolval"), PCONFIG(7), 0, 255); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(0) = getFormItemInt(F("i2c_addr")); + + PCONFIG(1) = getFormItemInt(F("clocktype")); + + PCONFIG(2) = getFormItemInt(F("csh10")); + PCONFIG(3) = getFormItemInt(F("csh1")); + PCONFIG(4) = getFormItemInt(F("csm10")); + PCONFIG(5) = getFormItemInt(F("csm1")); + PCONFIG(6) = getFormItemInt(F("cscol")); + PCONFIG(7) = getFormItemInt(F("cscolval")); + + success = true; + break; + } + + case PLUGIN_INIT: + { + success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P057_data_struct(PCONFIG(0))); + break; + } + + case PLUGIN_WRITE: + { + P057_data_struct *P057_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P057_data) { + return false; + } + + String command = parseString(string, 1); + + if (equals(command, F("mprint"))) + { + const String text = parseStringToEnd(string, 2); + + if (!text.isEmpty()) { + uint8_t seg = 0; + uint8_t txt = 0; // Separate indexers for text and segments + bool setDot; + + P057_data->ledMatrix.ClearRowBuffer(); + + while (txt < text.length() && text[txt] && seg < 8) + { + setDot = (txt < text.length() - 1 && text[txt + 1] == '.'); + char c = text[txt]; + + if ((':' != c) && (PCONFIG(6) > -1) && (seg == PCONFIG(6))) { // skip the colon segment when not putting a colon there + seg++; + } + P057_data->ledMatrix.SetDigit(seg, c, setDot); + seg++; + txt++; + + if (setDot) { txt++; } // extra increment to skip past the dot + } + P057_data->ledMatrix.TransmitRowBuffer(); + success = true; + } + } + else if (equals(command, F("mbr"))) { + const String param = parseString(string, 2); + int32_t brightness; + + if (validIntFromString(param, brightness)) { + if ((brightness >= 0) && (brightness <= 255)) { + P057_data->ledMatrix.SetBrightness(brightness); + } + } + success = true; + } + else if ((equals(command, 'm')) || (equals(command, F("mx"))) || (equals(command, F("mnum")))) + { + String param; + String paramKey; + String paramVal; + uint8_t paramIdx = 2; + uint8_t seg = 0; + uint16_t value = 0; + + String lString = string; + lString.replace(F(" "), F(" ")); + lString.replace(F(" ="), F("=")); + lString.replace(F("= "), F("=")); + + param = parseString(lString, paramIdx++); + + while (!param.isEmpty()) + { + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG_MORE, param); + # endif // ifndef BUILD_NO_DEBUG + + if (equals(param, F("log"))) + { + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("MX : "); + + for (uint8_t i = 0; i < 8; ++i) + { + log += formatToHex_no_prefix(P057_data->ledMatrix.GetRow(i)); + log += F("h, "); + } + addLogMove(LOG_LEVEL_INFO, log); + } + success = true; + } + + else if (equals(param, F("test"))) + { + for (uint8_t i = 0; i < 8; ++i) { + P057_data->ledMatrix.SetRow(i, 1 << i); + } + success = true; + } + + else if (equals(param, F("clear"))) + { + P057_data->ledMatrix.ClearRowBuffer(); + success = true; + } + + else + { + const int index = param.indexOf('='); + + if (index > 0) // syntax: "=" + { + paramKey = param.substring(0, index); + paramVal = param.substring(index + 1); + seg = paramKey.toInt(); + } + else // syntax: "" + { + paramVal = param; + } + + if (equals(command, F("mnum"))) + { + value = paramVal.toInt(); + + if (value < 16) { + P057_data->ledMatrix.SetDigit(seg, value); + } + else { + P057_data->ledMatrix.SetRow(seg, value); + } + } + else if (equals(command, F("mx"))) + { + char *ep; + value = strtol(paramVal.c_str(), &ep, 16); + P057_data->ledMatrix.SetRow(seg, value); + } + else + { + value = paramVal.toInt(); + P057_data->ledMatrix.SetRow(seg, value); + } + + success = true; + seg++; + } + + param = parseString(lString, paramIdx++); + } + + if (success) { + P057_data->ledMatrix.TransmitRowBuffer(); + } + success = true; + } + + break; + } + + case PLUGIN_CLOCK_IN: + { + P057_data_struct *P057_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if ((nullptr == P057_data) || (PCONFIG(1) == 0)) { + break; + } + + uint8_t hours = node_time.hour(); + const uint8_t minutes = node_time.minute(); + + // P057_data->ledMatrix.ClearRowBuffer(); + P057_data->ledMatrix.SetDigit(PCONFIG(5), minutes % 10); + P057_data->ledMatrix.SetDigit(PCONFIG(4), minutes / 10); + + if (PCONFIG(1) == 1) { // 24-hour clock + // 24-hour clock shows leading zero + P057_data->ledMatrix.SetDigit(PCONFIG(2), hours / 10); + P057_data->ledMatrix.SetDigit(PCONFIG(3), hours % 10); + } else if (PCONFIG(1) == 2) { // 12-hour clock + if (hours < 12) { + // to set AM marker, get buffer and add decimal to it. + P057_data->ledMatrix.SetRow(PCONFIG(5), (P057_data->ledMatrix.GetRow(PCONFIG(5)) | 0x80)); + } + + hours = hours % 12; + + if (hours == 0) { + hours = 12; + } + + P057_data->ledMatrix.SetDigit(PCONFIG(3), hours % 10); + + if (hours < 10) { + // 12-hour clock will show empty segment when hours < 10 + P057_data->ledMatrix.SetRow(PCONFIG(2), 0); + } else { + P057_data->ledMatrix.SetDigit(PCONFIG(2), hours / 10); + } + } + + // if (PCONFIG(6) >= 0) + // P057_data->ledMatrix.SetRow(PCONFIG(6), PCONFIG(7)); + P057_data->ledMatrix.TransmitRowBuffer(); + + success = true; + + break; + } + + case PLUGIN_TEN_PER_SECOND: + { + P057_data_struct *P057_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if ((nullptr == P057_data) || (PCONFIG(1) == 0)) { // clock enabled? + break; + } + + if (PCONFIG(6) >= 0) // colon used? + { + const uint8_t act = ((uint16_t)millis() >> 9) & 1; // blink with about 2 Hz + static uint8_t last = 0; + + if (act != last) + { + last = act; + P057_data->ledMatrix.SetRow(PCONFIG(6), (act) ? PCONFIG(7) : 0); + P057_data->ledMatrix.TransmitRowBuffer(); + } + } + } + } + return success; +} + +#endif // USES_P057 diff --git a/src/_P058_HT16K33_KeyPad.ino b/src/_P058_HT16K33_KeyPad.ino index ac3fa78970..7a0c23e80a 100644 --- a/src/_P058_HT16K33_KeyPad.ino +++ b/src/_P058_HT16K33_KeyPad.ino @@ -1,151 +1,146 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P058 - -// ####################################################################################################### -// #################################### Plugin 058: HT16K33 KeyPad ####################################### -// ####################################################################################################### - -// ESPEasy Plugin to scan a 13x3 key pad matrix chip HT16K33 -// written by Jochen Krapf (jk@nerd2nerd.org) - -// Connecting KeyPad to HT16K33-board: -// Column 1 = C1 (over diode) -// Column 2 = C2 (over diode) -// Column 3 = C3 (over diode) -// Row 1 = A3 -// Row 2 = A4 -// Row 3 = A5 -// ... -// Row 13 = A15 - -// ScanCode; -// 16*Column + Row -// Pressing the top left key (typically "1") the code is 17 (0x11) -// Pressing the key in column 2 and row 3 (typically "8") the code is 35 (0x23) - -// Use diodes (e.g. 1N4148) for column lines: -// HT16K33]-----|>|-----[key-matrix - -// Note: The HT16K33-LED-plugin and the HT16K33-key-plugin can be used at the same time with the same I2C address - - -# define PLUGIN_058 -# define PLUGIN_ID_058 58 -# define PLUGIN_NAME_058 "Keypad - HT16K33" -# define PLUGIN_VALUENAME1_058 "ScanCode" - - -# include "src/PluginStructs/P058_data_struct.h" - - -boolean Plugin_058(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_058; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_058); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_058)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: - { - const uint8_t i2cAddressValues[] = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77 }; - - if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - addFormSelectorI2C(F("i2c_addr"), 8, i2cAddressValues, PCONFIG(0)); - } else { - success = intArrayContains(8, i2cAddressValues, event->Par1); - } - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = PCONFIG(0); - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_WEBFORM_LOAD: - { - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(0) = getFormItemInt(F("i2c_addr")); - - success = true; - break; - } - - case PLUGIN_INIT: - { - success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P058_data_struct(PCONFIG(0))); - break; - } - - case PLUGIN_TEN_PER_SECOND: - { - P058_data_struct *P058_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P058_data) { - uint8_t key; - - if (P058_data->readKey(key)) - { - UserVar.setFloat(event->TaskIndex, 0, key); - event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH; - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, strformat(F("Mkey : key=0x%x"), key)); - } - - sendData(event); - } - } - success = true; - break; - } - - case PLUGIN_READ: - { - success = true; - break; - } - } - return success; -} - -#endif // USES_P058 +#include "_Plugin_Helper.h" +#ifdef USES_P058 + +// ####################################################################################################### +// #################################### Plugin 058: HT16K33 KeyPad ####################################### +// ####################################################################################################### + +// ESPEasy Plugin to scan a 13x3 key pad matrix chip HT16K33 +// written by Jochen Krapf (jk@nerd2nerd.org) + +// Connecting KeyPad to HT16K33-board: +// Column 1 = C1 (over diode) +// Column 2 = C2 (over diode) +// Column 3 = C3 (over diode) +// Row 1 = A3 +// Row 2 = A4 +// Row 3 = A5 +// ... +// Row 13 = A15 + +// ScanCode; +// 16*Column + Row +// Pressing the top left key (typically "1") the code is 17 (0x11) +// Pressing the key in column 2 and row 3 (typically "8") the code is 35 (0x23) + +// Use diodes (e.g. 1N4148) for column lines: +// HT16K33]-----|>|-----[key-matrix + +// Note: The HT16K33-LED-plugin and the HT16K33-key-plugin can be used at the same time with the same I2C address + + +# define PLUGIN_058 +# define PLUGIN_ID_058 58 +# define PLUGIN_NAME_058 "Keypad - HT16K33" +# define PLUGIN_VALUENAME1_058 "ScanCode" + + +# include "src/PluginStructs/P058_data_struct.h" + + +boolean Plugin_058(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_058; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_058); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_058)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: + { + const uint8_t i2cAddressValues[] = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77 }; + + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { + addFormSelectorI2C(F("i2c_addr"), 8, i2cAddressValues, PCONFIG(0)); + } else { + success = intArrayContains(8, i2cAddressValues, event->Par1); + } + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = PCONFIG(0); + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_WEBFORM_LOAD: + { + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(0) = getFormItemInt(F("i2c_addr")); + + success = true; + break; + } + + case PLUGIN_INIT: + { + success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P058_data_struct(PCONFIG(0))); + break; + } + + case PLUGIN_TEN_PER_SECOND: + { + P058_data_struct *P058_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P058_data) { + uint8_t key; + + if (P058_data->readKey(key)) + { + UserVar.setFloat(event->TaskIndex, 0, key); + event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH; + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, strformat(F("Mkey : key=0x%x"), key)); + } + + sendData(event); + } + } + success = true; + break; + } + + case PLUGIN_READ: + { + success = true; + break; + } + } + return success; +} + +#endif // USES_P058 diff --git a/src/_P059_Encoder.ino b/src/_P059_Encoder.ino index cb34f16f5b..5596aeeef3 100644 --- a/src/_P059_Encoder.ino +++ b/src/_P059_Encoder.ino @@ -1,211 +1,210 @@ -#include "_Plugin_Helper.h" - -#ifdef USES_P059 - -// ####################################################################################################### -// #################################### Plugin 059: Rotary Encoder ####################################### -// ####################################################################################################### - -// ESPEasy Plugin to process the quadrature encoder interface signals (e.g. rotary encoder) -// written by Jochen Krapf (jk@nerd2nerd.org) - -// Connection: -// Use 1st and 2nd GPIO for encoders A and B signal. -// Optional use 3rd GPIO for encoders I signal to reset counter to 0 at first trigger. -// If counter runs in wrong direction, change A and B GPIOs in settings page - -// Note: Up to 4 encoders can be used simultaneously - - -# define PLUGIN_059 -# define PLUGIN_ID_059 59 -# define PLUGIN_NAME_059 "Switch Input - Rotary Encoder" -# define PLUGIN_VALUENAME1_059 "Counter" - -# include - -std::map > P_059_sensordefs; - -boolean Plugin_059(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_059; - Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_059); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_059)); - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: - { - event->String1 = formatGpioName_input(F("A (CLK)")); - event->String2 = formatGpioName_input(F("B (DT)")); - event->String3 = formatGpioName_input_optional(F("I (Z)")); - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - // default values - if ((PCONFIG_LONG(0) == 0) && (PCONFIG_LONG(1) == 0)) { - PCONFIG_LONG(1) = 100; - } - - { - const __FlashStringHelper *options[3] = { F("1"), F("2"), F("4") }; - int optionValues[3] = { 1, 2, 4 }; - addFormSelector(F("Mode"), F("mode"), 3, options, optionValues, PCONFIG(0)); - addUnit(F("pulses per cycle")); - } - - addFormNumericBox(F("Limit min."), F("limitmin"), PCONFIG_LONG(0)); - addFormNumericBox(F("Limit max."), F("limitmax"), PCONFIG_LONG(1)); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(0) = getFormItemInt(F("mode")); - - PCONFIG_LONG(0) = getFormItemInt(F("limitmin")); - PCONFIG_LONG(1) = getFormItemInt(F("limitmax")); - - success = true; - break; - } - - case PLUGIN_INIT: - { - portStatusStruct newStatus; - - // create sensor instance and add to std::map - P_059_sensordefs.erase(event->TaskIndex); - P_059_sensordefs[event->TaskIndex] = std::shared_ptr(new QEIx4); - - P_059_sensordefs[event->TaskIndex]->begin(CONFIG_PIN1, CONFIG_PIN2, CONFIG_PIN3, PCONFIG(0)); - P_059_sensordefs[event->TaskIndex]->setLimit(PCONFIG_LONG(0), PCONFIG_LONG(1)); - P_059_sensordefs[event->TaskIndex]->setIndexTrigger(true); - - ExtraTaskSettings.TaskDeviceValueDecimals[event->BaseVarIndex] = 0; - - String log = F("QEI : GPIO: "); - - for (uint8_t i = 0; i < 3; ++i) - { - int pin = PIN(i); - - if (pin >= 0) - { - // pinMode(pin, (Settings.TaskDevicePin1PullUp[event->TaskIndex]) ? INPUT_PULLUP : INPUT); - constexpr pluginID_t P059_PLUGIN_ID{PLUGIN_ID_059}; - - const uint32_t key = createKey(P059_PLUGIN_ID, pin); - - // WARNING: operator [] creates an entry in the map if key does not exist - newStatus = globalMapPortStatus[key]; - newStatus.task++; // add this GPIO/port as a task - newStatus.mode = PIN_MODE_INPUT; - newStatus.state = 0; - savePortStatus(key, newStatus); - - // setPinState(PLUGIN_ID_059, pin, PIN_MODE_INPUT, 0); - } - log += pin; - log += ' '; - } - addLogMove(LOG_LEVEL_INFO, log); - - success = true; - break; - } - - case PLUGIN_EXIT: - { - P_059_sensordefs.erase(event->TaskIndex); - break; - } - - case PLUGIN_TEN_PER_SECOND: - { - if (P_059_sensordefs.count(event->TaskIndex) != 0) - { - if (P_059_sensordefs[event->TaskIndex]->hasChanged()) - { - long c = P_059_sensordefs[event->TaskIndex]->read(); - UserVar.setFloat(event->TaskIndex, 0, c); - event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH; - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, concat(F("QEI : "), c)); - } - - sendData(event); - } - } - success = true; - break; - } - - case PLUGIN_READ: - { - if (P_059_sensordefs.count(event->TaskIndex) != 0) - { - UserVar.setFloat(event->TaskIndex, 0, P_059_sensordefs[event->TaskIndex]->read()); - } - success = true; - break; - } - - case PLUGIN_WRITE: - { - if (P_059_sensordefs.count(event->TaskIndex) != 0) - { - String command = parseString(string, 1); - - if (equals(command, F("encwrite"))) - { - if (event->Par1 >= 0) - { - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, concat(F("QEI : "), string)); - } - P_059_sensordefs[event->TaskIndex]->write(event->Par1); - Scheduler.schedule_task_device_timer(event->TaskIndex, millis()); - } - success = true; // Command is handled. - } - } - break; - } - } - return success; -} - -#endif // USES_P059 +#include "_Plugin_Helper.h" + +#ifdef USES_P059 + +// ####################################################################################################### +// #################################### Plugin 059: Rotary Encoder ####################################### +// ####################################################################################################### + +/** Changelog: + * 2025-01-04 tonhuisman: Minor code cleanup + */ + +// ESPEasy Plugin to process the quadrature encoder interface signals (e.g. rotary encoder) +// written by Jochen Krapf (jk@nerd2nerd.org) + +// Connection: +// Use 1st and 2nd GPIO for encoders A and B signal. +// Optional use 3rd GPIO for encoders I signal to reset counter to 0 at first trigger. +// If counter runs in wrong direction, change A and B GPIOs in settings page + +// Note: Up to 4 encoders can be used simultaneously + + +# define PLUGIN_059 +# define PLUGIN_ID_059 59 +# define PLUGIN_NAME_059 "Switch Input - Rotary Encoder" +# define PLUGIN_VALUENAME1_059 "Counter" + +# include + +std::map > P_059_sensordefs; + +boolean Plugin_059(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_059; + Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_059); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_059)); + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: + { + event->String1 = formatGpioName_input(F("A (CLK)")); + event->String2 = formatGpioName_input(F("B (DT)")); + event->String3 = formatGpioName_input_optional(F("I (Z)")); + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + // default values + if ((PCONFIG_LONG(0) == 0) && (PCONFIG_LONG(1) == 0)) { + PCONFIG_LONG(1) = 100; + } + + { + const __FlashStringHelper *options[] = { F("1"), F("2"), F("4") }; + const int optionValues[] = { 1, 2, 4 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Mode"), F("mode"), optionCount, options, optionValues, PCONFIG(0)); + addUnit(F("pulses per cycle")); + } + + addFormNumericBox(F("Limit min."), F("limitmin"), PCONFIG_LONG(0)); + addFormNumericBox(F("Limit max."), F("limitmax"), PCONFIG_LONG(1)); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(0) = getFormItemInt(F("mode")); + + PCONFIG_LONG(0) = getFormItemInt(F("limitmin")); + PCONFIG_LONG(1) = getFormItemInt(F("limitmax")); + + success = true; + break; + } + + case PLUGIN_INIT: + { + portStatusStruct newStatus; + + // create sensor instance and add to std::map + P_059_sensordefs.erase(event->TaskIndex); + P_059_sensordefs[event->TaskIndex] = std::shared_ptr(new QEIx4); + + P_059_sensordefs[event->TaskIndex]->begin(CONFIG_PIN1, CONFIG_PIN2, CONFIG_PIN3, PCONFIG(0)); + P_059_sensordefs[event->TaskIndex]->setLimit(PCONFIG_LONG(0), PCONFIG_LONG(1)); + P_059_sensordefs[event->TaskIndex]->setIndexTrigger(true); + + ExtraTaskSettings.TaskDeviceValueDecimals[event->BaseVarIndex] = 0; + + String log = F("QEI : GPIO: "); + + for (uint8_t i = 0; i < 3; ++i) + { + const int pin = PIN(i); + + if (validGpio(pin)) + { + // pinMode(pin, (Settings.TaskDevicePin1PullUp[event->TaskIndex]) ? INPUT_PULLUP : INPUT); + constexpr pluginID_t P059_PLUGIN_ID{ PLUGIN_ID_059 }; + + const uint32_t key = createKey(P059_PLUGIN_ID, pin); + + // WARNING: operator [] creates an entry in the map if key does not exist + newStatus = globalMapPortStatus[key]; + newStatus.task++; // add this GPIO/port as a task + newStatus.mode = PIN_MODE_INPUT; + newStatus.state = 0; + savePortStatus(key, newStatus); + + // setPinState(PLUGIN_ID_059, pin, PIN_MODE_INPUT, 0); + } + log += pin; + log += ' '; + } + addLogMove(LOG_LEVEL_INFO, log); + + success = true; + break; + } + + case PLUGIN_EXIT: + { + P_059_sensordefs.erase(event->TaskIndex); + break; + } + + case PLUGIN_TEN_PER_SECOND: + { + if (P_059_sensordefs.count(event->TaskIndex) != 0) + { + if (P_059_sensordefs[event->TaskIndex]->hasChanged()) + { + const long c = P_059_sensordefs[event->TaskIndex]->read(); + UserVar.setFloat(event->TaskIndex, 0, c); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, concat(F("QEI : "), c)); + } + + sendData(event); + } + } + success = true; + break; + } + + case PLUGIN_READ: + { + if (P_059_sensordefs.count(event->TaskIndex) != 0) + { + UserVar.setFloat(event->TaskIndex, 0, P_059_sensordefs[event->TaskIndex]->read()); + } + success = true; + break; + } + + case PLUGIN_WRITE: + { + if (P_059_sensordefs.count(event->TaskIndex) != 0) + { + const String command = parseString(string, 1); + + if (equals(command, F("encwrite"))) + { + if (event->Par1 >= 0) + { + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, concat(F("QEI : "), string)); + } + P_059_sensordefs[event->TaskIndex]->write(event->Par1); + Scheduler.schedule_task_device_timer(event->TaskIndex, millis()); + } + success = true; // Command is handled. + } + } + break; + } + } + return success; +} + +#endif // USES_P059 diff --git a/src/_P060_MCP3221.ino b/src/_P060_MCP3221.ino index 396ae0a150..b589de8987 100644 --- a/src/_P060_MCP3221.ino +++ b/src/_P060_MCP3221.ino @@ -1,180 +1,175 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P060 - -// ####################################################################################################### -// #################################### Plugin 060: MCP3221 ############################################## -// ####################################################################################################### - -// Plugin to read 12-bit-values from ADC chip MCP3221. It is used e.g. in MinipH pH interface to sample a pH probe in an aquarium -// written by Jochen Krapf (jk@nerd2nerd.org) - - -# include "src/PluginStructs/P060_data_struct.h" - -# define PLUGIN_060 -# define PLUGIN_ID_060 60 -# define PLUGIN_NAME_060 "Analog input - MCP3221" -# define PLUGIN_VALUENAME1_060 "Analog" - - -boolean Plugin_060(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_060; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_060); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_060)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: - { - const uint8_t i2cAddressValues[] = { 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F }; - - if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - addFormSelectorI2C(F("i2c_addr"), 8, i2cAddressValues, PCONFIG(0), 0x4D); - } else { - success = intArrayContains(8, i2cAddressValues, event->Par1); - } - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = PCONFIG(0); - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_SET_DEFAULTS: - { - PCONFIG(0) = 0x4D; // Default address - - success = true; - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - addFormCheckBox(F("Oversampling"), F("oversampling"), PCONFIG(1)); - - addFormSubHeader(F("Two Point Calibration")); - - addFormCheckBox(F("Calibration Enabled"), F("cal"), PCONFIG(3)); - - addFormNumericBox(F("Point 1"), F("adc1"), PCONFIG_LONG(0), 0, 4095); - html_add_estimate_symbol(); - addTextBox(F("out1"), toString(PCONFIG_FLOAT(0), 3), 10); - - addFormNumericBox(F("Point 2"), F("adc2"), PCONFIG_LONG(1), 0, 4095); - html_add_estimate_symbol(); - addTextBox(F("out2"), toString(PCONFIG_FLOAT(1), 3), 10); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(0) = getFormItemInt(F("i2c_addr")); - - PCONFIG(1) = isFormItemChecked(F("oversampling")); - - PCONFIG(3) = isFormItemChecked(F("cal")); - - PCONFIG_LONG(0) = getFormItemInt(F("adc1")); - PCONFIG_FLOAT(0) = getFormItemFloat(F("out1")); - - PCONFIG_LONG(1) = getFormItemInt(F("adc2")); - PCONFIG_FLOAT(1) = getFormItemFloat(F("out2")); - - success = true; - break; - } - - case PLUGIN_INIT: - { - success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P060_data_struct(PCONFIG(0))); - break; - } - - - case PLUGIN_TEN_PER_SECOND: - { - if (PCONFIG(1)) // Oversampling? - { - P060_data_struct *P060_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P060_data) { - P060_data->overSampleRead(); - success = true; - } - } - break; - } - - case PLUGIN_READ: - { - P060_data_struct *P060_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P060_data) { - UserVar.setFloat(event->TaskIndex, 0, P060_data->getValue()); - - String log = concat(F("ADMCP: Analog value: "), formatUserVarNoCheck(event, 0)); - - if (PCONFIG(3)) // Calibration? - { - int adc1 = PCONFIG_LONG(0); - int adc2 = PCONFIG_LONG(1); - float out1 = PCONFIG_FLOAT(0); - float out2 = PCONFIG_FLOAT(1); - - if (adc1 != adc2) - { - const float normalized = (UserVar[event->BaseVarIndex] - adc1) / static_cast(adc2 - adc1); - UserVar.setFloat(event->TaskIndex, 0, normalized * (out2 - out1) + out1); - - log += concat(F(" = "), formatUserVarNoCheck(event, 0)); - } - } - - addLogMove(LOG_LEVEL_INFO, log); - success = true; - } - break; - } - } - return success; -} - -#endif // USES_P060 +#include "_Plugin_Helper.h" +#ifdef USES_P060 + +// ####################################################################################################### +// #################################### Plugin 060: MCP3221 ############################################## +// ####################################################################################################### + +// Plugin to read 12-bit-values from ADC chip MCP3221. It is used e.g. in MinipH pH interface to sample a pH probe in an aquarium +// written by Jochen Krapf (jk@nerd2nerd.org) + + +# include "src/PluginStructs/P060_data_struct.h" + +# define PLUGIN_060 +# define PLUGIN_ID_060 60 +# define PLUGIN_NAME_060 "Analog input - MCP3221" +# define PLUGIN_VALUENAME1_060 "Analog" + + +boolean Plugin_060(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_060; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_060); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_060)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: + { + const uint8_t i2cAddressValues[] = { 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F }; + + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { + addFormSelectorI2C(F("i2c_addr"), 8, i2cAddressValues, PCONFIG(0), 0x4D); + } else { + success = intArrayContains(8, i2cAddressValues, event->Par1); + } + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = PCONFIG(0); + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_SET_DEFAULTS: + { + PCONFIG(0) = 0x4D; // Default address + + success = true; + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + addFormCheckBox(F("Oversampling"), F("oversampling"), PCONFIG(1)); + + addFormSubHeader(F("Two Point Calibration")); + + addFormCheckBox(F("Calibration Enabled"), F("cal"), PCONFIG(3)); + + addFormNumericBox(F("Point 1"), F("adc1"), PCONFIG_LONG(0), 0, 4095); + html_add_estimate_symbol(); + addTextBox(F("out1"), toString(PCONFIG_FLOAT(0), 3), 10); + + addFormNumericBox(F("Point 2"), F("adc2"), PCONFIG_LONG(1), 0, 4095); + html_add_estimate_symbol(); + addTextBox(F("out2"), toString(PCONFIG_FLOAT(1), 3), 10); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(0) = getFormItemInt(F("i2c_addr")); + + PCONFIG(1) = isFormItemChecked(F("oversampling")); + + PCONFIG(3) = isFormItemChecked(F("cal")); + + PCONFIG_LONG(0) = getFormItemInt(F("adc1")); + PCONFIG_FLOAT(0) = getFormItemFloat(F("out1")); + + PCONFIG_LONG(1) = getFormItemInt(F("adc2")); + PCONFIG_FLOAT(1) = getFormItemFloat(F("out2")); + + success = true; + break; + } + + case PLUGIN_INIT: + { + success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P060_data_struct(PCONFIG(0))); + break; + } + + case PLUGIN_TEN_PER_SECOND: + { + if (PCONFIG(1)) // Oversampling? + { + P060_data_struct *P060_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P060_data) { + P060_data->overSampleRead(); + success = true; + } + } + break; + } + + case PLUGIN_READ: + { + P060_data_struct *P060_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P060_data) { + UserVar.setFloat(event->TaskIndex, 0, P060_data->getValue()); + + String log = concat(F("ADMCP: Analog value: "), formatUserVarNoCheck(event, 0)); + + if (PCONFIG(3)) // Calibration? + { + const int adc1 = PCONFIG_LONG(0); + const int adc2 = PCONFIG_LONG(1); + const float out1 = PCONFIG_FLOAT(0); + const float out2 = PCONFIG_FLOAT(1); + + if (adc1 != adc2) + { + const float normalized = (UserVar[event->BaseVarIndex] - adc1) / static_cast(adc2 - adc1); + UserVar.setFloat(event->TaskIndex, 0, normalized * (out2 - out1) + out1); + + log += concat(F(" = "), formatUserVarNoCheck(event, 0)); + } + } + + addLogMove(LOG_LEVEL_INFO, log); + success = true; + } + break; + } + } + return success; +} + +#endif // USES_P060 diff --git a/src/_P061_KeyPad.ino b/src/_P061_KeyPad.ino index 8e73305a8d..ffc9a3b5bd 100644 --- a/src/_P061_KeyPad.ino +++ b/src/_P061_KeyPad.ino @@ -1,218 +1,208 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P061 - -// ####################################################################################################### -// ################################ Plugin 061: PCF8574/MCP23017/PCF8575 KeyPad ########################## -// ####################################################################################################### - -/** Changelog: - * 2022-01-23 tonhuisman: Add support for MCP23017 Direct mode, see https://github.com/letscontrolit/ESPEasy/issues/557 - * Add support for PCF8575 Matrix and Direct mode (requires pull-ups, 10-100k, on all 8 or 16 inputs!) - * Support for PCF8575 can be disabled by disabling #define P061_ENABLE_PCF8575 - * Add logging in low-level read functions - * 2022-01-22 tonhuisman: Make plugin multi-instance compatible, by moving most code to src/PluginStructs/P061_data_struct.* - * Replaced PCONFIG(x) macros by more meaningful named macros - * Formatted source using Uncrustify - * - * pre-2022-01 No changelog recorded - * Originally written by Jochen Krapf (jk@nerd2nerd.org) - */ - -// ESPEasy Plugin to scan a (up to) 9x8 key pad matrix chip MCP23017 -// or a (up to) 5x4 key pad matrix chip PCF8574 -// written by Jochen Krapf (jk@nerd2nerd.org) - -// Connecting KeyPad matrix to MCP23017 / PCF8575 chip: -// row 0 = GND (optional if 9 rows needed) -// row 1 = GPA0 / P00 -// row 2 = GPA1 / P01 -// ... -// row 8 = GPA7 / P07 -// -// column 1 = GPB0 / P10 -// column 2 = GPB1 / P11 -// ... -// column 8 = GPB7 / P17 - -// Typical Key Pad: -// C1 C2 C3 -// R1 [1] [2] [3] -// R2 [4] [5] [6] -// R3 [7] [8] [9] -// R4 [*] [0] [#] - -// Connecting KeyPad matrix to PCF8574 chip: -// row 0 = GND (optional if 5 rows needed) -// row 1 = P0 -// row 2 = P1 -// row 3 = P2 -// row 4 = P3 -// -// column 1 = P4 -// column 2 = P5 -// column 3 = P6 -// column 4 = P7 - -// Connecting KeyPad direct to PCF8574 / MCP23017 / PCF8575 chip: -// common = GND -// key 1 = P0 / GPA0 / P00 -// key 2 = P1 / GPA1 / P01 -// ... -// key 8 = P7 / GPA7 / P07 -// For 16 bit I/O expanders -// key 9 = -- / GPB0 / P10 -// key 10 = -- / GPB1 / P11 -// ... -// key 16 = -- / GPB7 / P17 -// NB: PCF8575 needs pull-up resistors on all 16 pins to work as intended, as the chip doesn't have internal pull-ups - -// ScanCode; -// 16*col + row -// Pressing the top left key (typically "1") the code is 17 (0x11) -// Pressing the key in rowumn 2 and col 3 (typically "8") the code is 35 (0x23) -// No key - the code 0 -// If more than one key is pressed, the scan code is the code with the lowest value - -# include "src/PluginStructs/P061_data_struct.h" - -# define PLUGIN_061 -# define PLUGIN_ID_061 61 -# define PLUGIN_NAME_061 "Keypad - PCF8574 / MCP23017 / PCF8575" -# define PLUGIN_VALUENAME1_061 "ScanCode" - - -boolean Plugin_061(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_061; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_061); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_061)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: - { - const uint8_t i2cAddressValues[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; - - if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - addFormSelectorI2C(F("i2c_addr"), - (P061_CONFIG_KEYPAD_TYPE == 0 || P061_CONFIG_KEYPAD_TYPE > 2) ? 8 : 16, - i2cAddressValues, - P061_CONFIG_I2C_ADDRESS); - - if ((P061_CONFIG_KEYPAD_TYPE == 1) || (P061_CONFIG_KEYPAD_TYPE == 2)) { // PCF8574(A) - addFormNote(F("PCF8574 uses address 0x20+; PCF8574A uses address 0x38+")); - } - } else { - success = intArrayContains(16, i2cAddressValues, event->Par1); - } - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = P061_CONFIG_I2C_ADDRESS; - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_WEBFORM_LOAD: - { - const __FlashStringHelper *options[] = { - F("MCP23017 (Matrix 9x8)"), - F("PCF8574 (Matrix 5x4)"), - F("PCF8574 (Direct 8)"), - F("MCP23017 (Direct 16)"), - # ifdef P061_ENABLE_PCF8575 - F("PCF8575 (Matrix 9x8)"), - F("PCF8575 (Direct 16)") - # endif // ifdef P061_ENABLE_PCF8575 - }; - const int optionsCount = - # ifdef P061_ENABLE_PCF8575 - 6; - # else // ifdef P061_ENABLE_PCF8575 - 4; - # endif // ifdef P061_ENABLE_PCF8575 - addFormSelector(F("Chip (Mode)"), F("chip"), optionsCount, options, nullptr, P061_CONFIG_KEYPAD_TYPE); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - P061_CONFIG_I2C_ADDRESS = getFormItemInt(F("i2c_addr")); - - P061_CONFIG_KEYPAD_TYPE = getFormItemInt(F("chip")); - - success = true; - break; - } - - case PLUGIN_INIT: - { - initPluginTaskData(event->TaskIndex, new (std::nothrow) P061_data_struct(P061_CONFIG_I2C_ADDRESS, P061_CONFIG_KEYPAD_TYPE)); - P061_data_struct *P061_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P061_data) { - return success; - } - - success = P061_data->plugin_init(event); - - break; - } - - case PLUGIN_FIFTY_PER_SECOND: - { - P061_data_struct *P061_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P061_data) { - return success; - } - - success = P061_data->plugin_fifty_per_second(event); - break; - } - - case PLUGIN_READ: - { - // work is done in PLUGIN_FIFTY_PER_SECOND - success = true; - break; - } - } - return success; -} - -#endif // USES_P061 +#include "_Plugin_Helper.h" +#ifdef USES_P061 + +// ####################################################################################################### +// ################################ Plugin 061: PCF8574/MCP23017/PCF8575 KeyPad ########################## +// ####################################################################################################### + +/** Changelog: + * 2022-01-23 tonhuisman: Add support for MCP23017 Direct mode, see https://github.com/letscontrolit/ESPEasy/issues/557 + * Add support for PCF8575 Matrix and Direct mode (requires pull-ups, 10-100k, on all 8 or 16 inputs!) + * Support for PCF8575 can be disabled by disabling #define P061_ENABLE_PCF8575 + * Add logging in low-level read functions + * 2022-01-22 tonhuisman: Make plugin multi-instance compatible, by moving most code to src/PluginStructs/P061_data_struct.* + * Replaced PCONFIG(x) macros by more meaningful named macros + * Formatted source using Uncrustify + * + * pre-2022-01 No changelog recorded + * Originally written by Jochen Krapf (jk@nerd2nerd.org) + */ + +// ESPEasy Plugin to scan a (up to) 9x8 key pad matrix chip MCP23017 +// or a (up to) 5x4 key pad matrix chip PCF8574 +// written by Jochen Krapf (jk@nerd2nerd.org) + +// Connecting KeyPad matrix to MCP23017 / PCF8575 chip: +// row 0 = GND (optional if 9 rows needed) +// row 1 = GPA0 / P00 +// row 2 = GPA1 / P01 +// ... +// row 8 = GPA7 / P07 +// +// column 1 = GPB0 / P10 +// column 2 = GPB1 / P11 +// ... +// column 8 = GPB7 / P17 + +// Typical Key Pad: +// C1 C2 C3 +// R1 [1] [2] [3] +// R2 [4] [5] [6] +// R3 [7] [8] [9] +// R4 [*] [0] [#] + +// Connecting KeyPad matrix to PCF8574 chip: +// row 0 = GND (optional if 5 rows needed) +// row 1 = P0 +// row 2 = P1 +// row 3 = P2 +// row 4 = P3 +// +// column 1 = P4 +// column 2 = P5 +// column 3 = P6 +// column 4 = P7 + +// Connecting KeyPad direct to PCF8574 / MCP23017 / PCF8575 chip: +// common = GND +// key 1 = P0 / GPA0 / P00 +// key 2 = P1 / GPA1 / P01 +// ... +// key 8 = P7 / GPA7 / P07 +// For 16 bit I/O expanders +// key 9 = -- / GPB0 / P10 +// key 10 = -- / GPB1 / P11 +// ... +// key 16 = -- / GPB7 / P17 +// NB: PCF8575 needs pull-up resistors on all 16 pins to work as intended, as the chip doesn't have internal pull-ups + +// ScanCode; +// 16*col + row +// Pressing the top left key (typically "1") the code is 17 (0x11) +// Pressing the key in rowumn 2 and col 3 (typically "8") the code is 35 (0x23) +// No key - the code 0 +// If more than one key is pressed, the scan code is the code with the lowest value + +# include "src/PluginStructs/P061_data_struct.h" + +# define PLUGIN_061 +# define PLUGIN_ID_061 61 +# define PLUGIN_NAME_061 "Keypad - PCF8574 / MCP23017 / PCF8575" +# define PLUGIN_VALUENAME1_061 "ScanCode" + + +boolean Plugin_061(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_061; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_061); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_061)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: + { + const uint8_t i2cAddressValues[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; + + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { + addFormSelectorI2C(F("i2c_addr"), + (P061_CONFIG_KEYPAD_TYPE == 0 || P061_CONFIG_KEYPAD_TYPE > 2) ? 8 : 16, + i2cAddressValues, + P061_CONFIG_I2C_ADDRESS); + + if ((P061_CONFIG_KEYPAD_TYPE == 1) || (P061_CONFIG_KEYPAD_TYPE == 2)) { // PCF8574(A) + addFormNote(F("PCF8574 uses address 0x20+; PCF8574A uses address 0x38+")); + } + } else { + success = intArrayContains(16, i2cAddressValues, event->Par1); + } + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = P061_CONFIG_I2C_ADDRESS; + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_WEBFORM_LOAD: + { + const __FlashStringHelper *options[] = { + F("MCP23017 (Matrix 9x8)"), + F("PCF8574 (Matrix 5x4)"), + F("PCF8574 (Direct 8)"), + F("MCP23017 (Direct 16)"), + # ifdef P061_ENABLE_PCF8575 + F("PCF8575 (Matrix 9x8)"), + F("PCF8575 (Direct 16)") + # endif // ifdef P061_ENABLE_PCF8575 + }; + constexpr int optionsCount = NR_ELEMENTS(options); + addFormSelector(F("Chip (Mode)"), F("chip"), optionsCount, options, nullptr, P061_CONFIG_KEYPAD_TYPE); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + P061_CONFIG_I2C_ADDRESS = getFormItemInt(F("i2c_addr")); + + P061_CONFIG_KEYPAD_TYPE = getFormItemInt(F("chip")); + + success = true; + break; + } + + case PLUGIN_INIT: + { + initPluginTaskData(event->TaskIndex, new (std::nothrow) P061_data_struct(P061_CONFIG_I2C_ADDRESS, P061_CONFIG_KEYPAD_TYPE)); + P061_data_struct *P061_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P061_data) { + return success; + } + + success = P061_data->plugin_init(event); + + break; + } + + case PLUGIN_FIFTY_PER_SECOND: + { + P061_data_struct *P061_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P061_data) { + return success; + } + + success = P061_data->plugin_fifty_per_second(event); + break; + } + + case PLUGIN_READ: + { + // work is done in PLUGIN_FIFTY_PER_SECOND + success = true; + break; + } + } + return success; +} + +#endif // USES_P061 diff --git a/src/_P062_MPR121_KeyPad.ino b/src/_P062_MPR121_KeyPad.ino index d329e99a61..85ba88dec4 100644 --- a/src/_P062_MPR121_KeyPad.ino +++ b/src/_P062_MPR121_KeyPad.ino @@ -1,373 +1,366 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P062 - -// ####################################################################################################### -// #################################### Plugin 062: MPR121 KeyPad ######################################## -// ####################################################################################################### - -// ESPEasy Plugin to scan a 12 key touch pad chip MPR121 -// written by Jochen Krapf (jk@nerd2nerd.org) -// 2021-12-29 tonhuisman: Add setting for panel sensitivity, as requested in https://github.com/letscontrolit/ESPEasy/issues/3828 -// Reformat source using Uncrustify -// 2020-10-14 tonhuisman: Added settings for global and per-sensor sensitivity -// and getting 'calibration' touch pressure data (current, min, max) - -// ScanCode; -// Value 1...12 for the key number -// No key - the code 0 -// If more than one key is pressed, the scan code is the code with the lowest value - -// If ScanCode is unchecked the value is the KeyMap 1.Key=1, 2.Key=2, 3.Key=4, 4.Key=8 ... 1.Key=2048 -// If more than one key is pressed, the value is sum of all KeyMap-values - - -# define PLUGIN_062 -# define PLUGIN_ID_062 62 -# define PLUGIN_NAME_062 "Keypad - MPR121 Touch" -# define PLUGIN_VALUENAME1_062 "ScanCode" - - -# include "src/PluginStructs/P062_data_struct.h" - -# define P062_FLAGS_USE_CALIBRATION 0 // Set in P062_CONFIG_FLAGS - -# define P062_CONFIG_FLAGS PCONFIG_LONG(0) // 0-31 flags - -# define P062_DEFAULT_TOUCH_TRESHOLD 12 // Defaults got from MPR_121 source -# define P062_DEFAULT_RELEASE_TRESHOLD 6 - -boolean Plugin_062(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_062; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].ExitTaskBeforeSave = false; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_062); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_062)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: - { - const uint8_t i2cAddressValues[] = { 0x5A, 0x5B, 0x5C, 0x5D }; - - if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - addFormSelectorI2C(F("i2c_addr"), 4, i2cAddressValues, PCONFIG(0)); - } else { - success = intArrayContains(4, i2cAddressValues, event->Par1); - } - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = PCONFIG(0); - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_WEBFORM_LOAD: - { - addFormCheckBox(F("ScanCode"), F("scancode"), PCONFIG(1)); - - addFormSubHeader(F("Sensitivity")); - { - uint8_t touch_treshold = PCONFIG(2); - - if (touch_treshold == 0) { - touch_treshold = P062_DEFAULT_TOUCH_TRESHOLD; // default value - } - addFormNumericBox(F("Touch treshold (1..255)"), F("touch_treshold"), touch_treshold, 0, 255); - addUnit(concat(F("Default: "), P062_DEFAULT_TOUCH_TRESHOLD)); - } - - { - uint8_t release_treshold = PCONFIG(3); - - if (release_treshold == 0) { - release_treshold = P062_DEFAULT_RELEASE_TRESHOLD; // default value - } - addFormNumericBox(F("Release treshold (1..255)"), F("release_treshold"), release_treshold, 0, 255); - addUnit(concat(F("Default: "), P062_DEFAULT_RELEASE_TRESHOLD)); - } - { - const __FlashStringHelper *sensitivityOptions[] = { - F("Normal"), - F("Extra sensitive (behind 4-6mm glass cover)") - }; - const int sensitivityValues[] = { - MPR212_NORMAL_SENSITIVITY, - MPR212_EXTRA_SENSITIVITY - }; - addFormSelector(F("Panel sensitivity"), F("panel_sensitivity"), 2, sensitivityOptions, sensitivityValues, PCONFIG(4)); - } - { - bool canCalibrate = true; - bool tbUseCalibration = bitRead(P062_CONFIG_FLAGS, P062_FLAGS_USE_CALIBRATION); - - P062_data_struct *P062_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P062_data) { - P062_data = new (std::nothrow) P062_data_struct(); - canCalibrate = false; - - if (P062_data == nullptr) { - return success; - } - } - P062_data->loadTouchObjects(event->TaskIndex); - - addRowLabel(F("Object")); - html_table(EMPTY_STRING, false); // Sub-table - html_table_header(F(" # ")); - html_table_header(F("Touch (0..255)")); - html_table_header(F("Release (0..255)")); - - if (tbUseCalibration && canCalibrate) { - html_table_header(F("Current")); - html_table_header(F("Min")); - html_table_header(F("Max")); - } - - for (int objectNr = 0; objectNr < P062_MaxTouchObjects; ++objectNr) { - html_TR_TD(); - addHtml(F(" ")); - addHtmlInt(objectNr + 1); - html_TD(); - addNumericBox(getPluginCustomArgName(objectNr + 100), P062_data->StoredSettings.TouchObjects[objectNr].touch, 0, 255); - html_TD(); - addNumericBox(getPluginCustomArgName(objectNr + 200), P062_data->StoredSettings.TouchObjects[objectNr].release, 0, 255); - - if (tbUseCalibration && canCalibrate) { - uint16_t current = 0; - uint16_t min = 0; - uint16_t max = 0; - P062_data->getCalibrationData(objectNr, ¤t, &min, &max); - html_TD(); - addHtmlInt(current); - html_TD(); - addHtmlInt(min); - html_TD(); - addHtmlInt(max); - } - } - html_end_table(); - - if (canCalibrate) { - const int choice1 = tbUseCalibration ? 1 : 0; - addFormSelector_YesNo(F("Enable Calibration"), F("use_calibration"), choice1, true); - - if (tbUseCalibration) { - addFormCheckBox(F("Clear calibrationdata"), F("clear_calibrate"), false); - } - } - delete P062_data; - } - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(0) = getFormItemInt(F("i2c_addr")); - - PCONFIG(1) = isFormItemChecked(F("scancode")); - - PCONFIG(2) = getFormItemInt(F("touch_treshold")); - PCONFIG(3) = getFormItemInt(F("release_treshold")); - PCONFIG(4) = getFormItemInt(F("panel_sensitivity")); - - uint32_t lSettings = 0; - bool tbUseCalibration = getFormItemInt(F("use_calibration")) == 1; - bitWrite(lSettings, P062_FLAGS_USE_CALIBRATION, tbUseCalibration); - P062_CONFIG_FLAGS = lSettings; - - { - bool canCalibrate = true; - P062_data_struct *P062_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P062_data) { - P062_data = new (std::nothrow) P062_data_struct(); - canCalibrate = false; - - if (P062_data == nullptr) { - return success; // Save other settings even though this didn't initialize properly - } - } - P062_data->loadTouchObjects(event->TaskIndex); - - for (int objectNr = 0; objectNr < P062_MaxTouchObjects; ++objectNr) { - P062_data->StoredSettings.TouchObjects[objectNr].touch = getFormItemIntCustomArgName(objectNr + 100); - P062_data->StoredSettings.TouchObjects[objectNr].release = getFormItemIntCustomArgName(objectNr + 200); - } - # ifdef PLUGIN_062_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("P062_data save size: "); - log += sizeof(P062_data->StoredSettings); - addLogMove(LOG_LEVEL_INFO, log); - } - # endif // PLUGIN_062_DEBUG - SaveCustomTaskSettings(event->TaskIndex, reinterpret_cast(&(P062_data->StoredSettings)), - sizeof(P062_data->StoredSettings)); - - if (!canCalibrate) { - delete P062_data; - P062_data = nullptr; - } else { - bool clearCalibration = isFormItemChecked(F("clear_calibrate")); - - if (clearCalibration) { - P062_data->clearCalibrationData(); - # ifdef PLUGIN_062_DEBUG - addLog(LOG_LEVEL_INFO, F("p062 clear calibration")); - # endif // PLUGIN_062_DEBUG - } - } - } - success = true; - break; - } - - case PLUGIN_INIT: - { - bool tbUseCalibration = bitRead(P062_CONFIG_FLAGS, P062_FLAGS_USE_CALIBRATION); - - initPluginTaskData(event->TaskIndex, new (std::nothrow) P062_data_struct()); - P062_data_struct *P062_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P062_data) { - if (!P062_data->init(event->TaskIndex, PCONFIG(0), PCONFIG(1), tbUseCalibration, PCONFIG(4))) { - clearPluginTaskData(event->TaskIndex); - P062_data = nullptr; - } else { - success = true; - - uint8_t touch_treshold = PCONFIG(2); - - if (touch_treshold == 0) { - touch_treshold = P062_DEFAULT_TOUCH_TRESHOLD; // default value - } - uint8_t release_treshold = PCONFIG(3); - - if (release_treshold == 0) { - release_treshold = P062_DEFAULT_RELEASE_TRESHOLD; // default value - } - - if ((touch_treshold != P062_DEFAULT_TOUCH_TRESHOLD) && (release_treshold != P062_DEFAULT_RELEASE_TRESHOLD)) { - P062_data->setThresholds(touch_treshold, release_treshold); // Set custom tresholds, ignore default values - } - - for (uint8_t objectNr = 0; objectNr < P062_MaxTouchObjects; ++objectNr) { - if ((P062_data->StoredSettings.TouchObjects[objectNr].touch != 0) && - (P062_data->StoredSettings.TouchObjects[objectNr].release != 0)) { - P062_data->setThreshold(objectNr, - P062_data->StoredSettings.TouchObjects[objectNr].touch, - P062_data->StoredSettings.TouchObjects[objectNr].release); - } - } - } - } - - break; - } - - case PLUGIN_TEN_PER_SECOND: - { - P062_data_struct *P062_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P062_data) { - return success; - } else { - uint16_t key; - - if (P062_data->readKey(key)) - { - UserVar.setFloat(event->TaskIndex, 0, key); - event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH; - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("Tkey : "); - log.reserve(22); - - if (PCONFIG(1)) { - log += F("ScanCode="); - } - else { - log += F("KeyMap="); - } - log += formatToHex(key); - addLogMove(LOG_LEVEL_INFO, log); - - bool tbUseCalibration = bitRead(P062_CONFIG_FLAGS, P062_FLAGS_USE_CALIBRATION); - - if (tbUseCalibration) { - uint16_t colMask = 0x01; - - for (uint8_t col = 0; col < P062_MaxTouchObjects; ++col) - { - if (key & colMask) // this key pressed? - { - uint16_t current = 0; - uint16_t min = 0; - uint16_t max = 0; - P062_data->getCalibrationData(col, ¤t, &min, &max); - addLog(LOG_LEVEL_INFO, - strformat(F("P062 touch #%d current: %d min: %d max: %d"), - col, current, min, max)); - - if (!PCONFIG(1)) { - break; - } - } - colMask <<= 1; - } - } - } - - sendData(event); - } - } - success = true; - break; - } - - case PLUGIN_READ: - { - success = true; - break; - } - } - return success; -} - -#endif // USES_P062 +#include "_Plugin_Helper.h" +#ifdef USES_P062 + +// ####################################################################################################### +// #################################### Plugin 062: MPR121 KeyPad ######################################## +// ####################################################################################################### + +// ESPEasy Plugin to scan a 12 key touch pad chip MPR121 +// written by Jochen Krapf (jk@nerd2nerd.org) +// 2021-12-29 tonhuisman: Add setting for panel sensitivity, as requested in https://github.com/letscontrolit/ESPEasy/issues/3828 +// Reformat source using Uncrustify +// 2020-10-14 tonhuisman: Added settings for global and per-sensor sensitivity +// and getting 'calibration' touch pressure data (current, min, max) + +// ScanCode; +// Value 1...12 for the key number +// No key - the code 0 +// If more than one key is pressed, the scan code is the code with the lowest value + +// If ScanCode is unchecked the value is the KeyMap 1.Key=1, 2.Key=2, 3.Key=4, 4.Key=8 ... 1.Key=2048 +// If more than one key is pressed, the value is sum of all KeyMap-values + + +# define PLUGIN_062 +# define PLUGIN_ID_062 62 +# define PLUGIN_NAME_062 "Keypad - MPR121 Touch" +# define PLUGIN_VALUENAME1_062 "ScanCode" + + +# include "src/PluginStructs/P062_data_struct.h" + +# define P062_FLAGS_USE_CALIBRATION 0 // Set in P062_CONFIG_FLAGS + +# define P062_CONFIG_FLAGS PCONFIG_LONG(0) // 0-31 flags + +# define P062_DEFAULT_TOUCH_TRESHOLD 12 // Defaults got from MPR_121 source +# define P062_DEFAULT_RELEASE_TRESHOLD 6 + +boolean Plugin_062(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_062; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + Device[deviceCount].ExitTaskBeforeSave = false; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_062); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_062)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: + { + const uint8_t i2cAddressValues[] = { 0x5A, 0x5B, 0x5C, 0x5D }; + + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { + addFormSelectorI2C(F("i2c_addr"), 4, i2cAddressValues, PCONFIG(0)); + } else { + success = intArrayContains(4, i2cAddressValues, event->Par1); + } + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = PCONFIG(0); + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_WEBFORM_LOAD: + { + addFormCheckBox(F("ScanCode"), F("scancode"), PCONFIG(1)); + + addFormSubHeader(F("Sensitivity")); + { + uint8_t touch_treshold = PCONFIG(2); + + if (touch_treshold == 0) { + touch_treshold = P062_DEFAULT_TOUCH_TRESHOLD; // default value + } + addFormNumericBox(F("Touch treshold (1..255)"), F("ttreshold"), touch_treshold, 0, 255); + addUnit(concat(F("Default: "), P062_DEFAULT_TOUCH_TRESHOLD)); + } + + { + uint8_t release_treshold = PCONFIG(3); + + if (release_treshold == 0) { + release_treshold = P062_DEFAULT_RELEASE_TRESHOLD; // default value + } + addFormNumericBox(F("Release treshold (1..255)"), F("rtreshold"), release_treshold, 0, 255); + addUnit(concat(F("Default: "), P062_DEFAULT_RELEASE_TRESHOLD)); + } + { + const __FlashStringHelper *sensitivityOptions[] = { + F("Normal"), + F("Extra sensitive (behind 4-6mm glass cover)") + }; + const int sensitivityValues[] = { + MPR212_NORMAL_SENSITIVITY, + MPR212_EXTRA_SENSITIVITY + }; + constexpr size_t optionCount = NR_ELEMENTS(sensitivityValues); + addFormSelector(F("Panel sensitivity"), F("psens"), optionCount, sensitivityOptions, sensitivityValues, PCONFIG(4)); + } + { + bool canCalibrate = true; + bool tbUseCalibration = bitRead(P062_CONFIG_FLAGS, P062_FLAGS_USE_CALIBRATION); + + P062_data_struct *P062_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P062_data) { + P062_data = new (std::nothrow) P062_data_struct(); + canCalibrate = false; + + if (P062_data == nullptr) { + return success; + } + } + P062_data->loadTouchObjects(event->TaskIndex); + + addRowLabel(F("Object")); + html_table(EMPTY_STRING, false); // Sub-table + html_table_header(F(" # ")); + html_table_header(F("Touch (0..255)")); + html_table_header(F("Release (0..255)")); + + if (tbUseCalibration && canCalibrate) { + html_table_header(F("Current")); + html_table_header(F("Min")); + html_table_header(F("Max")); + } + + for (int objectNr = 0; objectNr < P062_MaxTouchObjects; ++objectNr) { + html_TR_TD(); + addHtml(F(" ")); + addHtmlInt(objectNr + 1); + html_TD(); + addNumericBox(getPluginCustomArgName(objectNr + 100), P062_data->StoredSettings.TouchObjects[objectNr].touch, 0, 255); + html_TD(); + addNumericBox(getPluginCustomArgName(objectNr + 200), P062_data->StoredSettings.TouchObjects[objectNr].release, 0, 255); + + if (tbUseCalibration && canCalibrate) { + uint16_t current = 0; + uint16_t min = 0; + uint16_t max = 0; + P062_data->getCalibrationData(objectNr, ¤t, &min, &max); + html_TD(); + addHtmlInt(current); + html_TD(); + addHtmlInt(min); + html_TD(); + addHtmlInt(max); + } + } + html_end_table(); + + if (canCalibrate) { + const int choice1 = tbUseCalibration ? 1 : 0; + addFormSelector_YesNo(F("Enable Calibration"), F("ucal"), choice1, true); + + if (tbUseCalibration) { + addFormCheckBox(F("Clear calibrationdata"), F("clr_cal"), false); + } + } + delete P062_data; + } + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(0) = getFormItemInt(F("i2c_addr")); + + PCONFIG(1) = isFormItemChecked(F("scancode")); + + PCONFIG(2) = getFormItemInt(F("ttreshold")); + PCONFIG(3) = getFormItemInt(F("rtreshold")); + PCONFIG(4) = getFormItemInt(F("psens")); + + uint32_t lSettings = 0; + bitWrite(lSettings, P062_FLAGS_USE_CALIBRATION, getFormItemInt(F("ucal")) == 1); + P062_CONFIG_FLAGS = lSettings; + + { + bool canCalibrate = true; + P062_data_struct *P062_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P062_data) { + P062_data = new (std::nothrow) P062_data_struct(); + canCalibrate = false; + + if (P062_data == nullptr) { + return success; // Save other settings even though this didn't initialize properly + } + } + P062_data->loadTouchObjects(event->TaskIndex); + + for (int objectNr = 0; objectNr < P062_MaxTouchObjects; ++objectNr) { + P062_data->StoredSettings.TouchObjects[objectNr].touch = getFormItemIntCustomArgName(objectNr + 100); + P062_data->StoredSettings.TouchObjects[objectNr].release = getFormItemIntCustomArgName(objectNr + 200); + } + # ifdef PLUGIN_062_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, strformat(F("P062_data save size: %u"), sizeof(P062_data->StoredSettings))); + } + # endif // PLUGIN_062_DEBUG + SaveCustomTaskSettings(event->TaskIndex, reinterpret_cast(&(P062_data->StoredSettings)), + sizeof(P062_data->StoredSettings)); + + if (!canCalibrate) { + delete P062_data; + P062_data = nullptr; + } else { + const bool clearCalibration = isFormItemChecked(F("clr_cal")); + + if (clearCalibration) { + P062_data->clearCalibrationData(); + # ifdef PLUGIN_062_DEBUG + addLog(LOG_LEVEL_INFO, F("p062 clear calibration")); + # endif // PLUGIN_062_DEBUG + } + } + } + success = true; + break; + } + + case PLUGIN_INIT: + { + bool tbUseCalibration = bitRead(P062_CONFIG_FLAGS, P062_FLAGS_USE_CALIBRATION); + + initPluginTaskData(event->TaskIndex, new (std::nothrow) P062_data_struct()); + P062_data_struct *P062_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P062_data) { + if (!P062_data->init(event->TaskIndex, PCONFIG(0), PCONFIG(1), tbUseCalibration, PCONFIG(4))) { + clearPluginTaskData(event->TaskIndex); + P062_data = nullptr; + } else { + success = true; + + uint8_t touch_treshold = PCONFIG(2); + + if (touch_treshold == 0) { + touch_treshold = P062_DEFAULT_TOUCH_TRESHOLD; // default value + } + uint8_t release_treshold = PCONFIG(3); + + if (release_treshold == 0) { + release_treshold = P062_DEFAULT_RELEASE_TRESHOLD; // default value + } + + if ((touch_treshold != P062_DEFAULT_TOUCH_TRESHOLD) && (release_treshold != P062_DEFAULT_RELEASE_TRESHOLD)) { + P062_data->setThresholds(touch_treshold, release_treshold); // Set custom tresholds, ignore default values + } + + for (uint8_t objectNr = 0; objectNr < P062_MaxTouchObjects; ++objectNr) { + if ((P062_data->StoredSettings.TouchObjects[objectNr].touch != 0) && + (P062_data->StoredSettings.TouchObjects[objectNr].release != 0)) { + P062_data->setThreshold(objectNr, + P062_data->StoredSettings.TouchObjects[objectNr].touch, + P062_data->StoredSettings.TouchObjects[objectNr].release); + } + } + } + } + + break; + } + + case PLUGIN_TEN_PER_SECOND: + { + P062_data_struct *P062_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P062_data) { + return success; + } else { + uint16_t key; + + if (P062_data->readKey(key)) + { + UserVar.setFloat(event->TaskIndex, 0, key); + event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH; + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("Tkey : "); + log.reserve(22); + + if (PCONFIG(1)) { + log += F("ScanCode="); + } + else { + log += F("KeyMap="); + } + log += formatToHex(key); + addLogMove(LOG_LEVEL_INFO, log); + + bool tbUseCalibration = bitRead(P062_CONFIG_FLAGS, P062_FLAGS_USE_CALIBRATION); + + if (tbUseCalibration) { + uint16_t colMask = 0x01; + + for (uint8_t col = 0; col < P062_MaxTouchObjects; ++col) + { + if (key & colMask) // this key pressed? + { + uint16_t current = 0; + uint16_t min = 0; + uint16_t max = 0; + P062_data->getCalibrationData(col, ¤t, &min, &max); + addLog(LOG_LEVEL_INFO, + strformat(F("P062 touch #%d current: %d min: %d max: %d"), + col, current, min, max)); + + if (!PCONFIG(1)) { + break; + } + } + colMask <<= 1; + } + } + } + + sendData(event); + } + } + success = true; + break; + } + + case PLUGIN_READ: + { + success = true; + break; + } + } + return success; +} + +#endif // USES_P062 diff --git a/src/_P063_TTP229_KeyPad.ino b/src/_P063_TTP229_KeyPad.ino index 2bd04914eb..5da2f1018c 100644 --- a/src/_P063_TTP229_KeyPad.ino +++ b/src/_P063_TTP229_KeyPad.ino @@ -1,228 +1,229 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P063 - -// ####################################################################################################### -// #################################### Plugin 063: TTP229 KeyPad ######################################## -// ####################################################################################################### - -// ESPEasy Plugin to scan a 16 key touch pad chip TTP229 -// written by Jochen Krapf (jk@nerd2nerd.org) - -// Important: There are several types of TTP299 chips with different features available. They are named all TTP229 but differ in the -// letter(s) followed. -// On the china boards (found on eBay and AliExpress) the TTP229-B is used which has NO! I2C-interface. It uses a proprietary serial -// protocol with clock (SCL) and bidirectional data (SDO) - -// ScanCode; -// Value 1...16 for the key number -// No key - the code 0 -// If more than one key is pressed, the scan code is the code with the lowest value - -// If ScanCode is unchecked the value is the KeyMap 1.Key=1, 2.Key=2, 3.Key=4, 4.Key=8 ... 16.Key=32768 -// If more than one key is pressed, the value is sum of all KeyMap-values - -// Electronics: -// Connect SCL to 1st GPIO and SDO to 2nd GPIO. Use 3.3 volt for VCC. -// Set the jumper for 16 key mode (TP2=jumper3). Additional set jumper for multi-key (TP3=jumper4, TP4=jumper5). -// Schematics: https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/TTP229B-Schematic-Diagram.pdf -// Datasheet: http://www.datasheet4u.com/download_new.php?id=996751 - -# define PLUGIN_063 -# define PLUGIN_ID_063 63 -# define PLUGIN_NAME_063 "Keypad - TTP229 Touch" -# define PLUGIN_VALUENAME1_063 "ScanCode" - - -uint16_t readTTP229(int16_t pinSCL, int16_t pinSDO) -{ - uint16_t value = 0; - uint16_t mask = 1; - - pinMode(pinSDO, OUTPUT); - digitalWrite(pinSDO, HIGH); - delayMicroseconds(100); - - digitalWrite(pinSDO, LOW); - delayMicroseconds(10); - - pinMode(pinSDO, INPUT); - - for (uint8_t i = 0; i < 16; ++i) - { - digitalWrite(pinSCL, HIGH); - delayMicroseconds(1); - digitalWrite(pinSCL, LOW); - - if (!digitalRead(pinSDO)) { - value |= mask; - } - delayMicroseconds(1); - mask <<= 1; - } - - return value; -} - -boolean Plugin_063(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_063; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_063); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_063)); - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: - { - event->String1 = formatGpioName_output(F("SCL")); - event->String2 = formatGpioName_bidirectional(F("SDO")); - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - addFormCheckBox(F("ScanCode"), F("scancode"), PCONFIG(1)); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(1) = isFormItemChecked(F("scancode")); - - success = true; - break; - } - - case PLUGIN_INIT: - { - portStatusStruct newStatus; - - int16_t pinSCL = CONFIG_PIN1; - int16_t pinSDO = CONFIG_PIN2; - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, strformat(F("Tkey : GPIO: %d %d"), pinSCL, pinSDO)); - } - - if (validGpio(pinSCL) && validGpio(pinSDO)) - { - pinMode(pinSCL, OUTPUT); - digitalWrite(pinSCL, LOW); - - constexpr pluginID_t P063_PLUGIN_ID{ PLUGIN_ID_063 }; - - uint32_t key = createKey(P063_PLUGIN_ID, pinSCL); - - // WARNING: operator [] creates an entry in the map if key does not exist - newStatus = globalMapPortStatus[key]; - newStatus.task++; // add this GPIO/port as a task - newStatus.mode = PIN_MODE_OUTPUT; - newStatus.state = 0; - savePortStatus(key, newStatus); - - // setPinState(PLUGIN_ID_063, pinSCL, PIN_MODE_OUTPUT, 0); - - pinMode(pinSDO, OUTPUT); - digitalWrite(pinSDO, LOW); - key = createKey(P063_PLUGIN_ID, pinSDO); - - // WARNING: operator [] creates an entry in the map if key does not exist - newStatus = globalMapPortStatus[key]; - newStatus.task++; // add this GPIO/port as a task - newStatus.mode = PIN_MODE_INPUT; - newStatus.state = 0; - savePortStatus(key, newStatus); - - // setPinState(PLUGIN_ID_063, pinSDO, PIN_MODE_INPUT, 0); - success = true; - } - - break; - } - - case PLUGIN_TEN_PER_SECOND: - { - static uint16_t keyLast = 0; - int16_t pinSCL = CONFIG_PIN1; - int16_t pinSDO = CONFIG_PIN2; - - uint16_t key = readTTP229(pinSCL, pinSDO); - - if (key && PCONFIG(1)) - { - uint16_t colMask = 0x01; - - for (uint8_t col = 1; col <= 16; ++col) - { - if (key & colMask) // this key pressed? - { - key = col; - break; - } - colMask <<= 1; - } - } - - if (keyLast != key) - { - keyLast = key; - UserVar.setFloat(event->TaskIndex, 0, key); - event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH; - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("Tkey : "); - - if (PCONFIG(1)) { - log = F("ScanCode="); - } - else { - log = F("KeyMap="); - } - log += formatToHex(key); - addLogMove(LOG_LEVEL_INFO, log); - } - - sendData(event); - } - - success = true; - break; - } - - case PLUGIN_READ: - { - // work is done in PLUGIN_TEN_PER_SECOND - success = true; - break; - } - } - return success; -} - -#endif // USES_P063 +#include "_Plugin_Helper.h" +#ifdef USES_P063 + +// ####################################################################################################### +// #################################### Plugin 063: TTP229 KeyPad ######################################## +// ####################################################################################################### + +/** Changelog: + * 2025-01-04 tonhuisman: Make plugin multi-instance by not using a static variable for lastKey, but reading back from UserVar + * Minor code optimizations + */ + +// ESPEasy Plugin to scan a 16 key touch pad chip TTP229 +// written by Jochen Krapf (jk@nerd2nerd.org) + +// Important: There are several types of TTP299 chips with different features available. They are named all TTP229 but differ in the +// letter(s) followed. +// On the china boards (found on eBay and AliExpress) the TTP229-B is used which has NO! I2C-interface. It uses a proprietary serial +// protocol with clock (SCL) and bidirectional data (SDO) + +// ScanCode; +// Value 1...16 for the key number +// No key - the code 0 +// If more than one key is pressed, the scan code is the code with the lowest value + +// If ScanCode is unchecked the value is the KeyMap 1.Key=1, 2.Key=2, 3.Key=4, 4.Key=8 ... 16.Key=32768 +// If more than one key is pressed, the value is sum of all KeyMap-values + +// Electronics: +// Connect SCL to 1st GPIO and SDO to 2nd GPIO. Use 3.3 volt for VCC. +// Set the jumper for 16 key mode (TP2=jumper3). Additional set jumper for multi-key (TP3=jumper4, TP4=jumper5). +// Schematics: https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/TTP229B-Schematic-Diagram.pdf +// Datasheet: http://www.datasheet4u.com/download_new.php?id=996751 + +# define PLUGIN_063 +# define PLUGIN_ID_063 63 +# define PLUGIN_NAME_063 "Keypad - TTP229 Touch" +# define PLUGIN_VALUENAME1_063 "ScanCode" + + +uint16_t readTTP229(int16_t pinSCL, int16_t pinSDO) +{ + uint16_t value = 0; + uint16_t mask = 1; + + pinMode(pinSDO, OUTPUT); + digitalWrite(pinSDO, HIGH); + delayMicroseconds(100); + + digitalWrite(pinSDO, LOW); + delayMicroseconds(10); + + pinMode(pinSDO, INPUT); + + for (uint8_t i = 0; i < 16; ++i) + { + digitalWrite(pinSCL, HIGH); + delayMicroseconds(1); + digitalWrite(pinSCL, LOW); + + if (!digitalRead(pinSDO)) { + value |= mask; + } + delayMicroseconds(1); + mask <<= 1; + } + + return value; +} + +boolean Plugin_063(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_063; + Device[deviceCount].Type = DEVICE_TYPE_DUAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_063); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_063)); + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: + { + event->String1 = formatGpioName_output(F("SCL")); + event->String2 = formatGpioName_bidirectional(F("SDO")); + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + addFormCheckBox(F("ScanCode"), F("scancode"), PCONFIG(1)); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(1) = isFormItemChecked(F("scancode")); + + success = true; + break; + } + + case PLUGIN_INIT: + { + portStatusStruct newStatus; + + int16_t pinSCL = CONFIG_PIN1; + int16_t pinSDO = CONFIG_PIN2; + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, strformat(F("Tkey : GPIO: %d %d"), pinSCL, pinSDO)); + } + + if (validGpio(pinSCL) && validGpio(pinSDO)) + { + pinMode(pinSCL, OUTPUT); + digitalWrite(pinSCL, LOW); + + constexpr pluginID_t P063_PLUGIN_ID{ PLUGIN_ID_063 }; + + uint32_t key = createKey(P063_PLUGIN_ID, pinSCL); + + // WARNING: operator [] creates an entry in the map if key does not exist + newStatus = globalMapPortStatus[key]; + newStatus.task++; // add this GPIO/port as a task + newStatus.mode = PIN_MODE_OUTPUT; + newStatus.state = 0; + savePortStatus(key, newStatus); + + // setPinState(PLUGIN_ID_063, pinSCL, PIN_MODE_OUTPUT, 0); + + pinMode(pinSDO, OUTPUT); + digitalWrite(pinSDO, LOW); + key = createKey(P063_PLUGIN_ID, pinSDO); + + // WARNING: operator [] creates an entry in the map if key does not exist + newStatus = globalMapPortStatus[key]; + newStatus.task++; // add this GPIO/port as a task + newStatus.mode = PIN_MODE_INPUT; + newStatus.state = 0; + savePortStatus(key, newStatus); + + // setPinState(PLUGIN_ID_063, pinSDO, PIN_MODE_INPUT, 0); + success = true; + } + + break; + } + + case PLUGIN_TEN_PER_SECOND: + { + const uint16_t keyLast = UserVar.getFloat(event->TaskIndex, 0); // Last set value, makes plugin multi-instance + const int16_t pinSCL = CONFIG_PIN1; + const int16_t pinSDO = CONFIG_PIN2; + + uint16_t key = readTTP229(pinSCL, pinSDO); + + if (key && PCONFIG(1)) + { + uint16_t colMask = 0x01; + + for (uint8_t col = 1; col <= 16; ++col) + { + if (key & colMask) // this key pressed? + { + key = col; + break; + } + colMask <<= 1; + } + } + + if (keyLast != key) + { + UserVar.setFloat(event->TaskIndex, 0, key); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("Tkey : "); + + if (PCONFIG(1)) { + log = F("ScanCode="); + } + else { + log = F("KeyMap="); + } + log += formatToHex(key); + addLogMove(LOG_LEVEL_INFO, log); + } + + sendData(event); + } + + success = true; + break; + } + + case PLUGIN_READ: + { + // work is done in PLUGIN_TEN_PER_SECOND + success = true; + break; + } + } + return success; +} + +#endif // USES_P063 diff --git a/src/_P064_APDS9960.ino b/src/_P064_APDS9960.ino index c25fc49483..a12d85fbb7 100644 --- a/src/_P064_APDS9960.ino +++ b/src/_P064_APDS9960.ino @@ -1,399 +1,398 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P064 - -// ####################################################################################################### -// #################################### Plugin 064: APDS9960 Gesture ############################## -// ####################################################################################################### - -// ESPEasy Plugin to scan a gesture, proximity and light chip APDS9960 -// written by Jochen Krapf (jk@nerd2nerd.org) - -// A new gesture is send immediately to controllers. -// Proximity and Light are scanned frequently by given 'Delay' setting. -// RGB is not scanned because there are only 4 vars per task. - -// Known BUG: While performing a gesture the reader function blocks rest of ESPEasy processing!!! (Feel free to fix...) -// See below, fixed by dropping out after 32 consecutive loops in reading gesture data. - -// Note: The chip has a wide view-of-angle. If housing is in this angle the chip blocks! - -// 2024-03-30 tonhuisman: Add 'Separate Gesture event' option (#Swipe=) so it doesn't interfere with light/color -// measurement -// 2022-08-12 tonhuisman: Remove [DEVELOPMENT] tag -// 2022-08-05 tonhuisman: Remove [TESTING] tag, Improvement: INIT, 10/sec and READ events now return false if errors occur during processing -// 2022-06-17 tonhuisman: Remove I2C address selector, as there is nothing to choose... -// Clean up source, avoid (memory) inefficient code -// 2022-03-21 tonhuisman: Attempt to stop the sensor from blocking ESPEasy, by dropping out after 32 loops in reading gesture data -// This should fix the Known BUG above. -// Lowered reading gesture data from 50/sec to 10/sec, as it still won't be processed quick enough -// Change sensor to TESTING from DEVELOPMENT -// 2020-04-25 tonhuisman: Added Plugin Mode setting to switch between Proximity/Ambient Light Sensor or R/G/B Colors. -// Added settings for Gain (Gesture, Proximity, Ambient Light Sensor), Led Power (Gesture and Proximity/ALS) and Led Boost (Gesture) -// to allow better tuning for use of the sensor. Also adapted the SparkFun_APDS9960 driver for enabling this. -// R/G/B Colors mode has it's settings shared with the Gesture/Proximity/ALS as they are the exact same parameters, but with different -// labels only. - - -# define PLUGIN_064 -# define PLUGIN_ID_064 64 -# define PLUGIN_NAME_064 "Gesture - APDS9960" -# define PLUGIN_GPL_VALUENAME1_064 "Gesture" -# define PLUGIN_GPL_VALUENAME2_064 "Proximity" -# define PLUGIN_GPL_VALUENAME3_064 "Light" - -# define PLUGIN_RGB_VALUENAME1_064 "R" -# define PLUGIN_RGB_VALUENAME2_064 "G" -# define PLUGIN_RGB_VALUENAME3_064 "B" - -# define PLUGIN_MODE_GPL_064 0 // GPL = Gesture/Proximity/(Ambient) Light Sensor mode -# define PLUGIN_MODE_RGB_064 1 // RGB = R/G/B Colors mode -# define P064_I2C_ADDRESS 0x39 - -# define P064_GESTURE_EVENT PCONFIG(0) -# define P064_MODE PCONFIG(1) -# define P064_GGAIN PCONFIG(2) -# define P064_GLDRIVE PCONFIG(3) -# define P064_LED_BOOST PCONFIG(4) -# define P064_PGAIN PCONFIG(5) -# define P064_AGAIN PCONFIG(6) -# define P064_LDRIVE PCONFIG(7) - -# define P064_IS_GPL_SENSOR (P064_MODE == PLUGIN_MODE_GPL_064) -# define P064_IS_RGB_SENSOR (P064_MODE == PLUGIN_MODE_RGB_064) - - -# include "src/PluginStructs/P064_data_struct.h" - - -boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_064; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_064); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_GPL_VALUENAME1_064)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_GPL_VALUENAME2_064)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_GPL_VALUENAME3_064)); - } else { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_RGB_VALUENAME1_064)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_RGB_VALUENAME2_064)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_RGB_VALUENAME3_064)); - } - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - { - success = (event->Par1 == P064_I2C_ADDRESS); - - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = P064_I2C_ADDRESS; - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_WEBFORM_LOAD: - { - { - const __FlashStringHelper *optionsPluginMode[2] = { - F("Gesture/Proximity/Ambient Light Sensor"), - F("R/G/B Colors") }; - const int optionsPluginModeValues[2] = { PLUGIN_MODE_GPL_064, PLUGIN_MODE_RGB_064 }; - addFormSelector(F("Plugin Mode"), F("mode"), 2, optionsPluginMode, optionsPluginModeValues, P064_MODE, true); - # ifndef BUILD_NO_DEBUG - addFormNote(F("After changing Plugin Mode you may want to change the Values names, below.")); - # endif // ifndef BUILD_NO_DEBUG - } - - if (P064_IS_RGB_SENSOR // R/G/B Colors mode and default Gesture/Proximity/ALS values: Set new default names - && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_GPL_VALUENAME1_064)) == 0) - && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_GPL_VALUENAME2_064)) == 0) - && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_GPL_VALUENAME3_064)) == 0)) { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_RGB_VALUENAME1_064)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_RGB_VALUENAME2_064)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_RGB_VALUENAME3_064)); - - // Reset values - UserVar.setFloat(event->TaskIndex, 0, 0.0f); - UserVar.setFloat(event->TaskIndex, 1, 0.0f); - UserVar.setFloat(event->TaskIndex, 2, 0.0f); - } - - if (P064_IS_GPL_SENSOR // Gesture/Proximity/ALS mode and default R/G/B values: Set new default names - && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_RGB_VALUENAME1_064)) == 0) - && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_RGB_VALUENAME2_064)) == 0) - && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_RGB_VALUENAME3_064)) == 0)) { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_GPL_VALUENAME1_064)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_GPL_VALUENAME2_064)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_GPL_VALUENAME3_064)); - - // Reset values - UserVar.setFloat(event->TaskIndex, 0, 0.0f); - UserVar.setFloat(event->TaskIndex, 1, 0.0f); - UserVar.setFloat(event->TaskIndex, 2, 0.0f); - } - - { - // Gain options, multiple gain optionsets in SparkFun_APDS9960.h have the same valueset, so only defined once here - const __FlashStringHelper *optionsGain[] = { - F("1x"), - F("2x"), - F("4x (default)"), - F("8x") }; - const int optionsGainValues[] = { PGAIN_1X, PGAIN_2X, PGAIN_4X, PGAIN_8X }; // Also used for optionsALSGain - - // Led_Drive options, all Led_Drive optionsets in SparkFun_APDS9960.h have the same valueset, so only defined once here - const __FlashStringHelper *optionsLedDrive[] = { - F("100 mA (default)"), - F("50 mA"), - F("25 mA"), - F("12.5 mA") }; - const int optionsLedDriveValues[] = { LED_DRIVE_100MA, LED_DRIVE_50MA, LED_DRIVE_25MA, LED_DRIVE_12_5MA }; - - - String lightSensorGainLabel; - String lightSensorDriveLabel; - - if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode - addFormSubHeader(F("Gesture parameters")); - - addFormSelector(F("Gesture Gain"), - F("ggain"), - NR_ELEMENTS(optionsGainValues), - optionsGain, - optionsGainValues, - P064_GGAIN); - - addFormSelector(F("Gesture LED Drive"), - F("gldrive"), - NR_ELEMENTS(optionsLedDriveValues), - optionsLedDrive, - optionsLedDriveValues, - P064_GLDRIVE); - { - // Gesture Led-boost values - const __FlashStringHelper *optionsLedBoost[] = { - F("100 %"), - F("150 %"), - F("200 %"), - F("300 % (default)") }; - const int optionsLedBoostValues[] = { LED_BOOST_100, LED_BOOST_150, LED_BOOST_200, LED_BOOST_300 }; - addFormSelector(F("Gesture LED Boost"), - F("lboost"), - NR_ELEMENTS(optionsLedBoostValues), - optionsLedBoost, - optionsLedBoostValues, - P064_LED_BOOST); - } - - addFormSubHeader(F("Proximity & Ambient Light Sensor parameters")); - - addFormSelector(F("Proximity Gain"), F("pgain"), NR_ELEMENTS(optionsGainValues), optionsGain, optionsGainValues, P064_PGAIN); - - lightSensorGainLabel = F("Ambient Light Sensor Gain"); - lightSensorDriveLabel = F("Proximity & ALS LED Drive"); - } else { - addFormSubHeader(F("R/G/B Colors parameters")); - - lightSensorGainLabel = F("Light Sensor Gain"); - lightSensorDriveLabel = F("Light Sensor LED Drive"); - } - { - // Ambient Light Sensor Gain options, values are equal to PGAIN values, so again avoid duplication - const __FlashStringHelper *optionsALSGain[] = { - F("1x"), - F("4x (default)"), - F("16x"), - F("64x") }; - addFormSelector(lightSensorGainLabel, F("again"), NR_ELEMENTS(optionsGainValues), optionsALSGain, optionsGainValues, P064_AGAIN); - } - addFormSelector(lightSensorDriveLabel, - F("ldrive"), - NR_ELEMENTS(optionsLedDriveValues), - optionsLedDrive, - optionsLedDriveValues, - P064_LDRIVE); - } - - addFormSubHeader(F("Event generation")); - - addFormCheckBox(F("Separate Gesture events"), F("gevent"), P064_GESTURE_EVENT == 1); - addFormNote(F("Generates event: <Taskname>#Swipe=<gesture>")); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - P064_MODE = getFormItemInt(F("mode")); - - if (P064_IS_GPL_SENSOR) { - P064_GGAIN = getFormItemInt(F("ggain")); - P064_GLDRIVE = getFormItemInt(F("gldrive")); - P064_LED_BOOST = getFormItemInt(F("lboost")); - P064_PGAIN = getFormItemInt(F("pgain")); - } - P064_AGAIN = getFormItemInt(F("again")); - P064_LDRIVE = getFormItemInt(F("ldrive")); - - P064_GESTURE_EVENT = isFormItemChecked(F("gevent")) ? 1 : 0; - - success = true; - break; - } - - case PLUGIN_INIT: - { - initPluginTaskData(event->TaskIndex, new (std::nothrow) P064_data_struct()); - P064_data_struct *P064_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P064_data) { - String log = F("APDS : "); - success = true; - - if (P064_data->sensor.init(P064_GGAIN, P064_GLDRIVE, P064_PGAIN, P064_AGAIN, P064_LDRIVE)) { - log += F("Init"); - - P064_data->sensor.enablePower(); - - if (!P064_data->sensor.enableLightSensor(false)) { - log += F(" Error during light sensor init!"); - success = false; - } - - // Always enable the proximity/gesture sensor. - if (!P064_data->sensor.enableProximitySensor(false)) { - log += F(" Error during proximity sensor init!"); - success = false; - } - - if (!P064_data->sensor.enableGestureSensor(false, P064_LED_BOOST)) { - log += F(" Error during gesture sensor init!"); - success = false; - } - } else { - log += F("Error during APDS-9960 init!"); - success = false; - } - - addLogMove(success ? LOG_LEVEL_INFO : LOG_LEVEL_ERROR, log); - } - break; - } - - case PLUGIN_TEN_PER_SECOND: - { - P064_data_struct *P064_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if ((nullptr == P064_data) || !P064_data->sensor.isGestureAvailable()) { - break; - } - - const int gesture = P064_data->sensor.readGesture(); - - if (gesture >= 0) { - # ifndef BUILD_NO_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - String log = F("APDS : Gesture="); - - switch (gesture) { - case DIR_UP: log += F("UP"); break; - case DIR_DOWN: log += F("DOWN"); break; - case DIR_LEFT: log += F("LEFT"); break; - case DIR_RIGHT: log += F("RIGHT"); break; - case DIR_NEAR: log += F("NEAR"); break; - case DIR_FAR: log += F("FAR"); break; - default: log += F("NONE"); break; - } - log += strformat(F(" (%d)"), gesture); - addLogMove(LOG_LEVEL_DEBUG, log); - } - # endif // ifndef BUILD_NO_DEBUG - - if (P064_MODE == PLUGIN_MODE_GPL_064) { - UserVar.setFloat(event->TaskIndex, 0, static_cast(gesture)); - } - - if (P064_GESTURE_EVENT == 1) { - const String eventvalues = strformat(F("%d"), gesture); - eventQueue.add(event->TaskIndex, F("Swipe"), eventvalues); - } else if (P064_MODE == PLUGIN_MODE_GPL_064) { - sendData(event); // Process immediately - } - - success = true; - } - - break; - } - - case PLUGIN_READ: - { - P064_data_struct *P064_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P064_data) { - // Gesture - work is done in PLUGIN_TEN_PER_SECOND - success = true; - - if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode - uint8_t proximity_data = 0; - success = success && P064_data->sensor.readProximity(proximity_data); - UserVar.setFloat(event->TaskIndex, 1, static_cast(proximity_data)); - - uint16_t ambient_light = 0; - success = success && P064_data->sensor.readAmbientLight(ambient_light); - UserVar.setFloat(event->TaskIndex, 2, static_cast(ambient_light)); - } else { - uint16_t red_light = 0; - uint16_t green_light = 0; - uint16_t blue_light = 0; - success = success && (P064_data->sensor.readRedLight(red_light) && - P064_data->sensor.readGreenLight(green_light) && - P064_data->sensor.readBlueLight(blue_light)); - UserVar.setFloat(event->TaskIndex, 0, static_cast(red_light)); - UserVar.setFloat(event->TaskIndex, 1, static_cast(green_light)); - UserVar.setFloat(event->TaskIndex, 2, static_cast(blue_light)); - } - } - break; - } - } - return success; -} - -#endif // USES_P064 +#include "_Plugin_Helper.h" +#ifdef USES_P064 + +// ####################################################################################################### +// #################################### Plugin 064: APDS9960 Gesture ############################## +// ####################################################################################################### + +// ESPEasy Plugin to scan a gesture, proximity and light chip APDS9960 +// written by Jochen Krapf (jk@nerd2nerd.org) + +// A new gesture is send immediately to controllers. +// Proximity and Light are scanned frequently by given 'Delay' setting. +// RGB is not scanned because there are only 4 vars per task. + +// Known BUG: While performing a gesture the reader function blocks rest of ESPEasy processing!!! (Feel free to fix...) +// See below, fixed by dropping out after 32 consecutive loops in reading gesture data. + +// Note: The chip has a wide view-of-angle. If housing is in this angle the chip blocks! + +// 2024-03-30 tonhuisman: Add 'Separate Gesture event' option (#Swipe=) so it doesn't interfere with light/color +// measurement +// 2022-08-12 tonhuisman: Remove [DEVELOPMENT] tag +// 2022-08-05 tonhuisman: Remove [TESTING] tag, Improvement: INIT, 10/sec and READ events now return false if errors occur during processing +// 2022-06-17 tonhuisman: Remove I2C address selector, as there is nothing to choose... +// Clean up source, avoid (memory) inefficient code +// 2022-03-21 tonhuisman: Attempt to stop the sensor from blocking ESPEasy, by dropping out after 32 loops in reading gesture data +// This should fix the Known BUG above. +// Lowered reading gesture data from 50/sec to 10/sec, as it still won't be processed quick enough +// Change sensor to TESTING from DEVELOPMENT +// 2020-04-25 tonhuisman: Added Plugin Mode setting to switch between Proximity/Ambient Light Sensor or R/G/B Colors. +// Added settings for Gain (Gesture, Proximity, Ambient Light Sensor), Led Power (Gesture and Proximity/ALS) and Led Boost (Gesture) +// to allow better tuning for use of the sensor. Also adapted the SparkFun_APDS9960 driver for enabling this. +// R/G/B Colors mode has it's settings shared with the Gesture/Proximity/ALS as they are the exact same parameters, but with different +// labels only. + + +# define PLUGIN_064 +# define PLUGIN_ID_064 64 +# define PLUGIN_NAME_064 "Gesture - APDS9960" +# define PLUGIN_GPL_VALUENAME1_064 "Gesture" +# define PLUGIN_GPL_VALUENAME2_064 "Proximity" +# define PLUGIN_GPL_VALUENAME3_064 "Light" + +# define PLUGIN_RGB_VALUENAME1_064 "R" +# define PLUGIN_RGB_VALUENAME2_064 "G" +# define PLUGIN_RGB_VALUENAME3_064 "B" + +# define PLUGIN_MODE_GPL_064 0 // GPL = Gesture/Proximity/(Ambient) Light Sensor mode +# define PLUGIN_MODE_RGB_064 1 // RGB = R/G/B Colors mode +# define P064_I2C_ADDRESS 0x39 + +# define P064_GESTURE_EVENT PCONFIG(0) +# define P064_MODE PCONFIG(1) +# define P064_GGAIN PCONFIG(2) +# define P064_GLDRIVE PCONFIG(3) +# define P064_LED_BOOST PCONFIG(4) +# define P064_PGAIN PCONFIG(5) +# define P064_AGAIN PCONFIG(6) +# define P064_LDRIVE PCONFIG(7) + +# define P064_IS_GPL_SENSOR (P064_MODE == PLUGIN_MODE_GPL_064) +# define P064_IS_RGB_SENSOR (P064_MODE == PLUGIN_MODE_RGB_064) + + +# include "src/PluginStructs/P064_data_struct.h" + + +boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_064; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; + Device[deviceCount].ValueCount = 3; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + Device[deviceCount].PluginStats = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_064); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_GPL_VALUENAME1_064)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_GPL_VALUENAME2_064)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_GPL_VALUENAME3_064)); + } else { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_RGB_VALUENAME1_064)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_RGB_VALUENAME2_064)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_RGB_VALUENAME3_064)); + } + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + { + success = (event->Par1 == P064_I2C_ADDRESS); + + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = P064_I2C_ADDRESS; + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_WEBFORM_LOAD: + { + { + const __FlashStringHelper *optionsPluginMode[] = { + F("Gesture/Proximity/Ambient Light Sensor"), + F("R/G/B Colors") }; + const int optionsPluginModeValues[] = { PLUGIN_MODE_GPL_064, PLUGIN_MODE_RGB_064 }; + constexpr size_t optionCount = NR_ELEMENTS(optionsPluginModeValues); + addFormSelector(F("Plugin Mode"), F("mode"), optionCount, optionsPluginMode, optionsPluginModeValues, P064_MODE, true); + # ifndef BUILD_NO_DEBUG + addFormNote(F("After changing Plugin Mode you may want to change the Values names, below.")); + # endif // ifndef BUILD_NO_DEBUG + } + + if (P064_IS_RGB_SENSOR // R/G/B Colors mode and default Gesture/Proximity/ALS values: Set new default names + && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_GPL_VALUENAME1_064)) == 0) + && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_GPL_VALUENAME2_064)) == 0) + && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_GPL_VALUENAME3_064)) == 0)) { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_RGB_VALUENAME1_064)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_RGB_VALUENAME2_064)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_RGB_VALUENAME3_064)); + + // Reset values + UserVar.setFloat(event->TaskIndex, 0, 0.0f); + UserVar.setFloat(event->TaskIndex, 1, 0.0f); + UserVar.setFloat(event->TaskIndex, 2, 0.0f); + } + + if (P064_IS_GPL_SENSOR // Gesture/Proximity/ALS mode and default R/G/B values: Set new default names + && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_RGB_VALUENAME1_064)) == 0) + && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_RGB_VALUENAME2_064)) == 0) + && (strcmp_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_RGB_VALUENAME3_064)) == 0)) { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_GPL_VALUENAME1_064)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_GPL_VALUENAME2_064)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_GPL_VALUENAME3_064)); + + // Reset values + UserVar.setFloat(event->TaskIndex, 0, 0.0f); + UserVar.setFloat(event->TaskIndex, 1, 0.0f); + UserVar.setFloat(event->TaskIndex, 2, 0.0f); + } + + { + // Gain options, multiple gain optionsets in SparkFun_APDS9960.h have the same valueset, so only defined once here + const __FlashStringHelper *optionsGain[] = { + F("1x"), + F("2x"), + F("4x (default)"), + F("8x") }; + const int optionsGainValues[] = { PGAIN_1X, PGAIN_2X, PGAIN_4X, PGAIN_8X }; // Also used for optionsALSGain + constexpr size_t optionsGainCount = NR_ELEMENTS(optionsGainValues); + + // Led_Drive options, all Led_Drive optionsets in SparkFun_APDS9960.h have the same valueset, so only defined once here + const __FlashStringHelper *optionsLedDrive[] = { + F("100 mA (default)"), + F("50 mA"), + F("25 mA"), + F("12.5 mA") }; + const int optionsLedDriveValues[] = { LED_DRIVE_100MA, LED_DRIVE_50MA, LED_DRIVE_25MA, LED_DRIVE_12_5MA }; + constexpr size_t optionsLedDriveCount = NR_ELEMENTS(optionsLedDriveValues); + + + String lightSensorGainLabel; + String lightSensorDriveLabel; + + if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode + addFormSubHeader(F("Gesture parameters")); + + addFormSelector(F("Gesture Gain"), + F("ggain"), + optionsGainCount, + optionsGain, + optionsGainValues, + P064_GGAIN); + + addFormSelector(F("Gesture LED Drive"), + F("gldrive"), + optionsLedDriveCount, + optionsLedDrive, + optionsLedDriveValues, + P064_GLDRIVE); + { + // Gesture Led-boost values + const __FlashStringHelper *optionsLedBoost[] = { + F("100 %"), + F("150 %"), + F("200 %"), + F("300 % (default)") }; + const int optionsLedBoostValues[] = { LED_BOOST_100, LED_BOOST_150, LED_BOOST_200, LED_BOOST_300 }; + constexpr size_t optionsLedBoostCount = NR_ELEMENTS(optionsLedBoostValues); + addFormSelector(F("Gesture LED Boost"), + F("lboost"), + optionsLedBoostCount, + optionsLedBoost, + optionsLedBoostValues, + P064_LED_BOOST); + } + + addFormSubHeader(F("Proximity & Ambient Light Sensor parameters")); + + addFormSelector(F("Proximity Gain"), F("pgain"), optionsGainCount, optionsGain, optionsGainValues, P064_PGAIN); + + lightSensorGainLabel = F("Ambient Light Sensor Gain"); + lightSensorDriveLabel = F("Proximity & ALS LED Drive"); + } else { + addFormSubHeader(F("R/G/B Colors parameters")); + + lightSensorGainLabel = F("Light Sensor Gain"); + lightSensorDriveLabel = F("Light Sensor LED Drive"); + } + { + // Ambient Light Sensor Gain options, values are equal to PGAIN values, so again avoid duplication + const __FlashStringHelper *optionsALSGain[] = { + F("1x"), + F("4x (default)"), + F("16x"), + F("64x") }; + addFormSelector(lightSensorGainLabel, F("again"), optionsGainCount, optionsALSGain, optionsGainValues, P064_AGAIN); + } + addFormSelector(lightSensorDriveLabel, + F("ldrive"), + optionsLedDriveCount, + optionsLedDrive, + optionsLedDriveValues, + P064_LDRIVE); + } + + addFormSubHeader(F("Event generation")); + + addFormCheckBox(F("Separate Gesture events"), F("gevent"), P064_GESTURE_EVENT == 1); + addFormNote(F("Generates event: <Taskname>#Swipe=<gesture>")); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + P064_MODE = getFormItemInt(F("mode")); + + if (P064_IS_GPL_SENSOR) { + P064_GGAIN = getFormItemInt(F("ggain")); + P064_GLDRIVE = getFormItemInt(F("gldrive")); + P064_LED_BOOST = getFormItemInt(F("lboost")); + P064_PGAIN = getFormItemInt(F("pgain")); + } + P064_AGAIN = getFormItemInt(F("again")); + P064_LDRIVE = getFormItemInt(F("ldrive")); + + P064_GESTURE_EVENT = isFormItemChecked(F("gevent")) ? 1 : 0; + + success = true; + break; + } + + case PLUGIN_INIT: + { + initPluginTaskData(event->TaskIndex, new (std::nothrow) P064_data_struct()); + P064_data_struct *P064_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P064_data) { + String log = F("APDS : "); + success = true; + + if (P064_data->sensor.init(P064_GGAIN, P064_GLDRIVE, P064_PGAIN, P064_AGAIN, P064_LDRIVE)) { + log += F("Init "); + + P064_data->sensor.enablePower(); + + if (!P064_data->sensor.enableLightSensor(false)) { + log += F("Error during light sensor init!"); + success = false; + } + + // Always enable the proximity/gesture sensor. + if (!P064_data->sensor.enableProximitySensor(false)) { + log += F("Error during proximity sensor init!"); + success = false; + } + + if (!P064_data->sensor.enableGestureSensor(false, P064_LED_BOOST)) { + log += F("Error during gesture sensor init!"); + success = false; + } + } else { + log += F("Error during APDS-9960 init!"); + success = false; + } + + addLogMove(success ? LOG_LEVEL_INFO : LOG_LEVEL_ERROR, log); + } + break; + } + + case PLUGIN_TEN_PER_SECOND: + { + P064_data_struct *P064_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if ((nullptr == P064_data) || !P064_data->sensor.isGestureAvailable()) { + break; + } + + const int gesture = P064_data->sensor.readGesture(); + + if (gesture >= 0) { + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + String log = F("APDS : Gesture="); + + switch (gesture) { + case DIR_UP: log += F("UP"); break; + case DIR_DOWN: log += F("DOWN"); break; + case DIR_LEFT: log += F("LEFT"); break; + case DIR_RIGHT: log += F("RIGHT"); break; + case DIR_NEAR: log += F("NEAR"); break; + case DIR_FAR: log += F("FAR"); break; + default: log += F("NONE"); break; + } + log += strformat(F(" (%d)"), gesture); + addLogMove(LOG_LEVEL_DEBUG, log); + } + # endif // ifndef BUILD_NO_DEBUG + + if (P064_MODE == PLUGIN_MODE_GPL_064) { + UserVar.setFloat(event->TaskIndex, 0, static_cast(gesture)); + } + + if (P064_GESTURE_EVENT == 1) { + const String eventvalues = strformat(F("%d"), gesture); + eventQueue.add(event->TaskIndex, F("Swipe"), eventvalues); + } else if (P064_MODE == PLUGIN_MODE_GPL_064) { + sendData(event); // Process immediately + } + + success = true; + } + + break; + } + + case PLUGIN_READ: + { + P064_data_struct *P064_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P064_data) { + // Gesture - work is done in PLUGIN_TEN_PER_SECOND + success = true; + + if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode + uint8_t proximity_data = 0; + success = success && P064_data->sensor.readProximity(proximity_data); + UserVar.setFloat(event->TaskIndex, 1, static_cast(proximity_data)); + + uint16_t ambient_light = 0; + success = success && P064_data->sensor.readAmbientLight(ambient_light); + UserVar.setFloat(event->TaskIndex, 2, static_cast(ambient_light)); + } else { + uint16_t red_light = 0; + uint16_t green_light = 0; + uint16_t blue_light = 0; + success = success && (P064_data->sensor.readRedLight(red_light) && + P064_data->sensor.readGreenLight(green_light) && + P064_data->sensor.readBlueLight(blue_light)); + UserVar.setFloat(event->TaskIndex, 0, static_cast(red_light)); + UserVar.setFloat(event->TaskIndex, 1, static_cast(green_light)); + UserVar.setFloat(event->TaskIndex, 2, static_cast(blue_light)); + } + } + break; + } + } + return success; +} + +#endif // USES_P064 diff --git a/src/_P065_DRF0299_MP3.ino b/src/_P065_DRF0299_MP3.ino index 0fcfec5954..b485f67533 100644 --- a/src/_P065_DRF0299_MP3.ino +++ b/src/_P065_DRF0299_MP3.ino @@ -62,17 +62,9 @@ boolean Plugin_065(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_065; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; - Device[deviceCount].GlobalSyncOption = false; + Device[++deviceCount].Number = PLUGIN_ID_065; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; break; } diff --git a/src/_P066_VEML6040.ino b/src/_P066_VEML6040.ino index d4dcf1ac90..b1b5371700 100644 --- a/src/_P066_VEML6040.ino +++ b/src/_P066_VEML6040.ino @@ -32,19 +32,14 @@ boolean Plugin_066(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_066; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = false; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_066; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -88,21 +83,29 @@ boolean Plugin_066(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { { - const __FlashStringHelper *optionsMode[6] = { F("40ms (16496)"), F("80ms (8248)"), F("160ms (4124)"), F("320ms (2062)"), F( - "640ms (1031)"), F( - "1280ms (515)") }; - addFormSelector(F("Integration Time (Max Lux)"), F("itime"), 6, optionsMode, nullptr, PCONFIG(1)); + const __FlashStringHelper *optionsMode[] = { + F("40ms (16496)"), + F("80ms (8248)"), + F("160ms (4124)"), + F("320ms (2062)"), + F("640ms (1031)"), + F("1280ms (515)"), + }; + constexpr size_t optionCount = NR_ELEMENTS(optionsMode); + addFormSelector(F("Integration Time (Max Lux)"), F("itime"), optionCount, optionsMode, nullptr, PCONFIG(1)); } { - const __FlashStringHelper *optionsVarMap[6] = { + const __FlashStringHelper *optionsVarMap[] = { F("R, G, B, W"), F("r, g, b, W - relative rgb [%]"), F("r, g, b, W - relative rgb^Gamma [%]"), F("R, G, B, Color Temperature [K]"), F("R, G, B, Ambient Light [Lux]"), - F("Color Temperature [K], Ambient Light [Lux], Y, W") }; - addFormSelector(F("Value Mapping"), F("map"), 6, optionsVarMap, nullptr, PCONFIG(2)); + F("Color Temperature [K], Ambient Light [Lux], Y, W"), + }; + constexpr size_t optionCount = NR_ELEMENTS(optionsVarMap); + addFormSelector(F("Value Mapping"), F("map"), optionCount, optionsVarMap, nullptr, PCONFIG(2)); } success = true; diff --git a/src/_P067_HX711_Load_Cell.ino b/src/_P067_HX711_Load_Cell.ino index 7a75d7b0aa..68664d6b8c 100644 --- a/src/_P067_HX711_Load_Cell.ino +++ b/src/_P067_HX711_Load_Cell.ino @@ -1,239 +1,238 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P067 - -// ####################################################################################################### -// ####################################### Plugin 067: HX711 Load Cell ################################### -// ####################################################################################################### - -// ESPEasy Plugin to scan a 24 bit AD value from a load cell chip HX711 -// written by Jochen Krapf (jk@nerd2nerd.org) -// -// Modified by chunter to support dual channel measurements. -// When both channels are enabled, sample-rate drops to approx. 1 sample/s for each channel. - -// Electronics: -// Connect SCL to 1st GPIO and DOUT to 2nd GPIO. Use 3.3 volt for VCC. - -// Datasheet: https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/hx711_english.pdf - -/** Changelog: - * 2023-02-23 tonhuisman: Ignore first PLUGIN_READ after startup, as no samples have been read yet so no measurement data is available - * 2023-01-01 tonhuisman: Minor string reductions - * 2022-12-30 tonhuisman: Fix no longer generating events, use DIRECT_pinRead() and DIRECT_pinWrite() to ensure proper working on ESP32, - * include Task number when logging values, reset any previous values on init, change Pin names to match board text - * 2022-12-28 tonhuisman: Refactor using PluginTaskData struct to eliminate the use of static and global variables - * 2022-12-28 tonhuisman: Add changelog, older log not registered - */ - - -# define PLUGIN_067 -# define PLUGIN_ID_067 67 -# define PLUGIN_NAME_067 "Weight - HX711 Load Cell" -# define PLUGIN_VALUENAME1_067 "WeightChanA" -# define PLUGIN_VALUENAME2_067 "WeightChanB" - -# include "./src/PluginStructs/P067_data_struct.h" - -boolean Plugin_067(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_067; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_067); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_067)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_067)); - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: - { - event->String1 = formatGpioName_output(F("SCK")); - event->String2 = formatGpioName_input(F("DT")); - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - float valFloat; - - // A ------------ - addFormSubHeader(F("Measurement Channel A")); - - addFormCheckBox(F("Oversampling"), F("osChA"), P067_GET_CHANNEL_A_OS); - - { - const __FlashStringHelper *optionsModeChanA[] = { F("Off"), F("Gain 64"), F("Gain 128") }; - addFormSelector(F("Mode"), F("modeChA"), 3, optionsModeChanA, nullptr, P067_GET_CHANNEL_A_MODE); - } - - P067_int2float(P067_OFFSET_CHANNEL_A_1, P067_OFFSET_CHANNEL_A_2, &valFloat); - addFormTextBox(F("Offset"), F("offsChA"), toString(valFloat, 3), 25); - addHtml(F("   ↩ Tare: ")); - addCheckBox(F("tareChA"), 0); // always off - - // B ------------ - addFormSubHeader(F("Measurement Channel B")); - - addFormCheckBox(F("Oversampling"), F("osChB"), P067_GET_CHANNEL_B_OS); - - { - const __FlashStringHelper *optionsModeChanB[] = { F("Off"), F("Gain 32") }; - addFormSelector(F("Mode"), F("modeChB"), 2, optionsModeChanB, nullptr, P067_GET_CHANNEL_B_MODE); - } - - P067_int2float(P067_OFFSET_CHANNEL_B_1, P067_OFFSET_CHANNEL_B_2, &valFloat); - addFormTextBox(F("Offset"), F("offsChB"), toString(valFloat, 3), 25); - addHtml(F("   ↩ Tare: ")); - addCheckBox(F("tareChB"), 0); // always off - - // A ------------ - addFormSubHeader(F("Two Point Calibration Channel A")); - addFormCheckBox(F("Calibration Enabled"), F("calChA"), P067_GET_CHANNEL_A_CALIB); - - addFormNumericBox(F("Point 1"), F("adc1ChA"), P067_CONFIG_CHANNEL_A_ADC1); - html_add_estimate_symbol(); - addTextBox(F("out1ChA"), toString(P067_CONFIG_CHANNEL_A_OUT1, 3), 10); - - addFormNumericBox(F("Point 2"), F("adc2ChA"), P067_CONFIG_CHANNEL_A_ADC2); - html_add_estimate_symbol(); - addTextBox(F("out2ChA"), toString(P067_CONFIG_CHANNEL_A_OUT2, 3), 10); - - // B ------------ - addFormSubHeader(F("Two Point Calibration Channel B")); - - addFormCheckBox(F("Calibration Enabled"), F("calChB"), P067_GET_CHANNEL_B_CALIB); - - addFormNumericBox(F("Point 1"), F("adc1ChB"), P067_CONFIG_CHANNEL_B_ADC1); - html_add_estimate_symbol(); - addTextBox(F("out1ChB"), toString(P067_CONFIG_CHANNEL_B_OUT1, 3), 10); - - addFormNumericBox(F("Point 2"), F("adc2ChB"), P067_CONFIG_CHANNEL_B_ADC2); - html_add_estimate_symbol(); - addTextBox(F("out2ChB"), toString(P067_CONFIG_CHANNEL_B_OUT2, 3), 10); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - float valFloat; - - P067_CONFIG_FLAGS = 0; - - P067_SET_CHANNEL_A_OS(isFormItemChecked(F("osChA"))); - P067_SET_CHANNEL_B_OS(isFormItemChecked(F("osChB"))); - - uint32_t tmp = P067_CONFIG_FLAGS; - set2BitToUL(tmp, P067_CONFIG_CHANNEL_A_MODE, getFormItemInt(F("modeChA"))); - P067_CONFIG_FLAGS = tmp; - - P067_SET_CHANNEL_B_MODE(getFormItemInt(F("modeChB"))); - - P067_SET_CHANNEL_A_CALIB(isFormItemChecked(F("calChA"))); - P067_SET_CHANNEL_B_CALIB(isFormItemChecked(F("calChB"))); - - if (isFormItemChecked(F("tareChA"))) { - valFloat = -UserVar[event->BaseVarIndex + 2]; - } else { - valFloat = getFormItemFloat(F("offsChA")); - } - P067_float2int(valFloat, &P067_OFFSET_CHANNEL_A_1, &P067_OFFSET_CHANNEL_A_2); - - if (isFormItemChecked(F("tareChB"))) { - valFloat = -UserVar[event->BaseVarIndex + 3]; - } else { - valFloat = getFormItemFloat(F("offsChB")); - } - P067_float2int(valFloat, &P067_OFFSET_CHANNEL_B_1, &P067_OFFSET_CHANNEL_B_2); - - P067_CONFIG_CHANNEL_A_ADC1 = getFormItemInt(F("adc1ChA")); - P067_CONFIG_CHANNEL_A_OUT1 = getFormItemFloat(F("out1ChA")); - - P067_CONFIG_CHANNEL_A_ADC2 = getFormItemInt(F("adc2ChA")); - P067_CONFIG_CHANNEL_A_OUT2 = getFormItemFloat(F("out2ChA")); - - P067_CONFIG_CHANNEL_B_ADC1 = getFormItemInt(F("adc1ChB")); - P067_CONFIG_CHANNEL_B_OUT1 = getFormItemFloat(F("out1ChB")); - - P067_CONFIG_CHANNEL_B_ADC2 = getFormItemInt(F("adc2ChB")); - P067_CONFIG_CHANNEL_B_OUT2 = getFormItemFloat(F("out2ChB")); - - success = true; - break; - } - - case PLUGIN_INIT: - { - initPluginTaskData(event->TaskIndex, new (std::nothrow) P067_data_struct(event, - CONFIG_PIN1, - CONFIG_PIN2)); - P067_data_struct *P067_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P067_data) { - success = P067_data->init(event); - } - - break; - } - - case PLUGIN_FIFTY_PER_SECOND: - { - P067_data_struct *P067_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P067_data) { - success = P067_data->plugin_fifty_per_second(event); - } - - break; - } - - case PLUGIN_READ: - { - P067_data_struct *P067_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P067_data) { - success = P067_data->plugin_read(event); - } - - break; - } - - case PLUGIN_WRITE: - { - P067_data_struct *P067_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P067_data) { - success = P067_data->plugin_write(event, string); - } - - break; - } - } - return success; -} - -#endif // USES_P067 +#include "_Plugin_Helper.h" +#ifdef USES_P067 + +// ####################################################################################################### +// ####################################### Plugin 067: HX711 Load Cell ################################### +// ####################################################################################################### + +// ESPEasy Plugin to scan a 24 bit AD value from a load cell chip HX711 +// written by Jochen Krapf (jk@nerd2nerd.org) +// +// Modified by chunter to support dual channel measurements. +// When both channels are enabled, sample-rate drops to approx. 1 sample/s for each channel. + +// Electronics: +// Connect SCL to 1st GPIO and DOUT to 2nd GPIO. Use 3.3 volt for VCC. + +// Datasheet: https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/hx711_english.pdf + +/** Changelog: + * 2023-02-23 tonhuisman: Ignore first PLUGIN_READ after startup, as no samples have been read yet so no measurement data is available + * 2023-01-01 tonhuisman: Minor string reductions + * 2022-12-30 tonhuisman: Fix no longer generating events, use DIRECT_pinRead() and DIRECT_pinWrite() to ensure proper working on ESP32, + * include Task number when logging values, reset any previous values on init, change Pin names to match board text + * 2022-12-28 tonhuisman: Refactor using PluginTaskData struct to eliminate the use of static and global variables + * 2022-12-28 tonhuisman: Add changelog, older log not registered + */ + + +# define PLUGIN_067 +# define PLUGIN_ID_067 67 +# define PLUGIN_NAME_067 "Weight - HX711 Load Cell" +# define PLUGIN_VALUENAME1_067 "WeightChanA" +# define PLUGIN_VALUENAME2_067 "WeightChanB" + +# include "./src/PluginStructs/P067_data_struct.h" + +boolean Plugin_067(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_067; + Device[deviceCount].Type = DEVICE_TYPE_DUAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_067); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_067)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_067)); + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: + { + event->String1 = formatGpioName_output(F("SCK")); + event->String2 = formatGpioName_input(F("DT")); + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + float valFloat; + + // A ------------ + addFormSubHeader(F("Measurement Channel A")); + + addFormCheckBox(F("Oversampling"), F("osChA"), P067_GET_CHANNEL_A_OS); + + { + const __FlashStringHelper *optionsModeChanA[] = { F("Off"), F("Gain 64"), F("Gain 128") }; + addFormSelector(F("Mode"), F("modeChA"), 3, optionsModeChanA, nullptr, P067_GET_CHANNEL_A_MODE); + } + + P067_int2float(P067_OFFSET_CHANNEL_A_1, P067_OFFSET_CHANNEL_A_2, &valFloat); + addFormTextBox(F("Offset"), F("offsChA"), toString(valFloat, 3), 25); + addHtml(F("   ↩ Tare: ")); + addCheckBox(F("tareChA"), 0); // always off + + // B ------------ + addFormSubHeader(F("Measurement Channel B")); + + addFormCheckBox(F("Oversampling"), F("osChB"), P067_GET_CHANNEL_B_OS); + + { + const __FlashStringHelper *optionsModeChanB[] = { F("Off"), F("Gain 32") }; + addFormSelector(F("Mode"), F("modeChB"), 2, optionsModeChanB, nullptr, P067_GET_CHANNEL_B_MODE); + } + + P067_int2float(P067_OFFSET_CHANNEL_B_1, P067_OFFSET_CHANNEL_B_2, &valFloat); + addFormTextBox(F("Offset"), F("offsChB"), toString(valFloat, 3), 25); + addHtml(F("   ↩ Tare: ")); + addCheckBox(F("tareChB"), 0); // always off + + // A ------------ + addFormSubHeader(F("Two Point Calibration Channel A")); + addFormCheckBox(F("Calibration Enabled"), F("calChA"), P067_GET_CHANNEL_A_CALIB); + + addFormNumericBox(F("Point 1"), F("adc1ChA"), P067_CONFIG_CHANNEL_A_ADC1); + html_add_estimate_symbol(); + addTextBox(F("out1ChA"), toString(P067_CONFIG_CHANNEL_A_OUT1, 3), 10); + + addFormNumericBox(F("Point 2"), F("adc2ChA"), P067_CONFIG_CHANNEL_A_ADC2); + html_add_estimate_symbol(); + addTextBox(F("out2ChA"), toString(P067_CONFIG_CHANNEL_A_OUT2, 3), 10); + + // B ------------ + addFormSubHeader(F("Two Point Calibration Channel B")); + + addFormCheckBox(F("Calibration Enabled"), F("calChB"), P067_GET_CHANNEL_B_CALIB); + + addFormNumericBox(F("Point 1"), F("adc1ChB"), P067_CONFIG_CHANNEL_B_ADC1); + html_add_estimate_symbol(); + addTextBox(F("out1ChB"), toString(P067_CONFIG_CHANNEL_B_OUT1, 3), 10); + + addFormNumericBox(F("Point 2"), F("adc2ChB"), P067_CONFIG_CHANNEL_B_ADC2); + html_add_estimate_symbol(); + addTextBox(F("out2ChB"), toString(P067_CONFIG_CHANNEL_B_OUT2, 3), 10); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + float valFloat; + + P067_CONFIG_FLAGS = 0; + + P067_SET_CHANNEL_A_OS(isFormItemChecked(F("osChA"))); + P067_SET_CHANNEL_B_OS(isFormItemChecked(F("osChB"))); + + uint32_t tmp = P067_CONFIG_FLAGS; + set2BitToUL(tmp, P067_CONFIG_CHANNEL_A_MODE, getFormItemInt(F("modeChA"))); + P067_CONFIG_FLAGS = tmp; + + P067_SET_CHANNEL_B_MODE(getFormItemInt(F("modeChB"))); + + P067_SET_CHANNEL_A_CALIB(isFormItemChecked(F("calChA"))); + P067_SET_CHANNEL_B_CALIB(isFormItemChecked(F("calChB"))); + + if (isFormItemChecked(F("tareChA"))) { + valFloat = -UserVar[event->BaseVarIndex + 2]; + } else { + valFloat = getFormItemFloat(F("offsChA")); + } + P067_float2int(valFloat, &P067_OFFSET_CHANNEL_A_1, &P067_OFFSET_CHANNEL_A_2); + + if (isFormItemChecked(F("tareChB"))) { + valFloat = -UserVar[event->BaseVarIndex + 3]; + } else { + valFloat = getFormItemFloat(F("offsChB")); + } + P067_float2int(valFloat, &P067_OFFSET_CHANNEL_B_1, &P067_OFFSET_CHANNEL_B_2); + + P067_CONFIG_CHANNEL_A_ADC1 = getFormItemInt(F("adc1ChA")); + P067_CONFIG_CHANNEL_A_OUT1 = getFormItemFloat(F("out1ChA")); + + P067_CONFIG_CHANNEL_A_ADC2 = getFormItemInt(F("adc2ChA")); + P067_CONFIG_CHANNEL_A_OUT2 = getFormItemFloat(F("out2ChA")); + + P067_CONFIG_CHANNEL_B_ADC1 = getFormItemInt(F("adc1ChB")); + P067_CONFIG_CHANNEL_B_OUT1 = getFormItemFloat(F("out1ChB")); + + P067_CONFIG_CHANNEL_B_ADC2 = getFormItemInt(F("adc2ChB")); + P067_CONFIG_CHANNEL_B_OUT2 = getFormItemFloat(F("out2ChB")); + + success = true; + break; + } + + case PLUGIN_INIT: + { + initPluginTaskData(event->TaskIndex, new (std::nothrow) P067_data_struct(event, + CONFIG_PIN1, + CONFIG_PIN2)); + P067_data_struct *P067_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P067_data) { + success = P067_data->init(event); + } + + break; + } + + case PLUGIN_FIFTY_PER_SECOND: + { + P067_data_struct *P067_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P067_data) { + success = P067_data->plugin_fifty_per_second(event); + } + + break; + } + + case PLUGIN_READ: + { + P067_data_struct *P067_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P067_data) { + success = P067_data->plugin_read(event); + } + + break; + } + + case PLUGIN_WRITE: + { + P067_data_struct *P067_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P067_data) { + success = P067_data->plugin_write(event, string); + } + + break; + } + } + return success; +} + +#endif // USES_P067 diff --git a/src/_P068_SHT3x.ino b/src/_P068_SHT3x.ino index 19c38a8313..96a7bd8fa8 100644 --- a/src/_P068_SHT3x.ino +++ b/src/_P068_SHT3x.ino @@ -1,146 +1,142 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P068 - -# include "src/PluginStructs/P068_data_struct.h" - -# include "src/Helpers/Convert.h" -# include "src/Helpers/ESPEasy_math.h" - -// ####################################################################################################### -// ################ Plugin 68: SHT30/SHT31/SHT35 Temperature and Humidity Sensor (I2C) ################### -// ####################################################################################################### -// ######################## Library source code for Arduino by WeMos, 2016 ############################### -// ####################################################################################################### -// ###################### Plugin for ESP Easy by B.E.I.C. ELECTRONICS, 2017 ############################## -// ############################### http://www.beicelectronics.com ######################################## -// ####################################################################################################### -// ########################## Adapted to ESPEasy 2.0 by Jochen Krapf ##################################### -// ####################################################################################################### - -// Changelog: -// 2023-04-28 @iz8mbw: Rename sensor to SHT3x from SHT30/31/35 -// 2021-06-12 @tonhuisman: Add temperature offset setting, with humidity compensation method 'borrowed' from BME280 sensor -// 2020-?? @TD-er: Maitenance updates -// 2017-07-18 @JK-de: Plugin adaption for ESPEasy 2.0 - -# define PLUGIN_068 -# define PLUGIN_ID_068 68 -# define PLUGIN_NAME_068 "Environment - SHT3x" -# define PLUGIN_VALUENAME1_068 "Temperature" -# define PLUGIN_VALUENAME2_068 "Humidity" - - -// ============================================== -// PLUGIN -// ============================================= - -boolean Plugin_068(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_068; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_068); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_068)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_068)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: - { - const uint8_t i2cAddressValues[] = { 0x44, 0x45 }; - - if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - addFormSelectorI2C(F("i2c_addr"), 2, i2cAddressValues, PCONFIG(0)); - } else { - success = intArrayContains(2, i2cAddressValues, event->Par1); - } - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = PCONFIG(0); - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_WEBFORM_LOAD: - { - addFormNumericBox(F("Temperature offset"), F("tempoffset"), PCONFIG(1)); - addUnit(F("x 0.1C")); - # ifndef BUILD_NO_DEBUG - addFormNote(F("Offset in units of 0.1 degree Celsius")); - # endif // ifndef BUILD_NO_DEBUG - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(0) = getFormItemInt(F("i2c_addr")); - PCONFIG(1) = getFormItemInt(F("tempoffset")); - - success = true; - break; - } - - case PLUGIN_INIT: - { - success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P068_SHT3X(PCONFIG(0))); - break; - } - - case PLUGIN_READ: - { - P068_SHT3X *sht3x = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == sht3x) { - addLog(LOG_LEVEL_ERROR, F("SHT3x: not initialised!")); - return success; - } - - sht3x->tmpOff = PCONFIG(1) / 10.0f; - sht3x->readFromSensor(); - UserVar.setFloat(event->TaskIndex, 0, sht3x->tmp); - UserVar.setFloat(event->TaskIndex, 1, sht3x->hum); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, concat(F("SHT3x: Temperature: "), formatUserVarNoCheck(event, 0))); - addLogMove(LOG_LEVEL_INFO, concat(F("SHT3x: Humidity: "), formatUserVarNoCheck(event, 1))); - } - success = true; - break; - } - } - return success; -} - -#endif // USES_P068 +#include "_Plugin_Helper.h" +#ifdef USES_P068 + +# include "src/PluginStructs/P068_data_struct.h" + +# include "src/Helpers/Convert.h" +# include "src/Helpers/ESPEasy_math.h" + +// ####################################################################################################### +// ################ Plugin 68: SHT30/SHT31/SHT35 Temperature and Humidity Sensor (I2C) ################### +// ####################################################################################################### +// ######################## Library source code for Arduino by WeMos, 2016 ############################### +// ####################################################################################################### +// ###################### Plugin for ESP Easy by B.E.I.C. ELECTRONICS, 2017 ############################## +// ############################### http://www.beicelectronics.com ######################################## +// ####################################################################################################### +// ########################## Adapted to ESPEasy 2.0 by Jochen Krapf ##################################### +// ####################################################################################################### + +// Changelog: +// 2023-04-28 @iz8mbw: Rename sensor to SHT3x from SHT30/31/35 +// 2021-06-12 @tonhuisman: Add temperature offset setting, with humidity compensation method 'borrowed' from BME280 sensor +// 2020-?? @TD-er: Maitenance updates +// 2017-07-18 @JK-de: Plugin adaption for ESPEasy 2.0 + +# define PLUGIN_068 +# define PLUGIN_ID_068 68 +# define PLUGIN_NAME_068 "Environment - SHT3x" +# define PLUGIN_VALUENAME1_068 "Temperature" +# define PLUGIN_VALUENAME2_068 "Humidity" + + +// ============================================== +// PLUGIN +// ============================================= + +boolean Plugin_068(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_068; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_068); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_068)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_068)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: + { + const uint8_t i2cAddressValues[] = { 0x44, 0x45 }; + + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { + addFormSelectorI2C(F("i2c_addr"), 2, i2cAddressValues, PCONFIG(0)); + } else { + success = intArrayContains(2, i2cAddressValues, event->Par1); + } + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = PCONFIG(0); + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_WEBFORM_LOAD: + { + addFormNumericBox(F("Temperature offset"), F("tempoffset"), PCONFIG(1)); + addUnit(F("x 0.1C")); + # ifndef BUILD_NO_DEBUG + addFormNote(F("Offset in units of 0.1 degree Celsius")); + # endif // ifndef BUILD_NO_DEBUG + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(0) = getFormItemInt(F("i2c_addr")); + PCONFIG(1) = getFormItemInt(F("tempoffset")); + + success = true; + break; + } + + case PLUGIN_INIT: + { + success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P068_SHT3X(PCONFIG(0))); + break; + } + + case PLUGIN_READ: + { + P068_SHT3X *sht3x = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == sht3x) { + addLog(LOG_LEVEL_ERROR, F("SHT3x: not initialised!")); + return success; + } + + sht3x->tmpOff = PCONFIG(1) / 10.0f; + sht3x->readFromSensor(); + UserVar.setFloat(event->TaskIndex, 0, sht3x->tmp); + UserVar.setFloat(event->TaskIndex, 1, sht3x->hum); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, concat(F("SHT3x: Temperature: "), formatUserVarNoCheck(event, 0))); + addLogMove(LOG_LEVEL_INFO, concat(F("SHT3x: Humidity: "), formatUserVarNoCheck(event, 1))); + } + success = true; + break; + } + } + return success; +} + +#endif // USES_P068 diff --git a/src/_P069_LM75A.ino b/src/_P069_LM75A.ino index 695dd11fdf..522bb63b83 100644 --- a/src/_P069_LM75A.ino +++ b/src/_P069_LM75A.ino @@ -13,13 +13,13 @@ // ####################################################################################################### -#define PLUGIN_069 -#define PLUGIN_ID_069 69 -#define PLUGIN_NAME_069 "Environment - LM75A" -#define PLUGIN_VALUENAME1_069 "Temperature" +# define PLUGIN_069 +# define PLUGIN_ID_069 69 +# define PLUGIN_NAME_069 "Environment - LM75A" +# define PLUGIN_VALUENAME1_069 "Temperature" -#include "src/PluginStructs/P069_data_struct.h" +# include "src/PluginStructs/P069_data_struct.h" boolean Plugin_069(uint8_t function, struct EventStruct *event, String& string) @@ -30,18 +30,14 @@ boolean Plugin_069(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_069; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_069; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -61,6 +57,7 @@ boolean Plugin_069(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: { const uint8_t i2cAddressValues[] = { 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F }; + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { addFormSelectorI2C(F("i2c_addr"), 8, i2cAddressValues, PCONFIG(0)); } else { @@ -117,7 +114,7 @@ boolean Plugin_069(uint8_t function, struct EventStruct *event, String& string) } else { - addLogMove(LOG_LEVEL_INFO, concat(F("LM75A: Temperature: "), formatUserVarNoCheck(event,0))); + addLogMove(LOG_LEVEL_INFO, concat(F("LM75A: Temperature: "), formatUserVarNoCheck(event, 0))); } } break; diff --git a/src/_P070_NeoPixel_Clock.ino b/src/_P070_NeoPixel_Clock.ino index bff2699b3a..8a6b666cef 100644 --- a/src/_P070_NeoPixel_Clock.ino +++ b/src/_P070_NeoPixel_Clock.ino @@ -36,11 +36,10 @@ boolean Plugin_070(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_070; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 3; + Device[++deviceCount].Number = PLUGIN_ID_070; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + Device[deviceCount].ValueCount = 3; Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); // FIXME TD-er: Not sure if access to any existing task data is needed when saving diff --git a/src/_P071_Kamstrup401.ino b/src/_P071_Kamstrup401.ino index 5b813b3e65..9783279250 100644 --- a/src/_P071_Kamstrup401.ino +++ b/src/_P071_Kamstrup401.ino @@ -1,30 +1,32 @@ #include "_Plugin_Helper.h" #ifdef USES_P071 -//####################################################################################################### -//############################# Plugin 071: Kamstrup Multical 401 ####################################### -//####################################################################################################### -//IR RX/TX sensor based on http://wiki.hal9k.dk/projects/kamstrup -//schematic http://wiki.hal9k.dk/_media/projects/kamstrup/schematic.pdf -//software based on http://elektronikforumet.com/forum/viewtopic.php?f=2&t=79853 +// ####################################################################################################### +// ############################# Plugin 071: Kamstrup Multical 401 ####################################### +// ####################################################################################################### -//Device pin 1 = RX -//Device pin 2 = TX +// IR RX/TX sensor based on http://wiki.hal9k.dk/projects/kamstrup +// schematic http://wiki.hal9k.dk/_media/projects/kamstrup/schematic.pdf +// software based on http://elektronikforumet.com/forum/viewtopic.php?f=2&t=79853 + +// Device pin 1 = RX +// Device pin 2 = TX /** Changelog: + * 2025-01-04 tonhuisman: Reformat source using Uncrustify, minor code optimizations * 2024-01-06 tonhuisman: Disable unused variables and some unused code, log optimizations * 2024-01-06 tonhuisman: Start changelog, newest entry on top */ -#include +# include -#include "src/ESPEasyCore/Serial.h" +# include "src/ESPEasyCore/Serial.h" -#define PLUGIN_071 -#define PLUGIN_ID_071 71 -#define PLUGIN_NAME_071 "Communication - Kamstrup Multical 401" -#define PLUGIN_VALUENAME1_071 "Heat" -#define PLUGIN_VALUENAME2_071 "Volume" +# define PLUGIN_071 +# define PLUGIN_ID_071 71 +# define PLUGIN_NAME_071 "Communication - Kamstrup Multical 401" +# define PLUGIN_VALUENAME1_071 "Heat" +# define PLUGIN_VALUENAME2_071 "Volume" // boolean Plugin_071_init = false; // uint8_t PIN_KAMSER_RX = 0; @@ -37,60 +39,56 @@ boolean Plugin_071(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_071; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - break; - } + { + Device[++deviceCount].Number = PLUGIN_ID_071; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + break; + } case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_071); - break; - } + { + string = F(PLUGIN_NAME_071); + break; + } case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_071)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_071)); - break; - } + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_071)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_071)); + break; + } case PLUGIN_GET_DEVICEGPIONAMES: - { - serialHelper_getGpioNames(event); - break; - } + { + serialHelper_getGpioNames(event); + break; + } case PLUGIN_WEBFORM_SHOW_CONFIG: - { - string += serialHelper_getSerialTypeLabel(event); - success = true; - break; - } + { + string += serialHelper_getSerialTypeLabel(event); + success = true; + break; + } case PLUGIN_INIT: - { - // Plugin_071_init = true; + { + // Plugin_071_init = true; - success = true; - break; - } + success = true; + break; + } case PLUGIN_WEBFORM_LOAD: - { - success = true; - break; - } + { + success = true; + break; + } case PLUGIN_WEBFORM_SAVE: { success = true; @@ -98,198 +96,214 @@ boolean Plugin_071(uint8_t function, struct EventStruct *event, String& string) } case PLUGIN_READ: - { - // PIN_KAMSER_RX = CONFIG_PIN1; - // PIN_KAMSER_TX = CONFIG_PIN2; - const ESPEasySerialPort port = static_cast(CONFIG_PORT); + { + // PIN_KAMSER_RX = CONFIG_PIN1; + // PIN_KAMSER_TX = CONFIG_PIN2; + const ESPEasySerialPort port = static_cast(CONFIG_PORT); - ESPeasySerial kamSer(port, CONFIG_PIN1, CONFIG_PIN2, false); // Initialize serial + ESPeasySerial kamSer(port, CONFIG_PIN1, CONFIG_PIN2, false); // Initialize serial - pinMode(CONFIG_PIN1,INPUT); - pinMode(CONFIG_PIN2,OUTPUT); + pinMode(CONFIG_PIN1, INPUT); + pinMode(CONFIG_PIN2, OUTPUT); - //read Kamstrup - uint8_t sendmsg1[] = { 175,163,177 }; // /#1 with even parity + // read Kamstrup + uint8_t sendmsg1[] = { 175, 163, 177 }; // /#1 with even parity - uint8_t r = 0; - uint8_t to = 0; - uint8_t i = 0; - char message[255]; - int parityerrors = 0; + uint8_t r = 0; + uint8_t to = 0; + uint8_t i = 0; + char message[255]; + int parityerrors = 0; - kamSer.begin(300); - for (int x = 0; x < 3; ++x) { - kamSer.write(sendmsg1[x]); - } + kamSer.begin(300); + + for (int x = 0; x < 3; ++x) { + kamSer.write(sendmsg1[x]); + } + + kamSer.flush(); - kamSer.flush(); - //kamSer.end(); - kamSer.begin(1200); + // kamSer.end(); + kamSer.begin(1200); - // to = 0; - // r = 0; - // i = 0; - // parityerrors = 0; - char *tmpstr; - ESPEASY_RULES_FLOAT_TYPE m_energy, m_volume; - // float m_tempin, m_tempout, m_tempdiff, m_power; - // long m_hours, m_flow; + // to = 0; + // r = 0; + // i = 0; + // parityerrors = 0; + char *tmpstr; + ESPEASY_RULES_FLOAT_TYPE m_energy, m_volume; - while(r != 0x0A) + // float m_tempin, m_tempout, m_tempdiff, m_power; + // long m_hours, m_flow; + + while (r != 0x0A) + { + if (kamSer.available()) { - if (kamSer.available()) - { - // receive uint8_t - r = kamSer.read(); - //serialPrintln(r); - if (parity_check(r)) - { - parityerrors += 1; - } - r = r & 127; // Mask MSB to remove parity + // receive uint8_t + r = kamSer.read(); - message[i++] = char(r); - } - else + // serialPrintln(r); + if (parity_check(r)) { - to++; - delay(25); + parityerrors += 1; } + r = r & 127; // Mask MSB to remove parity + + message[i++] = char(r); + } + else + { + to++; + delay(25); + } - if (i >= 79) + if (i >= 79) + { + if (parityerrors == 0) { - if (parityerrors == 0 ) - { -// serialPrint("OK: " ); -// serialPrintln(message); - message[i] = 0; - - tmpstr = strtok(message, " "); - if (tmpstr){ - m_energy = atol(tmpstr) / 3.6 * 1000; - } - else - m_energy = 0; - - tmpstr = strtok(nullptr, " "); - if (tmpstr) - m_volume = atol(tmpstr); - else - m_volume = 0; - - // tmpstr = strtok(nullptr, " "); - // if (tmpstr) - // m_hours = atol(tmpstr); - // else - // m_hours = 0; - - // tmpstr = strtok(nullptr, " "); - // if (tmpstr) - // m_tempin = atol(tmpstr) / 100.0f; - // else - // m_tempin = 0; - - // tmpstr = strtok(nullptr, " "); - // if (tmpstr) - // m_tempout = atol(tmpstr) / 100.0f; - // else - // m_tempout = 0; - - // tmpstr = strtok(nullptr, " "); - // if (tmpstr) - // m_tempdiff = atol(tmpstr) / 100.0f; - // else - // m_tempdiff = 0; - - // tmpstr = strtok(nullptr, " "); - // if (tmpstr) - // m_power = atol(tmpstr) / 10.0f; - // else - // m_power = 0; - - // tmpstr = strtok(nullptr, " "); - // if (tmpstr) - // m_flow = atol(tmpstr); - // else - // m_flow = 0; -// { -// String log = F("Kamstrup output: "); -// log += m_energy; -// log += F(" MJ; "); -// log += m_volume; -// log += F(" L; "); -// log += m_hours; -// log += F(" h; "); -// log += m_tempin; -// log += F(" C; "); -// log += m_tempout; -// log += F(" C; "); -// log += m_tempdiff; -// log += F(" C; "); -// log += m_power; -// log += ' '; -// log += m_flow; -// log += F(" L/H"); -// // addLog(LOG_LEVEL_INFO, log); -// } - UserVar.setFloat(event->TaskIndex, 0, m_energy); //gives energy in Wh - UserVar.setFloat(event->TaskIndex, 1, m_volume); //gives volume in liters - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, strformat(F("Kamstrup : Heat value: %.3f kWh"), m_energy / 1000)); - addLogMove(LOG_LEVEL_INFO, strformat(F("Kamstrup : Volume value: %d Liter"), m_volume)); - } + // serialPrint("OK: " ); + // serialPrintln(message); + message[i] = 0; + + tmpstr = strtok(message, " "); + + if (tmpstr) { + m_energy = atol(tmpstr) / 3.6 * 1000; + } + else { + m_energy = 0; + } + + tmpstr = strtok(nullptr, " "); + + if (tmpstr) { + m_volume = atol(tmpstr); } - else - { - message[i] = 0; - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - serialPrint("par"); // FIXME ? Why this ? - addLogMove(LOG_LEVEL_INFO, concat(F("ERR(PARITY):" ), String(message))); - } - //UserVar.setFloat(event->TaskIndex, 0, NAN); - //UserVar.setFloat(event->TaskIndex, 1, NAN); + else { + m_volume = 0; + } + + // tmpstr = strtok(nullptr, " "); + // if (tmpstr) + // m_hours = atol(tmpstr); + // else + // m_hours = 0; + + // tmpstr = strtok(nullptr, " "); + // if (tmpstr) + // m_tempin = atol(tmpstr) / 100.0f; + // else + // m_tempin = 0; + + // tmpstr = strtok(nullptr, " "); + // if (tmpstr) + // m_tempout = atol(tmpstr) / 100.0f; + // else + // m_tempout = 0; + + // tmpstr = strtok(nullptr, " "); + // if (tmpstr) + // m_tempdiff = atol(tmpstr) / 100.0f; + // else + // m_tempdiff = 0; + + // tmpstr = strtok(nullptr, " "); + // if (tmpstr) + // m_power = atol(tmpstr) / 10.0f; + // else + // m_power = 0; + + // tmpstr = strtok(nullptr, " "); + // if (tmpstr) + // m_flow = atol(tmpstr); + // else + // m_flow = 0; + // { + // String log = F("Kamstrup output: "); + // log += m_energy; + // log += F(" MJ; "); + // log += m_volume; + // log += F(" L; "); + // log += m_hours; + // log += F(" h; "); + // log += m_tempin; + // log += F(" C; "); + // log += m_tempout; + // log += F(" C; "); + // log += m_tempdiff; + // log += F(" C; "); + // log += m_power; + // log += ' '; + // log += m_flow; + // log += F(" L/H"); + // // addLog(LOG_LEVEL_INFO, log); + // } + UserVar.setFloat(event->TaskIndex, 0, m_energy); // gives energy in Wh + UserVar.setFloat(event->TaskIndex, 1, m_volume); // gives volume in liters + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, strformat(F("Kamstrup : Heat value: %.3f kWh"), m_energy / 1000)); + addLogMove(LOG_LEVEL_INFO, strformat(F("Kamstrup : Volume value: %d Liter"), m_volume)); } - break; } - if (to > 100) + else { message[i] = 0; + if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, concat(F("ERR(TIMEOUT):" ), String(message))); + serialPrint("par"); // FIXME ? Why this ? + addLogMove(LOG_LEVEL_INFO, concat(F("ERR(PARITY):"), String(message))); } - //UserVar.setFloat(event->TaskIndex, 0, NAN); - //UserVar.setFloat(event->TaskIndex, 1, NAN); - break; + // UserVar.setFloat(event->TaskIndex, 0, NAN); + // UserVar.setFloat(event->TaskIndex, 1, NAN); } + break; } - //end read Kamstrup + if (to > 100) + { + message[i] = 0; + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, concat(F("ERR(TIMEOUT):"), String(message))); + } - success = true; - break; + // UserVar.setFloat(event->TaskIndex, 0, NAN); + // UserVar.setFloat(event->TaskIndex, 1, NAN); + break; + } } + + // end read Kamstrup + + + success = true; + break; + } } return success; } bool parity_check(unsigned input) { bool inputparity = input & 128; - int x = input & 127; + int x = input & 127; int parity = 0; - while(x != 0) { + + while (x != 0) { parity ^= x; - x >>= 1; + x >>= 1; } - if ( (parity & 0x1) != inputparity ) - return(1); - else - return(0); + if ((parity & 0x1) != inputparity) { + return 1; + } + else { + return 0; + } } #endif // USES_P071 diff --git a/src/_P072_HDC1080.ino b/src/_P072_HDC1080.ino index c3ac8fd2be..95db3e33e6 100644 --- a/src/_P072_HDC1080.ino +++ b/src/_P072_HDC1080.ino @@ -1,128 +1,121 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P072 - -// ###################################################################################################### -// ####################### Plugin 072: Temperature and Humidity sensor HDC10xx (I2C) #################### -// ###################################################################################################### - -/** Changelog: - * 2023-02-09 tonhuisman: Fix typo in temperature calculation (was 65526.0f instead of 65536.0f (2^16)) - * 2023-02-08 tonhuisman: Add PLUGIN_I2C_GET_ADDRESS support - * 2023-02-09 tonhuisman: Start changelog - */ - -# define PLUGIN_072 -# define PLUGIN_ID_072 72 -# define PLUGIN_NAME_072 "Environment - HDC10xx (I2C)" -# define PLUGIN_VALUENAME1_072 "Temperature" -# define PLUGIN_VALUENAME2_072 "Humidity" - - -# define HDC1080_I2C_ADDRESS 0x40 // I2C address for the sensor - -boolean Plugin_072(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_072; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CNoDeviceCheck = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_072); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_072)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_072)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - { - success = (event->Par1 == HDC1080_I2C_ADDRESS); - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = HDC1080_I2C_ADDRESS; - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_INIT: - { - success = true; - break; - } - - case PLUGIN_READ: - { - uint8_t hdc1080_msb, hdc1080_lsb; - uint16_t hdc1080_rawtemp, hdc1080_rawhum; - float hdc1080_temp, hdc1080_hum; - - Wire.beginTransmission(HDC1080_I2C_ADDRESS); // start transmission to device - Wire.write(0x02); // sends HDC1080_CONFIGURATION - Wire.write(0b00000000); // set resolution to 14bits both for T and H - Wire.write(0x00); // **reserved** - Wire.endTransmission(); // end transmission - delay(10); - - Wire.beginTransmission(HDC1080_I2C_ADDRESS); // start transmission to device - Wire.write(0x00); // sends HDC1080_TEMPERATURE - Wire.endTransmission(); // end transmission - delay(9); - Wire.requestFrom(HDC1080_I2C_ADDRESS, 2); // read 2 bytes for temperature - hdc1080_msb = Wire.read(); - hdc1080_lsb = Wire.read(); - hdc1080_rawtemp = hdc1080_msb << 8 | hdc1080_lsb; - hdc1080_temp = (static_cast(hdc1080_rawtemp) / 65536.0f) * 165.0f - 40.0f; - - Wire.beginTransmission(HDC1080_I2C_ADDRESS); // start transmission to device - Wire.write(0x01); // sends HDC1080_HUMIDITY - Wire.endTransmission(); // end transmission - delay(9); - Wire.requestFrom(HDC1080_I2C_ADDRESS, 2); // read 2 bytes for humidity - hdc1080_msb = Wire.read(); - hdc1080_lsb = Wire.read(); - hdc1080_rawhum = hdc1080_msb << 8 | hdc1080_lsb; - hdc1080_hum = (static_cast(hdc1080_rawhum) / 65536.0f) * 100.0f; - - UserVar.setFloat(event->TaskIndex, 0, hdc1080_temp); - UserVar.setFloat(event->TaskIndex, 1, hdc1080_hum); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, concat(F("HDC10xx: Temperature: "), formatUserVarNoCheck(event, 0))); - addLogMove(LOG_LEVEL_INFO, concat(F("HDC10xx: Humidity: "), formatUserVarNoCheck(event, 1))); - } - success = true; - break; - } - } - return success; -} - -#endif // USES_P072 +#include "_Plugin_Helper.h" +#ifdef USES_P072 + +// ###################################################################################################### +// ####################### Plugin 072: Temperature and Humidity sensor HDC10xx (I2C) #################### +// ###################################################################################################### + +/** Changelog: + * 2025-01-04 tonhuisman: Send initialization (resolution setting) only once during INIT, small code optimizations + * 2023-02-09 tonhuisman: Fix typo in temperature calculation (was 65526.0f instead of 65536.0f (2^16)) + * 2023-02-08 tonhuisman: Add PLUGIN_I2C_GET_ADDRESS support + * 2023-02-09 tonhuisman: Start changelog + */ + +# define PLUGIN_072 +# define PLUGIN_ID_072 72 +# define PLUGIN_NAME_072 "Environment - HDC10xx (I2C)" +# define PLUGIN_VALUENAME1_072 "Temperature" +# define PLUGIN_VALUENAME2_072 "Humidity" + + +# define HDC1080_I2C_ADDRESS 0x40 // I2C address for the sensor + +boolean Plugin_072(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_072; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].I2CNoDeviceCheck = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_072); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_072)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_072)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + { + success = (event->Par1 == HDC1080_I2C_ADDRESS); + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = HDC1080_I2C_ADDRESS; + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_INIT: + { + // Send only once + Wire.beginTransmission(HDC1080_I2C_ADDRESS); // start transmission to device + Wire.write(0x02); // sends HDC1080_CONFIGURATION + Wire.write(0b00000000); // set resolution to 14bits both for T and H + Wire.write(0x00); // **reserved** + Wire.endTransmission(); // end transmission + delay(10); + + success = true; + break; + } + + case PLUGIN_READ: + { + uint16_t hdc1080_rawtemp, hdc1080_rawhum; + float hdc1080_temp, hdc1080_hum; + + Wire.beginTransmission(HDC1080_I2C_ADDRESS); // start transmission to device + Wire.write(0x00); // sends HDC1080_TEMPERATURE + Wire.endTransmission(); // end transmission + delay(9); + Wire.requestFrom(HDC1080_I2C_ADDRESS, 2); // read 2 bytes for temperature + hdc1080_rawtemp = Wire.read() << 8 | Wire.read(); + hdc1080_temp = (static_cast(hdc1080_rawtemp) / 65536.0f) * 165.0f - 40.0f; + + Wire.beginTransmission(HDC1080_I2C_ADDRESS); // start transmission to device + Wire.write(0x01); // sends HDC1080_HUMIDITY + Wire.endTransmission(); // end transmission + delay(9); + Wire.requestFrom(HDC1080_I2C_ADDRESS, 2); // read 2 bytes for humidity + hdc1080_rawhum = Wire.read() << 8 | Wire.read(); + hdc1080_hum = (static_cast(hdc1080_rawhum) / 65536.0f) * 100.0f; + + UserVar.setFloat(event->TaskIndex, 0, hdc1080_temp); + UserVar.setFloat(event->TaskIndex, 1, hdc1080_hum); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, concat(F("HDC10xx: Temperature: "), formatUserVarNoCheck(event, 0))); + addLogMove(LOG_LEVEL_INFO, concat(F("HDC10xx: Humidity: "), formatUserVarNoCheck(event, 1))); + } + success = true; + break; + } + } + return success; +} + +#endif // USES_P072 diff --git a/src/_P073_7DGT.ino b/src/_P073_7DGT.ino index 84ca01e3c8..279f25da77 100644 --- a/src/_P073_7DGT.ino +++ b/src/_P073_7DGT.ino @@ -87,11 +87,9 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_073; - Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 0; + Device[++deviceCount].Number = PLUGIN_ID_073; + Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); @@ -119,7 +117,8 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) F("TM1637 - 4 digit (dots)"), F("TM1637 - 6 digit"), F("MAX7219 - 8 digit") }; - addFormSelector(F("Display Type"), F("displtype"), 4, displtype, nullptr, PCONFIG(0)); + constexpr size_t optionCount = NR_ELEMENTS(displtype); + addFormSelector(F("Display Type"), F("displtype"), optionCount, displtype, nullptr, PCONFIG(0)); } { const __FlashStringHelper *displout[] = { F("Manual"), @@ -128,7 +127,8 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) F("Clock 12h - Blink"), F("Clock 12h - No Blink"), F("Date") }; - addFormSelector(F("Display Output"), F("displout"), 6, displout, nullptr, PCONFIG(1)); + constexpr size_t optionCount = NR_ELEMENTS(displout); + addFormSelector(F("Display Output"), F("displout"), optionCount, displout, nullptr, PCONFIG(1)); } addFormNumericBox(F("Brightness"), F("brightness"), PCONFIG(2), 0, 15); @@ -136,11 +136,12 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) # ifdef P073_EXTRA_FONTS { - const __FlashStringHelper *fontset[4] = { F("Default"), - F("Siekoo"), - F("Siekoo with uppercase 'CHNORUX'"), - F("dSEG7") }; - addFormSelector(F("Font set"), F("fontset"), 4, fontset, nullptr, PCONFIG(4)); + const __FlashStringHelper *fontset[] = { F("Default"), + F("Siekoo"), + F("Siekoo with uppercase 'CHNORUX'"), + F("dSEG7") }; + constexpr size_t optionCount = NR_ELEMENTS(fontset); + addFormSelector(F("Font set"), F("fontset"), optionCount, fontset, nullptr, PCONFIG(4)); addFormNote(F("Check documentation for examples of the font sets.")); } # endif // P073_EXTRA_FONTS diff --git a/src/_P074_TSL2591.ino b/src/_P074_TSL2591.ino index 05ce4ec4dd..21059f06ce 100644 --- a/src/_P074_TSL2591.ino +++ b/src/_P074_TSL2591.ino @@ -19,8 +19,8 @@ // https://github.com/adafruit/Adafruit_TSL2591_Library/issues/17 # define PLUGIN_074 -# define PLUGIN_ID_074 74 -# define PLUGIN_NAME_074 "Light/Lux - TSL2591" +# define PLUGIN_ID_074 74 +# define PLUGIN_NAME_074 "Light/Lux - TSL2591" # define PLUGIN_VALUENAME1_074 "Lux" # define PLUGIN_VALUENAME2_074 "Full" # define PLUGIN_VALUENAME3_074 "Visible" @@ -31,19 +31,14 @@ boolean Plugin_074(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_074; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = false; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_074; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -100,7 +95,8 @@ boolean Plugin_074(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *optionsMode[6] = { F("100"), F("200"), F("300"), F("400"), F("500"), F("600") }; - addFormSelector(F("Integration Time"), F("itime"), 6, optionsMode, + constexpr size_t optionCount = NR_ELEMENTS(optionsMode); + addFormSelector(F("Integration Time"), F("itime"), optionCount, optionsMode, nullptr, PCONFIG(1)); addUnit(F("ms")); } @@ -112,7 +108,8 @@ boolean Plugin_074(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *optionsGain[4] = { F("low gain (1x)"), F("medium gain (25x)"), F("medium gain (428x)"), F("max gain (9876x)") }; - addFormSelector(F("Value Mapping"), F("gain"), 4, optionsGain, nullptr, + constexpr size_t optionCount = NR_ELEMENTS(optionsGain); + addFormSelector(F("Value Mapping"), F("gain"), optionCount, optionsGain, nullptr, PCONFIG(2)); } diff --git a/src/_P075_Nextion.ino b/src/_P075_Nextion.ino index 4727469895..9ae904bba2 100644 --- a/src/_P075_Nextion.ino +++ b/src/_P075_Nextion.ino @@ -1,481 +1,466 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P075 - -# include "src/PluginStructs/P075_data_struct.h" - -# include "src/ESPEasyCore/ESPEasyWifi.h" - -// ####################################################################################################### -// ####################################################################################################### -// ################################### Plugin 075: Nextion ########################### -// ################################### Created on the work of majklovec ########################### -// ################################### Revisions by BertB, ThomasB and others ########################### -// ################################### Last Revision: 2022-09-27 ########################### -// ####################################################################################################### -// - -/** Changelog: - * 2022-09-27 tonhuisman: Use Changelog formatted updates - * Extend nr. of lines available for text/commands to 20, minor code improvements - * Updated: Oct-03-2018, ThomasB. - * Added P075_DEBUG_LOG define to reduce info log messages and prevent serial log flooding. - * Added SendStatus() to post log message on browser to acknowledge HTTP write. - * Added reserve() to minimize string memory allocations. - */ - -// ***************************************************************************************************** -// Defines start here -// ***************************************************************************************************** - -// #define P075_DEBUG_LOG // Enable this to include additional info messages in log output. - - -// Plug-In defines -# define PLUGIN_075 -# define PLUGIN_ID_075 75 -# define PLUGIN_NAME_075 "Display - Nextion" -# define PLUGIN_DEFAULT_NAME "NEXTION" -# define PLUGIN_VALUENAME1_075 "idx" -# define PLUGIN_VALUENAME2_075 "value" - - -// ***************************************************************************************************** -// PlugIn starts here -// ***************************************************************************************************** - -boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) { - case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_075; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; // Pullup is not used. - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; // Allow user to disable interval function. - Device[deviceCount].GlobalSyncOption = true; - - // FIXME TD-er: Not sure if access to any existing task data is needed when saving - Device[deviceCount].ExitTaskBeforeSave = false; - - break; - } - - - case PLUGIN_GET_DEVICENAME: { - string = F(PLUGIN_NAME_075); - break; - } - - - case PLUGIN_GET_DEVICEVALUENAMES: { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_075)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_075)); - break; - } - - - case PLUGIN_GET_DEVICEGPIONAMES: { - serialHelper_getGpioNames(event); - break; - } - - case PLUGIN_WEBFORM_SHOW_CONFIG: - { - string += serialHelper_getSerialTypeLabel(event); - success = true; - break; - } - - case PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS: - { - const __FlashStringHelper *options[4] = { - F("9600"), - F("38400"), - F("57600"), - F("115200") - }; - - addFormSelector(F("Baud Rate"), F("baud"), 4, options, nullptr, P075_BaudRate); - addUnit(F("baud")); - break; - } - - case PLUGIN_WEBFORM_LOAD: { - // ** DEVELOPER DEBUG MESSAGE AREA ** - // int datax = static_cast(Settings.TaskDeviceEnabled[event->TaskIndex]); // Debug value. - // String Data = "Debug. Plugin Enable State: "; - // Data += String(datax); - // addFormNote(Data); - - addFormSubHeader(F("")); // Blank line, vertical space. - addFormHeader(F("Nextion Command Statements (Optional)")); - P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P075_data) { - P075_data->loadDisplayLines(event->TaskIndex); - - for (int varNr = 0; varNr < P75_Nlines; varNr++) { - addFormTextBox(concat(F("Line "), varNr + 1), getPluginCustomArgName(varNr), P075_data->displayLines[varNr], P75_Nchars - 1); - } - } - - if (Settings.TaskDeviceTimer[event->TaskIndex] == 0) { // Is interval timer disabled? - addFormNote(concat(F("Interval Timer OFF, Nextion Lines (above)"), P075_IncludeValues - ? F(" and Values (below) NOT scheduled for updates") - : F(" NOT scheduled for updates"))); - } - - addFormSeparator(2); - addFormSubHeader(F("Interval Options")); - addFormCheckBox(F("Resend Values (below) at Interval"), F("IncludeValues"), P075_IncludeValues); - - success = true; - break; - } - - - case PLUGIN_WEBFORM_SAVE: { - { - // FIXME TD-er: This is a huge object allocated on the Stack. - char deviceTemplate[P75_Nlines][P75_Nchars] = {}; - String error; - - for (uint8_t varNr = 0; varNr < P75_Nlines; varNr++) - { - if (!safe_strncpy(deviceTemplate[varNr], webArg(getPluginCustomArgName(varNr)), P75_Nchars)) { - error += getCustomTaskSettingsError(varNr); - } - } - - if (error.length() > 0) { - addHtmlError(error); - } - SaveCustomTaskSettings(event->TaskIndex, (uint8_t *)&deviceTemplate, sizeof(deviceTemplate)); - } - - if (getTaskDeviceName(event->TaskIndex).isEmpty()) { // Check to see if user entered device name. - strcpy(ExtraTaskSettings.TaskDeviceName, PLUGIN_DEFAULT_NAME); // Name missing, populate default name. - } - - // PCONFIG(0) = isFormItemChecked(F("AdvHwSerial")); - P075_BaudRate = getFormItemInt(F("baud")); - P075_IncludeValues = isFormItemChecked(F("IncludeValues")); - - /* Task will be stopped and restarted, so no reason to reload the display here - P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P075_data) { - P075_data->loadDisplayLines(event->TaskIndex); - } - */ - success = true; - break; - } - - - case PLUGIN_INIT: { - uint8_t BaudCode = P075_BaudRate; - - if (BaudCode > P075_B115200) { BaudCode = P075_B9600; } - const uint32_t BaudArray[4] = { 9600UL, 38400UL, 57600UL, 115200UL }; - const ESPEasySerialPort port = static_cast(CONFIG_PORT); - initPluginTaskData(event->TaskIndex, new (std::nothrow) P075_data_struct(port, CONFIG_PIN1, CONFIG_PIN2, BaudArray[BaudCode])); - P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P075_data) { - P075_data->loadDisplayLines(event->TaskIndex); - addLog(LOG_LEVEL_INFO, P075_data->getLogString()); - success = true; - } - break; - } - - - case PLUGIN_READ: { - P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P075_data) { - String newString; - - // Get optional LINE command statements. Special RSSIBAR bargraph keyword is supported. - for (uint8_t x = 0; x < P75_Nlines; x++) { - if (P075_data->displayLines[x].length()) { - int RssiIndex; - { - String UcTmpString(P075_data->displayLines[x]); - UcTmpString.toUpperCase(); - RssiIndex = UcTmpString.indexOf(F("RSSIBAR")); // RSSI bargraph Keyword found, wifi value in dBm. - } - - if (RssiIndex >= 0) { - newString = concat( - P075_data->displayLines[x].substring(0, RssiIndex), - GetRSSI_quality() * 10); - } - else { - String tmpString(P075_data->displayLines[x]); - newString = parseTemplate(tmpString); - } - - P075_sendCommand(event->TaskIndex, newString.c_str()); - # ifdef P075_DEBUG_LOG - addLog(LOG_LEVEL_INFO, strformat(F("NEXTION075 : Cmd Statement Line-%d Sent: %s"), x + 1, newString.c_str())); - # endif // ifdef P075_DEBUG_LOG - } - } - - // At Interval timer, send idx & value data only if user enabled "values" interval mode. - if (P075_IncludeValues) { - # ifdef P075_DEBUG_LOG - addLogMove(LOG_LEVEL_INFO, - strformat(F("NEXTION075: Interval values data enabled, resending idx=%s, value=%s"), - formatUserVarNoCheck(event, 0).c_str(), - formatUserVarNoCheck(event, 1).c_str())); - # endif // ifdef P075_DEBUG_LOG - - success = true; - } - else { - # ifdef P075_DEBUG_LOG - addLog(LOG_LEVEL_INFO, F("NEXTION075: Interval values data disabled, idx & value not resent")); - # endif // ifdef P075_DEBUG_LOG - - success = false; - } - } - break; - } - - // Nextion commands received from events (including http) get processed here. PLUGIN_WRITE - // does NOT process publish commands that are sent. - case PLUGIN_WRITE: { - const String command = parseString(string, 1); - - // If device names match we have a command to write. - if (command.equalsIgnoreCase(getTaskDeviceName(event->TaskIndex))) { - success = true; // Set true only if plugin found a command to execute. - const String nextionArguments = parseStringToEndKeepCase(string, 2); - P075_sendCommand(event->TaskIndex, nextionArguments.c_str()); - { - const String log = concat(F("NEXTION075 : WRITE = "), nextionArguments); - # ifndef BUILD_NO_DEBUG - addLog(LOG_LEVEL_DEBUG, log); - # endif // ifndef BUILD_NO_DEBUG - SendStatus(event, log); // Reply (echo) to sender. This will print message on browser. - } - - // Enable addLog() code below to help debug plugin write problems. - - /* - String log; - log.reserve(140); // Prevent re-allocation - String log = F("Nextion arg0: "); - log += command; - log += F(", TaskDeviceName: "); - log += getTaskDeviceName(event->TaskIndex); - log += F(", event->TaskIndex: "); - log += String(event->TaskIndex); - log += F(", nextionArguments: "); - log += nextionArguments; - addLog(LOG_LEVEL_INFO, log); - */ - } - break; - } - - case PLUGIN_TEN_PER_SECOND: { - P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P075_data) { - break; - } - - if (P075_data->rxPin < 0) { - addLog(LOG_LEVEL_INFO, F("NEXTION075 : Missing RxD Pin, aborted serial receive")); - break; - } - - if (P075_data->easySerial == nullptr) { - break; // P075_data->easySerial missing, exit. - } - { - uint16_t i; - uint8_t c; - String Vidx; - String Nvalue; - String Svalue; - String Nswitch; - char __buffer[RXBUFFSZ + 1]; // Staging buffer. - uint8_t charCount = P075_data->easySerial->available(); // Prime the Soft Serial engine. - - if (charCount >= RXBUFFWARN) { - addLog(LOG_LEVEL_INFO, strformat(F("NEXTION075 : RxD P075_data->easySerial Buffer capacity warning, %d bytes"), charCount)); - } - uint32_t baudrate_delay_unit = P075_data->baudrate / 9600; - - if (baudrate_delay_unit == 0) { - baudrate_delay_unit = 1; - } - - while (charCount) { // This is the serial engine. It processes the serial Rx stream. - c = P075_data->easySerial->read(); - - if (c == 0x65) { - if (charCount < 6) { delay((5 / (baudrate_delay_unit)) + 1); // Let's wait for a few more chars to arrive. - } - charCount = P075_data->easySerial->available(); - - if (charCount >= 6) { - __buffer[0] = c; // Store in staging buffer. - - for (i = 1; i < 7; i++) { - __buffer[i] = P075_data->easySerial->read(); - } - - __buffer[i] = 0x00; - - // FIXME TD-er: (PVS Studio) A part of conditional expression is always false: (0xFF == __buffer[4]). The value range of char - // type: [-128, 127]. - if ((0xFF == __buffer[4]) && (0xFF == __buffer[5]) && (0xFF == __buffer[6])) { - UserVar.setFloat(event->TaskIndex, 0, (__buffer[1] * 256) + __buffer[2] + TOUCH_BASE); - UserVar.setFloat(event->TaskIndex, 1, __buffer[3]); - sendData(event); - - # ifdef P075_DEBUG_LOG - addLogMove(LOG_LEVEL_INFO, - strformat(F("NEXTION075 : code: %c,%c,%c"), - __buffer[1], - __buffer[2], - __buffer[3])); - # endif // ifdef P075_DEBUG_LOG - } - } - } - else { - if (c == '|') { - __buffer[0] = c; // Store in staging buffer. - - if (charCount < 8) { delay((9 / (baudrate_delay_unit)) + 1); // Let's wait for more chars to arrive. - } - else { delay((3 / (baudrate_delay_unit)) + 1); // Short wait for tardy chars. - } - charCount = P075_data->easySerial->available(); - - i = 1; - - while (P075_data->easySerial->available() > 0 && i < RXBUFFSZ) { // Copy global serial buffer to local buffer. - __buffer[i] = P075_data->easySerial->read(); - - if ((__buffer[i] == 0x0a) || (__buffer[i] == 0x0d)) { break; } - i++; - } - - __buffer[i] = 0x00; - - String tmpString = __buffer; - - # ifdef P075_DEBUG_LOG - addLogMove(LOG_LEVEL_INFO, concat(F("NEXTION075 : Code = "), tmpString)); - # endif // ifdef P075_DEBUG_LOG - - int argIndex = tmpString.indexOf(F(",i")); - int argEnd = tmpString.indexOf(',', argIndex + 1); - - if (argIndex) { Vidx = tmpString.substring(argIndex + 2, argEnd); } - - bool GotPipeCmd = false; - - switch (__buffer[1]) { - case 'u': - GotPipeCmd = true; - argIndex = argEnd; - argEnd = tmpString.indexOf(',', argIndex + 1); - - if (argIndex) { Nvalue = tmpString.substring(argIndex + 2, argEnd); } - argIndex = argEnd; - argEnd = tmpString.indexOf(0x0a); - - if (argIndex) { Svalue = tmpString.substring(argIndex + 2, argEnd); } - break; - case 's': - GotPipeCmd = true; - argIndex = argEnd; - argEnd = tmpString.indexOf(0x0a); - - if (argIndex) { Nvalue = tmpString.substring(argIndex + 2, argEnd); } - - if (equals(Nvalue, F("On"))) { Svalue = '1'; } - - if (equals(Nvalue, F("Off"))) { Svalue = '0'; } - break; - } - - if (GotPipeCmd) { - float Vidx_f{}; - float Svalue_f{}; - - validFloatFromString(Vidx, Vidx_f); - validFloatFromString(Svalue, Svalue_f); - UserVar.setFloat(event->TaskIndex, 0, Vidx_f); - UserVar.setFloat(event->TaskIndex, 1, Svalue_f); - sendData(event); - - # ifdef P075_DEBUG_LOG - String log; - log.reserve(80); // Prevent re-allocation - log += F("NEXTION075 : Pipe Command Sent: "); - log += __buffer; - log += formatUserVarNoCheck(event, 0); - addLogMove(LOG_LEVEL_INFO, log); - # endif // ifdef P075_DEBUG_LOG - } - else { - # ifdef P075_DEBUG_LOG - addLog(LOG_LEVEL_INFO, F("NEXTION075 : Unknown Pipe Command, skipped")); - # endif // ifdef P075_DEBUG_LOG - } - } - } - charCount = P075_data->easySerial->available(); - } - } - - success = true; - break; - } - } - return success; -} - -void P075_sendCommand(taskIndex_t taskIndex, const char *cmd) -{ - P075_data_struct *P075_data = static_cast(getPluginTaskData(taskIndex)); - - if (!P075_data) { return; } - - if (!validGpio(P075_data->txPin)) { - addLog(LOG_LEVEL_INFO, F("NEXTION075 : Missing TxD Pin Number, aborted sendCommand")); - } - else - { - if (P075_data->easySerial != nullptr) { - P075_data->easySerial->print(cmd); - P075_data->easySerial->write(0xff); - P075_data->easySerial->write(0xff); - P075_data->easySerial->write(0xff); - } - else { - addLog(LOG_LEVEL_INFO, F("NEXTION075 : P075_data->easySerial error, aborted sendCommand")); - } - } -} - -#endif // USES_P075 +#include "_Plugin_Helper.h" +#ifdef USES_P075 + +# include "src/PluginStructs/P075_data_struct.h" + +# include "src/ESPEasyCore/ESPEasyWifi.h" + +// ####################################################################################################### +// ####################################################################################################### +// ################################### Plugin 075: Nextion ########################### +// ################################### Created on the work of majklovec ########################### +// ################################### Revisions by BertB, ThomasB and others ########################### +// ################################### Last Revision: 2022-09-27 ########################### +// ####################################################################################################### +// + +/** Changelog: + * 2022-09-27 tonhuisman: Use Changelog formatted updates + * Extend nr. of lines available for text/commands to 20, minor code improvements + * Updated: Oct-03-2018, ThomasB. + * Added P075_DEBUG_LOG define to reduce info log messages and prevent serial log flooding. + * Added SendStatus() to post log message on browser to acknowledge HTTP write. + * Added reserve() to minimize string memory allocations. + */ + +// ***************************************************************************************************** +// Defines start here +// ***************************************************************************************************** + +// #define P075_DEBUG_LOG // Enable this to include additional info messages in log output. + + +// Plug-In defines +# define PLUGIN_075 +# define PLUGIN_ID_075 75 +# define PLUGIN_NAME_075 "Display - Nextion" +# define PLUGIN_DEFAULT_NAME "NEXTION" +# define PLUGIN_VALUENAME1_075 "idx" +# define PLUGIN_VALUENAME2_075 "value" + + +// ***************************************************************************************************** +// PlugIn starts here +// ***************************************************************************************************** + +boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) { + case PLUGIN_DEVICE_ADD: { + Device[++deviceCount].Number = PLUGIN_ID_075; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; // Allow user to disable interval function. + + // FIXME TD-er: Not sure if access to any existing task data is needed when saving + Device[deviceCount].ExitTaskBeforeSave = false; + + break; + } + + case PLUGIN_GET_DEVICENAME: { + string = F(PLUGIN_NAME_075); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_075)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_075)); + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: { + serialHelper_getGpioNames(event); + break; + } + + case PLUGIN_WEBFORM_SHOW_CONFIG: + { + string += serialHelper_getSerialTypeLabel(event); + success = true; + break; + } + + case PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS: + { + const __FlashStringHelper *options[] = { + F("9600"), + F("38400"), + F("57600"), + F("115200") + }; + + constexpr size_t optionCount = NR_ELEMENTS(options); + addFormSelector(F("Baud Rate"), F("baud"), optionCount, options, nullptr, P075_BaudRate); + addUnit(F("baud")); + break; + } + + case PLUGIN_WEBFORM_LOAD: { + // ** DEVELOPER DEBUG MESSAGE AREA ** + // int datax = static_cast(Settings.TaskDeviceEnabled[event->TaskIndex]); // Debug value. + // String Data = "Debug. Plugin Enable State: "; + // Data += String(datax); + // addFormNote(Data); + + addFormSubHeader(F("")); // Blank line, vertical space. + addFormHeader(F("Nextion Command Statements (Optional)")); + P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P075_data) { + P075_data->loadDisplayLines(event->TaskIndex); + + for (int varNr = 0; varNr < P75_Nlines; varNr++) { + addFormTextBox(concat(F("Line "), varNr + 1), getPluginCustomArgName(varNr), P075_data->displayLines[varNr], P75_Nchars - 1); + } + } + + if (Settings.TaskDeviceTimer[event->TaskIndex] == 0) { // Is interval timer disabled? + addFormNote(concat(F("Interval Timer OFF, Nextion Lines (above)"), P075_IncludeValues + ? F(" and Values (below) NOT scheduled for updates") + : F(" NOT scheduled for updates"))); + } + + addFormSeparator(2); + addFormSubHeader(F("Interval Options")); + addFormCheckBox(F("Resend Values (below) at Interval"), F("IncludeValues"), P075_IncludeValues); + + success = true; + break; + } + + + case PLUGIN_WEBFORM_SAVE: { + { + // FIXME TD-er: This is a huge object allocated on the Stack. + char deviceTemplate[P75_Nlines][P75_Nchars] = {}; + String error; + + for (uint8_t varNr = 0; varNr < P75_Nlines; varNr++) + { + if (!safe_strncpy(deviceTemplate[varNr], webArg(getPluginCustomArgName(varNr)), P75_Nchars)) { + error += getCustomTaskSettingsError(varNr); + } + } + + if (error.length() > 0) { + addHtmlError(error); + } + SaveCustomTaskSettings(event->TaskIndex, (uint8_t *)&deviceTemplate, sizeof(deviceTemplate)); + } + + if (getTaskDeviceName(event->TaskIndex).isEmpty()) { // Check to see if user entered device name. + strcpy(ExtraTaskSettings.TaskDeviceName, PLUGIN_DEFAULT_NAME); // Name missing, populate default name. + } + + P075_BaudRate = getFormItemInt(F("baud")); + P075_IncludeValues = isFormItemChecked(F("IncludeValues")); + + success = true; + break; + } + + + case PLUGIN_INIT: { + uint8_t BaudCode = P075_BaudRate; + + if (BaudCode > P075_B115200) { BaudCode = P075_B9600; } + constexpr uint32_t BaudArray[] = { 9600UL, 38400UL, 57600UL, 115200UL }; + const ESPEasySerialPort port = static_cast(CONFIG_PORT); + initPluginTaskData(event->TaskIndex, new (std::nothrow) P075_data_struct(port, CONFIG_PIN1, CONFIG_PIN2, BaudArray[BaudCode])); + P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P075_data) { + P075_data->loadDisplayLines(event->TaskIndex); + addLog(LOG_LEVEL_INFO, P075_data->getLogString()); + success = true; + } + break; + } + + + case PLUGIN_READ: { + P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P075_data) { + String newString; + + // Get optional LINE command statements. Special RSSIBAR bargraph keyword is supported. + for (uint8_t x = 0; x < P75_Nlines; x++) { + if (P075_data->displayLines[x].length()) { + int RssiIndex; + { + String UcTmpString(P075_data->displayLines[x]); + UcTmpString.toUpperCase(); + RssiIndex = UcTmpString.indexOf(F("RSSIBAR")); // RSSI bargraph Keyword found, wifi value in dBm. + } + + if (RssiIndex >= 0) { + newString = concat( + P075_data->displayLines[x].substring(0, RssiIndex), + GetRSSI_quality() * 10); + } + else { + String tmpString(P075_data->displayLines[x]); + newString = parseTemplate(tmpString); + } + + P075_sendCommand(event->TaskIndex, newString.c_str()); + # ifdef P075_DEBUG_LOG + addLog(LOG_LEVEL_INFO, strformat(F("NEXTION075 : Cmd Statement Line-%d Sent: %s"), x + 1, newString.c_str())); + # endif // ifdef P075_DEBUG_LOG + } + } + + // At Interval timer, send idx & value data only if user enabled "values" interval mode. + if (P075_IncludeValues) { + # ifdef P075_DEBUG_LOG + addLogMove(LOG_LEVEL_INFO, + strformat(F("NEXTION075: Interval values data enabled, resending idx=%s, value=%s"), + formatUserVarNoCheck(event, 0).c_str(), + formatUserVarNoCheck(event, 1).c_str())); + # endif // ifdef P075_DEBUG_LOG + + success = true; + } + else { + # ifdef P075_DEBUG_LOG + addLog(LOG_LEVEL_INFO, F("NEXTION075: Interval values data disabled, idx & value not resent")); + # endif // ifdef P075_DEBUG_LOG + + success = false; + } + } + break; + } + + // Nextion commands received from events (including http) get processed here. PLUGIN_WRITE + // does NOT process publish commands that are sent. + case PLUGIN_WRITE: { + const String command = parseString(string, 1); + + // If device names match we have a command to write. + if (command.equalsIgnoreCase(getTaskDeviceName(event->TaskIndex))) { + success = true; // Set true only if plugin found a command to execute. + const String nextionArguments = parseStringToEndKeepCase(string, 2); + P075_sendCommand(event->TaskIndex, nextionArguments.c_str()); + { + const String log = concat(F("NEXTION075 : WRITE = "), nextionArguments); + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG, log); + # endif // ifndef BUILD_NO_DEBUG + SendStatus(event, log); // Reply (echo) to sender. This will print message on browser. + } + + // Enable addLog() code below to help debug plugin write problems. + + /* + String log; + log.reserve(140); // Prevent re-allocation + String log = F("Nextion arg0: "); + log += command; + log += F(", TaskDeviceName: "); + log += getTaskDeviceName(event->TaskIndex); + log += F(", event->TaskIndex: "); + log += String(event->TaskIndex); + log += F(", nextionArguments: "); + log += nextionArguments; + addLog(LOG_LEVEL_INFO, log); + */ + } + break; + } + + case PLUGIN_TEN_PER_SECOND: { + P075_data_struct *P075_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P075_data) { + break; + } + + if (validGpio(P075_data->rxPin)) { + addLog(LOG_LEVEL_INFO, F("NEXTION075 : Missing RxD Pin, aborted serial receive")); + break; + } + + if (P075_data->easySerial == nullptr) { + break; // P075_data->easySerial missing, exit. + } + { + uint16_t i; + uint8_t c; + String Vidx; + String Nvalue; + String Svalue; + String Nswitch; + char __buffer[RXBUFFSZ + 1]; // Staging buffer. + uint8_t charCount = P075_data->easySerial->available(); // Prime the Soft Serial engine. + + if (charCount >= RXBUFFWARN) { + addLog(LOG_LEVEL_INFO, strformat(F("NEXTION075 : RxD P075_data->easySerial Buffer capacity warning, %d bytes"), charCount)); + } + uint32_t baudrate_delay_unit = P075_data->baudrate / 9600; + + if (baudrate_delay_unit == 0) { + baudrate_delay_unit = 1; + } + + while (charCount) { // This is the serial engine. It processes the serial Rx stream. + c = P075_data->easySerial->read(); + + if (c == 0x65) { + if (charCount < 6) { delay((5 / (baudrate_delay_unit)) + 1); // Let's wait for a few more chars to arrive. + } + charCount = P075_data->easySerial->available(); + + if (charCount >= 6) { + __buffer[0] = c; // Store in staging buffer. + + for (i = 1; i < 7; i++) { + __buffer[i] = P075_data->easySerial->read(); + } + + __buffer[i] = 0x00; + + // FIXME TD-er: (PVS Studio) A part of conditional expression is always false: (0xFF == __buffer[4]). The value range of char + // type: [-128, 127]. + if ((0xFF == __buffer[4]) && (0xFF == __buffer[5]) && (0xFF == __buffer[6])) { + UserVar.setFloat(event->TaskIndex, 0, (__buffer[1] * 256) + __buffer[2] + TOUCH_BASE); + UserVar.setFloat(event->TaskIndex, 1, __buffer[3]); + sendData(event); + + # ifdef P075_DEBUG_LOG + addLogMove(LOG_LEVEL_INFO, + strformat(F("NEXTION075 : code: %c,%c,%c"), + __buffer[1], + __buffer[2], + __buffer[3])); + # endif // ifdef P075_DEBUG_LOG + } + } + } + else { + if (c == '|') { + __buffer[0] = c; // Store in staging buffer. + + if (charCount < 8) { delay((9 / (baudrate_delay_unit)) + 1); // Let's wait for more chars to arrive. + } + else { delay((3 / (baudrate_delay_unit)) + 1); // Short wait for tardy chars. + } + charCount = P075_data->easySerial->available(); + + i = 1; + + while (P075_data->easySerial->available() > 0 && i < RXBUFFSZ) { // Copy global serial buffer to local buffer. + __buffer[i] = P075_data->easySerial->read(); + + if ((__buffer[i] == 0x0a) || (__buffer[i] == 0x0d)) { break; } + i++; + } + + __buffer[i] = 0x00; + + String tmpString = __buffer; + + # ifdef P075_DEBUG_LOG + addLogMove(LOG_LEVEL_INFO, concat(F("NEXTION075 : Code = "), tmpString)); + # endif // ifdef P075_DEBUG_LOG + + int argIndex = tmpString.indexOf(F(",i")); + int argEnd = tmpString.indexOf(',', argIndex + 1); + + if (argIndex) { Vidx = tmpString.substring(argIndex + 2, argEnd); } + + bool GotPipeCmd = false; + + switch (__buffer[1]) { + case 'u': + GotPipeCmd = true; + argIndex = argEnd; + argEnd = tmpString.indexOf(',', argIndex + 1); + + if (argIndex) { Nvalue = tmpString.substring(argIndex + 2, argEnd); } + argIndex = argEnd; + argEnd = tmpString.indexOf(0x0a); + + if (argIndex) { Svalue = tmpString.substring(argIndex + 2, argEnd); } + break; + case 's': + GotPipeCmd = true; + argIndex = argEnd; + argEnd = tmpString.indexOf(0x0a); + + if (argIndex) { Nvalue = tmpString.substring(argIndex + 2, argEnd); } + + if (equals(Nvalue, F("On"))) { Svalue = '1'; } + + if (equals(Nvalue, F("Off"))) { Svalue = '0'; } + break; + } + + if (GotPipeCmd) { + float Vidx_f{}; + float Svalue_f{}; + + validFloatFromString(Vidx, Vidx_f); + validFloatFromString(Svalue, Svalue_f); + UserVar.setFloat(event->TaskIndex, 0, Vidx_f); + UserVar.setFloat(event->TaskIndex, 1, Svalue_f); + sendData(event); + + # ifdef P075_DEBUG_LOG + String log; + log.reserve(80); // Prevent re-allocation + log += F("NEXTION075 : Pipe Command Sent: "); + log += __buffer; + log += formatUserVarNoCheck(event, 0); + addLogMove(LOG_LEVEL_INFO, log); + # endif // ifdef P075_DEBUG_LOG + } + else { + # ifdef P075_DEBUG_LOG + addLog(LOG_LEVEL_INFO, F("NEXTION075 : Unknown Pipe Command, skipped")); + # endif // ifdef P075_DEBUG_LOG + } + } + } + charCount = P075_data->easySerial->available(); + } + } + + success = true; + break; + } + } + return success; +} + +void P075_sendCommand(taskIndex_t taskIndex, const char *cmd) +{ + P075_data_struct *P075_data = static_cast(getPluginTaskData(taskIndex)); + + if (!P075_data) { return; } + + if (!validGpio(P075_data->txPin)) { + addLog(LOG_LEVEL_INFO, F("NEXTION075 : Missing TxD Pin Number, aborted sendCommand")); + } + else + { + if (P075_data->easySerial != nullptr) { + P075_data->easySerial->print(cmd); + P075_data->easySerial->write(0xff); + P075_data->easySerial->write(0xff); + P075_data->easySerial->write(0xff); + } + else { + addLog(LOG_LEVEL_INFO, F("NEXTION075 : P075_data->easySerial error, aborted sendCommand")); + } + } +} + +#endif // USES_P075 diff --git a/src/_P076_HLW8012.ino b/src/_P076_HLW8012.ino index 608fdc348e..27139f0251 100644 --- a/src/_P076_HLW8012.ino +++ b/src/_P076_HLW8012.ino @@ -30,9 +30,9 @@ HLW8012 *Plugin_076_hlw = nullptr; # define PLUGIN_076 -# define PLUGIN_ID_076 76 -# define PLUGIN_076_DEBUG false // activate extra log info in the debug -# define PLUGIN_NAME_076 "Energy (AC) - HLW8012/BL0937" +# define PLUGIN_ID_076 76 +# define PLUGIN_076_DEBUG false // activate extra log info in the debug +# define PLUGIN_NAME_076 "Energy (AC) - HLW8012/BL0937" # define PLUGIN_VALUENAME1_076 "Voltage" # define PLUGIN_VALUENAME2_076 "Current" # define PLUGIN_VALUENAME3_076 "Power" @@ -119,7 +119,6 @@ boolean Plugin_076(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_076; Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; Device[deviceCount].FormulaOption = true; Device[deviceCount].ValueCount = 4; Device[deviceCount].SendDataOption = true; diff --git a/src/_P077_CSE7766.ino b/src/_P077_CSE7766.ino index 5129c0a439..3ce0b78c78 100644 --- a/src/_P077_CSE7766.ino +++ b/src/_P077_CSE7766.ino @@ -21,7 +21,7 @@ # include "src/PluginStructs/P077_data_struct.h" # define PLUGIN_077 -# define PLUGIN_ID_077 77 +# define PLUGIN_ID_077 77 # ifdef PLUGIN_SET_SONOFF_POW # define PLUGIN_NAME_077 "Energy (AC) - CSE7766 (POW r2)" # else // ifdef PLUGIN_SET_SONOFF_POW @@ -40,21 +40,17 @@ boolean Plugin_077(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_077; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].TaskLogsOwnPeaks = true; + Device[++deviceCount].Number = PLUGIN_ID_077; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].TaskLogsOwnPeaks = true; break; } diff --git a/src/_P078_Eastron.ino b/src/_P078_Eastron.ino index 2accc84459..536ab9b04a 100644 --- a/src/_P078_Eastron.ino +++ b/src/_P078_Eastron.ino @@ -40,20 +40,16 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_078; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = P078_NR_OUTPUT_VALUES; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].TaskLogsOwnPeaks = true; + Device[++deviceCount].Number = PLUGIN_ID_078; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = P078_NR_OUTPUT_VALUES; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].TaskLogsOwnPeaks = true; break; } @@ -120,9 +116,10 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) String options_baudrate[6]; for (int i = 0; i < 6; ++i) { - options_baudrate[i] = String(p078_storageValueToBaudrate(i)); + options_baudrate[i] = p078_storageValueToBaudrate(i); } - addFormSelector(F("Baud Rate"), P078_BAUDRATE_LABEL, 6, options_baudrate, nullptr, P078_BAUDRATE); + constexpr size_t optionCount = NR_ELEMENTS(options_baudrate); + addFormSelector(F("Baud Rate"), P078_BAUDRATE_LABEL, optionCount, options_baudrate, nullptr, P078_BAUDRATE); addUnit(F("baud")); } diff --git a/src/_P079_Wemos_Motorshield.ino b/src/_P079_Wemos_Motorshield.ino index 336e630956..a2e5d958aa 100644 --- a/src/_P079_Wemos_Motorshield.ino +++ b/src/_P079_Wemos_Motorshield.ino @@ -84,16 +84,9 @@ boolean Plugin_079(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_079; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; + Device[++deviceCount].Number = PLUGIN_ID_079; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; break; } @@ -130,7 +123,8 @@ boolean Plugin_079(uint8_t function, struct EventStruct *event, String& string) static_cast(P079_BoardType::WemosMotorshield), static_cast(P079_BoardType::LolinMotorshield) }; - addFormSelector(F("Motor Shield Type"), F("shield_type"), 2, options, indices, SHIELD_VER_PCFG_P079); + constexpr size_t optionCount = NR_ELEMENTS(indices); + addFormSelector(F("Motor Shield Type"), F("shield_type"), optionCount, options, indices, SHIELD_VER_PCFG_P079); } if (Plugin_079_MotorShield_type == P079_BoardType::WemosMotorshield) { diff --git a/src/_P080_DallasIButton.ino b/src/_P080_DallasIButton.ino index a75a43c00a..f266b389a8 100644 --- a/src/_P080_DallasIButton.ino +++ b/src/_P080_DallasIButton.ino @@ -36,18 +36,13 @@ boolean Plugin_080(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_080; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; + Device[++deviceCount].Number = PLUGIN_ID_080; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; break; } diff --git a/src/_P081_Cron.ino b/src/_P081_Cron.ino index 0a80a9a4b0..1dc720dda9 100644 --- a/src/_P081_Cron.ino +++ b/src/_P081_Cron.ino @@ -12,8 +12,8 @@ # include "src/PluginStructs/P081_data_struct.h" # define PLUGIN_081 -# define PLUGIN_ID_081 81 // plugin id -# define PLUGIN_NAME_081 "Generic - CRON" // "Plugin Name" is what will be displayed in the selection list +# define PLUGIN_ID_081 81 // plugin id +# define PLUGIN_NAME_081 "Generic - CRON" // "Plugin Name" is what will be displayed in the selection list # define PLUGIN_VALUENAME1_081 "LastExecution" # define PLUGIN_VALUENAME2_081 "NextExecution" @@ -32,16 +32,9 @@ boolean Plugin_081(uint8_t function, struct EventStruct *event, String& string) Device[deviceCount].Type = DEVICE_TYPE_DUMMY; // how the device is connected Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; // type of value the plugin will return, used only for // Domoticz - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 2; // number of output variables. The value should match the number of keys - // PLUGIN_VALUENAME1_xxx - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; - Device[deviceCount].TimerOptional = false; - Device[deviceCount].GlobalSyncOption = true; + Device[deviceCount].ValueCount = 2; // number of output variables. The value should match the number of + // keys + // PLUGIN_VALUENAME1_xxx Device[deviceCount].DecimalsOnly = true; Device[deviceCount].HasFormatUserVar = true; break; diff --git a/src/_P082_GPS.ino b/src/_P082_GPS.ino index e993d3de84..c3b72507cb 100644 --- a/src/_P082_GPS.ino +++ b/src/_P082_GPS.ino @@ -30,25 +30,20 @@ # define PLUGIN_VALUENAME4_082 "Speed" - boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) { boolean success = false; switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_082; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_082; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -184,21 +179,22 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) addFormSubHeader(F("U-Blox specific")); { - const __FlashStringHelper *options[3] = { + const __FlashStringHelper *options[] = { toString(P082_PowerMode::Max_Performance), toString(P082_PowerMode::Power_Save), toString(P082_PowerMode::Eco) }; - const int indices[3] = { + const int indices[] = { static_cast(P082_PowerMode::Max_Performance), static_cast(P082_PowerMode::Power_Save), static_cast(P082_PowerMode::Eco) }; - addFormSelector(F("Power Mode"), F("pwrmode"), 3, options, indices, P082_POWER_MODE); + constexpr size_t optionCount = NR_ELEMENTS(indices); + addFormSelector(F("Power Mode"), F("pwrmode"), optionCount, options, indices, P082_POWER_MODE); } { - const __FlashStringHelper *options[10] = { + const __FlashStringHelper *options[] = { toString(P082_DynamicModel::Portable), toString(P082_DynamicModel::Stationary), toString(P082_DynamicModel::Pedestrian), @@ -210,7 +206,7 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) toString(P082_DynamicModel::Wrist), toString(P082_DynamicModel::Bike) }; - const int indices[10] = { + const int indices[] = { static_cast(P082_DynamicModel::Portable), static_cast(P082_DynamicModel::Stationary), static_cast(P082_DynamicModel::Pedestrian), @@ -222,7 +218,8 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) static_cast(P082_DynamicModel::Wrist), static_cast(P082_DynamicModel::Bike) }; - addFormSelector(F("Dynamic Platform Model"), F("dynmodel"), 10, options, indices, P082_DYNAMIC_MODEL); + constexpr size_t optionCount = NR_ELEMENTS(indices); + addFormSelector(F("Dynamic Platform Model"), F("dynmodel"), optionCount, options, indices, P082_DYNAMIC_MODEL); } # endif // P082_USE_U_BLOX_SPECIFIC @@ -289,9 +286,10 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) static_cast(getPluginTaskData(event->TaskIndex)); if (nullptr != P082_data) { - #if FEATURE_CHART_JS + # if FEATURE_CHART_JS P082_data->webformLoad_show_position_scatterplot(event); - #endif + # endif // if FEATURE_CHART_JS + for (uint8_t i = 0; i < P082_NR_OUTPUT_VALUES; ++i) { const uint8_t pconfigIndex = i + P082_QUERY1_CONFIG_POS; @@ -582,7 +580,7 @@ void P082_setOutputValue(struct EventStruct *event, uint8_t outputType, float va const uint8_t pconfigIndex = i + P082_QUERY1_CONFIG_POS; if (PCONFIG(pconfigIndex) == outputType) { - UserVar.setFloat(event->TaskIndex, i, value); + UserVar.setFloat(event->TaskIndex, i, value); } } } @@ -597,25 +595,16 @@ void P082_logStats(struct EventStruct *event) { if ((nullptr == P082_data) || !P082_data->isInitialized()) { return; } - String log; - - if (log.reserve(128)) { - log = F("GPS:"); - log += F(" Fix: "); - log += P082_data->hasFix(P082_TIMEOUT) ? 1 : 0; - log += F(" #sat: "); - log += P082_data->gps->satellites.value(); - log += F(" #SNR: "); - log += P082_data->gps->satellitesStats.getBestSNR(); - log += F(" HDOP: "); - log += P082_data->gps->hdop.value() / 100.0f; - log += F(" Chksum(pass/fail): "); - log += P082_data->gps->passedChecksum(); - log += '/'; - log += P082_data->gps->failedChecksum(); - log += F(" invalid: "); - log += P082_data->gps->invalidData(); - addLogMove(LOG_LEVEL_DEBUG, log); + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLogMove(LOG_LEVEL_DEBUG, strformat(F("GPS: Fix: %d #sat: %u #SNR: %u HDOP: %.3f Chksum(pass/fail): %u/%u invalid: %u"), + P082_data->hasFix(P082_TIMEOUT) ? 1 : 0, + P082_data->gps->satellites.value(), + P082_data->gps->satellitesStats.getBestSNR(), + P082_data->gps->hdop.value() / 100.0f, + P082_data->gps->passedChecksum(), + P082_data->gps->failedChecksum(), + P082_data->gps->invalidData())); } # endif // ifndef BUILD_NO_DEBUG } @@ -724,6 +713,7 @@ void P082_html_show_stats(struct EventStruct *event) { addRowLabel(F("UTC Time")); struct tm dateTime; + if (P082_data->getDateTime(dateTime)) { addHtml(formatDateTimeString(dateTime)); } else { @@ -741,22 +731,17 @@ void P082_html_show_stats(struct EventStruct *event) { } addRowLabel(F("Checksum (pass/fail/invalid)")); - { - String chksumStats; - - chksumStats = P082_data->gps->passedChecksum(); - chksumStats += '/'; - chksumStats += P082_data->gps->failedChecksum(); - chksumStats += '/'; - chksumStats += P082_data->gps->invalidData(); - addHtml(chksumStats); - } -#ifndef BUILD_NO_DEBUG -/* - addRowLabel(F("SW PPS stats")); - addHtml(P082_data->getPPSStats()); -*/ -#endif + addHtml(strformat(F("%u/%u/%u"), + P082_data->gps->passedChecksum(), + P082_data->gps->failedChecksum(), + P082_data->gps->invalidData())); +# ifndef BUILD_NO_DEBUG + + /* + addRowLabel(F("SW PPS stats")); + addHtml(P082_data->getPPSStats()); + */ +# endif // ifndef BUILD_NO_DEBUG } void P082_setSystemTime(struct EventStruct *event) { diff --git a/src/_P083_SGP30.ino b/src/_P083_SGP30.ino index 209aeaa8e4..57b058e1cf 100644 --- a/src/_P083_SGP30.ino +++ b/src/_P083_SGP30.ino @@ -32,18 +32,14 @@ boolean Plugin_083(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_083; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_083; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } diff --git a/src/_P084_VEML6070.ino b/src/_P084_VEML6070.ino index 2556925989..773c2b7930 100644 --- a/src/_P084_VEML6070.ino +++ b/src/_P084_VEML6070.ino @@ -43,19 +43,14 @@ boolean Plugin_084(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_084; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = false; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_084; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 3; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -90,8 +85,9 @@ boolean Plugin_084(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { - const __FlashStringHelper *optionsMode[4] = { F("1/2T"), F("1T"), F("2T"), F("4T (Default)") }; - addFormSelector(F("Refresh Time Determination"), F("itime"), 4, optionsMode, nullptr, PCONFIG(0)); + const __FlashStringHelper *optionsMode[] = { F("1/2T"), F("1T"), F("2T"), F("4T (Default)") }; + constexpr size_t optionCount = NR_ELEMENTS(optionsMode); + addFormSelector(F("Refresh Time Determination"), F("itime"), optionCount, optionsMode, nullptr, PCONFIG(0)); success = true; break; @@ -160,9 +156,8 @@ uint16_t VEML6070_ReadUv(bool *status) uint16_t uv_raw = 0; bool wire_status = false; - uv_raw = I2C_read8(VEML6070_ADDR_H, &wire_status); + uv_raw = I2C_read8(VEML6070_ADDR_H, &wire_status) << 8; *status = wire_status; - uv_raw <<= 8; uv_raw |= I2C_read8(VEML6070_ADDR_L, &wire_status); *status &= wire_status; diff --git a/src/_P085_AcuDC243.ino b/src/_P085_AcuDC243.ino index 478e8ac0f9..c7c1c33212 100644 --- a/src/_P085_AcuDC243.ino +++ b/src/_P085_AcuDC243.ino @@ -17,8 +17,8 @@ */ # define PLUGIN_085 -# define PLUGIN_ID_085 85 -# define PLUGIN_NAME_085 "Energy - AccuEnergy AcuDC24x" +# define PLUGIN_ID_085 85 +# define PLUGIN_NAME_085 "Energy - AccuEnergy AcuDC24x" # define PLUGIN_VALUENAME1_085 "" @@ -30,17 +30,14 @@ boolean Plugin_085(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_085; Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; Device[deviceCount].FormulaOption = true; Device[deviceCount].ValueCount = P085_NR_OUTPUT_VALUES; Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; Device[deviceCount].SendDataOption = true; Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; Device[deviceCount].ExitTaskBeforeSave = false; Device[deviceCount].PluginStats = true; + Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); break; } @@ -131,7 +128,7 @@ boolean Plugin_085(uint8_t function, struct EventStruct *event, String& string) addRowLabel(F("Checksum (pass/fail/nodata)")); uint32_t reads_pass, reads_crc_failed, reads_nodata; P085_data->modbus.getStatistics(reads_pass, reads_crc_failed, reads_nodata); - addHtml(strformat(F("%d/%d/%d"), reads_pass, reads_crc_failed, reads_nodata)); + addHtml(strformat(F("%u/%u/%u"), reads_pass, reads_crc_failed, reads_nodata)); addFormSubHeader(F("Calibration")); diff --git a/src/_P086_Homie.ino b/src/_P086_Homie.ino index 0b0db5270c..2702baba80 100644 --- a/src/_P086_Homie.ino +++ b/src/_P086_Homie.ino @@ -45,7 +45,6 @@ boolean Plugin_086(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_086; Device[deviceCount].Type = DEVICE_TYPE_DUMMY; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; Device[deviceCount].DecimalsOnly = true; Device[deviceCount].ValueCount = PLUGIN_086_VALUE_MAX; Device[deviceCount].Custom = true; diff --git a/src/_P087_SerialProxy.ino b/src/_P087_SerialProxy.ino index 0fc929179d..12d4d84087 100644 --- a/src/_P087_SerialProxy.ino +++ b/src/_P087_SerialProxy.ino @@ -73,17 +73,12 @@ boolean Plugin_087(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_087; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = false; + Device[++deviceCount].Number = PLUGIN_ID_087; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; // FIXME TD-er: Not sure if access to any existing task data is needed when saving Device[deviceCount].ExitTaskBeforeSave = false; @@ -389,7 +384,7 @@ void P087_html_show_matchForms(struct EventStruct *event) { const __FlashStringHelper *options[2]; options[P087_Filter_Comp::Equal] = F("=="); options[P087_Filter_Comp::NotEqual] = F("!="); - const int optionValues[2] = { P087_Filter_Comp::Equal, P087_Filter_Comp::NotEqual }; + const int optionValues[] = { P087_Filter_Comp::Equal, P087_Filter_Comp::NotEqual }; addSelector(id, 2, options, optionValues, nullptr, static_cast(comparator), false, true, F("")); break; } diff --git a/src/_P088_HeatpumpIR.ino b/src/_P088_HeatpumpIR.ino index 938d2d84ce..42a22cf4a6 100644 --- a/src/_P088_HeatpumpIR.ino +++ b/src/_P088_HeatpumpIR.ino @@ -34,7 +34,7 @@ * * The parameters are (in this order) * * The type of the heatpump as a string, see the implementations of different models, like - *https://github.com/ToniA/arduino-heatpumpir/blob/master/MitsubishiHeatpumpIR.cpp + * https://github.com/ToniA/arduino-heatpumpir/blob/master/MitsubishiHeatpumpIR.cpp * * power state (see https://github.com/ToniA/arduino-heatpumpir/blob/master/HeatpumpIR.h for modes) * * operating mode * * fan speed @@ -61,11 +61,9 @@ boolean Plugin_088(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_088; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 0; + Device[++deviceCount].Number = PLUGIN_ID_088; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); break; diff --git a/src/_P089_Ping.ino b/src/_P089_Ping.ino index 32faaa6879..5f87b5ad23 100644 --- a/src/_P089_Ping.ino +++ b/src/_P089_Ping.ino @@ -39,17 +39,13 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_089; - Device[deviceCount].Type = DEVICE_TYPE_CUSTOM0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + Device[++deviceCount].Number = PLUGIN_ID_089; + Device[deviceCount].Type = DEVICE_TYPE_CUSTOM0; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].DecimalsOnly = true; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; break; } @@ -131,7 +127,7 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string) if (equals(command, F("pingset"))) { - String taskName = parseString(string, 2); + const String taskName = parseString(string, 2); String param1 = parseString(string, 3); taskIndex_t taskIndex = findTaskIndexByName(taskName); @@ -147,7 +143,7 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string) // Avoid overflow and weird values if ((val_new > -1024) && (val_new < 1024)) { UserVar.setFloat(event->TaskIndex, 0, val_new); - success = true; + success = true; } } } diff --git a/src/_P090_CCS811.ino b/src/_P090_CCS811.ino index fa68997b46..8ee9b635a4 100644 --- a/src/_P090_CCS811.ino +++ b/src/_P090_CCS811.ino @@ -77,17 +77,14 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_090; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_090; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } @@ -111,8 +108,9 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) // I2C address choice if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - const __FlashStringHelper *options[2] = { F("0x5A (ADDR pin is LOW)"), F("0x5B (ADDR pin is HIGH)") }; - addFormSelector(F("I2C Address"), F("i2c_addr"), 2, options, i2cAddressValues, P090_I2C_ADDR); + const __FlashStringHelper *options[] = { F("0x5A (ADDR pin is LOW)"), F("0x5B (ADDR pin is HIGH)") }; + constexpr size_t optionCount = NR_ELEMENTS(options); + addFormSelector(F("I2C Address"), F("i2c_addr"), optionCount, options, i2cAddressValues, P090_I2C_ADDR); } else { success = intArrayContains(2, i2cAddressValues, event->Par1); } @@ -132,10 +130,11 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) { { // read frequency - int frequencyChoice = P090_READ_INTERVAL; - const __FlashStringHelper *frequencyOptions[3] = { F("1 second"), F("10 seconds"), F("60 seconds") }; - const int frequencyValues[3] = { 1, 2, 3 }; - addFormSelector(F("Take reading every"), F("temp_freq"), 3, frequencyOptions, frequencyValues, frequencyChoice); + const int frequencyChoice = P090_READ_INTERVAL; + const __FlashStringHelper *frequencyOptions[] = { F("1 second"), F("10 seconds"), F("60 seconds") }; + const int frequencyValues[] = { 1, 2, 3 }; + constexpr size_t optionCount = NR_ELEMENTS(frequencyValues); + addFormSelector(F("Take reading every"), F("temp_freq"), optionCount, frequencyOptions, frequencyValues, frequencyChoice); } addFormSeparator(2); @@ -176,9 +175,6 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) } } - // addFormSeparator(string); - // addFormSeparator(2); - success = true; break; } @@ -292,35 +288,35 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) if (P090_COMPENSATE_ENABLE) { // we're checking a var from another task, so calculate that basevar - uint8_t TaskIndex = P090_TEMPERATURE_TASK_INDEX; + const taskIndex_t TaskIndex = P090_TEMPERATURE_TASK_INDEX; if (validTaskIndex(TaskIndex)) { - uint8_t BaseVarIndex = TaskIndex * VARS_PER_TASK + P090_TEMPERATURE_TASK_VALUE; - float temperature = UserVar[BaseVarIndex]; // in degrees C + float temperature = UserVar.getFloat(TaskIndex, P090_TEMPERATURE_TASK_VALUE); // in degrees C // convert to celsius if required - int temperature_in_fahrenheit = P090_TEMPERATURE_SCALE; - String temp; - temp = 'C'; + # ifndef BUILD_NO_DEBUG + char temp('C'); + # endif // ifndef BUILD_NO_DEBUG - if (temperature_in_fahrenheit) + if (P090_TEMPERATURE_SCALE) { - temperature = ((temperature - 32) * 5.0f) / 9.0f; - temp = 'F'; + temperature = CelsiusToFahrenheit(temperature); + # ifndef BUILD_NO_DEBUG + temp = 'F'; + # endif // ifndef BUILD_NO_DEBUG } - uint8_t TaskIndex2 = P090_HUMIDITY_TASK_INDEX; + const taskIndex_t TaskIndex2 = P090_HUMIDITY_TASK_INDEX; if (validTaskIndex(TaskIndex2)) { - uint8_t BaseVarIndex2 = TaskIndex2 * VARS_PER_TASK + P090_HUMIDITY_TASK_VALUE; - float humidity = UserVar[BaseVarIndex2]; // in % relative + const float humidity = UserVar.getFloat(TaskIndex2, P090_HUMIDITY_TASK_VALUE); // in % relative - # ifndef BUILD_NO_DEBUG + # ifndef BUILD_NO_DEBUG if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - addLogMove(LOG_LEVEL_DEBUG, strformat(F("CCS811 : Compensating for Temperature: %s%s & Humidity: %s%%"), - toString(temperature).c_str(), temp.c_str(), toString(humidity).c_str())); + addLogMove(LOG_LEVEL_DEBUG, strformat(F("CCS811 : Compensating for Temperature: %s%c & Humidity: %s%%"), + toString(temperature).c_str(), temp, toString(humidity).c_str())); } - # endif // ifndef BUILD_NO_DEBUG + # endif // ifndef BUILD_NO_DEBUG P090_data->myCCS811.setEnvironmentalData(humidity, temperature); } @@ -335,7 +331,7 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) else if (P090_data->myCCS811.checkForStatusError()) { // get error and also clear it - String errorMsg = P090_data->myCCS811.getSensorError(); + const String errorMsg = P090_data->myCCS811.getSensorError(); if (loglevelActiveFor(LOG_LEVEL_ERROR)) { // If the CCS811 found an internal error, print it. diff --git a/src/_P091_SerSwitch.ino b/src/_P091_SerSwitch.ino index 14240226a0..1833c74a52 100644 --- a/src/_P091_SerSwitch.ino +++ b/src/_P091_SerSwitch.ino @@ -32,7 +32,7 @@ than return to inverse state (non-blocking) - ydim,[DIM_VALUE] Set DIM_VALUE to Tuya dimmer switch (value can be 0-255, no range check!) Of course, only the Tuya dimmer can do it... dim value can be read from plugin - #values. + #values. There are no checks for is it state on or off. Command Examples : @@ -88,18 +88,13 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_091; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; + Device[++deviceCount].Number = PLUGIN_ID_091; + Device[deviceCount].Type = DEVICE_TYPE_DUMMY; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; break; } case PLUGIN_GET_DEVICENAME: @@ -121,53 +116,57 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { { - const __FlashStringHelper *options[4] = { + const __FlashStringHelper *options[] = { F("Yewelink/TUYA"), F("Sonoff Dual"), F("LC TECH"), F("Moes Wifi Dimmer") }; - const int optionValues[4] = { SER_SWITCH_YEWE, SER_SWITCH_SONOFFDUAL, SER_SWITCH_LCTECH, SER_SWITCH_WIFIDIMMER }; - addFormSelector(F("Switch Type"), F("type"), 4, options, optionValues, PCONFIG(0)); + const int optionValues[] = { SER_SWITCH_YEWE, SER_SWITCH_SONOFFDUAL, SER_SWITCH_LCTECH, SER_SWITCH_WIFIDIMMER }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Switch Type"), F("type"), optionCount, options, optionValues, PCONFIG(0)); } if (PCONFIG(0) == SER_SWITCH_YEWE) { - const __FlashStringHelper *buttonOptions[4] = { + const __FlashStringHelper *buttonOptions[] = { F("1"), F("2/Dimmer#2"), F("3/Dimmer#3"), F("4"), }; - const int buttonoptionValues[4] = { 1, 2, 3, 4 }; - addFormSelector(F("Number of relays"), F("button"), 4, buttonOptions, buttonoptionValues, PCONFIG(1)); + const int buttonoptionValues[] = { 1, 2, 3, 4 }; + constexpr size_t optionCount = NR_ELEMENTS(buttonoptionValues); + addFormSelector(F("Number of relays"), F("button"), optionCount, buttonOptions, buttonoptionValues, PCONFIG(1)); } if (PCONFIG(0) == SER_SWITCH_SONOFFDUAL) { - const __FlashStringHelper *modeoptions[3] = { + const __FlashStringHelper *modeoptions[] = { F("Normal"), F("Exclude/Blinds mode"), F("Simultaneous mode"), }; - addFormSelector(F("Relay working mode"), F("mode"), 3, modeoptions, nullptr, PCONFIG(1)); + constexpr size_t optionCount = NR_ELEMENTS(modeoptions); + addFormSelector(F("Relay working mode"), F("mode"), optionCount, modeoptions, nullptr, PCONFIG(1)); } if (PCONFIG(0) == SER_SWITCH_LCTECH) { { - const __FlashStringHelper *buttonOptions[4] = { + const __FlashStringHelper *buttonOptions[] = { F("1"), F("2"), F("3"), F("4"), }; - const int buttonoptionValues[4] = { 1, 2, 3, 4 }; - addFormSelector(F("Number of relays"), F("button"), 4, buttonOptions, buttonoptionValues, PCONFIG(1)); + const int buttonoptionValues[] = { 1, 2, 3, 4 }; + constexpr size_t optionCount = NR_ELEMENTS(buttonoptionValues); + addFormSelector(F("Number of relays"), F("button"), optionCount, buttonOptions, buttonoptionValues, PCONFIG(1)); } { - const __FlashStringHelper *speedOptions[8] = { + const __FlashStringHelper *speedOptions[] = { F("9600"), F("19200"), F("115200"), @@ -177,7 +176,8 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) F("38400"), F("57600"), }; - addFormSelector(F("Serial speed"), F("speed"), 8, speedOptions, nullptr, PCONFIG(2)); + constexpr size_t optionCount = NR_ELEMENTS(speedOptions); + addFormSelector(F("Serial speed"), F("speed"), optionCount, speedOptions, nullptr, PCONFIG(2)); } addFormCheckBox(F("Use command doubling"), F("dbl"), PCONFIG(3)); @@ -540,11 +540,11 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WRITE: { + const String command = parseString(string, 1); String log; - String command = parseString(string, 1); - uint8_t rnum = 0; - uint8_t rcmd = 0; - uint8_t par3 = 0; + uint8_t rnum{}; + uint8_t rcmd{}; + uint8_t par3{}; if (Plugin_091_init) { @@ -578,7 +578,7 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) if ((par3 == 1) && (rcmd == 1) && (rnum < 2)) { // exclusive on mode for Dual - // FIXME TD-er: Is this a valid UserVar index? + // FIXME TD-er: Is this a valid UserVar index? UserVar.setFloat(event->TaskIndex, 1 - rnum, 0); } @@ -629,7 +629,7 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) if ((par3 == 1) && (rcmd == 1) && (rnum < 2)) { // exclusive on mode for Dual - // FIXME TD-er: Is this a valid UserVar index? + // FIXME TD-er: Is this a valid UserVar index? UserVar.setFloat(event->TaskIndex, 1 - rnum, 0); } @@ -681,7 +681,7 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) if ((par3 == 1) && (rcmd == 1) && (rnum < 2)) { // exclusive on mode for Dual - // FIXME TD-er: Is this a valid UserVar index? + // FIXME TD-er: Is this a valid UserVar index? UserVar.setFloat(event->TaskIndex, 1 - rnum, 0); } @@ -702,17 +702,12 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) addLogMove(LOG_LEVEL_INFO, strformat(F("SerSW : SetSwitchPulse r%d:%d Pulse for %d sec"), rnum, rcmd, event->Par3)); } } else - if (equals(command, F("ydim"))) // - // deal - // with - // dimmer - // command + + // deal with dimmer command + if (equals(command, F("ydim"))) { - if (((Plugin_091_globalpar0 == SER_SWITCH_YEWE) && (Plugin_091_numrelay > 1)) || (Plugin_091_globalpar0 == SER_SWITCH_WIFIDIMMER)) { // - // only - // on - // tuya - // dimmer + // only on tuya dimmer + if (((Plugin_091_globalpar0 == SER_SWITCH_YEWE) && (Plugin_091_numrelay > 1)) || (Plugin_091_globalpar0 == SER_SWITCH_WIFIDIMMER)) { success = true; // LoadTaskSettings(Plugin_091_ownindex); // get our own task values please @@ -767,7 +762,7 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) if ((par3 == 1) && (rcmd == 1) && (rnum < 2)) { // exclusive on mode for Dual - // FIXME TD-er: Is this a valid UserVar index? + // FIXME TD-er: Is this a valid UserVar index? UserVar.setFloat(event->TaskIndex, 1 - rnum, 0); } From ed88b35dc061d5252414d301799484af256d312f Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sun, 5 Jan 2025 23:21:41 +0100 Subject: [PATCH 4/9] [Build] More code reductions in .ino files [P092] .. [P110] --- src/_P092_DLbus.ino | 73 +- src/_P094_CULReader.ino | 15 +- src/_P095_ILI9341.ino | 27 +- src/_P096_eInk.ino | 98 ++- src/_P097_Esp32Touch.ino | 20 +- src/_P098_PWM_motor.ino | 26 +- src/_P099_XPT2046Touch.ino | 1011 +++++++++++++------------- src/_P100_DS2423_counter.ino | 309 ++++---- src/_P101_WakeOnLan.ino | 41 +- src/_P102_PZEM004Tv3.ino | 50 +- src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino | 27 +- src/_P104_max7219_Dotmatrix.ino | 9 - src/_P105_AHT.ino | 449 ++++++------ src/_P106_BME680.ino | 20 +- src/_P107_SI1145.ino | 20 +- src/_P108_DDS238.ino | 25 +- src/_P109_ThermOLED.ino | 35 +- src/_P110_VL53L0X.ino | 35 +- 18 files changed, 1104 insertions(+), 1186 deletions(-) diff --git a/src/_P092_DLbus.ino b/src/_P092_DLbus.ino index 4a2c0d001d..140d513599 100644 --- a/src/_P092_DLbus.ino +++ b/src/_P092_DLbus.ino @@ -90,19 +90,14 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_092; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_092; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].DecimalsOnly = true; + Device[deviceCount].PluginStats = true; break; } @@ -145,22 +140,23 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) addFormSelector(F("Pin mode"), F("ppinmode"), 2, options, optionValues, choice); } { - const __FlashStringHelper *Devices[P092_DLbus_DeviceCount] = { + const __FlashStringHelper *Devices[] = { F("ESR21"), F("UVR31"), F("UVR42"), F("UVR1611"), F("UVR 61-3 (up to v8.2)"), F("UVR 61-3 (v8.3 or higher)") }; - const int DevTypes[P092_DLbus_DeviceCount] = { 21, 31, 42, 1611, 6132, 6133 }; + const int DevTypes[] = { 21, 31, 42, 1611, 6132, 6133 }; + constexpr size_t optionCount = NR_ELEMENTS(Devices); - addFormSelector(F("DL-Bus Type"), F("pdlbtype"), P092_DLbus_DeviceCount, Devices, DevTypes, nullptr, PCONFIG(0), true); + addFormSelector(F("DL-Bus Type"), F("pdlbtype"), optionCount, Devices, DevTypes, nullptr, PCONFIG(0), true); } { int P092_ValueType, P092_ValueIdx; P092_Last_DLB_Pin = CONFIG_PIN1; - const String plugin_092_DefValueName = F(PLUGIN_VALUENAME1_092); - const int P092_OptionTypes[P092_DLbus_OptionCount] = { + const String plugin_092_DefValueName = F(PLUGIN_VALUENAME1_092); + const int P092_OptionTypes[] = { // Index der Variablen 0, // F("None") 1, // F("Sensor") @@ -171,7 +167,8 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) 6, // F("Heat power (kW)") 7 // F("Heat meter (MWh)") }; - const __FlashStringHelper *Options[P092_DLbus_OptionCount] = { + constexpr size_t optionCount = NR_ELEMENTS(P092_OptionTypes); + const __FlashStringHelper *Options[] = { F("None"), F("Sensor"), F("Ext. sensor"), @@ -182,18 +179,18 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) F("Heat meter (MWh)") }; - uint8_t P092_MaxIdx[P092_DLbus_OptionCount]; - - // Calculation of the max indices for each sensor type - // default indizes for UVR31 - P092_MaxIdx[0] = 0; // None - P092_MaxIdx[1] = 3; // Sensor - P092_MaxIdx[2] = 0; // Ext. sensor - P092_MaxIdx[3] = 1; // Digital output - P092_MaxIdx[4] = 0; // Speed step - P092_MaxIdx[5] = 0; // Analog output - P092_MaxIdx[6] = 0; // Heat power (kW) - P092_MaxIdx[7] = 0; // Heat meter (MWh) + uint8_t P092_MaxIdx[] { + // Calculation of the max indices for each sensor type + // default indizes for UVR31 + 0, // None + 3, // Sensor + 0, // Ext. sensor + 1, // Digital output + 0, // Speed step + 0, // Analog output + 0, // Heat power (kW) + 0, // Heat meter (MWh) + }; switch (PCONFIG(0)) { case 21: // ESR21 @@ -240,7 +237,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) addFormSelector(plugin_092_DefValueName, F("pValue"), - P092_DLbus_OptionCount, + optionCount, Options, P092_OptionTypes, nullptr, @@ -288,8 +285,8 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) P092_OptionValueDecimals[6] = 2; } - int OptionIdx = getFormItemInt(F("pValue")); - int CurIdx = getFormItemInt(F("pIdx")); + const int OptionIdx = getFormItemInt(F("pValue")); + int CurIdx = getFormItemInt(F("pIdx")); if (CurIdx < 1) { CurIdx = 1; @@ -324,13 +321,13 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) String log = F("PLUGIN_WEBFORM_SAVE :"); log += F(" DLB_Pin:"); log += CONFIG_PIN1; - log += F(" DLbus_MinPulseWidth:"); + log += F(" MinPulseWidth:"); log += P092_data->P092_DataSettings.DLbus_MinPulseWidth; - log += F(" DLbus_MaxPulseWidth:"); + log += F(" MaxPulseWidth:"); log += P092_data->P092_DataSettings.DLbus_MaxPulseWidth; - log += F(" DLbus_MinDoublePulseWidth:"); + log += F(" MinDoublePulseWidth:"); log += P092_data->P092_DataSettings.DLbus_MinDoublePulseWidth; - log += F(" DLbus_MaxDoublePulseWidth:"); + log += F(" MaxDoublePulseWidth:"); log += P092_data->P092_DataSettings.DLbus_MaxDoublePulseWidth; log += F(" IdxSensor:"); log += P092_data->P092_DataSettings.IdxSensor; diff --git a/src/_P094_CULReader.ino b/src/_P094_CULReader.ino index cf8db55d88..f653f72eb0 100644 --- a/src/_P094_CULReader.ino +++ b/src/_P094_CULReader.ino @@ -57,14 +57,9 @@ boolean Plugin_094(uint8_t function, struct EventStruct *event, String& string) Device[deviceCount].Type = DEVICE_TYPE_SERIAL; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; Device[deviceCount].OutputDataType = Output_Data_type_t::Default; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; Device[deviceCount].ValueCount = 1; Device[deviceCount].SendDataOption = true; Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = false; Device[deviceCount].DuplicateDetection = true; // FIXME TD-er: Not sure if access to any existing task data is needed when saving @@ -318,10 +313,8 @@ boolean Plugin_094(uint8_t function, struct EventStruct *event, String& string) # endif // if P094_DEBUG_OPTIONS if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("CUL Reader: Sending: "); - log += event->String2.substring(0, 20); - log += F("..."); - addLogMove(LOG_LEVEL_INFO, log); + addLogMove(LOG_LEVEL_INFO, strformat(F("CUL Reader: Sending: %s..."), + event->String2.substring(0, 20).c_str())); } // sendData_checkDuplicates(event, event->String2.substring(0, 22)); @@ -447,7 +440,7 @@ boolean Plugin_094(uint8_t function, struct EventStruct *event, String& string) break; } -#ifdef USES_ESPEASY_NOW +# ifdef USES_ESPEASY_NOW case PLUGIN_FILTEROUT_CONTROLLER_DATA: { // event->String1 => topic; @@ -463,7 +456,7 @@ boolean Plugin_094(uint8_t function, struct EventStruct *event, String& string) break; } -#endif +# endif // ifdef USES_ESPEASY_NOW } return success; } diff --git a/src/_P095_ILI9341.ino b/src/_P095_ILI9341.ino index f69cbc7f11..e2340e1e71 100644 --- a/src/_P095_ILI9341.ino +++ b/src/_P095_ILI9341.ino @@ -146,18 +146,13 @@ boolean Plugin_095(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_095; - Device[deviceCount].Type = DEVICE_TYPE_SPI3; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - success = true; + Device[++deviceCount].Number = PLUGIN_ID_095; + Device[deviceCount].Type = DEVICE_TYPE_SPI3; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + success = true; break; } @@ -265,9 +260,10 @@ boolean Plugin_095(uint8_t function, struct EventStruct *event, String& string) static_cast(ILI9xxx_type_e::ILI9488_320x480), # endif // if P095_ENABLE_ILI948X }; + constexpr size_t optionCount = NR_ELEMENTS(hardwareOptions); addFormSelector(F("TFT display model"), F("dsptype"), - NR_ELEMENTS(hardwareOptions), + optionCount, hardwareTypes, hardwareOptions, P095_CONFIG_FLAG_GET_TYPE); @@ -314,9 +310,10 @@ boolean Plugin_095(uint8_t function, struct EventStruct *event, String& string) static_cast(P095_CommandTrigger::ili9488), # endif // if P095_ENABLE_ILI948X }; + constexpr size_t optionCount = NR_ELEMENTS(commandTriggerOptions); addFormSelector(F("Write Command trigger"), F("commandtrigger"), - NR_ELEMENTS(commandTriggerOptions), + optionCount, commandTriggers, commandTriggerOptions, P095_CONFIG_FLAG_GET_CMD_TRIGGER); @@ -420,7 +417,7 @@ boolean Plugin_095(uint8_t function, struct EventStruct *event, String& string) strings[varNr] = webArg(getPluginCustomArgName(varNr)); } - String error = SaveCustomTaskSettings(event->TaskIndex, strings, P095_Nlines, 0); + const String error = SaveCustomTaskSettings(event->TaskIndex, strings, P095_Nlines, 0); if (error.length() > 0) { addHtmlError(error); diff --git a/src/_P096_eInk.ino b/src/_P096_eInk.ino index ed1a02db8c..fdb46957b9 100644 --- a/src/_P096_eInk.ino +++ b/src/_P096_eInk.ino @@ -114,13 +114,13 @@ # ifndef P096_USE_ADA_GRAPHICS -// declare functions for using default value parameters -void Plugin_096_printText(const char *string, - int X, - int Y, - unsigned int textSize = 1, - unsigned short color = EPD_WHITE, - unsigned short bkcolor = EPD_BLACK); +// // declare functions for using default value parameters +// void Plugin_096_printText(const char *string, +// int X, +// int Y, +// unsigned int textSize = 1, +// unsigned short color = EPD_WHITE, +// unsigned short bkcolor = EPD_BLACK); # endif // ifndef P096_USE_ADA_GRAPHICS // Define the default values for both ESP32/lolin32 and D1 Mini @@ -135,8 +135,8 @@ void Plugin_096_printText(const char *string, # else // ifdef ESP32 // for D1 Mini with shield connection - # define EPD_CS 16 // D0 - # define EPD_DC 15 // D8 + # define EPD_CS 16 // D0 + # define EPD_DC 15 // D8 # define EPD_RST -1 // can set to -1 and share with microcontroller Reset! # define EPD_BUSY -1 // can set to -1 to not use a pin (will wait a fixed delay) # endif // ifdef ESP32 @@ -175,22 +175,14 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_096; - Device[deviceCount].Type = DEVICE_TYPE_SPI3; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; + Device[++deviceCount].Number = PLUGIN_ID_096; + Device[deviceCount].Type = DEVICE_TYPE_SPI3; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; # if P096_USE_EXTENDED_SETTINGS Device[deviceCount].ValueCount = 2; Device[deviceCount].TimerOption = true; Device[deviceCount].TimerOptional = true; - # else // if P096_USE_EXTENDED_SETTINGS - Device[deviceCount].ValueCount = 0; - Device[deviceCount].TimerOption = false; # endif // if P096_USE_EXTENDED_SETTINGS - Device[deviceCount].SendDataOption = false; success = true; break; @@ -248,8 +240,7 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_SHOW_GPIO_DESCR: { - string = F("EPD BUSY: "); - string += formatGpioLabel(PIN(3), false); + string = concat(F("EPD BUSY: "), formatGpioLabel(PIN(3), false)); success = true; break; } @@ -282,9 +273,10 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) static_cast(EPD_type_e::EPD_WS2IN7) # endif // if P096_USE_WAVESHARE_2IN7 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues4); addFormSelector(F("eInk display model"), F("_type"), - static_cast(EPD_type_e::EPD_MAX), + optionCount, options4, optionValues4, P096_CONFIG_FLAG_GET_DISPLAYTYPE); @@ -297,9 +289,10 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) AdaGFXFormRotation(F("_rotate"), P096_CONFIG_ROTATION); # else // ifdef P096_USE_ADA_GRAPHICS { - const __FlashStringHelper *options2[4] = { F("Normal"), F("+90°"), F("+180°"), F("+270°") }; - int optionValues2[4] = { 0, 1, 2, 3 }; - addFormSelector(F("Rotation"), F("_rotate"), 4, options2, optionValues2, P096_CONFIG_ROTATION); + const __FlashStringHelper *options2[] = { F("Normal"), F("+90°"), F("+180°"), F("+270°") }; + int optionValues2[] = { 0, 1, 2, 3 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues2); + addFormSelector(F("Rotation"), F("_rotate"), optionCount, options2, optionValues2, P096_CONFIG_ROTATION); } # endif // ifdef P096_USE_ADA_GRAPHICS @@ -340,14 +333,15 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) # endif // if ADAGFX_SUPPORT_7COLOR }; - if (P096_CONFIG_FLAG_GET_COLORDEPTH == 0) { // Enum doesn't have 0 + if (P096_CONFIG_FLAG_GET_COLORDEPTH == 0) { // Enum doesn't have 0 uint32_t lSettings = 0; set4BitToUL(lSettings, P096_CONFIG_FLAG_COLORDEPTH, static_cast(AdaGFXColorDepth::Monochrome)); // Bit 20..23 Color depth P096_CONFIG_FLAGS = lSettings; } + constexpr size_t optionCount = NR_ELEMENTS(colorDepthOptions); addFormSelector(F("Greyscale levels"), F("_colorDepth"), - ADAGFX_MONOCOLORS_COUNT, + optionCount, colorDepths, colorDepthOptions, P096_CONFIG_FLAG_GET_COLORDEPTH); @@ -355,9 +349,9 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) AdaGFXFormTextPrintMode(F("_mode"), P096_CONFIG_FLAG_GET_MODE); - # if ADAGFX_FONTS_INCLUDED + # if ADAGFX_FONTS_INCLUDED AdaGFXFormDefaultFont(F("deffont"), P096_CONFIG_DEFAULT_FONT); - # endif // if ADAGFX_FONTS_INCLUDED + # endif // if ADAGFX_FONTS_INCLUDED AdaGFXFormFontScaling(F("_fontscale"), P096_CONFIG_FLAG_GET_FONTSCALE); @@ -384,9 +378,10 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) static_cast(P096_CommandTrigger::ws2in7) # endif // if P096_USE_WAVESHARE_2IN7 }; + constexpr size_t optionCount = NR_ELEMENTS(commandTriggerOptions); addFormSelector(F("Write Command trigger"), F("_commandtrigger"), - static_cast(P096_CommandTrigger::MAX), + optionCount, commandTriggers, commandTriggerOptions, P096_CONFIG_FLAG_GET_CMD_TRIGGER); @@ -576,7 +571,6 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) } break; } - } return success; @@ -584,26 +578,26 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) # ifndef P096_USE_ADA_GRAPHICS -// Print some text -// param [in] string : The text to display -// param [in] X : The left position (X) -// param [in] Y : The top position (Y) -// param [in] textSize : The text size (default 1) -// param [in] color : The fore color (default ILI9341_WHITE) -// param [in] bkcolor : The background color (default ILI9341_BLACK) -void Plugin_096_printText(const char *string, int X, int Y, unsigned int textSize, unsigned short color, unsigned short bkcolor) -{ - eInkScreen->clearBuffer(); - eInkScreen->clearDisplay(); - eInkScreen->setCursor(X, Y); - eInkScreen->setTextColor(color, bkcolor); - eInkScreen->setTextSize(textSize); - String fixString = string; - - Plugin_096_FixText(fixString); - eInkScreen->println(fixString); - eInkScreen->display(); -} +// // Print some text +// // param [in] string : The text to display +// // param [in] X : The left position (X) +// // param [in] Y : The top position (Y) +// // param [in] textSize : The text size (default 1) +// // param [in] color : The fore color (default ILI9341_WHITE) +// // param [in] bkcolor : The background color (default ILI9341_BLACK) +// void Plugin_096_printText(const char *string, int X, int Y, unsigned int textSize, unsigned short color, unsigned short bkcolor) +// { +// eInkScreen->clearBuffer(); +// eInkScreen->clearDisplay(); +// eInkScreen->setCursor(X, Y); +// eInkScreen->setTextColor(color, bkcolor); +// eInkScreen->setTextSize(textSize); +// String fixString = string; + +// Plugin_096_FixText(fixString); +// eInkScreen->println(fixString); +// eInkScreen->display(); +// } # endif // ifndef P096_USE_ADA_GRAPHICS diff --git a/src/_P097_Esp32Touch.ino b/src/_P097_Esp32Touch.ino index 56516a7547..494b62bd48 100644 --- a/src/_P097_Esp32Touch.ino +++ b/src/_P097_Esp32Touch.ino @@ -56,19 +56,13 @@ boolean Plugin_097(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_097; - Device[deviceCount].Type = DEVICE_TYPE_ANALOG; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].DecimalsOnly = false; - Device[deviceCount].TimerOption = false; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; + Device[++deviceCount].Number = PLUGIN_ID_097; + Device[deviceCount].Type = DEVICE_TYPE_ANALOG; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOptional = true; break; } diff --git a/src/_P098_PWM_motor.ino b/src/_P098_PWM_motor.ino index 3c2c99163c..b1d9beb834 100644 --- a/src/_P098_PWM_motor.ino +++ b/src/_P098_PWM_motor.ino @@ -51,17 +51,13 @@ boolean Plugin_098(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_098; - Device[deviceCount].Type = DEVICE_TYPE_CUSTOM0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + Device[++deviceCount].Number = PLUGIN_ID_098; + Device[deviceCount].Type = DEVICE_TYPE_CUSTOM0; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; break; } @@ -92,7 +88,7 @@ boolean Plugin_098(uint8_t function, struct EventStruct *event, String& string) F("Lim A"), F("Lim B") }; - int values[] = { + const int values[] = { CONFIG_PIN1, CONFIG_PIN2, CONFIG_PIN3, @@ -102,7 +98,7 @@ boolean Plugin_098(uint8_t function, struct EventStruct *event, String& string) P098_LIMIT_SWA_GPIO, P098_LIMIT_SWB_GPIO }; - constexpr size_t nrElements = sizeof(values) / sizeof(values[0]); + constexpr size_t nrElements = NR_ELEMENTS(values); for (size_t i = 0; i < nrElements; ++i) { if (i != 0) { addHtml(event->String1); } @@ -250,8 +246,8 @@ boolean Plugin_098(uint8_t function, struct EventStruct *event, String& string) CONFIG_PIN2 = getFormItemInt(F("taskdevicepin2")); CONFIG_PIN3 = getFormItemInt(F("taskdevicepin3")); - P098_ENC_TIMEOUT = getFormItemInt(F("enc_timeout")); - P098_VIRTUAL_SPEED = getFormItemInt(F("virtual_speed")); + P098_ENC_TIMEOUT = getFormItemInt(F("enc_timeout")); + P098_VIRTUAL_SPEED = getFormItemInt(F("virtual_speed")); P098_POS_0_SUPPLEMENT = getFormItemInt(F("pos0_supplement")); P098_LIMIT_SWA_GPIO = getFormItemInt(F("limit_a")); diff --git a/src/_P099_XPT2046Touch.ino b/src/_P099_XPT2046Touch.ino index c44b3538e7..7c53bc90db 100644 --- a/src/_P099_XPT2046Touch.ino +++ b/src/_P099_XPT2046Touch.ino @@ -1,510 +1,501 @@ -#ifdef USES_P099 - -// ####################################################################################################### -// #################################### Plugin 099: XPT2046 TFT Touchscreen ################################# -// ####################################################################################################### - -/** - * Changelog: - * 2020-11-01 tonhuisman: Solved previous strange rotation settings to be compatible with TFT ILI9341 - * 2020-11-01 tonhuisman: Add option to flip rotation by 180 deg, and command touch,flip,<0|1> - * 2020-11-01 tonhuisman: Add option for the debounce timeout for On/Off buttons - * 2020-11-01 tonhuisman: Some code cleanup and string optimizations - * 2020-09-23/24/25 tonhuisman: Add object disable/enable commands, add On/Off button mode, and inverted, for touchobjects - * 2020-09-10 tonhuisman: Clean up code, testing - * 2020-09-07/08/09 tonhuisman: Fix code issues - * 2020-09-06 tonhuisman: Add object 'layering' so the 'top-most' object only sends an event - * 2020-09-05 tonhuisman: Add touch to touchobject mapping, generate events - * 2020-09-03 tonhuisman: Add touchobject settings - * 2020-08-31 tonhuisman: Add Calibration settings - * 2020-08-30 tonhuisman: Add settings and 2/3 event support - * 2020-08-29 tonhuisman: Initial plugin, based on XPT2046_Touchscreen by Paul Stoffregen from - * https://github.com/PaulStoffregen/XPT2046_Touchscreen - */ - -/** - * Commands supported: - * ------------------- - * touch,rot,<0..3> : Set rotation to 0(0), 90(1), 180(2), 270(3) degrees - * touch,flip,<0|1> : Set rotation normal(0) or flipped by 180 degrees(1) - * touch,enable, : Enables a disabled objectname (removes a leading underscore) - * touch,disable, : Disables an enabled objectname (adds a leading underscore) - */ - -#define PLUGIN_099 -#define PLUGIN_ID_099 99 -#define PLUGIN_NAME_099 "Touch - XPT2046 on a TFT display" -#define PLUGIN_VALUENAME1_099 "X" -#define PLUGIN_VALUENAME2_099 "Y" -#define PLUGIN_VALUENAME3_099 "Z" - -#include "_Plugin_Helper.h" -#include "src/PluginStructs/P099_data_struct.h" - - -boolean Plugin_099(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_099; - Device[deviceCount].Type = DEVICE_TYPE_SPI; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; - success = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_099); - success = true; - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_099)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_099)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_099)); - success = true; - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: - { - event->String1 = formatGpioName_output(F("TS CS")); - break; - } - - case PLUGIN_SET_DEFAULTS: - { - // if already configured take it from settings, else use default values - if (P099_CONFIG_STATE != 1) { - P099_CONFIG_CS_PIN = P099_TS_CS; - P099_CONFIG_TRESHOLD = P099_TS_TRESHOLD; - P099_CONFIG_ROTATION = P099_TS_ROTATION; - P099_CONFIG_X_RES = P099_TS_X_RES; - P099_CONFIG_Y_RES = P099_TS_Y_RES; - P099_CONFIG_OBJECTCOUNT = P099_INIT_OBJECTCOUNT; - P099_CONFIG_DEBOUNCE_MS = P099_DEBOUNCE_MILLIS; - - constexpr uint32_t lSettings = 0 - + (P099_TS_SEND_XY ? (1 << P099_FLAGS_SEND_XY) : 0) - + (P099_TS_SEND_Z ? (1 << P099_FLAGS_SEND_Z) : 0) - + (P099_TS_SEND_OBJECTNAME ? (1 << P099_FLAGS_SEND_OBJECTNAME) : 0) - + (P099_TS_USE_CALIBRATION ? (1 << P099_FLAGS_USE_CALIBRATION) : 0) - + (P099_TS_LOG_CALIBRATION ? (1 << P099_FLAGS_LOG_CALIBRATION) : 0) - + (P099_TS_ROTATION_FLIPPED ? (1 << P099_FLAGS_ROTATION_FLIPPED) : 0); - P099_CONFIG_FLAGS = lSettings; - } - success = true; - break; - } - case PLUGIN_WEBFORM_LOAD: - { - addFormSubHeader(F("Screen")); - - uint16_t width_ = P099_CONFIG_X_RES; - - if (width_ == 0) { - width_ = P099_TS_X_RES; // default value - } - addFormNumericBox(F("Screen Width (px) (x)"), F("pwidth"), width_, 1, 65535); - - uint16_t height_ = P099_CONFIG_Y_RES; - - if (height_ == 0) { - height_ = P099_TS_Y_RES; // default value - } - addFormNumericBox(F("Screen Height (px) (y)"), F("pheight"), height_, 1, 65535); - - { - uint8_t choice2 = P099_CONFIG_ROTATION; - const __FlashStringHelper *options2[4] = { F("Normal"), F("+90°"), F("+180°"), F("+270°") }; // Avoid unicode - int optionValues2[4] = { 0, 1, 2, 3 }; // Rotation similar to the - // TFT ILI9341 rotation - addFormSelector(F("Rotation"), F("protate"), 4, options2, optionValues2, choice2); - } - - bool bRotationFlipped = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_ROTATION_FLIPPED); - addFormCheckBox(F("Flip rotation 180°"), F("protation_flipped"), bRotationFlipped); - addFormNote(F("Some touchscreens are mounted 180° rotated on the display.")); - - addFormSubHeader(F("Touch configuration")); - - uint8_t treshold = P099_CONFIG_TRESHOLD; - addFormNumericBox(F("Touch minimum pressure"), F("ptreshold"), treshold, 0, 255); - - #define P099_EVENTS_OPTIONS 6 - uint8_t choice3 = 0; - bitWrite(choice3, P099_FLAGS_SEND_XY, bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_XY)); - bitWrite(choice3, P099_FLAGS_SEND_Z, bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_Z)); - bitWrite(choice3, P099_FLAGS_SEND_OBJECTNAME, bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_OBJECTNAME)); - { - const __FlashStringHelper *options3[P099_EVENTS_OPTIONS] = - { F("None"), - F("X and Y"), - F("X, Y and Z"), - F("Objectnames only"), - F("Objectnames, X and Y"), - F("Objectnames, X, Y and Z") }; - int optionValues3[P099_EVENTS_OPTIONS] = { 0, 1, 3, 4, 5, 7 }; // Already used as a bitmap! - addFormSelector(F("Events"), F("pevents"), P099_EVENTS_OPTIONS, options3, optionValues3, choice3); - } - - if (!Settings.UseRules) { - addFormNote(F("Tools / Advanced / Rules must be enabled for events to be fired.")); - } - - { - P099_data_struct *P099_data = new (std::nothrow) P099_data_struct(); - - if (nullptr == P099_data) { - return success; - } - P099_data->loadTouchObjects(event->TaskIndex); - - addFormSubHeader(F("Calibration")); - - bool tbUseCalibration = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_USE_CALIBRATION); - addFormSelector_YesNo(F("Calibrate to screen resolution"), F("puse_calibration"), tbUseCalibration ? 1 : 0, true); - - if (tbUseCalibration) { - addRowLabel(F("Calibration")); - html_table(EMPTY_STRING, false); // Sub-table - html_table_header(F(""), 100); - html_table_header(F("x"), 70); - html_table_header(F("y"), 70); - html_table_header(F(""), 100); - html_table_header(F("x"), 70); - html_table_header(F("y"), 70); - - html_TR_TD(); - addHtml(F("Top-left")); - html_TD(); - addNumericBox(F("pcal_tl_x"), P099_data->StoredSettings.Calibration.top_left.x, 0, 65535); - html_TD(); - addNumericBox(F("pcal_tl_y"), P099_data->StoredSettings.Calibration.top_left.y, 0, 65535); - html_TD(); - addHtml(F("Bottom-right")); - html_TD(); - addNumericBox(F("pcal_br_x"), P099_data->StoredSettings.Calibration.bottom_right.x, 0, 65535); - html_TD(); - addNumericBox(F("pcal_br_y"), P099_data->StoredSettings.Calibration.bottom_right.y, 0, 65535); - - html_end_table(); - addFormNote(F("All x/y values must be <> 0 to enable calibration.")); - } - bool bEnableCalibrationLog = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_LOG_CALIBRATION); - addFormCheckBox(F("Enable logging for calibration"), F("plog_calibration"), bEnableCalibrationLog); - - addFormSubHeader(F("Touch objects")); - - { - if (P099_CONFIG_OBJECTCOUNT > P099_MaxObjectCount) { P099_CONFIG_OBJECTCOUNT = P099_MaxObjectCount; } - uint8_t choice5 = P099_CONFIG_OBJECTCOUNT; - - if (choice5 == 0) { // Uninitialized, so use default - choice5 = P099_CONFIG_OBJECTCOUNT = P099_INIT_OBJECTCOUNT; - } - #define P099_OBJECTCOUNT_OPTIONS 6 - { - const __FlashStringHelper *options5[P099_OBJECTCOUNT_OPTIONS] = { F("None"), F("8"), F("16"), F("24"), F("32"), F("40") }; - int optionValues5[P099_OBJECTCOUNT_OPTIONS] = { -1, 8, 16, 24, 32, 40 }; - addFormSelector(F("# of objects"), F("pobjectcount"), P099_OBJECTCOUNT_OPTIONS, options5, optionValues5, choice5, true); - } - } - - if (P099_CONFIG_OBJECTCOUNT > -1) { - addRowLabel(F("Object")); - html_table(EMPTY_STRING, false); // Sub-table - html_table_header(F(" # "), 30); - html_table_header(F("Objectname"), 200); - html_table_header(F("Top-left x"), 120); - html_table_header(F("Top-left y"), 120); - html_table_header(F("Bottom-right x"), 150); - html_table_header(F("Bottom-right y"), 150); - html_table_header(F("On/Off button"), 150); - html_table_header(F("Inverted"), 120); - - for (int objectNr = 0; objectNr < P099_CONFIG_OBJECTCOUNT; objectNr++) { - html_TR_TD(); - addHtml(F(" ")); - addHtmlInt(objectNr + 1); - html_TD(); - addTextBox(getPluginCustomArgName(objectNr), - String(P099_data->StoredSettings.TouchObjects[objectNr].objectname), - P099_MaxObjectNameLength - 1, - false, false, EMPTY_STRING, F("")); - html_TD(); - addNumericBox(getPluginCustomArgName(objectNr + 100), P099_data->StoredSettings.TouchObjects[objectNr].top_left.x, 0, 65535); - html_TD(); - addNumericBox(getPluginCustomArgName(objectNr + 200), P099_data->StoredSettings.TouchObjects[objectNr].top_left.y, 0, 65535); - html_TD(); - addNumericBox(getPluginCustomArgName(objectNr + 300), P099_data->StoredSettings.TouchObjects[objectNr].bottom_right.x, 0, 65535); - html_TD(); - addNumericBox(getPluginCustomArgName(objectNr + 400), P099_data->StoredSettings.TouchObjects[objectNr].bottom_right.y, 0, 65535); - html_TD(); - addCheckBox(getPluginCustomArgName(objectNr + 500), - bitRead(P099_data->StoredSettings.TouchObjects[objectNr].flags, P099_FLAGS_ON_OFF_BUTTON), false); - html_TD(); - addCheckBox(getPluginCustomArgName(objectNr + 600), - bitRead(P099_data->StoredSettings.TouchObjects[objectNr].flags, P099_FLAGS_INVERT_BUTTON), false); - } - html_end_table(); - addFormNote(F("Start objectname with '_' to ignore/disable the object (temporarily).")); - - uint8_t debounce = P099_CONFIG_DEBOUNCE_MS; - addFormNumericBox(F("Debounce delay for On/Off buttons"), F("pdebounce"), debounce, 0, 255); - addUnit(F("0-255 msec.")); - } - delete P099_data; - } - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - P099_CONFIG_STATE = 1; // mark config as already saved (next time, will not use default values) - P099_CONFIG_TRESHOLD = getFormItemInt(F("ptreshold")); - P099_CONFIG_ROTATION = getFormItemInt(F("protate")); - P099_CONFIG_X_RES = getFormItemInt(F("pwidth")); - P099_CONFIG_Y_RES = getFormItemInt(F("pheight")); - P099_CONFIG_OBJECTCOUNT = getFormItemInt(F("pobjectcount")); - - if (P099_CONFIG_OBJECTCOUNT > P099_MaxObjectCount) { P099_CONFIG_OBJECTCOUNT = P099_MaxObjectCount; } - - uint32_t lSettings = 0; - bitWrite(lSettings, P099_FLAGS_SEND_XY, bitRead(getFormItemInt(F("pevents")), P099_FLAGS_SEND_XY)); - bitWrite(lSettings, P099_FLAGS_SEND_Z, bitRead(getFormItemInt(F("pevents")), P099_FLAGS_SEND_Z)); - bitWrite(lSettings, P099_FLAGS_SEND_OBJECTNAME, bitRead(getFormItemInt(F("pevents")), P099_FLAGS_SEND_OBJECTNAME)); - bitWrite(lSettings, P099_FLAGS_USE_CALIBRATION, getFormItemInt(F("puse_calibration")) == 1); - bitWrite(lSettings, P099_FLAGS_LOG_CALIBRATION, isFormItemChecked(F("plog_calibration"))); - bitWrite(lSettings, P099_FLAGS_ROTATION_FLIPPED, isFormItemChecked(F("protation_flipped"))); - P099_CONFIG_FLAGS = lSettings; - - P099_data_struct *P099_data = new (std::nothrow) P099_data_struct(); - - if (nullptr == P099_data) { - return success; // Save other settings even though this didn't initialize properly - } - P099_data->StoredSettings.Calibration.top_left.x = getFormItemInt(F("pcal_tl_x")); - P099_data->StoredSettings.Calibration.top_left.y = getFormItemInt(F("pcal_tl_y")); - P099_data->StoredSettings.Calibration.bottom_right.x = getFormItemInt(F("pcal_br_x")); - P099_data->StoredSettings.Calibration.bottom_right.y = getFormItemInt(F("pcal_br_y")); - - String error; - - for (int objectNr = 0; objectNr < P099_CONFIG_OBJECTCOUNT; objectNr++) { - if (!safe_strncpy(P099_data->StoredSettings.TouchObjects[objectNr].objectname, webArg(getPluginCustomArgName(objectNr)), - P099_MaxObjectNameLength)) { - error += getCustomTaskSettingsError(objectNr); - } - P099_data->StoredSettings.TouchObjects[objectNr].objectname[P099_MaxObjectNameLength - 1] = 0; // Terminate in - // case of - // uninitalized - // data - - if (!ExtraTaskSettings.checkInvalidCharInNames(&P099_data->StoredSettings.TouchObjects[objectNr].objectname[0])) { // Check for - // invalid - // characters in - // objectname - error += concat(F("Invalid character in objectname #"), objectNr + 1); - error += F(". Do not use ',-+/*=^%!#[]{}()' or space.\n"); - } - P099_data->StoredSettings.TouchObjects[objectNr].top_left.x = getFormItemIntCustomArgName(objectNr + 100); - P099_data->StoredSettings.TouchObjects[objectNr].top_left.y = getFormItemIntCustomArgName(objectNr + 200); - P099_data->StoredSettings.TouchObjects[objectNr].bottom_right.x = getFormItemIntCustomArgName(objectNr + 300); - P099_data->StoredSettings.TouchObjects[objectNr].bottom_right.y = getFormItemIntCustomArgName(objectNr + 400); - - uint8_t flags = 0; - bitWrite(flags, P099_FLAGS_ON_OFF_BUTTON, isFormItemChecked(getPluginCustomArgName(objectNr + 500))); - bitWrite(flags, P099_FLAGS_INVERT_BUTTON, isFormItemChecked(getPluginCustomArgName(objectNr + 600))); - P099_data->StoredSettings.TouchObjects[objectNr].flags = flags; - } - - if (P099_CONFIG_OBJECTCOUNT > 0) { - P099_CONFIG_DEBOUNCE_MS = getFormItemInt(F("pdebounce")); - } - - if (error.length() > 0) { - addHtmlError(error); - } - #ifdef PLUGIN_099_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, concat(F("P099 data save size: "), sizeof(P099_data->StoredSettings))); - } - #endif // PLUGIN_099_DEBUG - SaveCustomTaskSettings(event->TaskIndex, reinterpret_cast(&(P099_data->StoredSettings)), - sizeof(P099_data->StoredSettings)); - delete P099_data; - - success = true; - break; - } - - case PLUGIN_INIT: - { - initPluginTaskData(event->TaskIndex, new (std::nothrow) P099_data_struct()); - P099_data_struct *P099_data = static_cast(getPluginTaskData(event->TaskIndex)); - - success = (nullptr != P099_data) && P099_data->init(event->TaskIndex, - P099_CONFIG_CS_PIN, - P099_CONFIG_ROTATION, - bitRead(P099_CONFIG_FLAGS, P099_FLAGS_ROTATION_FLIPPED), - P099_CONFIG_TRESHOLD, - bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_XY), - bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_Z), - bitRead(P099_CONFIG_FLAGS, P099_FLAGS_USE_CALIBRATION), - P099_CONFIG_X_RES, - P099_CONFIG_Y_RES); - - break; - } - - case PLUGIN_EXIT: - { - success = true; - break; - } - - // case PLUGIN_READ: // Not implemented on purpose, *only* send out events/values when device is touched, and configured to send events - - case PLUGIN_WRITE: - { - P099_data_struct *P099_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P099_data) { - success = P099_data->plugin_write(event, string); - } - - break; - } - - case PLUGIN_TEN_PER_SECOND: // Should be often/fast enough, as this is user-interaction - { - P099_data_struct *P099_data = static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr == P099_data) { - return success; - } - - if (P099_data->isInitialized()) { - if (P099_data->touched()) { - uint16_t x, y, rx, ry; - uint8_t z; - P099_data->readData(&x, &y, &z); - - if (!((x >= P099_TOUCH_X_INVALID) || (y >= P099_TOUCH_Y_INVALID) || (z == P099_TOUCH_Z_INVALID) || (z <= P099_CONFIG_TRESHOLD))) { - rx = x; - ry = y; - P099_data->scaleRawToCalibrated(x, y); // Map to screen coordinates if so configured - - P099_SET_VALUE_X(x); - P099_SET_VALUE_Y(y); - P099_SET_VALUE_Z(z); - - bool bEnableCalibrationLog = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_LOG_CALIBRATION); - - if (bEnableCalibrationLog && loglevelActiveFor(LOG_LEVEL_INFO)) { - // REQUIRED for calibration and setting up objects, so do not - // make this optional! - // Space before the logged values was added for readability - addLogMove(LOG_LEVEL_INFO, strformat( - F("Touch calibration rx= %u, ry= %u; z= %u, x= %u, y= %u"), - rx, - ry, - z, // Always log the z value even if not used. - x, - y)); - } - - if (Settings.UseRules) { // No events to handle if rules not - // enabled - if (bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_XY)) { // Send events for each touch - const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(event->TaskIndex); - - if (!bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_Z) && validDeviceIndex(DeviceIndex)) { // Do NOT send a Z event for each - // touch? - // FIXME TD-er: Should not change anything in the Device vector. - #ifdef ESP8266 - Device[DeviceIndex].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[DeviceIndex].ValueCount = 2; - #else // ifdef ESP8266 - Device.getDeviceStructForEdit(DeviceIndex).VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device.getDeviceStructForEdit(DeviceIndex).ValueCount = 2; - #endif // ifdef ESP8266 - } - sendData(event); // Send X/Y(/Z) event - - if (!bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_Z) && validDeviceIndex(DeviceIndex)) { // Reset device configuration - // FIXME TD-er: Should not change anything in the Device vector. - #ifdef ESP8266 - Device[DeviceIndex].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[DeviceIndex].ValueCount = 3; - #else // ifdef ESP8266 - Device.getDeviceStructForEdit(DeviceIndex).VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device.getDeviceStructForEdit(DeviceIndex).ValueCount = 3; - #endif // ifdef ESP8266 - } - } - - if (bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_OBJECTNAME)) { // Send events for objectname if within reach - String selectedObjectName; - int selectedObjectIndex = -1; - - if (P099_data->isValidAndTouchedTouchObject(x, y, selectedObjectName, selectedObjectIndex, P099_CONFIG_OBJECTCOUNT)) { - if ((selectedObjectIndex > -1) && - bitRead(P099_data->StoredSettings.TouchObjects[selectedObjectIndex].flags, P099_FLAGS_ON_OFF_BUTTON)) { - if ((P099_data->TouchTimers[selectedObjectIndex] == 0) || - (P099_data->TouchTimers[selectedObjectIndex] < millis() - (2 * P099_CONFIG_DEBOUNCE_MS))) { // Not touched yet or - // too long ago - P099_data->TouchTimers[selectedObjectIndex] = millis() + P099_CONFIG_DEBOUNCE_MS; // From now wait the - // debounce time - } else { - if (P099_data->TouchTimers[selectedObjectIndex] <= millis()) { // Debouncing time - // elapsed? - P099_data->TouchStates[selectedObjectIndex] = !P099_data->TouchStates[selectedObjectIndex]; - P099_data->TouchTimers[selectedObjectIndex] = 0; - - bool eventValue = P099_data->TouchStates[selectedObjectIndex]; - - if (bitRead(P099_data->StoredSettings.TouchObjects[selectedObjectIndex].flags, P099_FLAGS_INVERT_BUTTON)) { - eventValue = !eventValue; // Act like an inverted button, 0 = On, 1 = Off - } - eventQueue.add(event->TaskIndex, selectedObjectName, eventValue); - } - } - } else { - // Matching object is found, send # event with x, y and z as %eventvalue1/2/3% - eventQueue.add( - event->TaskIndex, - selectedObjectName, - strformat(F("%u,%u,%u"), x, y, z)); - } - } - } - } - success = true; - } - } - } - break; - } - } // switch(function) - return success; -} // Plugin_099 - -#endif // USES_P099 +#ifdef USES_P099 + +// ####################################################################################################### +// #################################### Plugin 099: XPT2046 TFT Touchscreen ################################# +// ####################################################################################################### + +/** + * Changelog: + * 2020-11-01 tonhuisman: Solved previous strange rotation settings to be compatible with TFT ILI9341 + * 2020-11-01 tonhuisman: Add option to flip rotation by 180 deg, and command touch,flip,<0|1> + * 2020-11-01 tonhuisman: Add option for the debounce timeout for On/Off buttons + * 2020-11-01 tonhuisman: Some code cleanup and string optimizations + * 2020-09-23/24/25 tonhuisman: Add object disable/enable commands, add On/Off button mode, and inverted, for touchobjects + * 2020-09-10 tonhuisman: Clean up code, testing + * 2020-09-07/08/09 tonhuisman: Fix code issues + * 2020-09-06 tonhuisman: Add object 'layering' so the 'top-most' object only sends an event + * 2020-09-05 tonhuisman: Add touch to touchobject mapping, generate events + * 2020-09-03 tonhuisman: Add touchobject settings + * 2020-08-31 tonhuisman: Add Calibration settings + * 2020-08-30 tonhuisman: Add settings and 2/3 event support + * 2020-08-29 tonhuisman: Initial plugin, based on XPT2046_Touchscreen by Paul Stoffregen from + * https://github.com/PaulStoffregen/XPT2046_Touchscreen + */ + +/** + * Commands supported: + * ------------------- + * touch,rot,<0..3> : Set rotation to 0(0), 90(1), 180(2), 270(3) degrees + * touch,flip,<0|1> : Set rotation normal(0) or flipped by 180 degrees(1) + * touch,enable, : Enables a disabled objectname (removes a leading underscore) + * touch,disable, : Disables an enabled objectname (adds a leading underscore) + */ + +#define PLUGIN_099 +#define PLUGIN_ID_099 99 +#define PLUGIN_NAME_099 "Touch - XPT2046 on a TFT display" +#define PLUGIN_VALUENAME1_099 "X" +#define PLUGIN_VALUENAME2_099 "Y" +#define PLUGIN_VALUENAME3_099 "Z" + +#include "_Plugin_Helper.h" +#include "src/PluginStructs/P099_data_struct.h" + + +boolean Plugin_099(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_099; + Device[deviceCount].Type = DEVICE_TYPE_SPI; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + Device[deviceCount].ValueCount = 3; + success = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_099); + success = true; + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_099)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_099)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_099)); + success = true; + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: + { + event->String1 = formatGpioName_output(F("TS CS")); + break; + } + + case PLUGIN_SET_DEFAULTS: + { + // if already configured take it from settings, else use default values + if (P099_CONFIG_STATE != 1) { + P099_CONFIG_CS_PIN = P099_TS_CS; + P099_CONFIG_TRESHOLD = P099_TS_TRESHOLD; + P099_CONFIG_ROTATION = P099_TS_ROTATION; + P099_CONFIG_X_RES = P099_TS_X_RES; + P099_CONFIG_Y_RES = P099_TS_Y_RES; + P099_CONFIG_OBJECTCOUNT = P099_INIT_OBJECTCOUNT; + P099_CONFIG_DEBOUNCE_MS = P099_DEBOUNCE_MILLIS; + + constexpr uint32_t lSettings = 0 + + (P099_TS_SEND_XY ? (1 << P099_FLAGS_SEND_XY) : 0) + + (P099_TS_SEND_Z ? (1 << P099_FLAGS_SEND_Z) : 0) + + (P099_TS_SEND_OBJECTNAME ? (1 << P099_FLAGS_SEND_OBJECTNAME) : 0) + + (P099_TS_USE_CALIBRATION ? (1 << P099_FLAGS_USE_CALIBRATION) : 0) + + (P099_TS_LOG_CALIBRATION ? (1 << P099_FLAGS_LOG_CALIBRATION) : 0) + + (P099_TS_ROTATION_FLIPPED ? (1 << P099_FLAGS_ROTATION_FLIPPED) : 0); + P099_CONFIG_FLAGS = lSettings; + } + success = true; + break; + } + case PLUGIN_WEBFORM_LOAD: + { + addFormSubHeader(F("Screen")); + + uint16_t width_ = P099_CONFIG_X_RES; + + if (width_ == 0) { + width_ = P099_TS_X_RES; // default value + } + addFormNumericBox(F("Screen Width (px) (x)"), F("pwidth"), width_, 1, 65535); + + uint16_t height_ = P099_CONFIG_Y_RES; + + if (height_ == 0) { + height_ = P099_TS_Y_RES; // default value + } + addFormNumericBox(F("Screen Height (px) (y)"), F("pheight"), height_, 1, 65535); + + { + const uint8_t choice2 = P099_CONFIG_ROTATION; + const __FlashStringHelper *options2[] = { F("Normal"), F("+90°"), F("+180°"), F("+270°") }; // Avoid unicode + const int optionValues2[] = { 0, 1, 2, 3 }; // Rotation similar to the + // TFT ILI9341 rotation + constexpr size_t optionCount = NR_ELEMENTS(optionValues2); + addFormSelector(F("Rotation"), F("protate"), optionCount, options2, optionValues2, choice2); + } + + const bool bRotationFlipped = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_ROTATION_FLIPPED); + addFormCheckBox(F("Flip rotation 180°"), F("protation_flipped"), bRotationFlipped); + addFormNote(F("Some touchscreens are mounted 180° rotated on the display.")); + + addFormSubHeader(F("Touch configuration")); + + addFormNumericBox(F("Touch minimum pressure"), F("ptreshold"), P099_CONFIG_TRESHOLD, 0, 255); + + uint8_t choice3 = 0; + bitWrite(choice3, P099_FLAGS_SEND_XY, bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_XY)); + bitWrite(choice3, P099_FLAGS_SEND_Z, bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_Z)); + bitWrite(choice3, P099_FLAGS_SEND_OBJECTNAME, bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_OBJECTNAME)); + { + const __FlashStringHelper *options3[] = + { F("None"), + F("X and Y"), + F("X, Y and Z"), + F("Objectnames only"), + F("Objectnames, X and Y"), + F("Objectnames, X, Y and Z") }; + const int optionValues3[] = { 0, 1, 3, 4, 5, 7 }; // Already used as a bitmap! + constexpr size_t optionCount = NR_ELEMENTS(optionValues3); + addFormSelector(F("Events"), F("pevents"), optionCount, options3, optionValues3, choice3); + } + + if (!Settings.UseRules) { + addFormNote(F("Tools / Advanced / Rules must be enabled for events to be fired.")); + } + + { + P099_data_struct *P099_data = new (std::nothrow) P099_data_struct(); + + if (nullptr == P099_data) { + return success; + } + P099_data->loadTouchObjects(event->TaskIndex); + + addFormSubHeader(F("Calibration")); + + const bool tbUseCalibration = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_USE_CALIBRATION); + addFormSelector_YesNo(F("Calibrate to screen resolution"), F("puse_calibration"), tbUseCalibration ? 1 : 0, true); + + if (tbUseCalibration) { + addRowLabel(F("Calibration")); + html_table(EMPTY_STRING, false); // Sub-table + html_table_header(F(""), 100); + html_table_header(F("x"), 70); + html_table_header(F("y"), 70); + html_table_header(F(""), 100); + html_table_header(F("x"), 70); + html_table_header(F("y"), 70); + + html_TR_TD(); + addHtml(F("Top-left")); + html_TD(); + addNumericBox(F("pcal_tl_x"), P099_data->StoredSettings.Calibration.top_left.x, 0, 65535); + html_TD(); + addNumericBox(F("pcal_tl_y"), P099_data->StoredSettings.Calibration.top_left.y, 0, 65535); + html_TD(); + addHtml(F("Bottom-right")); + html_TD(); + addNumericBox(F("pcal_br_x"), P099_data->StoredSettings.Calibration.bottom_right.x, 0, 65535); + html_TD(); + addNumericBox(F("pcal_br_y"), P099_data->StoredSettings.Calibration.bottom_right.y, 0, 65535); + + html_end_table(); + addFormNote(F("All x/y values must be <> 0 to enable calibration.")); + } + const bool bEnableCalibrationLog = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_LOG_CALIBRATION); + addFormCheckBox(F("Enable logging for calibration"), F("plog_calibration"), bEnableCalibrationLog); + + addFormSubHeader(F("Touch objects")); + + { + if (P099_CONFIG_OBJECTCOUNT > P099_MaxObjectCount) { P099_CONFIG_OBJECTCOUNT = P099_MaxObjectCount; } + uint8_t choice5 = P099_CONFIG_OBJECTCOUNT; + + if (choice5 == 0) { // Uninitialized, so use default + choice5 = P099_CONFIG_OBJECTCOUNT = P099_INIT_OBJECTCOUNT; + } + { + const __FlashStringHelper *options5[] = { F("None"), F("8"), F("16"), F("24"), F("32"), F("40") }; + const int optionValues5[] = { -1, 8, 16, 24, 32, 40 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues5); + addFormSelector(F("# of objects"), F("pobjectcount"), optionCount, options5, optionValues5, choice5, true); + } + } + + if (P099_CONFIG_OBJECTCOUNT > -1) { + addRowLabel(F("Object")); + html_table(EMPTY_STRING, false); // Sub-table + html_table_header(F(" # "), 30); + html_table_header(F("Objectname"), 200); + html_table_header(F("Top-left x"), 120); + html_table_header(F("Top-left y"), 120); + html_table_header(F("Bottom-right x"), 150); + html_table_header(F("Bottom-right y"), 150); + html_table_header(F("On/Off button"), 150); + html_table_header(F("Inverted"), 120); + + for (int objectNr = 0; objectNr < P099_CONFIG_OBJECTCOUNT; ++objectNr) { + html_TR_TD(); + addHtml(F(" ")); + addHtmlInt(objectNr + 1); + html_TD(); + addTextBox(getPluginCustomArgName(objectNr), + String(P099_data->StoredSettings.TouchObjects[objectNr].objectname), + P099_MaxObjectNameLength - 1, + false, false, EMPTY_STRING, F("")); + html_TD(); + addNumericBox(getPluginCustomArgName(objectNr + 100), P099_data->StoredSettings.TouchObjects[objectNr].top_left.x, 0, 65535); + html_TD(); + addNumericBox(getPluginCustomArgName(objectNr + 200), P099_data->StoredSettings.TouchObjects[objectNr].top_left.y, 0, 65535); + html_TD(); + addNumericBox(getPluginCustomArgName(objectNr + 300), P099_data->StoredSettings.TouchObjects[objectNr].bottom_right.x, 0, 65535); + html_TD(); + addNumericBox(getPluginCustomArgName(objectNr + 400), P099_data->StoredSettings.TouchObjects[objectNr].bottom_right.y, 0, 65535); + html_TD(); + addCheckBox(getPluginCustomArgName(objectNr + 500), + bitRead(P099_data->StoredSettings.TouchObjects[objectNr].flags, P099_FLAGS_ON_OFF_BUTTON), false); + html_TD(); + addCheckBox(getPluginCustomArgName(objectNr + 600), + bitRead(P099_data->StoredSettings.TouchObjects[objectNr].flags, P099_FLAGS_INVERT_BUTTON), false); + } + html_end_table(); + addFormNote(F("Start objectname with '_' to ignore/disable the object (temporarily).")); + + const uint8_t debounce = P099_CONFIG_DEBOUNCE_MS; + addFormNumericBox(F("Debounce delay for On/Off buttons"), F("pdebounce"), debounce, 0, 255); + addUnit(F("0-255 msec.")); + } + delete P099_data; + } + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + P099_CONFIG_STATE = 1; // mark config as already saved (next time, will not use default values) + P099_CONFIG_TRESHOLD = getFormItemInt(F("ptreshold")); + P099_CONFIG_ROTATION = getFormItemInt(F("protate")); + P099_CONFIG_X_RES = getFormItemInt(F("pwidth")); + P099_CONFIG_Y_RES = getFormItemInt(F("pheight")); + P099_CONFIG_OBJECTCOUNT = getFormItemInt(F("pobjectcount")); + + if (P099_CONFIG_OBJECTCOUNT > P099_MaxObjectCount) { P099_CONFIG_OBJECTCOUNT = P099_MaxObjectCount; } + + uint32_t lSettings = 0; + bitWrite(lSettings, P099_FLAGS_SEND_XY, bitRead(getFormItemInt(F("pevents")), P099_FLAGS_SEND_XY)); + bitWrite(lSettings, P099_FLAGS_SEND_Z, bitRead(getFormItemInt(F("pevents")), P099_FLAGS_SEND_Z)); + bitWrite(lSettings, P099_FLAGS_SEND_OBJECTNAME, bitRead(getFormItemInt(F("pevents")), P099_FLAGS_SEND_OBJECTNAME)); + bitWrite(lSettings, P099_FLAGS_USE_CALIBRATION, getFormItemInt(F("puse_calibration")) == 1); + bitWrite(lSettings, P099_FLAGS_LOG_CALIBRATION, isFormItemChecked(F("plog_calibration"))); + bitWrite(lSettings, P099_FLAGS_ROTATION_FLIPPED, isFormItemChecked(F("protation_flipped"))); + P099_CONFIG_FLAGS = lSettings; + + P099_data_struct *P099_data = new (std::nothrow) P099_data_struct(); + + if (nullptr == P099_data) { + return success; // Save other settings even though this didn't initialize properly + } + P099_data->StoredSettings.Calibration.top_left.x = getFormItemInt(F("pcal_tl_x")); + P099_data->StoredSettings.Calibration.top_left.y = getFormItemInt(F("pcal_tl_y")); + P099_data->StoredSettings.Calibration.bottom_right.x = getFormItemInt(F("pcal_br_x")); + P099_data->StoredSettings.Calibration.bottom_right.y = getFormItemInt(F("pcal_br_y")); + + String error; + + for (int objectNr = 0; objectNr < P099_CONFIG_OBJECTCOUNT; objectNr++) { + if (!safe_strncpy(P099_data->StoredSettings.TouchObjects[objectNr].objectname, webArg(getPluginCustomArgName(objectNr)), + P099_MaxObjectNameLength)) { + error += getCustomTaskSettingsError(objectNr); + } + P099_data->StoredSettings.TouchObjects[objectNr] + .objectname[P099_MaxObjectNameLength - 1] = 0; // Terminate in case of uninitalized data + + if (!ExtraTaskSettings.checkInvalidCharInNames( + &P099_data->StoredSettings.TouchObjects[objectNr].objectname[0])) { // Check for invalid characters in objectname + error += strformat(F("Invalid character in objectname #%d. " + "Do not use ',-+/*=^%!#[]{}()' or space.\n"), + objectNr + 1); + } + P099_data->StoredSettings.TouchObjects[objectNr].top_left.x = getFormItemIntCustomArgName(objectNr + 100); + P099_data->StoredSettings.TouchObjects[objectNr].top_left.y = getFormItemIntCustomArgName(objectNr + 200); + P099_data->StoredSettings.TouchObjects[objectNr].bottom_right.x = getFormItemIntCustomArgName(objectNr + 300); + P099_data->StoredSettings.TouchObjects[objectNr].bottom_right.y = getFormItemIntCustomArgName(objectNr + 400); + + uint8_t flags = 0; + bitWrite(flags, P099_FLAGS_ON_OFF_BUTTON, isFormItemChecked(getPluginCustomArgName(objectNr + 500))); + bitWrite(flags, P099_FLAGS_INVERT_BUTTON, isFormItemChecked(getPluginCustomArgName(objectNr + 600))); + P099_data->StoredSettings.TouchObjects[objectNr].flags = flags; + } + + if (P099_CONFIG_OBJECTCOUNT > 0) { + P099_CONFIG_DEBOUNCE_MS = getFormItemInt(F("pdebounce")); + } + + if (error.length() > 0) { + addHtmlError(error); + } + #ifdef PLUGIN_099_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, concat(F("P099 data save size: "), sizeof(P099_data->StoredSettings))); + } + #endif // PLUGIN_099_DEBUG + SaveCustomTaskSettings(event->TaskIndex, reinterpret_cast(&(P099_data->StoredSettings)), + sizeof(P099_data->StoredSettings)); + delete P099_data; + + success = true; + break; + } + + case PLUGIN_INIT: + { + initPluginTaskData(event->TaskIndex, new (std::nothrow) P099_data_struct()); + P099_data_struct *P099_data = static_cast(getPluginTaskData(event->TaskIndex)); + + success = (nullptr != P099_data) && P099_data->init(event->TaskIndex, + P099_CONFIG_CS_PIN, + P099_CONFIG_ROTATION, + bitRead(P099_CONFIG_FLAGS, P099_FLAGS_ROTATION_FLIPPED), + P099_CONFIG_TRESHOLD, + bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_XY), + bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_Z), + bitRead(P099_CONFIG_FLAGS, P099_FLAGS_USE_CALIBRATION), + P099_CONFIG_X_RES, + P099_CONFIG_Y_RES); + + break; + } + + case PLUGIN_EXIT: + { + success = true; + break; + } + + // case PLUGIN_READ: // Not implemented on purpose, *only* send out events/values when device is touched, and configured to send events + + case PLUGIN_WRITE: + { + P099_data_struct *P099_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P099_data) { + success = P099_data->plugin_write(event, string); + } + + break; + } + + case PLUGIN_TEN_PER_SECOND: // Should be often/fast enough, as this is user-interaction + { + P099_data_struct *P099_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P099_data) { + return success; + } + + if (P099_data->isInitialized()) { + if (P099_data->touched()) { + uint16_t x, y, rx, ry; + uint8_t z; + P099_data->readData(&x, &y, &z); + + if (!((x >= P099_TOUCH_X_INVALID) || (y >= P099_TOUCH_Y_INVALID) || (z == P099_TOUCH_Z_INVALID) || (z <= P099_CONFIG_TRESHOLD))) { + rx = x; + ry = y; + P099_data->scaleRawToCalibrated(x, y); // Map to screen coordinates if so configured + + P099_SET_VALUE_X(x); + P099_SET_VALUE_Y(y); + P099_SET_VALUE_Z(z); + + bool bEnableCalibrationLog = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_LOG_CALIBRATION); + + if (bEnableCalibrationLog && loglevelActiveFor(LOG_LEVEL_INFO)) { + // REQUIRED for calibration and setting up objects, so do not + // make this optional! + // Space before the logged values was added for readability + addLogMove(LOG_LEVEL_INFO, strformat( + F("Touch calibration rx= %u, ry= %u; z= %u, x= %u, y= %u"), + rx, + ry, + z, // Always log the z value even if not used. + x, + y)); + } + + if (Settings.UseRules) { // No events to handle if rules not + // enabled + if (bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_XY)) { // Send events for each touch + const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(event->TaskIndex); + + if (!bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_Z) && validDeviceIndex(DeviceIndex)) { // Do NOT send a Z event for each + // touch? + // FIXME TD-er: Should not change anything in the Device vector. + #ifdef ESP8266 + Device[DeviceIndex].VType = Sensor_VType::SENSOR_TYPE_DUAL; + Device[DeviceIndex].ValueCount = 2; + #else // ifdef ESP8266 + Device.getDeviceStructForEdit(DeviceIndex).VType = Sensor_VType::SENSOR_TYPE_DUAL; + Device.getDeviceStructForEdit(DeviceIndex).ValueCount = 2; + #endif // ifdef ESP8266 + } + sendData(event); // Send X/Y(/Z) event + + if (!bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_Z) && validDeviceIndex(DeviceIndex)) { // Reset device configuration + // FIXME TD-er: Should not change anything in the Device vector. + #ifdef ESP8266 + Device[DeviceIndex].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + Device[DeviceIndex].ValueCount = 3; + #else // ifdef ESP8266 + Device.getDeviceStructForEdit(DeviceIndex).VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + Device.getDeviceStructForEdit(DeviceIndex).ValueCount = 3; + #endif // ifdef ESP8266 + } + } + + if (bitRead(P099_CONFIG_FLAGS, P099_FLAGS_SEND_OBJECTNAME)) { // Send events for objectname if within reach + String selectedObjectName; + int selectedObjectIndex = -1; + + if (P099_data->isValidAndTouchedTouchObject(x, y, selectedObjectName, selectedObjectIndex, P099_CONFIG_OBJECTCOUNT)) { + if ((selectedObjectIndex > -1) && + bitRead(P099_data->StoredSettings.TouchObjects[selectedObjectIndex].flags, P099_FLAGS_ON_OFF_BUTTON)) { + if ((P099_data->TouchTimers[selectedObjectIndex] == 0) || + (P099_data->TouchTimers[selectedObjectIndex] < millis() - (2 * P099_CONFIG_DEBOUNCE_MS))) { // Not touched yet or + // too long ago + P099_data->TouchTimers[selectedObjectIndex] = millis() + P099_CONFIG_DEBOUNCE_MS; // From now wait the + // debounce time + } else { + if (P099_data->TouchTimers[selectedObjectIndex] <= millis()) { // Debouncing time + // elapsed? + P099_data->TouchStates[selectedObjectIndex] = !P099_data->TouchStates[selectedObjectIndex]; + P099_data->TouchTimers[selectedObjectIndex] = 0; + + bool eventValue = P099_data->TouchStates[selectedObjectIndex]; + + if (bitRead(P099_data->StoredSettings.TouchObjects[selectedObjectIndex].flags, P099_FLAGS_INVERT_BUTTON)) { + eventValue = !eventValue; // Act like an inverted button, 0 = On, 1 = Off + } + eventQueue.add(event->TaskIndex, selectedObjectName, eventValue); + } + } + } else { + // Matching object is found, send # event with x, y and z as %eventvalue1/2/3% + eventQueue.add( + event->TaskIndex, + selectedObjectName, + strformat(F("%u,%u,%u"), x, y, z)); + } + } + } + } + success = true; + } + } + } + break; + } + } // switch(function) + return success; +} // Plugin_099 + +#endif // USES_P099 diff --git a/src/_P100_DS2423_counter.ino b/src/_P100_DS2423_counter.ino index 03e707cb27..2d7a70e9d6 100644 --- a/src/_P100_DS2423_counter.ino +++ b/src/_P100_DS2423_counter.ino @@ -1,157 +1,152 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P100 - -// ####################################################################################################### -// #################################### Plugin 100: Counter Dallas DS2423 ############################### -// ####################################################################################################### - -// Maxim Integrated (ex Dallas) DS2423 datasheet : https://datasheets.maximintegrated.com/en/ds/DS2423.pdf - -# include "src/Helpers/Dallas1WireHelper.h" - -# define PLUGIN_100 -# define PLUGIN_ID_100 100 -# define PLUGIN_NAME_100 "Pulse Counter - DS2423" -# define PLUGIN_VALUENAME1_100 "CountDelta" - -boolean Plugin_100(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_100; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_100); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_100)); - break; - } - - case PLUGIN_GET_DEVICEGPIONAMES: - { - event->String1 = formatGpioName_bidirectional(F("1-Wire")); - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - addFormNote(F("External pull up resistor is needed, see docs!")); - - // Scan the onewire bus and fill dropdown list with devicecount on this GPIO. - int8_t Plugin_100_DallasPin = CONFIG_PIN1; - - if (validGpio(Plugin_100_DallasPin)) { - Dallas_addr_selector_webform_load(event->TaskIndex, Plugin_100_DallasPin, Plugin_100_DallasPin); - - // Counter select - const __FlashStringHelper * resultsOptions[2] = { F("A"), F("B") }; - int resultsOptionValues[2] = { 0, 1 }; - addFormSelector(F("Counter"), F("counter"), 2, resultsOptions, resultsOptionValues, PCONFIG(0)); - addFormNote(F("Counter value is incremental")); - } - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - // Counter choice - PCONFIG(0) = getFormItemInt(F("counter")); - - // 1-wire device address - Dallas_addr_selector_webform_save(event->TaskIndex, CONFIG_PIN1, CONFIG_PIN1); - - success = true; - break; - } - - case PLUGIN_WEBFORM_SHOW_CONFIG: - { - uint8_t addr[8]; - Dallas_plugin_get_addr(addr, event->TaskIndex); - string = Dallas_format_address(addr); - success = true; - break; - } - - case PLUGIN_INIT: - { - UserVar.setFloat(event->TaskIndex, 0, 0); - UserVar.setFloat(event->TaskIndex, 1, 0); - UserVar.setFloat(event->TaskIndex, 2, 0); - - if (validGpio(CONFIG_PIN1)) { - // Explicitly set the pinMode using the "slow" pinMode function - // This way we know for sure the state of any pull-up or -down resistor is known. - pinMode(CONFIG_PIN1, INPUT); - } - - success = true; - break; - } - - case PLUGIN_READ: - { - uint8_t addr[8]; - Dallas_plugin_get_addr(addr, event->TaskIndex); - - if (addr[0] != 0) { - if (validGpio(CONFIG_PIN1)) { - float value = 0.0f; - - if (Dallas_readCounter(addr, &value, CONFIG_PIN1, CONFIG_PIN1, PCONFIG(0))) - { - UserVar.setFloat(event->TaskIndex, 0, UserVar[event->BaseVarIndex + 2] != 0 - ? value - UserVar[event->BaseVarIndex + 1] - : 0); - UserVar.setFloat(event->TaskIndex, 2, 1); - UserVar.setFloat(event->TaskIndex, 1, value); - success = true; - } - else - { - UserVar.setFloat(event->TaskIndex, 0, NAN); - } - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = strformat(F("[P100]DS : Counter %c :"), PCONFIG(0) == 0 ? 'A' : 'B'); - - if (success) { - log += formatUserVarNoCheck(event, 0); - } else { - log += F("Error!"); - } - log += concat(F(" (%s)"), Dallas_format_address(addr).c_str()); - addLogMove(LOG_LEVEL_INFO, log); - } - } - } - break; - } - } - return success; -} - - -#endif // USES_P100 +#include "_Plugin_Helper.h" +#ifdef USES_P100 + +// ####################################################################################################### +// #################################### Plugin 100: Counter Dallas DS2423 ############################### +// ####################################################################################################### + +// Maxim Integrated (ex Dallas) DS2423 datasheet : https://datasheets.maximintegrated.com/en/ds/DS2423.pdf + +# include "src/Helpers/Dallas1WireHelper.h" + +# define PLUGIN_100 +# define PLUGIN_ID_100 100 +# define PLUGIN_NAME_100 "Pulse Counter - DS2423" +# define PLUGIN_VALUENAME1_100 "CountDelta" + +boolean Plugin_100(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_100; + Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 1; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_100); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_100)); + break; + } + + case PLUGIN_GET_DEVICEGPIONAMES: + { + event->String1 = formatGpioName_bidirectional(F("1-Wire")); + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + addFormNote(F("External pull up resistor is needed, see docs!")); + + // Scan the onewire bus and fill dropdown list with devicecount on this GPIO. + int8_t Plugin_100_DallasPin = CONFIG_PIN1; + + if (validGpio(Plugin_100_DallasPin)) { + Dallas_addr_selector_webform_load(event->TaskIndex, Plugin_100_DallasPin, Plugin_100_DallasPin); + + // Counter select + const __FlashStringHelper *resultsOptions[] = { F("A"), F("B") }; + constexpr size_t optionCount = NR_ELEMENTS(resultsOptions); + addFormSelector(F("Counter"), F("counter"), optionCount, resultsOptions, nullptr, PCONFIG(0)); + addFormNote(F("Counter value is incremental")); + } + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + // Counter choice + PCONFIG(0) = getFormItemInt(F("counter")); + + // 1-wire device address + Dallas_addr_selector_webform_save(event->TaskIndex, CONFIG_PIN1, CONFIG_PIN1); + + success = true; + break; + } + + case PLUGIN_WEBFORM_SHOW_CONFIG: + { + uint8_t addr[8]; + Dallas_plugin_get_addr(addr, event->TaskIndex); + string = Dallas_format_address(addr); + success = true; + break; + } + + case PLUGIN_INIT: + { + UserVar.setFloat(event->TaskIndex, 0, 0); + UserVar.setFloat(event->TaskIndex, 1, 0); + UserVar.setFloat(event->TaskIndex, 2, 0); + + if (validGpio(CONFIG_PIN1)) { + // Explicitly set the pinMode using the "slow" pinMode function + // This way we know for sure the state of any pull-up or -down resistor is known. + pinMode(CONFIG_PIN1, INPUT); + } + + success = true; + break; + } + + case PLUGIN_READ: + { + uint8_t addr[8]; + Dallas_plugin_get_addr(addr, event->TaskIndex); + + if (addr[0] != 0) { + if (validGpio(CONFIG_PIN1)) { + float value = 0.0f; + + if (Dallas_readCounter(addr, &value, CONFIG_PIN1, CONFIG_PIN1, PCONFIG(0))) + { + UserVar.setFloat(event->TaskIndex, 0, UserVar[event->BaseVarIndex + 2] != 0 + ? value - UserVar[event->BaseVarIndex + 1] + : 0); + UserVar.setFloat(event->TaskIndex, 2, 1); + UserVar.setFloat(event->TaskIndex, 1, value); + success = true; + } + else + { + UserVar.setFloat(event->TaskIndex, 0, NAN); + } + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = strformat(F("[P100]DS : Counter %c :"), PCONFIG(0) == 0 ? 'A' : 'B'); + + if (success) { + log += formatUserVarNoCheck(event, 0); + } else { + log += F("Error!"); + } + log += strformat(F(" (%s)"), Dallas_format_address(addr).c_str()); + addLogMove(LOG_LEVEL_INFO, log); + } + } + } + break; + } + } + return success; +} + +#endif // USES_P100 diff --git a/src/_P101_WakeOnLan.ino b/src/_P101_WakeOnLan.ino index 6fb8ea5f50..592f712158 100644 --- a/src/_P101_WakeOnLan.ino +++ b/src/_P101_WakeOnLan.ino @@ -113,16 +113,9 @@ boolean Plugin_101(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_101; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; + Device[++deviceCount].Number = PLUGIN_ID_101; + Device[deviceCount].Type = DEVICE_TYPE_DUMMY; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; break; } @@ -167,7 +160,7 @@ boolean Plugin_101(uint8_t function, struct EventStruct *event, String& string) String errorStr; // Check Task Name. - uint8_t nameCode = safeName(event->TaskIndex); + const uint8_t nameCode = safeName(event->TaskIndex); if ((nameCode == NAME_MISSING) || (nameCode == NAME_UNSAFE)) { // Check to see if user submitted safe device name. strcpy(ExtraTaskSettings.TaskDeviceName, PSTR(DEF_TASK_NAME_P101)); // Use default name. @@ -237,7 +230,7 @@ boolean Plugin_101(uint8_t function, struct EventStruct *event, String& string) } case PLUGIN_READ: { - success = false; + // Do nothing on purpose break; } @@ -362,11 +355,13 @@ bool validateIp(const String& ipStr) { if ((length < IP_MIN_SIZE_P101) || (length > IP_ADDR_SIZE_P101)) { return false; } - else if (ip.fromString(ipStr) == false) { // ThomasTech's Trick to Check IP for valid formatting. - return false; - } - return true; + // else if (ip.fromString(ipStr) == false) { // ThomasTech's Trick to Check IP for valid formatting. + // return false; + // } + + // return true; + return ip.fromString(ipStr); // Trick is nice, code not so readable :-) } // ************************************************************************************************ @@ -405,19 +400,9 @@ bool validateMac(const String& macStr) { // Arg: Port Number String (decimal). // Return true if Port string appears legit. bool validatePort(const String& portStr) { - bool pass = true; - long portNumber; - - portNumber = portStr.toInt(); - - if ((portNumber < 0) || (portNumber > PORT_MAX_P101)) { - pass = false; - } - else if (!isDigit(portStr.charAt(0))) { - pass = false; - } + uint32_t portNumber{}; - return pass; + return validUIntFromString(portStr, portNumber) && portNumber <= PORT_MAX_P101; } // ************************************************************************************************ diff --git a/src/_P102_PZEM004Tv3.ino b/src/_P102_PZEM004Tv3.ino index 726d19dd88..e8f42741a5 100644 --- a/src/_P102_PZEM004Tv3.ino +++ b/src/_P102_PZEM004Tv3.ino @@ -58,18 +58,14 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_102; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = false; + Device[++deviceCount].Number = PLUGIN_ID_102; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; break; } @@ -147,21 +143,24 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even if (P102_PZEM_FIRST == event->TaskIndex) // If first PZEM, serial config available { addHtml(F("
This PZEM is the first. Its configuration of serial Pins will affect next PZEM. ")); - addHtml(F( - "
If several PZEMs foreseen, don't use HW serial (or invert Tx and Rx to configure as SW serial).
")); + addHtml(F("
If several PZEMs foreseen, " + "don't use HW serial (or invert Tx and Rx to configure as SW serial).
")); addFormSubHeader(F("PZEM actions")); { - const __FlashStringHelper *options_model[3] = { F("Read_value"), F("Reset_Energy"), F("Program_adress") }; - addFormSelector(F("PZEM Mode"), F("PZEM_mode"), 3, options_model, nullptr, P102_PZEM_mode); + const __FlashStringHelper *options_model[] = { F("Read_value"), F("Reset_Energy"), F("Program_adress") }; + constexpr size_t optionCount = NR_ELEMENTS(options_model); + addFormSelector(F("PZEM Mode"), F("PZEM_mode"), optionCount, options_model, nullptr, P102_PZEM_mode); } if (P102_PZEM_mode == 2) { - addHtml(F( - "
When programming an address, only one PZEMv30 must be connected. Otherwise, all connected PZEMv30s will get the same address, which would cause a conflict during reading.
")); + addHtml(F("
When programming an address, only one PZEMv30 must be connected. " + "Otherwise, all connected PZEMv30s will get the same address, which would cause a conflict during reading.
")); { - const __FlashStringHelper *options_confirm[2] = { F("NO"), F("YES") }; - addFormSelector(F("Confirm address programming ?"), F("PZEM_addr_set"), 2, options_confirm, nullptr, P102_PZEM_ADDR_SET); + const __FlashStringHelper *options_confirm[] = { F("NO"), F("YES") }; + constexpr size_t optionCount = NR_ELEMENTS(options_confirm); + addFormSelector(F("Confirm address programming ?"), F("PZEM_addr_set"), optionCount, options_confirm, nullptr, + P102_PZEM_ADDR_SET); } addFormNumericBox(F("Address of PZEM"), F("PZEM_addr"), (P102_PZEM_ADDR < 1) ? 1 : P102_PZEM_ADDR, 1, 247); addHtml(F("Select the address to set PZEM. Programming address 0 is forbidden.")); @@ -182,8 +181,9 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even { addFormSubHeader(F("PZEM actions")); { - const __FlashStringHelper *options_model[2] = { F("Read_value"), F("Reset_Energy") }; - addFormSelector(F("PZEM Mode"), F("PZEM_mode"), 2, options_model, nullptr, P102_PZEM_mode); + const __FlashStringHelper *options_model[] = { F("Read_value"), F("Reset_Energy") }; + constexpr size_t optionCount = NR_ELEMENTS(options_model); + addFormSelector(F("PZEM Mode"), F("PZEM_mode"), optionCount, options_model, nullptr, P102_PZEM_mode); } addHtml(F(" Tx/Rx Pins config disabled: Configuration is available in the first PZEM plugin.
")); addFormNumericBox(F("Address of PZEM"), F("PZEM_addr"), P102_PZEM_ADDR, 1, 247); @@ -223,8 +223,8 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even // FIXME TD-er: This will fail if the set to be first taskindex is no longer enabled if (P102_PZEM_FIRST == event->TaskIndex) // If first PZEM, serial config available { - int rxPin = CONFIG_PIN1; - int txPin = CONFIG_PIN2; + const int rxPin = CONFIG_PIN1; + const int txPin = CONFIG_PIN2; const ESPEasySerialPort port = static_cast(CONFIG_PORT); if (P102_PZEM_sensor != nullptr) { @@ -349,7 +349,7 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even { if (Plugin_102_init) { - String command = parseString(string, 1); + const String command = parseString(string, 1); if ((equals(command, F("resetenergy"))) && (P102_PZEM_FIRST == event->TaskIndex)) { diff --git a/src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino b/src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino index bda8579e01..c7bb9a2645 100644 --- a/src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino +++ b/src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino @@ -51,14 +51,14 @@ boolean Plugin_103(uint8_t function, struct EventStruct *event, String& string) { boolean success = false; - AtlasEZO_Sensors_e board_type = AtlasEZO_Sensors_e::UNKNOWN; - const uint8_t i2cAddressValues[] = { 0x63, 0x62, 0x64, 0x61, 0x6F - # if P103_USE_RTD - , 0x66 - # endif // if P103_USE_RTD - # if P103_USE_FLOW - , 0x68 - # endif // if P103_USE_FLOW + AtlasEZO_Sensors_e board_type = AtlasEZO_Sensors_e::UNKNOWN; + constexpr uint8_t i2cAddressValues[] = { 0x63, 0x62, 0x64, 0x61, 0x6F, + # if P103_USE_RTD + 0x66, + # endif // if P103_USE_RTD + # if P103_USE_FLOW + 0x68, + # endif // if P103_USE_FLOW }; constexpr int i2c_nr_elements = NR_ELEMENTS(i2cAddressValues); @@ -75,7 +75,6 @@ boolean Plugin_103(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_103; Device[deviceCount].Type = DEVICE_TYPE_I2C; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; Device[deviceCount].FormulaOption = true; Device[deviceCount].ValueCount = 2; Device[deviceCount].SendDataOption = true; @@ -503,8 +502,8 @@ boolean Plugin_103(uint8_t function, struct EventStruct *event, String& string) if ((AtlasEZO_Sensors_e::PH == board_type) || (AtlasEZO_Sensors_e::EC == board_type) || (AtlasEZO_Sensors_e::DO == board_type)) { - char deviceTemperatureTemplate[40]{}; - String tmpString = webArg(F("_template")); + char deviceTemperatureTemplate[40]{}; + const String tmpString = webArg(F("_template")); safe_strncpy(deviceTemperatureTemplate, tmpString.c_str(), sizeof(deviceTemperatureTemplate) - 1); ZERO_TERMINATE(deviceTemperatureTemplate); // be sure that our string ends with a \0 @@ -585,7 +584,7 @@ boolean Plugin_103(uint8_t function, struct EventStruct *event, String& string) UserVar.setFloat(event->TaskIndex, 0, -1); if (P103_send_I2C_command(P103_I2C_ADDRESS, readCommand, boarddata)) { - String sensorString(boarddata); + const String sensorString(boarddata); addLog(LOG_LEVEL_INFO, concat(F("P103: READ result: "), sensorString)); float sensor_f{}; @@ -625,8 +624,8 @@ boolean Plugin_103(uint8_t function, struct EventStruct *event, String& string) UserVar.setFloat(event->TaskIndex, 1, -1); if (P103_send_I2C_command(P103_I2C_ADDRESS, F("Status"), boarddata)) { - String voltage(boarddata); - float volt_f{}; + const String voltage(boarddata); + float volt_f{}; string2float(voltage.substring(voltage.lastIndexOf(',') + 1), volt_f); UserVar.setFloat(event->TaskIndex, 1, volt_f); } diff --git a/src/_P104_max7219_Dotmatrix.ino b/src/_P104_max7219_Dotmatrix.ino index c5ebe15dca..3f00d0cf43 100644 --- a/src/_P104_max7219_Dotmatrix.ino +++ b/src/_P104_max7219_Dotmatrix.ino @@ -140,15 +140,6 @@ boolean Plugin_104(uint8_t function, struct EventStruct *event, String& string) Device[++deviceCount].Number = PLUGIN_ID_104; Device[deviceCount].Type = DEVICE_TYPE_SPI; Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; - Device[deviceCount].TimerOptional = false; - Device[deviceCount].GlobalSyncOption = true; Device[deviceCount].ExitTaskBeforeSave = false; break; } diff --git a/src/_P105_AHT.ino b/src/_P105_AHT.ino index b11240f814..ac05a1e233 100644 --- a/src/_P105_AHT.ino +++ b/src/_P105_AHT.ino @@ -1,224 +1,225 @@ -#include "_Plugin_Helper.h" -#ifdef USES_P105 - -// ####################################################################################################### -// ######################## Plugin 105 AHT I2C Temperature and Humidity Sensor ########################## -// ####################################################################################################### -// data sheet AHT10: https://wiki.liutyi.info/display/ARDUINO/AHT10 -// device AHT10: http://www.aosong.com/en/products-40.html -// device and manual AHT20: http://www.aosong.com/en/products-32.html -// device and manual AHT21: http://www.aosong.com/en/products-60.html - -/* AHT10/15/20 - Temperature and Humidity - * - * (Comment copied from _P248_TempHumidity_AHT1x.ino) - * - * AHT1x I2C Address: 0x38, 0x39 - * the driver supports two I2c adresses but only one Sensor allowed. - * - * ATTENTION: The AHT10/15 Sensor is incompatible with other I2C devices on I2C bus. - * - * The Datasheet write: - * "Only a single AHT10 can be connected to the I2C bus and no other I2C - * devices can be connected". - * - * after lot of search and tests, now is confirmed that works only reliable with one sensor - * on I2C Bus - */ - -/** History: - * 2024-12-03 tonhuisman: Add alternative initialization for AHT10 (clone), see https://github.com/letscontrolit/ESPEasy/issues/5172 - * Small code optimization. - * 2024-04-28 tonhuisman: Update plugin name and documentation as DHT20 and AM2301B actually contain an AHT20! - * DHT20: https://www.adafruit.com/product/5183 (Description) - * AM2301B: https://www.adafruit.com/product/5181 (Description) - * 2021-08-01 tonhuisman: Plugin migrated from ESPEsyPluginPlayground repository - * Minor adjustments, changed castings to use static_cast(var) method, - * Added check for other I2C devices configured on ESPEasy tasks to give a warning - * about I2C incompatibility, for AHT10/AHT15 device only - * 2021-03 sakinit: Initial plugin, added on ESPEasyPluginPlayground - */ - -# include "src/PluginStructs/P105_data_struct.h" - -# define PLUGIN_105 -# define PLUGIN_ID_105 105 -# define PLUGIN_NAME_105 "Environment - AHT1x/AHT2x/DHT20/AM2301B" -# define PLUGIN_VALUENAME1_105 "Temperature" -# define PLUGIN_VALUENAME2_105 "Humidity" - - -boolean Plugin_105(uint8_t function, struct EventStruct *event, String& string) -{ - boolean success = false; - - switch (function) - { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_105; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - break; - } - - case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_105); - break; - } - - case PLUGIN_GET_DEVICEVALUENAMES: - { - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_105)); - strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_105)); - break; - } - - case PLUGIN_I2C_HAS_ADDRESS: - case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: - { - const uint8_t i2cAddressValues[2] = { 0x38, 0x39 }; - - if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { - addFormSelectorI2C(F("i2c_addr"), 2, i2cAddressValues, PCONFIG(0)); - addFormNote(F("SDO Low=0x38, High=0x39. NB: Only available on AHT1x sensors.")); - } else { - success = intArrayContains(2, i2cAddressValues, event->Par1); - } - - break; - } - - # if FEATURE_I2C_GET_ADDRESS - case PLUGIN_I2C_GET_ADDRESS: - { - event->Par1 = PCONFIG(0); - success = true; - break; - } - # endif // if FEATURE_I2C_GET_ADDRESS - - case PLUGIN_SET_DEFAULTS: - { - PCONFIG(1) = static_cast(AHTx_device_type::AHT20_DEVICE); - break; - } - - case PLUGIN_WEBFORM_LOAD: - { - if (static_cast(PCONFIG(1)) == AHTx_device_type::AHT10_DEVICE) { - bool hasOtherI2CDevices = false; - - for (taskIndex_t x = 0; validTaskIndex(x) && !hasOtherI2CDevices; ++x) { - const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(x); - - if (validDeviceIndex(DeviceIndex) - && (Settings.TaskDeviceDataFeed[x] == 0) - && ((Device[DeviceIndex].Type == DEVICE_TYPE_I2C) - # ifdef PLUGIN_USES_SERIAL // Has I2C Serial option - || (Device[DeviceIndex].Type == DEVICE_TYPE_SERIAL) - || (Device[DeviceIndex].Type == DEVICE_TYPE_SERIAL_PLUS1) - # endif // ifdef PLUGIN_USES_SERIAL - ) - ) { - hasOtherI2CDevices = true; - } - } - - if (hasOtherI2CDevices) { - addRowLabel(EMPTY_STRING, EMPTY_STRING); - addHtmlDiv(F("note warning"), - F("Attention: Sensor model AHT1x may cause I2C issues when combined with other I2C devices on the same bus!")); - } - } - { - const __FlashStringHelper *options[] = { F("AHT1x"), F("AHT20"), F("AHT21") }; - const int indices[] = { static_cast(AHTx_device_type::AHT10_DEVICE), - static_cast(AHTx_device_type::AHT20_DEVICE), - static_cast(AHTx_device_type::AHT21_DEVICE) }; - addFormSelector(F("Sensor model"), F("ahttype"), 3, options, indices, PCONFIG(1), true); - addFormNote(F("Changing Sensor model will reload the page.")); - - if (static_cast(AHTx_device_type::AHT10_DEVICE) == PCONFIG(1)) { - addFormCheckBox(F("AHT10 Alternative initialization"), F("altinit"), PCONFIG(2)); - } - } - - success = true; - break; - } - - case PLUGIN_WEBFORM_SAVE: - { - PCONFIG(1) = getFormItemInt(F("ahttype")); - - if (static_cast(PCONFIG(1)) != AHTx_device_type::AHT10_DEVICE) { - PCONFIG(0) = 0x38; // AHT20/AHT21 only support a single I2C address. - } else { - PCONFIG(0) = getFormItemInt(F("i2c_addr")); - PCONFIG(2) = isFormItemChecked(F("altinit")) ? 1 : 0; - } - success = true; - break; - } - - case PLUGIN_INIT: - { - success = initPluginTaskData( - event->TaskIndex, - new (std::nothrow) P105_data_struct(PCONFIG(0), static_cast(PCONFIG(1)), 1 == PCONFIG(2))); - break; - } - - case PLUGIN_ONCE_A_SECOND: - { - P105_data_struct *P105_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P105_data) { - if (P105_data->updateMeasurements(event->TaskIndex)) { - // Update was succesfull, schedule a read. - Scheduler.schedule_task_device_timer(event->TaskIndex, millis() + 10); - } - } - break; - } - - case PLUGIN_READ: - { - P105_data_struct *P105_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P105_data) { - if (P105_data->state != AHTx_state::AHTx_New_values) { - break; - } - P105_data->state = AHTx_state::AHTx_Values_read; - - UserVar.setFloat(event->TaskIndex, 0, P105_data->getTemperature()); - UserVar.setFloat(event->TaskIndex, 1, P105_data->getHumidity()); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, strformat(F("%s : Addr: 0x%02x"), P105_data->getDeviceName().c_str(), PCONFIG(0))); - addLogMove(LOG_LEVEL_INFO, - strformat(F("%s : Temperature: %s : Humidity: %s"), - P105_data->getDeviceName().c_str(), - formatUserVarNoCheck(event, 0).c_str(), - formatUserVarNoCheck(event, 1).c_str())); - } - success = true; - } - break; - } - } - return success; -} - -#endif // USES_P105 +#include "_Plugin_Helper.h" +#ifdef USES_P105 + +// ####################################################################################################### +// ######################## Plugin 105 AHT I2C Temperature and Humidity Sensor ########################## +// ####################################################################################################### +// data sheet AHT10: https://wiki.liutyi.info/display/ARDUINO/AHT10 +// device AHT10: http://www.aosong.com/en/products-40.html +// device and manual AHT20: http://www.aosong.com/en/products-32.html +// device and manual AHT21: http://www.aosong.com/en/products-60.html + +/* AHT10/15/20 - Temperature and Humidity + * + * (Comment copied from _P248_TempHumidity_AHT1x.ino) + * + * AHT1x I2C Address: 0x38, 0x39 + * the driver supports two I2c adresses but only one Sensor allowed. + * + * ATTENTION: The AHT10/15 Sensor is incompatible with other I2C devices on I2C bus. + * + * The Datasheet write: + * "Only a single AHT10 can be connected to the I2C bus and no other I2C + * devices can be connected". + * + * after lot of search and tests, now is confirmed that works only reliable with one sensor + * on I2C Bus + */ + +/** History: + * 2024-12-03 tonhuisman: Add alternative initialization for AHT10 (clone), see https://github.com/letscontrolit/ESPEasy/issues/5172 + * Small code optimization. + * 2024-04-28 tonhuisman: Update plugin name and documentation as DHT20 and AM2301B actually contain an AHT20! + * DHT20: https://www.adafruit.com/product/5183 (Description) + * AM2301B: https://www.adafruit.com/product/5181 (Description) + * 2021-08-01 tonhuisman: Plugin migrated from ESPEsyPluginPlayground repository + * Minor adjustments, changed castings to use static_cast(var) method, + * Added check for other I2C devices configured on ESPEasy tasks to give a warning + * about I2C incompatibility, for AHT10/AHT15 device only + * 2021-03 sakinit: Initial plugin, added on ESPEasyPluginPlayground + */ + +# include "src/PluginStructs/P105_data_struct.h" + +# define PLUGIN_105 +# define PLUGIN_ID_105 105 +# define PLUGIN_NAME_105 "Environment - AHT1x/AHT2x/DHT20/AM2301B" +# define PLUGIN_VALUENAME1_105 "Temperature" +# define PLUGIN_VALUENAME2_105 "Humidity" + + +boolean Plugin_105(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + Device[++deviceCount].Number = PLUGIN_ID_105; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_105); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_105)); + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_105)); + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: + { + const uint8_t i2cAddressValues[] = { 0x38, 0x39 }; + + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { + addFormSelectorI2C(F("i2c_addr"), 2, i2cAddressValues, PCONFIG(0)); + addFormNote(F("SDO Low=0x38, High=0x39. NB: Only available on AHT1x sensors.")); + } else { + success = intArrayContains(2, i2cAddressValues, event->Par1); + } + + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = PCONFIG(0); + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_SET_DEFAULTS: + { + PCONFIG(1) = static_cast(AHTx_device_type::AHT20_DEVICE); + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + if (static_cast(PCONFIG(1)) == AHTx_device_type::AHT10_DEVICE) { + bool hasOtherI2CDevices = false; + + for (taskIndex_t x = 0; validTaskIndex(x) && !hasOtherI2CDevices; ++x) { + const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(x); + + if (validDeviceIndex(DeviceIndex) + && (Settings.TaskDeviceDataFeed[x] == 0) + && ((Device[DeviceIndex].Type == DEVICE_TYPE_I2C) + # ifdef PLUGIN_USES_SERIAL // Has I2C Serial option + || (Device[DeviceIndex].Type == DEVICE_TYPE_SERIAL) + || (Device[DeviceIndex].Type == DEVICE_TYPE_SERIAL_PLUS1) + # endif // ifdef PLUGIN_USES_SERIAL + ) + ) { + hasOtherI2CDevices = true; + break; + } + } + + if (hasOtherI2CDevices) { + addRowLabel(EMPTY_STRING, EMPTY_STRING); + addHtmlDiv(F("note warning"), + F("Attention: Sensor model AHT1x may cause I2C issues when combined with other I2C devices on the same bus!")); + } + } + { + const __FlashStringHelper *options[] = { F("AHT1x"), F("AHT20"), F("AHT21") }; + const int indices[] = { static_cast(AHTx_device_type::AHT10_DEVICE), + static_cast(AHTx_device_type::AHT20_DEVICE), + static_cast(AHTx_device_type::AHT21_DEVICE) }; + constexpr size_t optionCount = NR_ELEMENTS(indices); + addFormSelector(F("Sensor model"), F("ahttype"), optionCount, options, indices, PCONFIG(1), true); + addFormNote(F("Changing Sensor model will reload the page.")); + + if (static_cast(AHTx_device_type::AHT10_DEVICE) == PCONFIG(1)) { + addFormCheckBox(F("AHT10 Alternative initialization"), F("altinit"), PCONFIG(2)); + } + } + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + PCONFIG(1) = getFormItemInt(F("ahttype")); + + if (static_cast(PCONFIG(1)) != AHTx_device_type::AHT10_DEVICE) { + PCONFIG(0) = 0x38; // AHT20/AHT21 only support a single I2C address. + } else { + PCONFIG(0) = getFormItemInt(F("i2c_addr")); + PCONFIG(2) = isFormItemChecked(F("altinit")) ? 1 : 0; + } + success = true; + break; + } + + case PLUGIN_INIT: + { + success = initPluginTaskData( + event->TaskIndex, + new (std::nothrow) P105_data_struct(PCONFIG(0), static_cast(PCONFIG(1)), 1 == PCONFIG(2))); + break; + } + + case PLUGIN_ONCE_A_SECOND: + { + P105_data_struct *P105_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P105_data) { + if (P105_data->updateMeasurements(event->TaskIndex)) { + // Update was succesfull, schedule a read. + Scheduler.schedule_task_device_timer(event->TaskIndex, millis() + 10); + } + } + break; + } + + case PLUGIN_READ: + { + P105_data_struct *P105_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P105_data) { + if (P105_data->state != AHTx_state::AHTx_New_values) { + break; + } + P105_data->state = AHTx_state::AHTx_Values_read; + + UserVar.setFloat(event->TaskIndex, 0, P105_data->getTemperature()); + UserVar.setFloat(event->TaskIndex, 1, P105_data->getHumidity()); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, strformat(F("%s : Addr: 0x%02x"), P105_data->getDeviceName().c_str(), PCONFIG(0))); + addLogMove(LOG_LEVEL_INFO, + strformat(F("%s : Temperature: %s : Humidity: %s"), + P105_data->getDeviceName().c_str(), + formatUserVarNoCheck(event, 0).c_str(), + formatUserVarNoCheck(event, 1).c_str())); + } + success = true; + } + break; + } + } + return success; +} + +#endif // USES_P105 diff --git a/src/_P106_BME680.ino b/src/_P106_BME680.ino index 66836f659a..f3c6f80d54 100644 --- a/src/_P106_BME680.ino +++ b/src/_P106_BME680.ino @@ -44,18 +44,14 @@ boolean Plugin_106(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_106; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_106; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } diff --git a/src/_P107_SI1145.ino b/src/_P107_SI1145.ino index 0f74814111..a7ed587950 100644 --- a/src/_P107_SI1145.ino +++ b/src/_P107_SI1145.ino @@ -22,18 +22,14 @@ boolean Plugin_107(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_107; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_107; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 3; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; break; } diff --git a/src/_P108_DDS238.ino b/src/_P108_DDS238.ino index e2209716eb..bcda9fb34e 100644 --- a/src/_P108_DDS238.ino +++ b/src/_P108_DDS238.ino @@ -37,19 +37,16 @@ boolean Plugin_108(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_108; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = P108_NR_OUTPUT_VALUES; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_108; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = P108_NR_OUTPUT_VALUES; + Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].PluginStats = true; + Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); break; } @@ -62,7 +59,7 @@ boolean Plugin_108(uint8_t function, struct EventStruct *event, String& string) for (uint8_t i = 0; i < VARS_PER_TASK; ++i) { if (i < P108_NR_OUTPUT_VALUES) { const uint8_t pconfigIndex = i + P108_QUERY1_CONFIG_POS; - uint8_t choice = PCONFIG(pconfigIndex); + const uint8_t choice = PCONFIG(pconfigIndex); ExtraTaskSettings.setTaskDeviceValueName(i, Plugin_108_valuename(choice, false)); } else { ExtraTaskSettings.clearTaskDeviceValueName(i); diff --git a/src/_P109_ThermOLED.ino b/src/_P109_ThermOLED.ino index 7951064887..afaa57668f 100644 --- a/src/_P109_ThermOLED.ino +++ b/src/_P109_ThermOLED.ino @@ -85,15 +85,13 @@ boolean Plugin_109(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_109; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; + Device[++deviceCount].Number = PLUGIN_ID_109; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 4; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; break; } @@ -138,16 +136,16 @@ boolean Plugin_109(uint8_t function, struct EventStruct *event, String& string) # ifndef LIMIT_BUILD_SIZE case PLUGIN_WEBFORM_SHOW_GPIO_DESCR: { - const char* separator = event->String1.c_str(); + const char*separator = event->String1.c_str(); string = strformat( F("Btn L: %s%sBtn R: %s%sBtn M: %s%sRelay: %s"), - formatGpioLabel(CONFIG_PIN1, false).c_str(), - separator, - formatGpioLabel(CONFIG_PIN2, false).c_str(), - separator, - formatGpioLabel(CONFIG_PIN3, false).c_str(), - separator, - formatGpioLabel(P109_CONFIG_RELAYPIN, false).c_str()); + formatGpioLabel(CONFIG_PIN1, false).c_str(), + separator, + formatGpioLabel(CONFIG_PIN2, false).c_str(), + separator, + formatGpioLabel(CONFIG_PIN3, false).c_str(), + separator, + formatGpioLabel(P109_CONFIG_RELAYPIN, false).c_str()); success = true; break; } @@ -181,7 +179,8 @@ boolean Plugin_109(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *options4[] = { F("0.2"), F("0.5"), F("1") }; const int optionValues4[] = { 2, 5, 10 }; - addFormSelector(F("Hysteresis"), F("hyst"), 3, options4, optionValues4, static_cast(P109_CONFIG_HYSTERESIS * 10.0f)); + constexpr size_t optionCount = NR_ELEMENTS(optionValues4); + addFormSelector(F("Hysteresis"), F("hyst"), optionCount, options4, optionValues4, static_cast(P109_CONFIG_HYSTERESIS * 10.0f)); } { diff --git a/src/_P110_VL53L0X.ino b/src/_P110_VL53L0X.ino index 0f45c94ac4..b3880b1b3c 100644 --- a/src/_P110_VL53L0X.ino +++ b/src/_P110_VL53L0X.ino @@ -40,19 +40,15 @@ boolean Plugin_110(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_110; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + Device[++deviceCount].Number = PLUGIN_ID_110; + Device[deviceCount].Type = DEVICE_TYPE_I2C; + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = 2; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].TimerOptional = true; + Device[deviceCount].PluginStats = true; break; } @@ -97,20 +93,21 @@ boolean Plugin_110(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { { - const __FlashStringHelper *optionsMode2[3] = { + const __FlashStringHelper *optionsMode2[] = { F("Normal"), F("Fast"), F("Accurate") }; - const int optionValuesMode2[3] = { 80, 20, 320 }; - addFormSelector(F("Timing"), F("ptiming"), 3, optionsMode2, optionValuesMode2, P110_TIMING); + const int optionValuesMode2[] = { 80, 20, 320 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); + addFormSelector(F("Timing"), F("ptiming"), optionCount, optionsMode2, optionValuesMode2, P110_TIMING); } { - const __FlashStringHelper *optionsMode3[2] = { + const __FlashStringHelper *optionsMode3[] = { F("Normal"), F("Long") }; - const int optionValuesMode3[2] = { 0, 1 }; - addFormSelector(F("Range"), F("prange"), 2, optionsMode3, optionValuesMode3, P110_RANGE); + constexpr size_t optionCount = NR_ELEMENTS(optionsMode3); + addFormSelector(F("Range"), F("prange"), optionCount, optionsMode3, nullptr, P110_RANGE); } addFormCheckBox(F("Send event when value unchanged"), F("notchanged"), P110_SEND_ALWAYS == 1); addFormNote(F("When checked, 'Trigger delta' setting is ignored!")); From b6c3fc26611b2a25ce82028deeabc1aa627372c0 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Mon, 6 Jan 2025 23:10:24 +0100 Subject: [PATCH 5/9] [Build] More code reductions in .ino files: Cleanup PLUGIN_DEVICE_ADD --- src/_P001_Switch.ino | 19 +-- src/_P002_ADC.ino | 19 +-- src/_P003_Pulse.ino | 23 +-- src/_P004_Dallas.ino | 21 +-- src/_P005_DHT.ino | 17 +- src/_P006_BMP085.ino | 17 +- src/_P007_PCF8591.ino | 19 +-- src/_P008_RFID.ino | 11 +- src/_P009_MCP.ino | 17 +- src/_P010_BH1750.ino | 17 +- src/_P011_PME.ino | 17 +- src/_P012_LCD.ino | 9 +- src/_P013_HCSR04.ino | 21 +-- src/_P014_SI70xx.ino | 21 +-- src/_P015_TSL2561.ino | 17 +- src/_P016_IR.ino | 21 +-- src/_P017_PN532.ino | 13 +- src/_P018_Dust.ino | 19 +-- src/_P019_PCF8574.ino | 17 +- src/_P020_Ser2Net.ino | 14 +- src/_P021_Level.ino | 13 +- src/_P022_PCA9685.ino | 13 +- src/_P023_OLED.ino | 11 +- src/_P024_MLX90614.ino | 21 +-- src/_P025_ADS1115.ino | 19 +-- src/_P026_Sysinfo.ino | 17 +- src/_P027_INA219.ino | 17 +- src/_P028_BME280.ino | 19 +-- src/_P029_Output.ino | 13 +- src/_P031_SHT1X.ino | 19 +-- src/_P032_MS5611.ino | 17 +- src/_P033_Dummy.ino | 21 +-- src/_P034_DHT12.ino | 15 +- src/_P035_IRTX.ino | 9 +- src/_P036_FrameOLED.ino | 11 +- src/_P037_MQTTImport.ino | 11 +- src/_P038_NeoPixel.ino | 9 +- src/_P039_Thermosensors.ino | 17 +- src/_P040_ID12.ino | 9 +- src/_P041_NeoClock.ino | 9 +- src/_P042_Candle.ino | 15 +- src/_P043_ClkOutput.ino | 15 +- src/_P044_P1WifiGateway.ino | 9 +- src/_P045_MPU6050.ino | 17 +- src/_P046_VentusW266.ino | 19 +-- src/_P047_i2c-soil-moisture-sensor.ino | 17 +- src/_P048_Motorshield_v2.ino | 9 +- src/_P049_MHZ19.ino | 19 +-- src/_P050_TCS34725.ino | 17 +- src/_P051_AM2320.ino | 19 +-- src/_P052_SenseAir.ino | 21 +-- src/_P053_PMSx003.ino | 29 ++-- src/_P054_DMX512.ino | 7 +- src/_P055_Chiming.ino | 15 +- src/_P056_SDS011-Dust.ino | 17 +- src/_P057_HT16K33_LED.ino | 7 +- src/_P058_HT16K33_KeyPad.ino | 15 +- src/_P059_Encoder.ino | 15 +- src/_P060_MCP3221.ino | 17 +- src/_P061_KeyPad.ino | 15 +- src/_P062_MPR121_KeyPad.ino | 17 +- src/_P063_TTP229_KeyPad.ino | 17 +- src/_P064_APDS9960.ino | 17 +- src/_P065_DRF0299_MP3.ino | 7 +- src/_P066_VEML6040.ino | 17 +- src/_P067_HX711_Load_Cell.ino | 19 +-- src/_P068_SHT3x.ino | 17 +- src/_P069_LM75A.ino | 17 +- src/_P070_NeoPixel_Clock.ino | 13 +- src/_P071_Kamstrup401.ino | 15 +- src/_P072_HDC1080.ino | 19 +-- src/_P073_7DGT.ino | 13 +- src/_P074_TSL2591.ino | 17 +- src/_P075_Nextion.ino | 17 +- src/_P076_HLW8012.ino | 19 +-- src/_P077_CSE7766.ino | 23 +-- src/_P078_Eastron.ino | 21 +-- src/_P079_Wemos_Motorshield.ino | 7 +- src/_P080_DallasIButton.ino | 15 +- src/_P081_Cron.ino | 16 +- src/_P082_GPS.ino | 19 +-- src/_P083_SGP30.ino | 17 +- src/_P084_VEML6070.ino | 17 +- src/_P085_AcuDC243.ino | 23 +-- src/_P086_Homie.ino | 13 +- src/_P087_SerialProxy.ino | 15 +- src/_P088_HeatpumpIR.ino | 9 +- src/_P089_Ping.ino | 15 +- src/_P090_CCS811.ino | 17 +- src/_P091_SerSwitch.ino | 15 +- src/_P092_DLbus.ino | 17 +- src/_P093_MitsubishiHP.ino | 15 +- src/_P094_CULReader.ino | 19 +-- src/_P095_ILI9341.ino | 14 +- src/_P096_eInk.ino | 15 +- src/_P097_Esp32Touch.ino | 15 +- src/_P098_PWM_motor.ino | 15 +- src/_P099_XPT2046Touch.ino | 10 +- src/_P100_DS2423_counter.ino | 15 +- src/_P101_WakeOnLan.ino | 7 +- src/_P102_PZEM004Tv3.ino | 17 +- src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino | 15 +- src/_P104_max7219_Dotmatrix.ino | 9 +- src/_P105_AHT.ino | 17 +- src/_P106_BME680.ino | 17 +- src/_P107_SI1145.ino | 17 +- src/_P108_DDS238.ino | 21 +-- src/_P109_ThermOLED.ino | 15 +- src/_P110_VL53L0X.ino | 19 +-- src/_P111_RC522_RFID.ino | 18 +-- src/_P112_AS7265x.ino | 24 ++- src/_P113_VL53L1X.ino | 20 +-- src/_P114_VEML6075.ino | 21 ++- src/_P115_MAX1704x_v2.ino | 23 ++- src/_P116_ST77xx.ino | 18 +-- src/_P117_SCD30.ino | 23 ++- src/_P118_Itho.ino | 18 +-- src/_P119_ITG3205_Gyro.ino | 20 +-- src/_P120_ADXL345_Accelerometer.ino | 22 +-- src/_P121_HMC5883L.ino | 23 ++- src/_P122_SHT2x.ino | 30 ++-- src/_P123_I2CTouch.ino | 20 +-- src/_P124_MultiRelay.ino | 20 ++- src/_P125_ADXL345_SPI.ino | 22 +-- src/_P126_74HC595.ino | 24 +-- src/_P127_CDM7160.ino | 26 ++- src/_P128_NeoPixelBusFX.ino | 22 +-- src/_P129_74HC165.ino | 22 +-- src/_P131_NeoPixelMatrix.ino | 23 +-- src/_P132_INA3221.ino | 21 ++- src/_P133_LTR390.ino | 21 ++- src/_P134_A02YYUW.ino | 19 +-- src/_P135_SCD4x.ino | 23 ++- src/_P137_AXP192.ino | 23 +-- src/_P138_IP5306.ino | 21 +-- src/_P141_PCD8544_Nokia5110.ino | 19 +-- src/_P142_AS5600.ino | 23 ++- src/_P143_I2C_Rotary.ino | 19 +-- src/_P144_Vindriktning.ino | 93 ++++++----- src/_P145_MQxxx.ino | 215 ++++++++++++++----------- src/_P146_CacheControllerReader.ino | 28 ++-- src/_P147_SGP4x.ino | 21 ++- src/_P148_POWRxxD_THR3xxD.ino | 24 ++- src/_P150_TMP117.ino | 21 ++- src/_P151_Honeywell_pressure.ino | 76 +++++---- src/_P152_DAC.ino | 29 ++-- src/_P153_SHT4x.ino | 21 ++- src/_P154_BMP3xx.ino | 21 ++- src/_P159_LD2410.ino | 24 +-- src/_P162_MCP42xxx.ino | 21 ++- src/_P163_RadSens.ino | 21 ++- src/_P164_gases_ens160.ino | 34 ++-- src/_P165_7SegNeopixel.ino | 9 +- src/_P166_GP8403.ino | 23 ++- src/_P167_Vindstyrka.ino | 27 ++-- src/_P168_VEML6030_7700.ino | 19 ++- src/_P169_AS3935_LightningDetector.ino | 23 ++- src/_P170_Waterlevel.ino | 21 ++- src/_P172_BMP3xx_SPI.ino | 21 ++- src/_P173_SHTC3.ino | 18 +-- src/_P175_PMSx003i.ino | 23 +-- src/_P176_VE_Direct.ino | 23 +-- src/_Pxxx_PluginTemplate.ino | 38 ++--- 163 files changed, 1637 insertions(+), 1610 deletions(-) diff --git a/src/_P001_Switch.ino b/src/_P001_Switch.ino index e3fdd4893a..2d16e8858c 100644 --- a/src/_P001_Switch.ino +++ b/src/_P001_Switch.ino @@ -34,15 +34,16 @@ boolean Plugin_001(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_001; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].PullUpOption = true; - Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + 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; } diff --git a/src/_P002_ADC.ino b/src/_P002_ADC.ino index e76fb7bb6a..21fa912681 100644 --- a/src/_P002_ADC.ino +++ b/src/_P002_ADC.ino @@ -23,15 +23,16 @@ boolean Plugin_002(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_002; - Device[deviceCount].Type = DEVICE_TYPE_ANALOG; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].TaskLogsOwnPeaks = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_002; + dev.Type = DEVICE_TYPE_ANALOG; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.TaskLogsOwnPeaks = true; break; } diff --git a/src/_P003_Pulse.ino b/src/_P003_Pulse.ino index b7bace50b4..dfbeeee601 100644 --- a/src/_P003_Pulse.ino +++ b/src/_P003_Pulse.ino @@ -53,17 +53,18 @@ boolean Plugin_003(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_003; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].PullUpOption = true; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = PLUGIN_NR_VALUENAMES_003; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].TaskLogsOwnPeaks = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_003; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.PullUpOption = true; + dev.FormulaOption = true; + dev.ValueCount = PLUGIN_NR_VALUENAMES_003; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; + dev.TaskLogsOwnPeaks = true; break; } diff --git a/src/_P004_Dallas.ino b/src/_P004_Dallas.ino index e1cbc8c133..01b1ce4105 100644 --- a/src/_P004_Dallas.ino +++ b/src/_P004_Dallas.ino @@ -51,16 +51,17 @@ boolean Plugin_004(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_004; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_004; + dev.Type = DEVICE_TYPE_DUAL; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.PluginStats = true; + dev.setPin2Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P005_DHT.ino b/src/_P005_DHT.ino index ecc321ec48..592fd08aa9 100644 --- a/src/_P005_DHT.ino +++ b/src/_P005_DHT.ino @@ -23,14 +23,15 @@ boolean Plugin_005(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_005; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_005; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P006_BMP085.ino b/src/_P006_BMP085.ino index 9b8e21f1e0..c44177a09a 100644 --- a/src/_P006_BMP085.ino +++ b/src/_P006_BMP085.ino @@ -23,14 +23,15 @@ boolean Plugin_006(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_006; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_006; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P007_PCF8591.ino b/src/_P007_PCF8591.ino index 31951babf1..241fb92214 100644 --- a/src/_P007_PCF8591.ino +++ b/src/_P007_PCF8591.ino @@ -36,15 +36,16 @@ boolean Plugin_007(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_007; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].I2CMax100kHz = true; // Max 100 kHz allowed/supported + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_007; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.I2CMax100kHz = true; // Max 100 kHz allowed/supported break; } diff --git a/src/_P008_RFID.ino b/src/_P008_RFID.ino index 69637b8151..12cd9ecff0 100644 --- a/src/_P008_RFID.ino +++ b/src/_P008_RFID.ino @@ -47,11 +47,12 @@ boolean Plugin_008(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_008; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_008; + dev.Type = DEVICE_TYPE_DUAL; + dev.VType = Sensor_VType::SENSOR_TYPE_ULONG; + dev.ValueCount = 1; + dev.SendDataOption = true; break; } diff --git a/src/_P009_MCP.ino b/src/_P009_MCP.ino index 4931e09869..8bbfb00785 100644 --- a/src/_P009_MCP.ino +++ b/src/_P009_MCP.ino @@ -28,14 +28,15 @@ boolean Plugin_009(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_009; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_009; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.InverseLogicOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P010_BH1750.ino b/src/_P010_BH1750.ino index b45ed9b8e7..b62be65a69 100644 --- a/src/_P010_BH1750.ino +++ b/src/_P010_BH1750.ino @@ -23,14 +23,15 @@ boolean Plugin_010(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_010; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_010; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P011_PME.ino b/src/_P011_PME.ino index 7222aadcbd..f867281c10 100644 --- a/src/_P011_PME.ino +++ b/src/_P011_PME.ino @@ -40,14 +40,15 @@ boolean Plugin_011(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_011; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].Ports = PLUGIN_011_PORTS; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_011; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.Ports = PLUGIN_011_PORTS; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P012_LCD.ino b/src/_P012_LCD.ino index 9079b5a3c0..416b83036f 100644 --- a/src/_P012_LCD.ino +++ b/src/_P012_LCD.ino @@ -45,10 +45,11 @@ boolean Plugin_012(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_012; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_012; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.TimerOption = true; break; } diff --git a/src/_P013_HCSR04.ino b/src/_P013_HCSR04.ino index 473de0b87a..1a2f15902e 100644 --- a/src/_P013_HCSR04.ino +++ b/src/_P013_HCSR04.ino @@ -47,16 +47,17 @@ boolean Plugin_013(uint8_t function, struct EventStruct *even { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_013; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_013; + dev.Type = DEVICE_TYPE_DUAL; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P014_SI70xx.ino b/src/_P014_SI70xx.ino index 588bfb24d2..20aca65c4d 100644 --- a/src/_P014_SI70xx.ino +++ b/src/_P014_SI70xx.ino @@ -44,16 +44,17 @@ boolean Plugin_014(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_014; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].I2CNoDeviceCheck = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::All; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_014; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.I2CNoDeviceCheck = true; + dev.PluginStats = true; + dev.OutputDataType = Output_Data_type_t::All; break; } diff --git a/src/_P015_TSL2561.ino b/src/_P015_TSL2561.ino index a413538432..aed807dca1 100644 --- a/src/_P015_TSL2561.ino +++ b/src/_P015_TSL2561.ino @@ -36,14 +36,15 @@ boolean Plugin_015(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_015; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_015; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index ad7a2c4c16..df10524aa7 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -199,19 +199,20 @@ boolean Plugin_016(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_016; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_016; + dev.Type = DEVICE_TYPE_SINGLE; # if P016_SEND_IR_TO_CONTROLLER - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; + dev.VType = Sensor_VType::SENSOR_TYPE_STRING; # else // if P016_SEND_IR_TO_CONTROLLER - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; + dev.VType = Sensor_VType::SENSOR_TYPE_ULONG; # endif // if P016_SEND_IR_TO_CONTROLLER - Device[deviceCount].PullUpOption = true; - Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + dev.PullUpOption = true; + dev.InverseLogicOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P017_PN532.ino b/src/_P017_PN532.ino index b9a29b1ebd..4dd48b96ea 100644 --- a/src/_P017_PN532.ino +++ b/src/_P017_PN532.ino @@ -84,12 +84,13 @@ boolean Plugin_017(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_017; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_017; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_ULONG; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P018_Dust.ino b/src/_P018_Dust.ino index 968371e0d4..44ca1c1fa1 100644 --- a/src/_P018_Dust.ino +++ b/src/_P018_Dust.ino @@ -27,15 +27,16 @@ boolean Plugin_018(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_018; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_018; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P019_PCF8574.ino b/src/_P019_PCF8574.ino index bbc242b87a..46c204eda8 100644 --- a/src/_P019_PCF8574.ino +++ b/src/_P019_PCF8574.ino @@ -26,14 +26,15 @@ boolean Plugin_019(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_019; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_019; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.InverseLogicOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P020_Ser2Net.ino b/src/_P020_Ser2Net.ino index 017b62db73..70d58e0465 100644 --- a/src/_P020_Ser2Net.ino +++ b/src/_P020_Ser2Net.ino @@ -86,15 +86,17 @@ boolean Plugin_020(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { + auto& dev = Device[++deviceCount]; + if (P020_Emulate_P044) { - Device[++deviceCount].Number = PLUGIN_ID_020_044; - Device[deviceCount].SendDataOption = false; + dev.Number = PLUGIN_ID_020_044; + dev.SendDataOption = false; } else { - Device[++deviceCount].Number = PLUGIN_ID_020; - Device[deviceCount].SendDataOption = true; + dev.Number = PLUGIN_ID_020; + dev.SendDataOption = true; } - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_STRING; break; } case PLUGIN_GET_DEVICENAME: diff --git a/src/_P021_Level.ino b/src/_P021_Level.ino index 2fc077dea4..942bd4d829 100644 --- a/src/_P021_Level.ino +++ b/src/_P021_Level.ino @@ -110,12 +110,13 @@ boolean Plugin_021(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_021; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_021; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P022_PCA9685.ino b/src/_P022_PCA9685.ino index 4048769e93..14af526a3d 100644 --- a/src/_P022_PCA9685.ino +++ b/src/_P022_PCA9685.ino @@ -54,12 +54,13 @@ boolean Plugin_022(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_022; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 1; - Device[deviceCount].Custom = true; - Device[deviceCount].ExitTaskBeforeSave = false; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_022; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.Ports = 1; + dev.Custom = true; + dev.ExitTaskBeforeSave = false; break; } diff --git a/src/_P023_OLED.ino b/src/_P023_OLED.ino index 8ad2b3541d..5c192ca020 100644 --- a/src/_P023_OLED.ino +++ b/src/_P023_OLED.ino @@ -40,11 +40,12 @@ boolean Plugin_023(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_023; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_023; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P024_MLX90614.ino b/src/_P024_MLX90614.ino index 76f8606ef7..10fc1dfd09 100644 --- a/src/_P024_MLX90614.ino +++ b/src/_P024_MLX90614.ino @@ -29,16 +29,17 @@ boolean Plugin_024(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_024; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 16; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CMax100kHz = true; // Max 100 kHz allowed/supported + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_024; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.Ports = 16; + dev.FormulaOption = true; + dev.SendDataOption = true; + dev.ValueCount = 1; + dev.TimerOption = true; + dev.PluginStats = true; + dev.I2CMax100kHz = true; // Max 100 kHz allowed/supported break; } diff --git a/src/_P025_ADS1115.ino b/src/_P025_ADS1115.ino index 6b9ee509dd..274d627f5f 100644 --- a/src/_P025_ADS1115.ino +++ b/src/_P025_ADS1115.ino @@ -23,15 +23,16 @@ boolean Plugin_025(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_025; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_025; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.PluginStats = true; break; } diff --git a/src/_P026_Sysinfo.ino b/src/_P026_Sysinfo.ino index ff78587673..64ccf4f0b2 100644 --- a/src/_P026_Sysinfo.ino +++ b/src/_P026_Sysinfo.ino @@ -32,14 +32,15 @@ boolean Plugin_026(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_026; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_026; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.FormulaOption = true; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.PluginStats = true; break; } diff --git a/src/_P027_INA219.ino b/src/_P027_INA219.ino index 72d3418b40..1aca517611 100644 --- a/src/_P027_INA219.ino +++ b/src/_P027_INA219.ino @@ -53,14 +53,15 @@ boolean Plugin_027(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_027; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_027; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P028_BME280.ino b/src/_P028_BME280.ino index 9c40d41b64..61dabdab43 100644 --- a/src/_P028_BME280.ino +++ b/src/_P028_BME280.ino @@ -33,15 +33,16 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_028; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM_BARO; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].ErrorStateValues = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_028; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM_BARO; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.ErrorStateValues = true; + dev.PluginStats = true; break; } diff --git a/src/_P029_Output.ino b/src/_P029_Output.ino index 7e788a4bf6..572e416e61 100644 --- a/src/_P029_Output.ino +++ b/src/_P029_Output.ino @@ -25,12 +25,13 @@ boolean Plugin_029(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_029; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_029; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.Ports = 0; + dev.ValueCount = 1; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P031_SHT1X.ino b/src/_P031_SHT1X.ino index f4aa9f537b..81c54986e1 100644 --- a/src/_P031_SHT1X.ino +++ b/src/_P031_SHT1X.ino @@ -22,15 +22,16 @@ boolean Plugin_031(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_031; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].PullUpOption = true; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_031; + dev.Type = DEVICE_TYPE_DUAL; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.PullUpOption = true; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.TimerOption = true; + dev.PluginStats = true; + dev.setPin2Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P032_MS5611.ino b/src/_P032_MS5611.ino index a613721a1b..b0f289d660 100644 --- a/src/_P032_MS5611.ino +++ b/src/_P032_MS5611.ino @@ -23,14 +23,15 @@ boolean Plugin_032(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_032; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_032; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P033_Dummy.ino b/src/_P033_Dummy.ino index b313f804fe..0c5e85b3a6 100644 --- a/src/_P033_Dummy.ino +++ b/src/_P033_Dummy.ino @@ -17,16 +17,17 @@ boolean Plugin_033(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_033; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::All; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_033; + dev.Type = DEVICE_TYPE_DUMMY; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.DecimalsOnly = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.OutputDataType = Output_Data_type_t::All; + dev.PluginStats = true; break; } diff --git a/src/_P034_DHT12.ino b/src/_P034_DHT12.ino index 0401fb35fc..3c12f5138a 100644 --- a/src/_P034_DHT12.ino +++ b/src/_P034_DHT12.ino @@ -22,13 +22,14 @@ boolean Plugin_034(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_034; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_034; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P035_IRTX.ino b/src/_P035_IRTX.ino index 456e84eb2f..1a0497bf2d 100644 --- a/src/_P035_IRTX.ino +++ b/src/_P035_IRTX.ino @@ -59,10 +59,11 @@ boolean Plugin_035(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_035; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_035; + dev.Type = DEVICE_TYPE_SINGLE; + dev.SendDataOption = false; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P036_FrameOLED.ino b/src/_P036_FrameOLED.ino index ca86d782a4..16eafa20c9 100644 --- a/src/_P036_FrameOLED.ino +++ b/src/_P036_FrameOLED.ino @@ -242,11 +242,12 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_036; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_036; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P037_MQTTImport.ino b/src/_P037_MQTTImport.ino index 1b3bd33f8a..3acc31a90f 100644 --- a/src/_P037_MQTTImport.ino +++ b/src/_P037_MQTTImport.ino @@ -113,11 +113,12 @@ boolean Plugin_037(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_037; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; // This means it has a single pin - Device[deviceCount].DecimalsOnly = true; // We only want to have the decimals option - Device[deviceCount].ValueCount = VARS_PER_TASK; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_037; + dev.Type = DEVICE_TYPE_DUMMY; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; // This means it has a single pin + dev.DecimalsOnly = true; // We only want to have the decimals option + dev.ValueCount = VARS_PER_TASK; break; } diff --git a/src/_P038_NeoPixel.ino b/src/_P038_NeoPixel.ino index 294e053c52..d775f39bed 100644 --- a/src/_P038_NeoPixel.ino +++ b/src/_P038_NeoPixel.ino @@ -57,10 +57,11 @@ boolean Plugin_038(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_038; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].TimerOption = false; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_038; + dev.Type = DEVICE_TYPE_SINGLE; + dev.TimerOption = false; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P039_Thermosensors.ino b/src/_P039_Thermosensors.ino index 131b59c0b9..a016f68d07 100644 --- a/src/_P039_Thermosensors.ino +++ b/src/_P039_Thermosensors.ino @@ -259,14 +259,15 @@ boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_039; - Device[deviceCount].Type = DEVICE_TYPE_SPI; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_039; + dev.Type = DEVICE_TYPE_SPI; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P040_ID12.ino b/src/_P040_ID12.ino index 22ad32ab70..88ba10bdc0 100644 --- a/src/_P040_ID12.ino +++ b/src/_P040_ID12.ino @@ -25,10 +25,11 @@ boolean Plugin_040(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_040; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_040; + dev.VType = Sensor_VType::SENSOR_TYPE_ULONG; + dev.ValueCount = 1; + dev.SendDataOption = true; break; } diff --git a/src/_P041_NeoClock.ino b/src/_P041_NeoClock.ino index 7751795ab9..3612da2b49 100644 --- a/src/_P041_NeoClock.ino +++ b/src/_P041_NeoClock.ino @@ -36,10 +36,11 @@ boolean Plugin_041(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_041; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_041; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P042_Candle.ino b/src/_P042_Candle.ino index 6e5305c37a..6cc8c62086 100644 --- a/src/_P042_Candle.ino +++ b/src/_P042_Candle.ino @@ -92,13 +92,14 @@ boolean Plugin_042(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_042; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_042; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P043_ClkOutput.ino b/src/_P043_ClkOutput.ino index 6a7f897818..695c9e1c48 100644 --- a/src/_P043_ClkOutput.ino +++ b/src/_P043_ClkOutput.ino @@ -68,13 +68,14 @@ boolean Plugin_043(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_043; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_043; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P044_P1WifiGateway.ino b/src/_P044_P1WifiGateway.ino index d4465b0e52..b2d795d02b 100644 --- a/src/_P044_P1WifiGateway.ino +++ b/src/_P044_P1WifiGateway.ino @@ -35,10 +35,11 @@ boolean Plugin_044(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_044; - Device[deviceCount].Type = DEVICE_TYPE_CUSTOM2; - Device[deviceCount].Custom = true; - Device[deviceCount].TimerOption = false; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_044; + dev.Type = DEVICE_TYPE_CUSTOM2; + dev.Custom = true; + dev.TimerOption = false; break; } diff --git a/src/_P045_MPU6050.ino b/src/_P045_MPU6050.ino index 3ae6f00da0..b6cad82981 100644 --- a/src/_P045_MPU6050.ino +++ b/src/_P045_MPU6050.ino @@ -82,14 +82,15 @@ boolean Plugin_045(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_045; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].ValueCount = 1; // Unfortunatly domoticz has no custom multivalue sensors. - Device[deviceCount].SendDataOption = true; // and I use Domoticz ... so there. - Device[deviceCount].TimerOption = true; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_045; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.ValueCount = 1; // Unfortunatly domoticz has no custom multivalue sensors. + dev.SendDataOption = true; // and I use Domoticz ... so there. + dev.TimerOption = true; + dev.FormulaOption = false; + dev.PluginStats = true; break; } diff --git a/src/_P046_VentusW266.ino b/src/_P046_VentusW266.ino index ddeab9da85..5143597d43 100644 --- a/src/_P046_VentusW266.ino +++ b/src/_P046_VentusW266.ino @@ -144,15 +144,16 @@ boolean Plugin_046(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_046; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; // Nothing else really fit the bill ... - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; // New type, see ESPEasy.ino - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].ValueCount = 3; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_046; + dev.Type = DEVICE_TYPE_DUMMY; // Nothing else really fit the bill ... + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; // New type, see ESPEasy.ino + dev.Ports = 0; + dev.PullUpOption = false; + dev.InverseLogicOption = false; + dev.FormulaOption = true; + dev.SendDataOption = true; + dev.ValueCount = 3; break; } diff --git a/src/_P047_i2c-soil-moisture-sensor.ino b/src/_P047_i2c-soil-moisture-sensor.ino index 514c7aa3da..735f7d96b9 100644 --- a/src/_P047_i2c-soil-moisture-sensor.ino +++ b/src/_P047_i2c-soil-moisture-sensor.ino @@ -46,14 +46,15 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_047; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_047; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P048_Motorshield_v2.ino b/src/_P048_Motorshield_v2.ino index b8954a299a..666c545d4c 100644 --- a/src/_P048_Motorshield_v2.ino +++ b/src/_P048_Motorshield_v2.ino @@ -32,10 +32,11 @@ boolean Plugin_048(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_048; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].I2CNoDeviceCheck = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_048; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.I2CNoDeviceCheck = true; break; } diff --git a/src/_P049_MHZ19.ino b/src/_P049_MHZ19.ino index 09bbc97562..a993ca59a1 100644 --- a/src/_P049_MHZ19.ino +++ b/src/_P049_MHZ19.ino @@ -48,15 +48,16 @@ boolean Plugin_049(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_049; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].ExitTaskBeforeSave = false; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_049; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.ExitTaskBeforeSave = false; break; } diff --git a/src/_P050_TCS34725.ino b/src/_P050_TCS34725.ino index 0b0829f9a5..d4f6a11393 100644 --- a/src/_P050_TCS34725.ino +++ b/src/_P050_TCS34725.ino @@ -47,14 +47,15 @@ boolean Plugin_050(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_050; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_050; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P051_AM2320.ino b/src/_P051_AM2320.ino index 1d50c60c9b..7718a8943f 100644 --- a/src/_P051_AM2320.ino +++ b/src/_P051_AM2320.ino @@ -35,15 +35,16 @@ boolean Plugin_051(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_051; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CNoDeviceCheck = true; // Avoid device check + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_051; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.I2CNoDeviceCheck = true; // Avoid device check break; } diff --git a/src/_P052_SenseAir.ino b/src/_P052_SenseAir.ino index 7abfb07880..ba018e1409 100644 --- a/src/_P052_SenseAir.ino +++ b/src/_P052_SenseAir.ino @@ -38,16 +38,17 @@ boolean Plugin_052(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_052; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].ExitTaskBeforeSave = false; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_052; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.ExitTaskBeforeSave = false; + dev.PluginStats = true; break; } diff --git a/src/_P053_PMSx003.ino b/src/_P053_PMSx003.ino index 193773bbcc..dc7abfe18b 100644 --- a/src/_P053_PMSx003.ino +++ b/src/_P053_PMSx003.ino @@ -44,23 +44,24 @@ boolean Plugin_053(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_053; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_053; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.Ports = 0; + dev.PullUpOption = false; + dev.InverseLogicOption = false; # ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; + dev.FormulaOption = true; + dev.ValueCount = 4; # else // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 3; + dev.FormulaOption = false; + dev.ValueCount = 3; # endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.GlobalSyncOption = true; + dev.PluginStats = true; success = true; break; } diff --git a/src/_P054_DMX512.ino b/src/_P054_DMX512.ino index 3d61af844f..7c42c4ec84 100644 --- a/src/_P054_DMX512.ino +++ b/src/_P054_DMX512.ino @@ -89,9 +89,10 @@ boolean Plugin_054(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_054; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_054; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; break; } diff --git a/src/_P055_Chiming.ino b/src/_P055_Chiming.ino index eaf6781271..1a45df5cb9 100644 --- a/src/_P055_Chiming.ino +++ b/src/_P055_Chiming.ino @@ -94,13 +94,14 @@ boolean Plugin_055(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_055; - Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].InverseLogicOption = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); - Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); - Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_055; + dev.Type = DEVICE_TYPE_TRIPLE; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.InverseLogicOption = true; + dev.setPin1Direction(gpio_direction::gpio_output); + dev.setPin2Direction(gpio_direction::gpio_output); + dev.setPin3Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P056_SDS011-Dust.ino b/src/_P056_SDS011-Dust.ino index d5b76072b7..f57149d1e7 100644 --- a/src/_P056_SDS011-Dust.ino +++ b/src/_P056_SDS011-Dust.ino @@ -37,14 +37,15 @@ boolean Plugin_056(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_056; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_056; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P057_HT16K33_LED.ino b/src/_P057_HT16K33_LED.ino index f0f6eb0afd..4500296195 100644 --- a/src/_P057_HT16K33_LED.ino +++ b/src/_P057_HT16K33_LED.ino @@ -85,9 +85,10 @@ boolean Plugin_057(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_057; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_057; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; break; } diff --git a/src/_P058_HT16K33_KeyPad.ino b/src/_P058_HT16K33_KeyPad.ino index 7a0c23e80a..3f20d612ca 100644 --- a/src/_P058_HT16K33_KeyPad.ino +++ b/src/_P058_HT16K33_KeyPad.ino @@ -46,13 +46,14 @@ boolean Plugin_058(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_058; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_058; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P059_Encoder.ino b/src/_P059_Encoder.ino index 5596aeeef3..f05ae91980 100644 --- a/src/_P059_Encoder.ino +++ b/src/_P059_Encoder.ino @@ -38,13 +38,14 @@ boolean Plugin_059(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_059; - Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_059; + dev.Type = DEVICE_TYPE_TRIPLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P060_MCP3221.ino b/src/_P060_MCP3221.ino index b589de8987..23c83e1a1b 100644 --- a/src/_P060_MCP3221.ino +++ b/src/_P060_MCP3221.ino @@ -25,14 +25,15 @@ boolean Plugin_060(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_060; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_060; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P061_KeyPad.ino b/src/_P061_KeyPad.ino index ffc9a3b5bd..541366ba13 100644 --- a/src/_P061_KeyPad.ino +++ b/src/_P061_KeyPad.ino @@ -89,13 +89,14 @@ boolean Plugin_061(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_061; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_061; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P062_MPR121_KeyPad.ino b/src/_P062_MPR121_KeyPad.ino index 85ba88dec4..8de0cffbb5 100644 --- a/src/_P062_MPR121_KeyPad.ino +++ b/src/_P062_MPR121_KeyPad.ino @@ -44,14 +44,15 @@ boolean Plugin_062(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_062; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].ExitTaskBeforeSave = false; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_062; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.ExitTaskBeforeSave = false; break; } diff --git a/src/_P063_TTP229_KeyPad.ino b/src/_P063_TTP229_KeyPad.ino index 5da2f1018c..9e16226c22 100644 --- a/src/_P063_TTP229_KeyPad.ino +++ b/src/_P063_TTP229_KeyPad.ino @@ -76,14 +76,15 @@ boolean Plugin_063(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_063; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_063; + dev.Type = DEVICE_TYPE_DUAL; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P064_APDS9960.ino b/src/_P064_APDS9960.ino index a12d85fbb7..61d0fc33c5 100644 --- a/src/_P064_APDS9960.ino +++ b/src/_P064_APDS9960.ino @@ -73,14 +73,15 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_064; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_064; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P065_DRF0299_MP3.ino b/src/_P065_DRF0299_MP3.ino index b485f67533..ec0a70f255 100644 --- a/src/_P065_DRF0299_MP3.ino +++ b/src/_P065_DRF0299_MP3.ino @@ -62,9 +62,10 @@ boolean Plugin_065(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_065; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_065; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; break; } diff --git a/src/_P066_VEML6040.ino b/src/_P066_VEML6040.ino index b1b5371700..082a73bf8f 100644 --- a/src/_P066_VEML6040.ino +++ b/src/_P066_VEML6040.ino @@ -32,14 +32,15 @@ boolean Plugin_066(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_066; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_066; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P067_HX711_Load_Cell.ino b/src/_P067_HX711_Load_Cell.ino index 68664d6b8c..1321ec4f44 100644 --- a/src/_P067_HX711_Load_Cell.ino +++ b/src/_P067_HX711_Load_Cell.ino @@ -42,15 +42,16 @@ boolean Plugin_067(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_067; - Device[deviceCount].Type = DEVICE_TYPE_DUAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_067; + dev.Type = DEVICE_TYPE_DUAL; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P068_SHT3x.ino b/src/_P068_SHT3x.ino index 96a7bd8fa8..749c8fc0ce 100644 --- a/src/_P068_SHT3x.ino +++ b/src/_P068_SHT3x.ino @@ -42,14 +42,15 @@ boolean Plugin_068(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_068; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_068; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P069_LM75A.ino b/src/_P069_LM75A.ino index 522bb63b83..2597e5b02b 100644 --- a/src/_P069_LM75A.ino +++ b/src/_P069_LM75A.ino @@ -30,14 +30,15 @@ boolean Plugin_069(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_069; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_069; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P070_NeoPixel_Clock.ino b/src/_P070_NeoPixel_Clock.ino index 8a6b666cef..338a55a075 100644 --- a/src/_P070_NeoPixel_Clock.ino +++ b/src/_P070_NeoPixel_Clock.ino @@ -36,14 +36,15 @@ boolean Plugin_070(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_070; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_070; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; + dev.setPin1Direction(gpio_direction::gpio_output); // FIXME TD-er: Not sure if access to any existing task data is needed when saving - Device[deviceCount].ExitTaskBeforeSave = false; + dev.ExitTaskBeforeSave = false; break; } diff --git a/src/_P071_Kamstrup401.ino b/src/_P071_Kamstrup401.ino index 9783279250..6047f70768 100644 --- a/src/_P071_Kamstrup401.ino +++ b/src/_P071_Kamstrup401.ino @@ -40,13 +40,14 @@ boolean Plugin_071(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_071; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_071; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P072_HDC1080.ino b/src/_P072_HDC1080.ino index 95db3e33e6..cbc9eab859 100644 --- a/src/_P072_HDC1080.ino +++ b/src/_P072_HDC1080.ino @@ -29,15 +29,16 @@ boolean Plugin_072(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_072; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CNoDeviceCheck = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_072; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.I2CNoDeviceCheck = true; break; } diff --git a/src/_P073_7DGT.ino b/src/_P073_7DGT.ino index 279f25da77..b96abca7c5 100644 --- a/src/_P073_7DGT.ino +++ b/src/_P073_7DGT.ino @@ -87,12 +87,13 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_073; - Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); - Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); - Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_073; + dev.Type = DEVICE_TYPE_TRIPLE; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.setPin1Direction(gpio_direction::gpio_output); + dev.setPin2Direction(gpio_direction::gpio_output); + dev.setPin3Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P074_TSL2591.ino b/src/_P074_TSL2591.ino index 21059f06ce..ef373e10c4 100644 --- a/src/_P074_TSL2591.ino +++ b/src/_P074_TSL2591.ino @@ -31,14 +31,15 @@ boolean Plugin_074(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_074; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_074; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P075_Nextion.ino b/src/_P075_Nextion.ino index 9ae904bba2..f1e3789786 100644 --- a/src/_P075_Nextion.ino +++ b/src/_P075_Nextion.ino @@ -49,16 +49,17 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_075; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; // Allow user to disable interval function. + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_075; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; // Allow user to disable interval function. // FIXME TD-er: Not sure if access to any existing task data is needed when saving - Device[deviceCount].ExitTaskBeforeSave = false; + dev.ExitTaskBeforeSave = false; break; } diff --git a/src/_P076_HLW8012.ino b/src/_P076_HLW8012.ino index 27139f0251..0fc0d00cab 100644 --- a/src/_P076_HLW8012.ino +++ b/src/_P076_HLW8012.ino @@ -116,15 +116,16 @@ boolean Plugin_076(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_076; - Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_076; + dev.Type = DEVICE_TYPE_TRIPLE; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P077_CSE7766.ino b/src/_P077_CSE7766.ino index 3ce0b78c78..4594e1b580 100644 --- a/src/_P077_CSE7766.ino +++ b/src/_P077_CSE7766.ino @@ -40,17 +40,18 @@ boolean Plugin_077(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_077; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].TaskLogsOwnPeaks = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_077; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; + dev.TaskLogsOwnPeaks = true; break; } diff --git a/src/_P078_Eastron.ino b/src/_P078_Eastron.ino index 536ab9b04a..4784d825dc 100644 --- a/src/_P078_Eastron.ino +++ b/src/_P078_Eastron.ino @@ -40,16 +40,17 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_078; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = P078_NR_OUTPUT_VALUES; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].TaskLogsOwnPeaks = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_078; + dev.Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = P078_NR_OUTPUT_VALUES; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.TaskLogsOwnPeaks = true; break; } diff --git a/src/_P079_Wemos_Motorshield.ino b/src/_P079_Wemos_Motorshield.ino index a2e5d958aa..f79e967c9e 100644 --- a/src/_P079_Wemos_Motorshield.ino +++ b/src/_P079_Wemos_Motorshield.ino @@ -84,9 +84,10 @@ boolean Plugin_079(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_079; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_079; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; break; } diff --git a/src/_P080_DallasIButton.ino b/src/_P080_DallasIButton.ino index f266b389a8..de1e97f8c0 100644 --- a/src/_P080_DallasIButton.ino +++ b/src/_P080_DallasIButton.ino @@ -36,13 +36,14 @@ boolean Plugin_080(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_080; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_080; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P081_Cron.ino b/src/_P081_Cron.ino index 1dc720dda9..1170896b77 100644 --- a/src/_P081_Cron.ino +++ b/src/_P081_Cron.ino @@ -28,15 +28,13 @@ boolean Plugin_081(uint8_t function, struct EventStruct *event, String& string) { // This case defines the device characteristics, edit appropriately - Device[++deviceCount].Number = PLUGIN_ID_081; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; // how the device is connected - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; // type of value the plugin will return, used only for - // Domoticz - Device[deviceCount].ValueCount = 2; // number of output variables. The value should match the number of - // keys - // PLUGIN_VALUENAME1_xxx - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].HasFormatUserVar = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_081; + dev.Type = DEVICE_TYPE_DUMMY; // how the device is connected + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; // type of value the plugin will return, used only for Domoticz + dev.ValueCount = 2; // number of output variables. + dev.DecimalsOnly = true; + dev.HasFormatUserVar = true; break; } diff --git a/src/_P082_GPS.ino b/src/_P082_GPS.ino index c3b72507cb..41aa8e2863 100644 --- a/src/_P082_GPS.ino +++ b/src/_P082_GPS.ino @@ -35,15 +35,16 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_082; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_082; + dev.Type = DEVICE_TYPE_SERIAL_PLUS1; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P083_SGP30.ino b/src/_P083_SGP30.ino index 57b058e1cf..d87af5e5c3 100644 --- a/src/_P083_SGP30.ino +++ b/src/_P083_SGP30.ino @@ -32,14 +32,15 @@ boolean Plugin_083(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_083; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_083; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P084_VEML6070.ino b/src/_P084_VEML6070.ino index 773c2b7930..02334ad44f 100644 --- a/src/_P084_VEML6070.ino +++ b/src/_P084_VEML6070.ino @@ -43,14 +43,15 @@ boolean Plugin_084(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_084; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_084; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P085_AcuDC243.ino b/src/_P085_AcuDC243.ino index c7c1c33212..e542bfc9c3 100644 --- a/src/_P085_AcuDC243.ino +++ b/src/_P085_AcuDC243.ino @@ -27,17 +27,18 @@ boolean Plugin_085(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_085; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = P085_NR_OUTPUT_VALUES; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].ExitTaskBeforeSave = false; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_085; + dev.Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = P085_NR_OUTPUT_VALUES; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.ExitTaskBeforeSave = false; + dev.PluginStats = true; + dev.setPin3Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P086_Homie.ino b/src/_P086_Homie.ino index 2702baba80..5fbef766f2 100644 --- a/src/_P086_Homie.ino +++ b/src/_P086_Homie.ino @@ -42,12 +42,13 @@ boolean Plugin_086(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_086; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].ValueCount = PLUGIN_086_VALUE_MAX; - Device[deviceCount].Custom = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_086; + dev.Type = DEVICE_TYPE_DUMMY; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.DecimalsOnly = true; + dev.ValueCount = PLUGIN_086_VALUE_MAX; + dev.Custom = true; break; } diff --git a/src/_P087_SerialProxy.ino b/src/_P087_SerialProxy.ino index 12d4d84087..01aca2edd0 100644 --- a/src/_P087_SerialProxy.ino +++ b/src/_P087_SerialProxy.ino @@ -73,15 +73,16 @@ boolean Plugin_087(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_087; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_087; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_STRING; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; // FIXME TD-er: Not sure if access to any existing task data is needed when saving - Device[deviceCount].ExitTaskBeforeSave = false; + dev.ExitTaskBeforeSave = false; break; } diff --git a/src/_P088_HeatpumpIR.ino b/src/_P088_HeatpumpIR.ino index 42a22cf4a6..cb669b3d00 100644 --- a/src/_P088_HeatpumpIR.ino +++ b/src/_P088_HeatpumpIR.ino @@ -61,10 +61,11 @@ boolean Plugin_088(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_088; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_088; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P089_Ping.ino b/src/_P089_Ping.ino index 5f87b5ad23..0782eb7730 100644 --- a/src/_P089_Ping.ino +++ b/src/_P089_Ping.ino @@ -39,13 +39,14 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_089; - Device[deviceCount].Type = DEVICE_TYPE_CUSTOM0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_089; + dev.Type = DEVICE_TYPE_CUSTOM0; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.ValueCount = 1; + dev.DecimalsOnly = true; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P090_CCS811.ino b/src/_P090_CCS811.ino index 8ee9b635a4..b234f51586 100644 --- a/src/_P090_CCS811.ino +++ b/src/_P090_CCS811.ino @@ -77,14 +77,15 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_090; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_090; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P091_SerSwitch.ino b/src/_P091_SerSwitch.ino index 1833c74a52..6f0cccdca9 100644 --- a/src/_P091_SerSwitch.ino +++ b/src/_P091_SerSwitch.ino @@ -88,13 +88,14 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_091; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_091; + dev.Type = DEVICE_TYPE_DUMMY; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } case PLUGIN_GET_DEVICENAME: diff --git a/src/_P092_DLbus.ino b/src/_P092_DLbus.ino index 140d513599..aa911f85a1 100644 --- a/src/_P092_DLbus.ino +++ b/src/_P092_DLbus.ino @@ -90,14 +90,15 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_092; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_092; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.DecimalsOnly = true; + dev.PluginStats = true; break; } diff --git a/src/_P093_MitsubishiHP.ino b/src/_P093_MitsubishiHP.ino index 8fee38dbbc..93d2ab30d7 100644 --- a/src/_P093_MitsubishiHP.ino +++ b/src/_P093_MitsubishiHP.ino @@ -44,13 +44,14 @@ boolean Plugin_093(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_093; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_093; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_STRING; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P094_CULReader.ino b/src/_P094_CULReader.ino index f653f72eb0..affafc6675 100644 --- a/src/_P094_CULReader.ino +++ b/src/_P094_CULReader.ino @@ -53,17 +53,18 @@ boolean Plugin_094(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_094; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_STRING; - Device[deviceCount].OutputDataType = Output_Data_type_t::Default; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].DuplicateDetection = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_094; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_STRING; + dev.OutputDataType = Output_Data_type_t::Default; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.DuplicateDetection = true; // FIXME TD-er: Not sure if access to any existing task data is needed when saving - Device[deviceCount].ExitTaskBeforeSave = true; + dev.ExitTaskBeforeSave = true; break; } diff --git a/src/_P095_ILI9341.ino b/src/_P095_ILI9341.ino index e2340e1e71..bb0a7e148b 100644 --- a/src/_P095_ILI9341.ino +++ b/src/_P095_ILI9341.ino @@ -146,13 +146,13 @@ boolean Plugin_095(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_095; - Device[deviceCount].Type = DEVICE_TYPE_SPI3; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - success = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_095; + dev.Type = DEVICE_TYPE_SPI3; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.ValueCount = 2; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P096_eInk.ino b/src/_P096_eInk.ino index fdb46957b9..534268c7e2 100644 --- a/src/_P096_eInk.ino +++ b/src/_P096_eInk.ino @@ -175,16 +175,15 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_096; - Device[deviceCount].Type = DEVICE_TYPE_SPI3; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_096; + dev.Type = DEVICE_TYPE_SPI3; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; # if P096_USE_EXTENDED_SETTINGS - Device[deviceCount].ValueCount = 2; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + dev.ValueCount = 2; + dev.TimerOption = true; + dev.TimerOptional = true; # endif // if P096_USE_EXTENDED_SETTINGS - - success = true; break; } diff --git a/src/_P097_Esp32Touch.ino b/src/_P097_Esp32Touch.ino index 494b62bd48..7196f2167e 100644 --- a/src/_P097_Esp32Touch.ino +++ b/src/_P097_Esp32Touch.ino @@ -56,13 +56,14 @@ boolean Plugin_097(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_097; - Device[deviceCount].Type = DEVICE_TYPE_ANALOG; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_097; + dev.Type = DEVICE_TYPE_ANALOG; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P098_PWM_motor.ino b/src/_P098_PWM_motor.ino index b1d9beb834..4fb4a54fa8 100644 --- a/src/_P098_PWM_motor.ino +++ b/src/_P098_PWM_motor.ino @@ -51,13 +51,14 @@ boolean Plugin_098(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_098; - Device[deviceCount].Type = DEVICE_TYPE_CUSTOM0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_098; + dev.Type = DEVICE_TYPE_CUSTOM0; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P099_XPT2046Touch.ino b/src/_P099_XPT2046Touch.ino index 7c53bc90db..cfe6f688de 100644 --- a/src/_P099_XPT2046Touch.ino +++ b/src/_P099_XPT2046Touch.ino @@ -50,11 +50,11 @@ boolean Plugin_099(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_099; - Device[deviceCount].Type = DEVICE_TYPE_SPI; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].ValueCount = 3; - success = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_099; + dev.Type = DEVICE_TYPE_SPI; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; break; } diff --git a/src/_P100_DS2423_counter.ino b/src/_P100_DS2423_counter.ino index 2d7a70e9d6..5ab8fa770e 100644 --- a/src/_P100_DS2423_counter.ino +++ b/src/_P100_DS2423_counter.ino @@ -22,13 +22,14 @@ boolean Plugin_100(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_100; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_100; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P101_WakeOnLan.ino b/src/_P101_WakeOnLan.ino index 592f712158..1dece4346c 100644 --- a/src/_P101_WakeOnLan.ino +++ b/src/_P101_WakeOnLan.ino @@ -113,9 +113,10 @@ boolean Plugin_101(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_101; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_101; + dev.Type = DEVICE_TYPE_DUMMY; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; break; } diff --git a/src/_P102_PZEM004Tv3.ino b/src/_P102_PZEM004Tv3.ino index e8f42741a5..bff9c8a47f 100644 --- a/src/_P102_PZEM004Tv3.ino +++ b/src/_P102_PZEM004Tv3.ino @@ -58,14 +58,15 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_102; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_102; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino b/src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino index c7bb9a2645..f61a913526 100644 --- a/src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino +++ b/src/_P103_Atlas_EZO_pH_ORP_EC_DO.ino @@ -72,13 +72,14 @@ boolean Plugin_103(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_103; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_103; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P104_max7219_Dotmatrix.ino b/src/_P104_max7219_Dotmatrix.ino index 3f00d0cf43..adb30e00ba 100644 --- a/src/_P104_max7219_Dotmatrix.ino +++ b/src/_P104_max7219_Dotmatrix.ino @@ -137,10 +137,11 @@ boolean Plugin_104(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_104; - Device[deviceCount].Type = DEVICE_TYPE_SPI; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].ExitTaskBeforeSave = false; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_104; + dev.Type = DEVICE_TYPE_SPI; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.ExitTaskBeforeSave = false; break; } diff --git a/src/_P105_AHT.ino b/src/_P105_AHT.ino index ac05a1e233..73cb7c6df7 100644 --- a/src/_P105_AHT.ino +++ b/src/_P105_AHT.ino @@ -56,14 +56,15 @@ boolean Plugin_105(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_105; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_105; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P106_BME680.ino b/src/_P106_BME680.ino index f3c6f80d54..9113ddf738 100644 --- a/src/_P106_BME680.ino +++ b/src/_P106_BME680.ino @@ -44,14 +44,15 @@ boolean Plugin_106(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_106; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_106; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P107_SI1145.ino b/src/_P107_SI1145.ino index a7ed587950..2dd03067d8 100644 --- a/src/_P107_SI1145.ino +++ b/src/_P107_SI1145.ino @@ -22,14 +22,15 @@ boolean Plugin_107(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_107; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_107; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P108_DDS238.ino b/src/_P108_DDS238.ino index bcda9fb34e..d914f225c5 100644 --- a/src/_P108_DDS238.ino +++ b/src/_P108_DDS238.ino @@ -37,16 +37,17 @@ boolean Plugin_108(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_108; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = P108_NR_OUTPUT_VALUES; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_108; + dev.Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = P108_NR_OUTPUT_VALUES; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.setPin3Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P109_ThermOLED.ino b/src/_P109_ThermOLED.ino index afaa57668f..b07946ceb7 100644 --- a/src/_P109_ThermOLED.ino +++ b/src/_P109_ThermOLED.ino @@ -85,13 +85,14 @@ boolean Plugin_109(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_109; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_109; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P110_VL53L0X.ino b/src/_P110_VL53L0X.ino index b3880b1b3c..72320e7a14 100644 --- a/src/_P110_VL53L0X.ino +++ b/src/_P110_VL53L0X.ino @@ -40,15 +40,16 @@ boolean Plugin_110(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_110; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_110; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P111_RC522_RFID.ino b/src/_P111_RC522_RFID.ino index 4b462cf44b..f084413988 100644 --- a/src/_P111_RC522_RFID.ino +++ b/src/_P111_RC522_RFID.ino @@ -34,16 +34,12 @@ boolean Plugin_111(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_111; - Device[deviceCount].Type = DEVICE_TYPE_SPI2; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_ULONG; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = false; - Device[deviceCount].GlobalSyncOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_111; + dev.Type = DEVICE_TYPE_SPI2; + dev.VType = Sensor_VType::SENSOR_TYPE_ULONG; + dev.ValueCount = 1; + dev.SendDataOption = true; break; } @@ -89,7 +85,7 @@ boolean Plugin_111(uint8_t function, struct EventStruct *event, String& string) F("Tag removal detection + Time-out") # endif // ifdef P111_USE_REMOVAL }; - const int removalopts[P111_removaltypes] = { // A-typical order for logical order and backward compatibility + const int removalopts[P111_removaltypes] = { // A-typical order for logical order and backward compatibility 1, 0, # ifdef P111_USE_REMOVAL 2 diff --git a/src/_P112_AS7265x.ino b/src/_P112_AS7265x.ino index 324827de08..082ed3ae82 100644 --- a/src/_P112_AS7265x.ino +++ b/src/_P112_AS7265x.ino @@ -32,20 +32,16 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_112; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::All; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_112; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; + dev.DecimalsOnly = true; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.OutputDataType = Output_Data_type_t::All; + dev.PluginStats = true; break; } diff --git a/src/_P113_VL53L1X.ino b/src/_P113_VL53L1X.ino index 6186a56980..d3f3e2eebc 100644 --- a/src/_P113_VL53L1X.ino +++ b/src/_P113_VL53L1X.ino @@ -40,16 +40,16 @@ boolean Plugin_113(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_113; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_113; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P114_VEML6075.ino b/src/_P114_VEML6075.ino index ef7c9b3853..9d47c8cb68 100644 --- a/src/_P114_VEML6075.ino +++ b/src/_P114_VEML6075.ino @@ -27,18 +27,15 @@ boolean Plugin_114(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_114; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_114; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P115_MAX1704x_v2.ino b/src/_P115_MAX1704x_v2.ino index 8d93779c3d..0397b1179b 100644 --- a/src/_P115_MAX1704x_v2.ino +++ b/src/_P115_MAX1704x_v2.ino @@ -37,19 +37,16 @@ boolean Plugin_115(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_115; - Device[deviceCount].Type = DEVICE_TYPE_I2C; // how the device is connected - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; // type of value the plugin will return - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].DecimalsOnly = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_115; + dev.Type = DEVICE_TYPE_I2C; // how the device is connected + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; // type of value the plugin will return + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.DecimalsOnly = true; + dev.PluginStats = true; break; } diff --git a/src/_P116_ST77xx.ino b/src/_P116_ST77xx.ino index a966cc4386..8e1e34ec0a 100644 --- a/src/_P116_ST77xx.ino +++ b/src/_P116_ST77xx.ino @@ -51,17 +51,13 @@ boolean Plugin_116(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_116; - Device[deviceCount].Type = DEVICE_TYPE_SPI3; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_116; + dev.Type = DEVICE_TYPE_SPI3; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.ValueCount = 2; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P117_SCD30.ino b/src/_P117_SCD30.ino index be35763525..b8fad4df6d 100644 --- a/src/_P117_SCD30.ino +++ b/src/_P117_SCD30.ino @@ -45,19 +45,16 @@ boolean Plugin_117(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_117; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CMax100kHz = true; // Max 100 kHz allowed/supported + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_117; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.I2CMax100kHz = true; // Max 100 kHz allowed/supported break; } diff --git a/src/_P118_Itho.ino b/src/_P118_Itho.ino index 51185e0e9f..17cac816d8 100644 --- a/src/_P118_Itho.ino +++ b/src/_P118_Itho.ino @@ -124,18 +124,12 @@ boolean Plugin_118(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_118; - Device[deviceCount].Type = DEVICE_TYPE_SPI2; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = false; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_118; + dev.Type = DEVICE_TYPE_SPI2; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; + dev.SendDataOption = true; break; } diff --git a/src/_P119_ITG3205_Gyro.ino b/src/_P119_ITG3205_Gyro.ino index aa89009416..c34d3f50ac 100644 --- a/src/_P119_ITG3205_Gyro.ino +++ b/src/_P119_ITG3205_Gyro.ino @@ -47,16 +47,16 @@ boolean Plugin_119(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_119; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_119; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; + dev.FormulaOption = true; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P120_ADXL345_Accelerometer.ino b/src/_P120_ADXL345_Accelerometer.ino index 2201656184..7d70f149d0 100644 --- a/src/_P120_ADXL345_Accelerometer.ino +++ b/src/_P120_ADXL345_Accelerometer.ino @@ -40,17 +40,17 @@ boolean Plugin_120(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_120; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_120; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; + dev.FormulaOption = true; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; + dev.OutputDataType = Output_Data_type_t::Simple; break; } diff --git a/src/_P121_HMC5883L.ino b/src/_P121_HMC5883L.ino index f8efc70c42..d31eaffef9 100644 --- a/src/_P121_HMC5883L.ino +++ b/src/_P121_HMC5883L.ino @@ -42,19 +42,16 @@ boolean Plugin_121(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_121; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - success = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_121; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + success = true; break; } diff --git a/src/_P122_SHT2x.ino b/src/_P122_SHT2x.ino index 800d025e79..e19b97e414 100644 --- a/src/_P122_SHT2x.ino +++ b/src/_P122_SHT2x.ino @@ -51,21 +51,19 @@ boolean Plugin_122(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_DEVICE_ADD: { // This case defines the device characteristics - Device[++deviceCount].Number = PLUGIN_ID_122; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].I2CNoDeviceCheck = true; - - // Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Default; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_122; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.I2CNoDeviceCheck = true; + + // dev.GlobalSyncOption = true; + dev.PluginStats = true; + dev.OutputDataType = Output_Data_type_t::Default; break; } @@ -251,4 +249,4 @@ boolean Plugin_122(uint8_t function, struct EventStruct *event, String& string) return success; } // function -#endif //USES_P122 +#endif // USES_P122 diff --git a/src/_P123_I2CTouch.ino b/src/_P123_I2CTouch.ino index 3dab764c9c..667e278a9c 100644 --- a/src/_P123_I2CTouch.ino +++ b/src/_P123_I2CTouch.ino @@ -71,19 +71,13 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_123; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = false; - Device[deviceCount].ExitTaskBeforeSave = false; - Device[deviceCount].I2CNoDeviceCheck = true; - success = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_123; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; + dev.ExitTaskBeforeSave = false; + dev.I2CNoDeviceCheck = true; break; } diff --git a/src/_P124_MultiRelay.ino b/src/_P124_MultiRelay.ino index 15a329d1dc..e17ae31f9c 100644 --- a/src/_P124_MultiRelay.ino +++ b/src/_P124_MultiRelay.ino @@ -40,17 +40,15 @@ boolean Plugin_124(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_124; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_124; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P125_ADXL345_SPI.ino b/src/_P125_ADXL345_SPI.ino index 84491ffeeb..1f41868da8 100644 --- a/src/_P125_ADXL345_SPI.ino +++ b/src/_P125_ADXL345_SPI.ino @@ -38,17 +38,17 @@ boolean Plugin_125(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_125; - Device[deviceCount].Type = DEVICE_TYPE_SPI; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_125; + dev.Type = DEVICE_TYPE_SPI; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.ValueCount = 3; + dev.FormulaOption = true; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; + dev.OutputDataType = Output_Data_type_t::Simple; break; } diff --git a/src/_P126_74HC595.ino b/src/_P126_74HC595.ino index b7ef09d8f8..bc1e8dd4e5 100644 --- a/src/_P126_74HC595.ino +++ b/src/_P126_74HC595.ino @@ -79,11 +79,11 @@ boolean Plugin_126(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_126; - Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_126; + dev.Type = DEVICE_TYPE_TRIPLE; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.ValueCount = # if P126_MAX_CHIP_COUNT <= 4 1 # elif P126_MAX_CHIP_COUNT <= 8 @@ -94,13 +94,13 @@ boolean Plugin_126(uint8_t function, struct EventStruct *event, String& string) 4 # endif // if P126_MAX_CHIP_COUNT <= 4 ; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].HasFormatUserVar = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); - Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); - Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.HasFormatUserVar = true; + dev.setPin1Direction(gpio_direction::gpio_output); + dev.setPin2Direction(gpio_direction::gpio_output); + dev.setPin3Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P127_CDM7160.ino b/src/_P127_CDM7160.ino index d9fe0d5fcf..ba305957b0 100644 --- a/src/_P127_CDM7160.ino +++ b/src/_P127_CDM7160.ino @@ -35,18 +35,16 @@ boolean Plugin_127(uint8_t function, struct EventStruct *event, String& string) switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_127; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_127; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.GlobalSyncOption = true; + dev.PluginStats = true; break; } @@ -151,8 +149,8 @@ boolean Plugin_127(uint8_t function, struct EventStruct *event, String& string) if (loglevelActiveFor(LOG_LEVEL_INFO)) { addLogMove(LOG_LEVEL_INFO, strformat(F("CDM7160: Address: 0x%02x: CO2 ppm: %d, alt: %d, comp: %d"), - P127_CONFIG_I2C_ADDRESS, - UserVar[event->BaseVarIndex], + P127_CONFIG_I2C_ADDRESS, + UserVar[event->BaseVarIndex], P127_data->getAltitude(), P127_data->getCompensation())); } diff --git a/src/_P128_NeoPixelBusFX.ino b/src/_P128_NeoPixelBusFX.ino index 5f1829a878..137a7656e0 100644 --- a/src/_P128_NeoPixelBusFX.ino +++ b/src/_P128_NeoPixelBusFX.ino @@ -147,21 +147,21 @@ boolean Plugin_128(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_128; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_128; # if defined(ESP32) - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; + dev.Type = DEVICE_TYPE_SINGLE; # endif // if defined(ESP32) # if defined(ESP8266) - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; + dev.Type = DEVICE_TYPE_DUMMY; # endif // if defined(ESP8266) - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Custom = true; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.Custom = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P129_74HC165.ino b/src/_P129_74HC165.ino index be2213ee70..195b090c91 100644 --- a/src/_P129_74HC165.ino +++ b/src/_P129_74HC165.ino @@ -62,11 +62,11 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_129; - Device[deviceCount].Type = DEVICE_TYPE_TRIPLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_129; + dev.Type = DEVICE_TYPE_TRIPLE; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.ValueCount = # if P129_MAX_CHIP_COUNT <= 4 1 # elif P129_MAX_CHIP_COUNT <= 8 @@ -77,12 +77,12 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string) 4 # endif // if P129_MAX_CHIP_COUNT <= 4 ; - Device[deviceCount].SendDataOption = true; // No use in sending the Values to a controller - Device[deviceCount].TimerOption = true; // Used to update the Devices page - Device[deviceCount].TimerOptional = true; - Device[deviceCount].HasFormatUserVar = true; - Device[deviceCount].setPin2Direction(gpio_direction::gpio_output); - Device[deviceCount].setPin3Direction(gpio_direction::gpio_output); + dev.SendDataOption = true; // No use in sending the Values to a controller + dev.TimerOption = true; // Used to update the Devices page + dev.TimerOptional = true; + dev.HasFormatUserVar = true; + dev.setPin2Direction(gpio_direction::gpio_output); + dev.setPin3Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P131_NeoPixelMatrix.ino b/src/_P131_NeoPixelMatrix.ino index 7bea0062db..38307ec4b5 100644 --- a/src/_P131_NeoPixelMatrix.ino +++ b/src/_P131_NeoPixelMatrix.ino @@ -42,14 +42,13 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_131; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_131; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.setPin1Direction(gpio_direction::gpio_output); break; } @@ -271,7 +270,8 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) if ((P131_CONFIG_TILE_HEIGHT > 1) && (varNr == P131_CONFIG_TILE_HEIGHT - 1)) { html_TD(); - addUnit(concat(F("Remaining: "), static_cast(remain))); + addUnit(concat(F("Remaining: "), + static_cast(remain))); } } html_end_table(); @@ -378,8 +378,9 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) P131_CONFIG_FLAG_GET_ROTATION, P131_CONFIG_FLAG_GET_FONTSCALE, static_cast(P131_CONFIG_FLAG_GET_MODE), - P131_CommandTrigger_toString(static_cast( - P131_CONFIG_FLAG_GET_CMD_TRIGGER)), + P131_CommandTrigger_toString( + static_cast( + P131_CONFIG_FLAG_GET_CMD_TRIGGER)), P131_CONFIG_FLAG_GET_BRIGHTNESS, P131_CONFIG_FLAG_GET_MAXBRIGHT, P131_CONFIG_GET_COLOR_FOREGROUND, diff --git a/src/_P132_INA3221.ino b/src/_P132_INA3221.ino index 43aaf8c081..10e2ea5874 100644 --- a/src/_P132_INA3221.ino +++ b/src/_P132_INA3221.ino @@ -34,18 +34,15 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_132; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_132; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P133_LTR390.ino b/src/_P133_LTR390.ino index 925006c70e..f45f408a59 100644 --- a/src/_P133_LTR390.ino +++ b/src/_P133_LTR390.ino @@ -27,18 +27,15 @@ boolean Plugin_133(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_133; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_133; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P134_A02YYUW.ino b/src/_P134_A02YYUW.ino index 12d8034e3e..ee2f14c082 100644 --- a/src/_P134_A02YYUW.ino +++ b/src/_P134_A02YYUW.ino @@ -28,17 +28,14 @@ boolean Plugin_134(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_134; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_134; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; break; } diff --git a/src/_P135_SCD4x.ino b/src/_P135_SCD4x.ino index eb737a6a9b..0a7c6f7f7c 100644 --- a/src/_P135_SCD4x.ino +++ b/src/_P135_SCD4x.ino @@ -42,19 +42,16 @@ boolean Plugin_135(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_135; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CMax100kHz = true; // Max 100 kHz allowed/supported + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_135; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.I2CMax100kHz = true; // Max 100 kHz allowed/supported break; } diff --git a/src/_P137_AXP192.ino b/src/_P137_AXP192.ino index 142f9da14f..3085420459 100644 --- a/src/_P137_AXP192.ino +++ b/src/_P137_AXP192.ino @@ -81,17 +81,18 @@ boolean Plugin_137(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_137; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].PowerManager = true; // So it can be started before SPI is initialized - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_137; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.PowerManager = true; // So it can be started before SPI is initialized + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P138_IP5306.ino b/src/_P138_IP5306.ino index 97735a739a..6843301b26 100644 --- a/src/_P138_IP5306.ino +++ b/src/_P138_IP5306.ino @@ -48,16 +48,17 @@ boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_138; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_138; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P141_PCD8544_Nokia5110.ino b/src/_P141_PCD8544_Nokia5110.ino index abb98b00f1..547a0f0caa 100644 --- a/src/_P141_PCD8544_Nokia5110.ino +++ b/src/_P141_PCD8544_Nokia5110.ino @@ -43,19 +43,16 @@ boolean Plugin_141(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_141; - Device[deviceCount].Type = DEVICE_TYPE_SPI3; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_141; + dev.Type = DEVICE_TYPE_SPI3; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; # if P141_FEATURE_CURSOR_XY_VALUES - Device[deviceCount].ValueCount = 2; + dev.ValueCount = 2; # endif // if P141_FEATURE_CURSOR_XY_VALUES - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; + dev.SendDataOption = false; + dev.TimerOption = true; + dev.TimerOptional = true; break; } diff --git a/src/_P142_AS5600.ino b/src/_P142_AS5600.ino index 6f581f5d9d..21683b0a2a 100644 --- a/src/_P142_AS5600.ino +++ b/src/_P142_AS5600.ino @@ -44,18 +44,17 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_142; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_142; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P143_I2C_Rotary.ino b/src/_P143_I2C_Rotary.ino index 6da3d1a04c..87d26bd7b9 100644 --- a/src/_P143_I2C_Rotary.ino +++ b/src/_P143_I2C_Rotary.ino @@ -48,18 +48,13 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_143; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = false; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_143; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; break; } diff --git a/src/_P144_Vindriktning.ino b/src/_P144_Vindriktning.ino index ff0e1a7e5e..18fbaa3a4b 100644 --- a/src/_P144_Vindriktning.ino +++ b/src/_P144_Vindriktning.ino @@ -1,31 +1,32 @@ -//####################################################################################################### -//################################## Plugin 144: Dust Sensor Ikea Vindriktning ########################## -//####################################################################################################### +// ####################################################################################################### +// ################################## Plugin 144: Dust Sensor Ikea Vindriktning ########################## +// ####################################################################################################### + /* - Plugin is based upon various open sources on the internet. Plugin uses the serial lib to access a serial port - This plugin was written by flashmark + Plugin is based upon various open sources on the internet. Plugin uses the serial lib to access a serial port + This plugin was written by flashmark - This plugin reads the particle concentration from the PM1006 sensor in the Ikea Vindriktning - The original Ikea processor is controlling the PM1006 sensor, the plugin is eavesdropping the responses - DevicePin1 - RX on ESP, TX on PM1006 - DevicePin2 - TX on ESP, RX on PM1006 (optional, currently not accessed by the plugin) - This plugin is intended to be extended with stand alone support for the PM1006 and PM1006K sensors - The stand alone support is not implemented yet -*/ + This plugin reads the particle concentration from the PM1006 sensor in the Ikea Vindriktning + The original Ikea processor is controlling the PM1006 sensor, the plugin is eavesdropping the responses + DevicePin1 - RX on ESP, TX on PM1006 + DevicePin2 - TX on ESP, RX on PM1006 (optional, currently not accessed by the plugin) + This plugin is intended to be extended with stand alone support for the PM1006 and PM1006K sensors + The stand alone support is not implemented yet + */ // #include section #include "_Plugin_Helper.h" #ifdef USES_P144 -#include "src/PluginStructs/P144_data_struct.h" // Sensor abstraction for P144 +# include "src/PluginStructs/P144_data_struct.h" // Sensor abstraction for P144 // Standard plugin defines -#define PLUGIN_144 -#define PLUGIN_ID_144 144 // plugin id -#define PLUGIN_NAME_144 "Dust - PM1006(K) (Vindriktning)" // "Plugin Name" is what will be dislpayed in the selection list -#define PLUGIN_VALUENAME1_144 "PM2.5" // variable output of the plugin. The label is in quotation marks +# define PLUGIN_144 +# define PLUGIN_ID_144 144 // plugin id +# define PLUGIN_NAME_144 "Dust - PM1006(K) (Vindriktning)" // "Plugin Name" is what will be dislpayed in the selection list +# define PLUGIN_VALUENAME1_144 "PM2.5" // variable output of the plugin. The label is in quotation marks // PIN/port configuration is stored in the following: -// CONFIG_PIN1 - Used by plugin_Helper_serial (RX pin) +// CONFIG_PIN1 - Used by plugin_Helper_serial (RX pin) // CONFIG_PIN2 - Used by plugin_Helper_serial (TX pin) // CONFIG_PIN3 - Not used // CONFIG_PORT - Used by the plugin_Helper_serial (serialType) @@ -37,7 +38,7 @@ // N.B. these are aliases for a longer less readable amount of code. See _Plugin_Helper.h // // -// PCONFIG_LABEL(x) is a function to generate a unique label used as HTML id to be able to match +// PCONFIG_LABEL(x) is a function to generate a unique label used as HTML id to be able to match // returned values when saving a configuration. @@ -56,21 +57,15 @@ boolean Plugin_144(uint8_t function, struct EventStruct *event, String& string) { // This case defines the device characteristics - Device[++deviceCount].Number = PLUGIN_ID_144; // Plugin ID number. (PLUGIN_ID_xxx) - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; // How the device is connected. e.g. DEVICE_TYPE_SINGLE => connected through 1 datapin - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; // Type of value the plugin will return. e.g. SENSOR_TYPE_STRING - Device[deviceCount].Ports = 0; // Port to use when device has multiple I/O pins (N.B. not used much) - Device[deviceCount].ValueCount = 1; // The number of output values of a plugin. The value should match the number of keys PLUGIN_VALUENAME1_xxx - Device[deviceCount].OutputDataType = Output_Data_type_t::Default; // Subset of selectable output data types (Default = no selection) - Device[deviceCount].PullUpOption = false; // Allow to set internal pull-up resistors. - Device[deviceCount].InverseLogicOption = false; // Allow to invert the boolean state (e.g. a switch) - Device[deviceCount].FormulaOption = true; // Allow to enter a formula to convert values during read. (not possible with Custom enabled) - Device[deviceCount].Custom = false; - Device[deviceCount].SendDataOption = true; // Allow to send data to a controller. - Device[deviceCount].GlobalSyncOption = true; // No longer used. Was used for ESPeasy values sync between nodes - Device[deviceCount].TimerOption = true; // Allow to set the "Interval" timer for the plugin. - Device[deviceCount].TimerOptional = false; // When taskdevice timer is not set and not optional, use default "Interval" delay (Settings.Delay) - Device[deviceCount].DecimalsOnly = false; // Allow to set the number of decimals (otherwise treated a 0 decimals) + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_144; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.ValueCount = 1; + dev.OutputDataType = Output_Data_type_t::Default; + dev.FormulaOption = true; + dev.SendDataOption = true; + dev.TimerOption = true; break; } @@ -103,7 +98,7 @@ boolean Plugin_144(uint8_t function, struct EventStruct *event, String& string) success = true; break; } - + case PLUGIN_SET_DEFAULTS: { // Set a default config here, which will be called when a plugin is assigned to a task. @@ -136,7 +131,7 @@ boolean Plugin_144(uint8_t function, struct EventStruct *event, String& string) /// addFormNumericBox(string, F("description"), F("plugin_144_description"), PCONFIG(1), min - value, max - value); // after the form has been loaded, set success and break - //serialHelper_serialconfig_webformLoad(event, true); + // serialHelper_serialconfig_webformLoad(event, true); success = true; break; } @@ -146,7 +141,7 @@ boolean Plugin_144(uint8_t function, struct EventStruct *event, String& string) // this case defines the code to be executed when the form is submitted // the plugin settings should be saved to PCONFIG(x) // ping configuration should be read from CONFIG_PIN1 and stored - //serialHelper_webformSave(event); + // serialHelper_webformSave(event); // after the form has been saved successfuly, set success and break success = true; @@ -155,18 +150,18 @@ boolean Plugin_144(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_INIT: { // this case defines code to be executed when the plugin is initialised - const int8_t rxPin = serialHelper_getRxPin(event); - const int8_t txPin = serialHelper_getTxPin(event); - const ESPEasySerialPort portType = serialHelper_getSerialType(event); + const int8_t rxPin = serialHelper_getRxPin(event); + const int8_t txPin = serialHelper_getTxPin(event); + const ESPEasySerialPort portType = serialHelper_getSerialType(event); // Create the P144_data_struct object that will do all the sensor interaction initPluginTaskData(event->TaskIndex, new (std::nothrow) P144_data_struct()); P144_data_struct *P144_data = static_cast(getPluginTaskData(event->TaskIndex)); - if (P144_data != nullptr) + if (P144_data != nullptr) { - success = P144_data->setSerial(portType, rxPin, txPin); // Initialize with existing task data + success = P144_data->setSerial(portType, rxPin, txPin); // Initialize with existing task data } break; } @@ -179,13 +174,14 @@ boolean Plugin_144(uint8_t function, struct EventStruct *event, String& string) static_cast(getPluginTaskData(event->TaskIndex)); if (P144_data != nullptr) { - UserVar.setFloat(event->TaskIndex, 0, P144_data->getValue()); - #ifdef PLUGIN_144_DEBUG + UserVar.setFloat(event->TaskIndex, 0, P144_data->getValue()); + # ifdef PLUGIN_144_DEBUG + if (loglevelActiveFor(LOG_LEVEL_INFO)) { addLogMove(LOG_LEVEL_INFO, concat(F("P144 : READ "), UserVar[event->BaseVarIndex])); } - #endif + # endif // ifdef PLUGIN_144_DEBUG } success = true; break; @@ -204,9 +200,10 @@ boolean Plugin_144(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_EXIT: { // perform cleanup tasks here. For example, free memory - + P144_data_struct *P144_data = static_cast(getPluginTaskData(event->TaskIndex)); + if (P144_data != nullptr) { P144_data->disconnectSerial(); } @@ -227,15 +224,15 @@ boolean Plugin_144(uint8_t function, struct EventStruct *event, String& string) // be careful on what is added here. Heavy processing will result in slowing the module down! P144_data_struct *P144_data = static_cast(getPluginTaskData(event->TaskIndex)); + if (P144_data != nullptr) { success = P144_data->processSensor(); } break; } - } // switch return success; } // function -#endif \ No newline at end of file +#endif // ifdef USES_P144 diff --git a/src/_P145_MQxxx.ino b/src/_P145_MQxxx.ino index 80d52671c9..5e5e895797 100644 --- a/src/_P145_MQxxx.ino +++ b/src/_P145_MQxxx.ino @@ -1,7 +1,7 @@ -//####################################################################################################### -//#################################### Plugin 145: MQ-xx ################################################ -//#################################### by flashmark ################################################ -//####################################################################################################### +// ####################################################################################################### +// #################################### Plugin 145: MQ-xx ################################################ +// #################################### by flashmark ################################################ +// ####################################################################################################### // Analog gas sensors based upon electro-chemical resistance changes like the cheap MQ-xxx series // // References: @@ -11,11 +11,16 @@ // http://davidegironi.blogspot.com/2014/01/cheap-co2-meter-using-mq135-sensor-with.html // https://hackaday.io/project/3475-sniffing-trinket/log/12363-mq135-arduino-library // -//#################################### Change log ############################################### -// 2020-05-21 Refactored and extended by flashmark -// 2022-07-11 Refactored, first attempt for calibration -// 2023-01-06 Reworked after review -//#################################### Description ################################################ +// #################################### Change log ############################################### + +/** Changelog: + * 2025-01-06 tonhuisman: Formatted source uing Uncrustify and small cleanups + * 2023-01-06 Reworked after review + * 2022-07-11 Refactored, first attempt for calibration + * 2020-05-21 Refactored and extended by flashmark + */ + +// #################################### Description ################################################ // This plugin supports some gas sensors for which the resistance depends on a gas concentration (MQ-xxx) // Conversion depends on the sensor type. Main property is the logarithmic Rsensor/Rzero curve // It expects a measurement circuit measuring the voltage over a load resistance Rload using an analog in @@ -34,7 +39,7 @@ // Reference:Reference value expected when calibrating Rzero (configuration P145_PCONFIG_REF) // Rcal: Computed Rzero as if the current measurement value is at Reference level // -// Temperature/humidity compensation is supported for some sensors. +// Temperature/humidity compensation is supported for some sensors. // In these cases the value will be read from another task. // temperature: Read from task/value configured in P145_PCONFIG_TEMP_TASK/P145_PCONFIG_TEMP_VAL // humidity: Read from task/value configured in P145_PCONFIG_HUM_TASK/P145_PCONFIG_HUM_VAL @@ -47,16 +52,16 @@ // Sensor resistance is logaritmic to the concentration of a gas. Sensors are not specific to a single // gas. Key is the ratio between the measured Rs and a reference resistor Rzero (Rs/Rzero). // For each specific gas a somewhat linear relation between gas concentration and the ratio (Rs/Rzero) is -// shown on a log-log chart. Various algorithms are described in above mentioned literature. +// shown on a log-log chart. Various algorithms are described in above mentioned literature. // This plugin supports 3, almost similar, algorithms to make it easier to copy a parameter set from the // internet for a specific sensor/gas combination. -// +// // Calibration algorithm: // Each measurement calculate Rcal assuming the concentration is at the reference level -// Remember the lowest value of Rcal assuming it belongs to measuring the lowest concentration -//################################### Configuration data ############################################### -// This plugin uses the following predefined static data storage -// P145_PCONFIG_RLOAD PCONFIG_FLOAT(0) RLOAD [Ohm] +// Remember the lowest value of Rcal assuming it belongs to measuring the lowest concentration +// ################################### Configuration data ############################################### +// This plugin uses the following predefined static data storage +// P145_PCONFIG_RLOAD PCONFIG_FLOAT(0) RLOAD [Ohm] // P145_PCONFIG_RZERO PCONFIG_FLOAT(1) RZERO [Ohm] // P145_PCONFIG_REF PCONFIG_FLOAT(2) REF. level [ppm] // P145_PCONFIG_FLAGS PCONFIG(0) Enable compensation & Enable Calibration & use low Vcc @@ -65,51 +70,51 @@ // P145_PCONFIG_HUM_TASK PCONFIG(3) Humidity compensation task // P145_PCONFIG_HUM_VAL PCONFIG(4) Humidity compensation value // P145_PCONFIG_SENSORT PCONFIG(5) Sensor type -//####################################################################################################### +// ####################################################################################################### #include "_Plugin_Helper.h" #ifdef USES_P145 -#include "src/PluginStructs/P145_data_struct.h" // MQ-xxx sensor specific data +# include "src/PluginStructs/P145_data_struct.h" // MQ-xxx sensor specific data -#define PLUGIN_145 -#define PLUGIN_ID_145 145 // plugin id -#define PLUGIN_NAME_145 "Gases - MQxxx (MQ135 CO2, MQ3 Alcohol)" // "Plugin Name" is what will be displayed in the selection list -#define PLUGIN_VALUENAME1_145 "level" // variable output of the plugin. The label is in quotation marks -#define PLUGIN_145_DEBUG false // set to true for extra log info in the debug +# define PLUGIN_145 +# define PLUGIN_ID_145 145 // plugin id +# define PLUGIN_NAME_145 "Gases - MQxxx (MQ135 CO2, MQ3 Alcohol)" // "Plugin Name" is what will be displayed in the selection list +# define PLUGIN_VALUENAME1_145 "level" // variable output of the plugin. The label is in quotation marks +# define PLUGIN_145_DEBUG false // set to true for extra log info in the debug // Static, per plugin instance, data stored in the generic ESPeasy structures see usage defined above // PCONFIG(n) : stores an integer (8) // PCONFIG_FLOAT : stors a float (4) // PCONFIG_LONG : stores a long (4, shared with PCONFIG_ULONG) // PCONFIG_ULONG : stores an unsigned long (4, shared with PCONFIG_LONG) -#define P145_PCONFIG_RLOAD PCONFIG_FLOAT(0) -#define P145_PCONFIG_RZERO PCONFIG_FLOAT(1) -#define P145_PCONFIG_REF PCONFIG_FLOAT(2) -#define P145_PCONFIG_FLAGS PCONFIG(0) -#define P145_PCONFIG_TEMP_TASK PCONFIG(1) -#define P145_PCONFIG_TEMP_VAL PCONFIG(2) -#define P145_PCONFIG_HUM_TASK PCONFIG(3) -#define P145_PCONFIG_HUM_VAL PCONFIG(4) -#define P145_PCONFIG_SENSORT PCONFIG(5) +# define P145_PCONFIG_RLOAD PCONFIG_FLOAT(0) +# define P145_PCONFIG_RZERO PCONFIG_FLOAT(1) +# define P145_PCONFIG_REF PCONFIG_FLOAT(2) +# define P145_PCONFIG_FLAGS PCONFIG(0) +# define P145_PCONFIG_TEMP_TASK PCONFIG(1) +# define P145_PCONFIG_TEMP_VAL PCONFIG(2) +# define P145_PCONFIG_HUM_TASK PCONFIG(3) +# define P145_PCONFIG_HUM_VAL PCONFIG(4) +# define P145_PCONFIG_SENSORT PCONFIG(5) // PIN/port configuration is stored in the following: -#define P145_CONFIG_PIN_AIN CONFIG_PIN1 -#define P145_CONFIG_PIN_HEATER CONFIG_PIN2 +# define P145_CONFIG_PIN_AIN CONFIG_PIN1 +# define P145_CONFIG_PIN_HEATER CONFIG_PIN2 // Form IDs used on the device setup page. Should be a short unique string. -#define P145_GUID_TYPE "f01" -#define P145_GUID_RLOAD "f02" -#define P145_GUID_RZERO "f03" -#define P145_GUID_RREFLEVEL "f04" -#define P145_GUID_CAL "f05" -#define P145_GUID_COMP "f06" -#define P145_GUID_LOWVCC "f07" -#define P145_GUID_TEMP_T "f08" -#define P145_GUID_TEMP_V "f09" -#define P145_GUID_HUM_T "f10" -#define P145_GUID_HUM_V "f11" -#define P145_GUID_AINPIN "f12" -#define P145_GUID_HEATPIN "f13" +# define P145_GUID_TYPE "f01" +# define P145_GUID_RLOAD "f02" +# define P145_GUID_RZERO "f03" +# define P145_GUID_RREFLEVEL "f04" +# define P145_GUID_CAL "f05" +# define P145_GUID_COMP "f06" +# define P145_GUID_LOWVCC "f07" +# define P145_GUID_TEMP_T "f08" +# define P145_GUID_TEMP_V "f09" +# define P145_GUID_HUM_T "f10" +# define P145_GUID_HUM_V "f11" +# define P145_GUID_AINPIN "f12" +# define P145_GUID_HEATPIN "f13" // A plugin has to implement the following function // ------------------------------------------------ @@ -122,20 +127,17 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) // Make the plugin known with its options case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_145; - Device[deviceCount].Type = DEVICE_TYPE_CUSTOM0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_145; + dev.Type = DEVICE_TYPE_CUSTOM0; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 1; + dev.SendDataOption = true; + dev.TimerOption = true; break; } - + // Return the DEVICENAME for this plugin case PLUGIN_GET_DEVICENAME: { @@ -153,12 +155,13 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) // Add custom GPIO description on device overview page case PLUGIN_WEBFORM_SHOW_GPIO_DESCR: { - string = F("AIN: "); + string = F("AIN: "); # ifdef ESP32 string += formatGpioLabel(P145_CONFIG_PIN_AIN, false); -#else +# else // ifdef ESP32 string += F("ADC (TOUT)"); -#endif +# endif // ifdef ESP32 + if (validGpio(P145_CONFIG_PIN_HEATER)) { string += F("
HEAT: "); @@ -172,32 +175,38 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { const bool compensate = P145_PCONFIG_FLAGS & 0x0001; // Compensation enable flag - const bool calibrate = (P145_PCONFIG_FLAGS >> 1) & 0x0001; // Calibration enable flag - const bool lowvcc = (P145_PCONFIG_FLAGS >> 2) & 0x0001; // Low voltage power supply indicator - + const bool calibrate = (P145_PCONFIG_FLAGS >> 1) & 0x0001; // Calibration enable flag + const bool lowvcc = (P145_PCONFIG_FLAGS >> 2) & 0x0001; // Low voltage power supply indicator + // FormSelector with all predefined "Sensor - Gas" options String options[P145_MAXTYPES] = {}; - int x = P145_data_struct::getNbrOfTypes(); - if (x > P145_MAXTYPES) + int x = P145_data_struct::getNbrOfTypes(); + + if (x > P145_MAXTYPES) { - x = P145_MAXTYPES; // Clip to prevent array boundary out of range access + x = P145_MAXTYPES; // Clip to prevent array boundary out of range access } - for (int i=0; i(getPluginTaskData(event->TaskIndex)); + if (P145_data != nullptr) { float calVal = P145_data->getCalibrationValue(); - if (definitelyGreaterThan(calVal, 0.0f)) + + if (definitelyGreaterThan(calVal, 0.0f)) { addFormNote(concat(F("Current measurement suggests Rzero= "), calVal)); } @@ -217,26 +228,32 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) addFormCheckBox(F("Low sensor supply voltage"), F(P145_GUID_LOWVCC), lowvcc); addFormSeparator(2); + // Auto calibration and Temp/hum compensation flags are bitfields in P145_PCONFIG_FLAGS addFormCheckBox(F("Enable automatic calibration"), F(P145_GUID_CAL), calibrate); addFormSelector_YesNo(F("Enable temp/humid compensation"), F(P145_GUID_COMP), compensate, true); + // Above selector will fore reloading the page and thus updating the compensate flag // Show the compensation details only when compensation is enabled if (compensate) { addFormNote(F("If compensation is enabled, the Temperature and Humidity values below need to be configured.")); + // temperature addRowLabel(F("Temperature")); addTaskSelect(F(P145_GUID_TEMP_T), P145_PCONFIG_TEMP_TASK); + if (validTaskIndex(P145_PCONFIG_TEMP_TASK)) { LoadTaskSettings(P145_PCONFIG_TEMP_TASK); // we need to load the values from another task for selection! addRowLabel(F("Temperature Value")); addTaskValueSelect(F(P145_GUID_TEMP_V), P145_PCONFIG_TEMP_VAL, P145_PCONFIG_TEMP_TASK); } + // humidity addRowLabel(F("Humidity")); addTaskSelect(F(P145_GUID_HUM_T), P145_PCONFIG_HUM_TASK); + if (validTaskIndex(P145_PCONFIG_HUM_TASK)) { LoadTaskSettings(P145_PCONFIG_HUM_TASK); // we need to load the values from another task for selection! @@ -253,27 +270,29 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) // Save setting from web form for the task case PLUGIN_WEBFORM_SAVE: { - P145_PCONFIG_SENSORT = getFormItemInt(F(P145_GUID_TYPE)); - P145_PCONFIG_RLOAD = getFormItemFloat(F(P145_GUID_RLOAD)); - P145_PCONFIG_RZERO = getFormItemFloat(F(P145_GUID_RZERO)); - P145_PCONFIG_REF = getFormItemFloat(F(P145_GUID_RREFLEVEL)); - const bool compensate = (getFormItemInt(F(P145_GUID_COMP)) == 1); - const bool calibrate = isFormItemChecked(F(P145_GUID_CAL)); - const bool lowvcc = isFormItemChecked(F(P145_GUID_LOWVCC)); + P145_PCONFIG_SENSORT = getFormItemInt(F(P145_GUID_TYPE)); + P145_PCONFIG_RLOAD = getFormItemFloat(F(P145_GUID_RLOAD)); + P145_PCONFIG_RZERO = getFormItemFloat(F(P145_GUID_RZERO)); + P145_PCONFIG_REF = getFormItemFloat(F(P145_GUID_RREFLEVEL)); + const bool compensate = (getFormItemInt(F(P145_GUID_COMP)) == 1); + const bool calibrate = isFormItemChecked(F(P145_GUID_CAL)); + const bool lowvcc = isFormItemChecked(F(P145_GUID_LOWVCC)); P145_PCONFIG_FLAGS = compensate + (calibrate << 1) + (lowvcc << 2); P145_PCONFIG_TEMP_TASK = getFormItemInt(F(P145_GUID_TEMP_T)); P145_PCONFIG_TEMP_VAL = getFormItemInt(F(P145_GUID_TEMP_V)); P145_PCONFIG_HUM_TASK = getFormItemInt(F(P145_GUID_HUM_T)); P145_PCONFIG_HUM_VAL = getFormItemInt(F(P145_GUID_HUM_V)); # ifdef ESP32 - P145_CONFIG_PIN_AIN = getFormItemInt(F(P145_GUID_AINPIN)); -#endif + P145_CONFIG_PIN_AIN = getFormItemInt(F(P145_GUID_AINPIN)); +# endif // ifdef ESP32 P145_CONFIG_PIN_HEATER = getFormItemInt(F(P145_GUID_HEATPIN)); P145_data_struct *P145_data = static_cast(getPluginTaskData(event->TaskIndex)); + if (P145_data != nullptr) { - P145_data->setSensorData(P145_PCONFIG_SENSORT, compensate, calibrate, lowvcc, P145_PCONFIG_RLOAD, P145_PCONFIG_RZERO, P145_PCONFIG_REF); + P145_data->setSensorData(P145_PCONFIG_SENSORT, compensate, calibrate, lowvcc, P145_PCONFIG_RLOAD, P145_PCONFIG_RZERO, + P145_PCONFIG_REF); P145_data->setSensorPins(P145_CONFIG_PIN_AIN, P145_CONFIG_PIN_HEATER); P145_data->dump(); } @@ -285,14 +304,17 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) case PLUGIN_INIT: { P145_data_struct *P145_data = static_cast(getPluginTaskData(event->TaskIndex)); + if (P145_data == nullptr) { P145_data = new (std::nothrow) P145_data_struct(); initPluginTaskData(event->TaskIndex, P145_data); + if (P145_data != nullptr) { P145_data->plugin_init(); - P145_data->setSensorData(P145_PCONFIG_SENSORT, P145_PCONFIG_FLAGS & 0x0001, (P145_PCONFIG_FLAGS >> 1) & 0x0001, (P145_PCONFIG_FLAGS >> 2) & 0x0001, P145_PCONFIG_RLOAD, P145_PCONFIG_RZERO, P145_PCONFIG_REF); + P145_data->setSensorData(P145_PCONFIG_SENSORT, P145_PCONFIG_FLAGS & 0x0001, (P145_PCONFIG_FLAGS >> 1) & 0x0001, + (P145_PCONFIG_FLAGS >> 2) & 0x0001, P145_PCONFIG_RLOAD, P145_PCONFIG_RZERO, P145_PCONFIG_REF); P145_data->setSensorPins(P145_CONFIG_PIN_AIN, P145_CONFIG_PIN_HEATER); P145_data->dump(); } @@ -305,6 +327,7 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) case PLUGIN_TEN_PER_SECOND: { P145_data_struct *P145_data = static_cast(getPluginTaskData(event->TaskIndex)); + if (P145_data != nullptr) { success = P145_data->plugin_ten_per_second(); @@ -316,16 +339,18 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) case PLUGIN_READ: { P145_data_struct *P145_data = static_cast(getPluginTaskData(event->TaskIndex)); + if (P145_data != nullptr) { - float temperature = 20.0f; // A reasonable value in case temperature source task is invalid - float humidity = 60.0f; // A reasonable value in case humidity source task is invalid + float temperature = 20.0f; // A reasonable value in case temperature source task is invalid + float humidity = 60.0f; // A reasonable value in case humidity source task is invalid const bool compensate = P145_PCONFIG_FLAGS & 0x0001; + if (compensate && validTaskIndex(P145_PCONFIG_TEMP_TASK) && validTaskIndex(P145_PCONFIG_HUM_TASK)) { // we're checking a var from another task, so calculate that basevar temperature = UserVar.getFloat(P145_PCONFIG_TEMP_TASK, P145_PCONFIG_TEMP_VAL); // in degrees C - humidity = UserVar.getFloat(P145_PCONFIG_HUM_TASK, P145_PCONFIG_HUM_VAL); // in % relative + humidity = UserVar.getFloat(P145_PCONFIG_HUM_TASK, P145_PCONFIG_HUM_VAL); // in % relative } UserVar.setFloat(event->TaskIndex, 0, P145_data->readValue(temperature, humidity)); success = true; @@ -337,19 +362,21 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) case PLUGIN_ONCE_A_SECOND: { P145_data_struct *P145_data = static_cast(getPluginTaskData(event->TaskIndex)); + if (P145_data != nullptr) { - if ((P145_PCONFIG_FLAGS >> 1) & 0x0001) // Calibration flag + if ((P145_PCONFIG_FLAGS >> 1) & 0x0001) // Calibration flag { // Update Rzero in case of autocalibration // TODO is there an event to signal the plugin code that the value has been updated to prevent polling? - P145_PCONFIG_RZERO = P145_data->getAutoCalibrationValue(); // Store autocalibration value + P145_PCONFIG_RZERO = P145_data->getAutoCalibrationValue(); // Store autocalibration value } - P145_data->heaterControl(); // Execute heater control algorithm + P145_data->heaterControl(); // Execute heater control algorithm } break; } } return success; -} // function Plugin_145() -#endif // USES_P145 \ No newline at end of file +} // function Plugin_145() + +#endif // USES_P145 diff --git a/src/_P146_CacheControllerReader.ino b/src/_P146_CacheControllerReader.ino index 1956d6b255..f383daacca 100644 --- a/src/_P146_CacheControllerReader.ino +++ b/src/_P146_CacheControllerReader.ino @@ -41,20 +41,13 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_146; - Device[deviceCount].Type = DEVICE_TYPE_DUMMY; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].DecimalsOnly = false; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = false; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Default; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_146; + dev.Type = DEVICE_TYPE_DUMMY; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.OutputDataType = Output_Data_type_t::Default; break; } @@ -136,7 +129,7 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string) if (P146_GET_ERASE_BINFILES) { // Check whether we must delete the oldest file - if (P146_TASKVALUE_FILENR != 0 && P146_TASKVALUE_FILENR < readFileNr) { + if ((P146_TASKVALUE_FILENR != 0) && (P146_TASKVALUE_FILENR < readFileNr)) { ControllerCache.deleteCacheBlock(P146_TASKVALUE_FILENR); } } @@ -174,7 +167,8 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string) if (P146_GET_ERASE_BINFILES) { // Check whether we must delete the oldest file const int filenr = P146_TASKVALUE_FILENR; - if (filenr != 0 && filenr < readFileNr) { + + if ((filenr != 0) && (filenr < readFileNr)) { ControllerCache.deleteCacheBlock(filenr); } } @@ -229,7 +223,7 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string) addFormSelector(F("Separator"), F("separator"), 3, separatorLabels, separatorOptions, P146_SEPARATOR_CHARACTER); } addFormCheckBox(F("Join Samples with same Timestamp"), F("jointimestamp"), P146_GET_JOIN_TIMESTAMP); - addFormCheckBox(F("Export only enabled tasks"), F("onlysettasks"), P146_GET_ONLY_SET_TASKS); + addFormCheckBox(F("Export only enabled tasks"), F("onlysettasks"), P146_GET_ONLY_SET_TASKS); addFormNote(F("Download button link only updated after saving")); diff --git a/src/_P147_SGP4x.ino b/src/_P147_SGP4x.ino index 14ff0d5887..cfacd3beb6 100644 --- a/src/_P147_SGP4x.ino +++ b/src/_P147_SGP4x.ino @@ -50,18 +50,15 @@ boolean Plugin_147(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_147; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_147; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P148_POWRxxD_THR3xxD.ino b/src/_P148_POWRxxD_THR3xxD.ino index ad9c6d43dd..235e631356 100644 --- a/src/_P148_POWRxxD_THR3xxD.ino +++ b/src/_P148_POWRxxD_THR3xxD.ino @@ -39,18 +39,12 @@ boolean Plugin_148(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_148; - Device[deviceCount].Type = DEVICE_TYPE_CUSTOM0; - Device[deviceCount].Ports = 0; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = false; - Device[deviceCount].ValueCount = 0; - Device[deviceCount].SendDataOption = false; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_148; + dev.Type = DEVICE_TYPE_CUSTOM0; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.TimerOption = true; + dev.TimerOptional = true; break; } @@ -147,9 +141,9 @@ boolean Plugin_148(uint8_t function, struct EventStruct *event, String& string) html_TR_TD(); addHtml(F("")); diff --git a/src/_P150_TMP117.ino b/src/_P150_TMP117.ino index b4e65a8f49..3c4c6290a8 100644 --- a/src/_P150_TMP117.ino +++ b/src/_P150_TMP117.ino @@ -32,18 +32,15 @@ boolean Plugin_150(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_150; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_150; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P151_Honeywell_pressure.ino b/src/_P151_Honeywell_pressure.ino index 8c0d68f0d5..9684963378 100644 --- a/src/_P151_Honeywell_pressure.ino +++ b/src/_P151_Honeywell_pressure.ino @@ -22,19 +22,16 @@ boolean Plugin_151(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_151; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_151; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } @@ -65,14 +62,14 @@ boolean Plugin_151(uint8_t function, struct EventStruct *event, String& string) // 136 (88 hex) // 152 (98 hex) const uint8_t i2cAddressValues[] = { - 0x28 , - 0x38 , - 0x48 , - 0x58 , - 0x68 , - 0x78 , - 0x88 , - 0x98 + 0x28, + 0x38, + 0x48, + 0x58, + 0x68, + 0x78, + 0x88, + 0x98 }; constexpr size_t addrCount = sizeof(i2cAddressValues) / sizeof(uint8_t); @@ -155,29 +152,30 @@ boolean Plugin_151(uint8_t function, struct EventStruct *event, String& string) break; } -/* - case PLUGIN_TEN_PER_SECOND: - { - P151_data_struct *P151_data = static_cast(getPluginTaskData(event->TaskIndex)); - if (nullptr != P151_data) { - success = P151_data->plugin_ten_per_second(event); - } + /* + case PLUGIN_TEN_PER_SECOND: + { + P151_data_struct *P151_data = static_cast(getPluginTaskData(event->TaskIndex)); - break; - } + if (nullptr != P151_data) { + success = P151_data->plugin_ten_per_second(event); + } - case PLUGIN_FIFTY_PER_SECOND: - { - P151_data_struct *P151_data = static_cast(getPluginTaskData(event->TaskIndex)); + break; + } - if (nullptr != P151_data) { - success = P151_data->plugin_fifty_per_second(event); - } + case PLUGIN_FIFTY_PER_SECOND: + { + P151_data_struct *P151_data = static_cast(getPluginTaskData(event->TaskIndex)); - break; - } -*/ + if (nullptr != P151_data) { + success = P151_data->plugin_fifty_per_second(event); + } + + break; + } + */ } return success; } diff --git a/src/_P152_DAC.ino b/src/_P152_DAC.ino index c9bdf9a6b8..6cc829a21d 100644 --- a/src/_P152_DAC.ino +++ b/src/_P152_DAC.ino @@ -15,13 +15,13 @@ #if defined(SOC_DAC_SUPPORTED) && SOC_DAC_SUPPORTED -#define PLUGIN_152 -#define PLUGIN_ID_152 152 -#define PLUGIN_NAME_152 "Output - ESP32 DAC" -#define PLUGIN_VALUENAME1_152 "Output" +# define PLUGIN_152 +# define PLUGIN_ID_152 152 +# define PLUGIN_NAME_152 "Output - ESP32 DAC" +# define PLUGIN_VALUENAME1_152 "Output" -#define P152_DAC_VALUE UserVar[event->BaseVarIndex] -#define P152_SET_DAC_VALUE(x) UserVar.setFloat(event->TaskIndex, 0, x) +# define P152_DAC_VALUE UserVar[event->BaseVarIndex] +# define P152_SET_DAC_VALUE(x) UserVar.setFloat(event->TaskIndex, 0, x) boolean Plugin_152(uint8_t function, struct EventStruct *event, String& string) @@ -32,14 +32,13 @@ boolean Plugin_152(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_152; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Custom = true; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 1; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_152; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.Custom = true; + dev.FormulaOption = true; + dev.ValueCount = 1; break; } @@ -121,6 +120,6 @@ boolean Plugin_152(uint8_t function, struct EventStruct *event, String& string) return success; } -#endif +#endif // if defined(SOC_DAC_SUPPORTED) && SOC_DAC_SUPPORTED #endif // USES_P152 diff --git a/src/_P153_SHT4x.ino b/src/_P153_SHT4x.ino index f7e3b19e9b..7fd10e4ddf 100644 --- a/src/_P153_SHT4x.ino +++ b/src/_P153_SHT4x.ino @@ -54,18 +54,15 @@ boolean Plugin_153(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_153; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_153; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P154_BMP3xx.ino b/src/_P154_BMP3xx.ino index 5334dc12fa..c4da78f459 100644 --- a/src/_P154_BMP3xx.ino +++ b/src/_P154_BMP3xx.ino @@ -21,18 +21,15 @@ boolean Plugin_154(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_154; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_154; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P159_LD2410.ino b/src/_P159_LD2410.ino index 7493b314ca..81abcac8a6 100644 --- a/src/_P159_LD2410.ino +++ b/src/_P159_LD2410.ino @@ -77,18 +77,18 @@ boolean Plugin_159(uint8_t function, struct EventStruct *event, String& string) { // This case defines the device characteristics - Device[++deviceCount].Number = PLUGIN_ID_159; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].ExitTaskBeforeSave = false; // Enable calling PLUGIN_WEBFORM_SAVE on the instantiated object + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_159; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.ValueCount = 4; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.FormulaOption = true; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; + dev.ExitTaskBeforeSave = false; // Enable calling PLUGIN_WEBFORM_SAVE on the instantiated object break; } diff --git a/src/_P162_MCP42xxx.ino b/src/_P162_MCP42xxx.ino index fd85766991..62ef550503 100644 --- a/src/_P162_MCP42xxx.ino +++ b/src/_P162_MCP42xxx.ino @@ -29,17 +29,16 @@ boolean Plugin_162(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_162; - Device[deviceCount].Type = DEVICE_TYPE_SPI3; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_162; + dev.Type = DEVICE_TYPE_SPI3; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.FormulaOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P163_RadSens.ino b/src/_P163_RadSens.ino index c5933a3aae..e3fb8d233e 100644 --- a/src/_P163_RadSens.ino +++ b/src/_P163_RadSens.ino @@ -37,17 +37,16 @@ boolean Plugin_163(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_163; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_163; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P164_gases_ens160.ino b/src/_P164_gases_ens160.ino index 9537971a0a..b1fbd3a263 100644 --- a/src/_P164_gases_ens160.ino +++ b/src/_P164_gases_ens160.ino @@ -6,7 +6,7 @@ // ####################################################################################################### // P164 "GASES - ENS16x (TVOC, eCO2)" // Plugin for ENS160 & ENS161 TVOC and eCO2 sensor with I2C interface from ScioSense -// For documentation of the ENS160 hardware device see +// For documentation of the ENS160 hardware device see // https://www.sciosense.com/wp-content/uploads/documents/SC-001224-DS-9-ENS160-Datasheet.pdf // // PLugin code: @@ -29,18 +29,15 @@ boolean Plugin_164(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_164; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_164; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } @@ -85,7 +82,7 @@ boolean Plugin_164(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_SET_DEFAULTS: { P164_PCONFIG_I2C_ADDR = P164_ENS160_I2CADDR_1; - success = true; + success = true; break; } @@ -107,10 +104,10 @@ boolean Plugin_164(uint8_t function, struct EventStruct *event, String& string) break; } - float temperature = 20.0f; // A reasonable value in case temperature source task is invalid - float humidity = 50.0f; // A reasonable value in case humidity source task is invalid - float tvoc = 0.0f; // tvoc value to be retrieved from device - float eco2 = 0.0f; // eCO2 value to be retrieved from device + float temperature = 20.0f; // A reasonable value in case temperature source task is invalid + float humidity = 50.0f; // A reasonable value in case humidity source task is invalid + float tvoc = 0.0f; // tvoc value to be retrieved from device + float eco2 = 0.0f; // eCO2 value to be retrieved from device if (validTaskIndex(P164_PCONFIG_TEMP_TASK) && validTaskIndex(P164_PCONFIG_HUM_TASK)) { @@ -140,6 +137,7 @@ boolean Plugin_164(uint8_t function, struct EventStruct *event, String& string) { P164_data_struct *P164_data = static_cast(getPluginTaskData(event->TaskIndex)); + if (nullptr == P164_data) { break; } diff --git a/src/_P165_7SegNeopixel.ino b/src/_P165_7SegNeopixel.ino index 094cc1cdd2..e8b3823df1 100644 --- a/src/_P165_7SegNeopixel.ino +++ b/src/_P165_7SegNeopixel.ino @@ -54,10 +54,11 @@ boolean Plugin_165(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_165; - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE; - Device[deviceCount].setPin1Direction(gpio_direction::gpio_output); + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_165; + dev.Type = DEVICE_TYPE_SINGLE; + dev.VType = Sensor_VType::SENSOR_TYPE_NONE; + dev.setPin1Direction(gpio_direction::gpio_output); break; } diff --git a/src/_P166_GP8403.ino b/src/_P166_GP8403.ino index 4b8d7040d1..5280f89540 100644 --- a/src/_P166_GP8403.ino +++ b/src/_P166_GP8403.ino @@ -53,19 +53,16 @@ boolean Plugin_166(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_166; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; // FIXME: Is this useful? + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_166; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; // FIXME: Is this useful? break; } diff --git a/src/_P167_Vindstyrka.ino b/src/_P167_Vindstyrka.ino index 70cdf8db62..c31dfcbd92 100644 --- a/src/_P167_Vindstyrka.ino +++ b/src/_P167_Vindstyrka.ino @@ -32,21 +32,18 @@ boolean Plugin_167(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_DEVICE_ADD: { // This case defines the device characteristics - Device[++deviceCount].Number = PLUGIN_ID_167; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].I2CNoDeviceCheck = true; - Device[deviceCount].I2CMax100kHz = true; // SEN5x only supports up to 100 kHz - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].OutputDataType = Output_Data_type_t::Simple; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_167; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.I2CNoDeviceCheck = true; + dev.I2CMax100kHz = true; // SEN5x only supports up to 100 kHz + dev.PluginStats = true; + dev.OutputDataType = Output_Data_type_t::Simple; break; } diff --git a/src/_P168_VEML6030_7700.ino b/src/_P168_VEML6030_7700.ino index f58d1c436a..85c4dd1703 100644 --- a/src/_P168_VEML6030_7700.ino +++ b/src/_P168_VEML6030_7700.ino @@ -29,16 +29,15 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_168; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 3; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_168; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_SINGLE; + dev.FormulaOption = true; + dev.ValueCount = 3; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P169_AS3935_LightningDetector.ino b/src/_P169_AS3935_LightningDetector.ino index 8f1f8692bd..fcabe3e257 100644 --- a/src/_P169_AS3935_LightningDetector.ino +++ b/src/_P169_AS3935_LightningDetector.ino @@ -24,19 +24,16 @@ boolean Plugin_169(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_169; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TRIPLE; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].I2CNoDeviceCheck = true; // Sensor may sometimes not respond immediately - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_169; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TRIPLE; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.I2CNoDeviceCheck = true; // Sensor may sometimes not respond immediately + dev.PluginStats = true; break; } diff --git a/src/_P170_Waterlevel.ino b/src/_P170_Waterlevel.ino index ff35455d6c..4209400cc0 100644 --- a/src/_P170_Waterlevel.ino +++ b/src/_P170_Waterlevel.ino @@ -30,17 +30,16 @@ boolean Plugin_170(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_170; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_170; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_P172_BMP3xx_SPI.ino b/src/_P172_BMP3xx_SPI.ino index e6c3442ee9..d420b72723 100644 --- a/src/_P172_BMP3xx_SPI.ino +++ b/src/_P172_BMP3xx_SPI.ino @@ -25,18 +25,15 @@ boolean Plugin_172(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_172; - Device[deviceCount].Type = DEVICE_TYPE_SPI; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_172; + dev.Type = DEVICE_TYPE_SPI; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_BARO; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P173_SHTC3.ino b/src/_P173_SHTC3.ino index 318eb073d1..67a8841b97 100644 --- a/src/_P173_SHTC3.ino +++ b/src/_P173_SHTC3.ino @@ -26,15 +26,15 @@ boolean Plugin_173(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_173; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 2; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_173; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_TEMP_HUM; + dev.FormulaOption = true; + dev.ValueCount = 2; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; break; } diff --git a/src/_P175_PMSx003i.ino b/src/_P175_PMSx003i.ino index 88a48dc369..2e6c2fcb05 100644 --- a/src/_P175_PMSx003i.ino +++ b/src/_P175_PMSx003i.ino @@ -21,23 +21,24 @@ boolean Plugin_175(uint8_t function, struct EventStruct *event, String& string) { boolean success = false; + P053_for_P175 = true; // Ignore this error, compiler can see it as all .ino files are smart-copied into ESPEasy.ino switch (function) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_175; - Device[deviceCount].Type = DEVICE_TYPE_I2C; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].PluginStats = true; - Device[deviceCount].I2CMax100kHz = true; // Max I2C Clock speed 100 kHz - success = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_175; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.PluginStats = true; + dev.I2CMax100kHz = true; // Max I2C Clock speed 100 kHz + break; } diff --git a/src/_P176_VE_Direct.ino b/src/_P176_VE_Direct.ino index 5151030ccc..2b074a38d3 100644 --- a/src/_P176_VE_Direct.ino +++ b/src/_P176_VE_Direct.ino @@ -6,7 +6,8 @@ // ####################################################################################################### /** Changelog: - * 2024-11-24 tonhuisman: Add setting "Events only on updated data" to not generate events/Controller output if no new packets have been received + * 2024-11-24 tonhuisman: Add setting "Events only on updated data" to not generate events/Controller output if no new packets have been + *received * This check is independent from the Updated GetConfig value. * 2024-11-10 tonhuisman: Renamed GetConfig ischanged to updated. * 2024-11-08 tonhuisman: Add successcount, errorcount and ischanged values for GetConfig. IsChanged will reset the state on each call, so @@ -43,16 +44,16 @@ boolean Plugin_176(uint8_t function, struct EventStruct *event, String& string) { case PLUGIN_DEVICE_ADD: { - Device[++deviceCount].Number = PLUGIN_ID_176; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL; - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = 4; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].TimerOptional = true; - Device[deviceCount].PluginStats = true; + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_176; + dev.Type = DEVICE_TYPE_SERIAL; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; break; } diff --git a/src/_Pxxx_PluginTemplate.ino b/src/_Pxxx_PluginTemplate.ino index b72a7b9c63..6de59e6455 100644 --- a/src/_Pxxx_PluginTemplate.ino +++ b/src/_Pxxx_PluginTemplate.ino @@ -104,22 +104,24 @@ boolean Plugin_xxx(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_DEVICE_ADD: { // This case defines the device characteristics, edit appropriately - - Device[++deviceCount].Number = PLUGIN_ID_xxx; // Plugin ID number. (PLUGIN_ID_xxx) - Device[deviceCount].Type = DEVICE_TYPE_SINGLE; // How the device is connected. e.g. DEVICE_TYPE_SINGLE => connected through 1 datapin - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SWITCH; // Type of value the plugin will return. e.g. SENSOR_TYPE_STRING - Device[deviceCount].Ports = 0; // Port to use when device has multiple I/O pins (N.B. not used much) - Device[deviceCount].ValueCount = 0; // The number of output values of a plugin. The value should match the number of keys PLUGIN_VALUENAME1_xxx - Device[deviceCount].OutputDataType = Output_Data_type_t::Default; // Subset of selectable output data types (Default = no selection) - Device[deviceCount].PullUpOption = false; // Allow to set internal pull-up resistors. - Device[deviceCount].InverseLogicOption = false; // Allow to invert the boolean state (e.g. a switch) - Device[deviceCount].FormulaOption = false; // Allow to enter a formula to convert values during read. (not possible with Custom enabled) - Device[deviceCount].Custom = false; - Device[deviceCount].SendDataOption = false; // Allow to send data to a controller. - Device[deviceCount].GlobalSyncOption = true; // No longer used. Was used for ESPeasy values sync between nodes - Device[deviceCount].TimerOption = false; // Allow to set the "Interval" timer for the plugin. - Device[deviceCount].TimerOptional = false; // When taskdevice timer is not set and not optional, use default "Interval" delay (Settings.Delay) - Device[deviceCount].DecimalsOnly = true; // Allow to set the number of decimals (otherwise treated a 0 decimals) + // Attention: dev Values set to 0 or false should be removed to save a few bytes (unneeded assignments) + + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_xxx; // Plugin ID number. (PLUGIN_ID_xxx) + dev.Type = DEVICE_TYPE_SINGLE; // How the device is connected. e.g. DEVICE_TYPE_SINGLE => connected through 1 datapin + dev.VType = Sensor_VType::SENSOR_TYPE_SWITCH; // Type of value the plugin will return. e.g. SENSOR_TYPE_STRING + dev.Ports = 0; // Port to use when device has multiple I/O pins (N.B. not used much) + dev.ValueCount = 0; // The number of output values of a plugin. The value should match the number of keys PLUGIN_VALUENAME1_xxx + dev.OutputDataType = Output_Data_type_t::Default; // Subset of selectable output data types (Default = no selection) + dev.PullUpOption = false; // Allow to set internal pull-up resistors. + dev.InverseLogicOption = false; // Allow to invert the boolean state (e.g. a switch) + dev.FormulaOption = false; // Allow to enter a formula to convert values during read. (not possible with Custom enabled) + dev.Custom = false; + dev.SendDataOption = false; // Allow to send data to a controller. + dev.GlobalSyncOption = true; // No longer used. Was used for ESPeasy values sync between nodes + dev.TimerOption = false; // Allow to set the "Interval" timer for the plugin. + dev.TimerOptional = false; // When taskdevice timer is not set and not optional, use default "Interval" delay (Settings.Delay) + dev.DecimalsOnly = true; // Allow to set the number of decimals (otherwise treated a 0 decimals) break; } @@ -177,7 +179,7 @@ boolean Plugin_xxx(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_GET_DEVICEVALUECOUNT: { - // This is only called when Device[deviceCount].OutputDataType is not Output_Data_type_t::Default + // This is only called when dev.OutputDataType is not Output_Data_type_t::Default // The position in the config parameters used in this example is PCONFIG(Pxxx_OUTPUT_TYPE_INDEX) // Must match the one used in case PLUGIN_GET_DEVICEVTYPE (best to use a define for it) // see P026_Sysinfo.ino for more examples. @@ -188,7 +190,7 @@ boolean Plugin_xxx(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_GET_DEVICEVTYPE: { - // This is only called when Device[deviceCount].OutputDataType is not Output_Data_type_t::Default + // This is only called when dev.OutputDataType is not Output_Data_type_t::Default // The position in the config parameters used in this example is PCONFIG(Pxxx_OUTPUT_TYPE_INDEX) // Must match the one used in case PLUGIN_GET_DEVICEVALUECOUNT (best to use a define for it) // IDX is used here to mark the PCONFIG position used to store the Device VType. From dab8d30993171dd87e5a2dedfae454035afd7d87 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Tue, 7 Jan 2025 23:42:50 +0100 Subject: [PATCH 6/9] [Build] Small code reductions in .ino files [P111] .. [P122] --- src/_P111_RC522_RFID.ino | 10 +++------- src/_P112_AS7265x.ino | 18 ++++++++++++------ src/_P113_VL53L1X.ino | 18 ++++++++++-------- src/_P114_VEML6075.ino | 12 +++++++----- src/_P115_MAX1704x_v2.ino | 3 ++- src/_P117_SCD30.ino | 28 ++++++++++------------------ src/_P119_ITG3205_Gyro.ino | 5 +++-- src/_P121_HMC5883L.ino | 3 --- src/_P122_SHT2x.ino | 28 ++++++++++++++-------------- 9 files changed, 61 insertions(+), 64 deletions(-) diff --git a/src/_P111_RC522_RFID.ino b/src/_P111_RC522_RFID.ino index f084413988..a865e1d106 100644 --- a/src/_P111_RC522_RFID.ino +++ b/src/_P111_RC522_RFID.ino @@ -73,24 +73,20 @@ boolean Plugin_111(uint8_t function, struct EventStruct *event, String& string) addFormSubHeader(F("Options")); { - # ifdef P111_USE_REMOVAL - # define P111_removaltypes 3 - # else // ifdef P111_USE_REMOVAL - # define P111_removaltypes 2 - # endif // ifdef P111_USE_REMOVAL - const __FlashStringHelper *removaltype[P111_removaltypes] = { + const __FlashStringHelper *removaltype[] = { F("None"), F("Autoremove after Time-out"), # ifdef P111_USE_REMOVAL F("Tag removal detection + Time-out") # endif // ifdef P111_USE_REMOVAL }; - const int removalopts[P111_removaltypes] = { // A-typical order for logical order and backward compatibility + const int removalopts[] = { // A-typical order for logical order and backward compatibility 1, 0, # ifdef P111_USE_REMOVAL 2 # endif // P111_USE_REMOVAL }; + constexpr size_t P111_removaltypes = NR_ELEMENTS(removalopts); addFormSelector(F("Tag removal mode"), F("autotagremoval"), P111_removaltypes, removaltype, removalopts, P111_TAG_AUTOREMOVAL); } diff --git a/src/_P112_AS7265x.ino b/src/_P112_AS7265x.ino index 082ed3ae82..b515e4c7c5 100644 --- a/src/_P112_AS7265x.ino +++ b/src/_P112_AS7265x.ino @@ -116,7 +116,8 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) AS7265X_GAIN_16X, AS7265X_GAIN_64X, }; - addFormSelector(F("Gain"), F("Gain"), 4, optionsMode, optionValuesMode, PCONFIG_LONG(0)); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode); + addFormSelector(F("Gain"), F("Gain"), optionCount, optionsMode, optionValuesMode, PCONFIG_LONG(0)); } { // Integration cycles from 0 (2.78ms) to 255 (711ms) @@ -138,7 +139,8 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) 99, 254, }; - addFormSelector(F("Integration Time"), F("IntegrationTime"), 6, optionsMode2, optionValuesMode2, PCONFIG_LONG(1)); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); + addFormSelector(F("Integration Time"), F("IntegrationTime"), optionCount, optionsMode2, optionValuesMode2, PCONFIG_LONG(1)); } # ifndef BUILD_NO_DEBUG addFormNote(F("Raw Readings shall not reach the upper limit of 65535 (Sensor Saturation).")); @@ -164,7 +166,8 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) AS7265X_INDICATOR_CURRENT_LIMIT_4MA, AS7265X_INDICATOR_CURRENT_LIMIT_8MA, }; - addFormSelector(EMPTY_STRING, PCONFIG_LABEL(1), 4, optionsMode3, optionValuesMode3, PCONFIG(1)); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode3); + addFormSelector(EMPTY_STRING, PCONFIG_LABEL(1), optionCount, optionsMode3, optionValuesMode3, PCONFIG(1)); } addHtml(F(" Current Limit")); # ifndef BUILD_NO_DEBUG @@ -189,7 +192,8 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) AS7265X_LED_CURRENT_LIMIT_50MA, AS7265X_LED_CURRENT_LIMIT_100MA, }; - addFormSelector(F("White"), PCONFIG_LABEL(2), 4, optionsMode4, optionValuesMode4, PCONFIG(2)); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode4); + addFormSelector(F("White"), PCONFIG_LABEL(2), optionCount, optionsMode4, optionValuesMode4, PCONFIG(2)); } addHtml(F(" Current Limit")); @@ -209,7 +213,8 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) AS7265X_LED_CURRENT_LIMIT_25MA, AS7265X_LED_CURRENT_LIMIT_50MA, }; - addFormSelector(F("IR"), PCONFIG_LABEL(3), 3, optionsMode5, optionValuesMode5, PCONFIG(3)); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode5); + addFormSelector(F("IR"), PCONFIG_LABEL(3), optionCount, optionsMode5, optionValuesMode5, PCONFIG(3)); } { @@ -220,7 +225,8 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) // sensor.setBulbCurrent(AS7265X_LED_CURRENT_LIMIT_100MA, AS7265x_LED_UV-bad); //Not allowed const __FlashStringHelper *optionsMode6[] = { F("12.5 mA (default)") }; const int optionValuesMode6[] = { AS7265X_LED_CURRENT_LIMIT_12_5MA }; - addFormSelector(F("UV"), PCONFIG_LABEL(4), 1, optionsMode6, optionValuesMode6, PCONFIG(4)); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode6); + addFormSelector(F("UV"), PCONFIG_LABEL(4), optionCount, optionsMode6, optionValuesMode6, PCONFIG(4)); } addFormNote(F("Control Gain and Integration Time after any change to avoid Sensor Saturation!")); diff --git a/src/_P113_VL53L1X.ino b/src/_P113_VL53L1X.ino index d3f3e2eebc..f431101556 100644 --- a/src/_P113_VL53L1X.ino +++ b/src/_P113_VL53L1X.ino @@ -110,7 +110,8 @@ boolean Plugin_113(uint8_t function, struct EventStruct *event, String& string) F("500ms"), }; const int optionValuesMode2[] = { 100, 20, 33, 50, 200, 500 }; - addFormSelector(F("Timing"), F("timing"), 6, optionsMode2, optionValuesMode2, P113_TIMING); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); + addFormSelector(F("Timing"), F("timing"), optionCount, optionsMode2, optionValuesMode2, P113_TIMING); } { @@ -119,7 +120,8 @@ boolean Plugin_113(uint8_t function, struct EventStruct *event, String& string) F("Long (~400cm)"), }; const int optionValuesMode3[2] = { 0, 1 }; - addFormSelector(F("Range"), F("range"), 2, optionsMode3, optionValuesMode3, P113_RANGE); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode3); + addFormSelector(F("Range"), F("range"), optionCount, optionsMode3, optionValuesMode3, P113_RANGE); } addFormCheckBox(F("Send event when value unchanged"), F("notchanged"), P113_SEND_ALWAYS == 1); addFormNote(F("When checked, 'Trigger delta' setting is ignored!")); @@ -180,9 +182,9 @@ boolean Plugin_113(uint8_t function, struct EventStruct *event, String& string) html_add_script(false); addHtml(F("document.addEventListener('DOMContentLoaded', p113_main);")); const __FlashStringHelper *_fmt = F("document.getElementById('%s').onchange=function(){p113_main.upDsp()};"); - addHtml(strformat(_fmt, String(F("roix")).c_str())); - addHtml(strformat(_fmt, String(F("roiy")).c_str())); - addHtml(strformat(_fmt, String(F("optc")).c_str())); + addHtml(strformat(_fmt, FsP(F("roix")))); + addHtml(strformat(_fmt, FsP(F("roiy")))); + addHtml(strformat(_fmt, FsP(F("optc")))); html_add_script_end(); # endif // if P113_USE_ROI @@ -267,11 +269,11 @@ boolean Plugin_113(uint8_t function, struct EventStruct *event, String& string) # if P113_USE_ROI void P113_CheckMinMaxValues(struct EventStruct *event) { - if (0 == P113_ROI_X) { P113_ROI_X = 16; } // Default + if (0 == P113_ROI_X) { P113_ROI_X = 16; } // Default - if (0 == P113_ROI_Y) { P113_ROI_Y = 16; } // Default + if (0 == P113_ROI_Y) { P113_ROI_Y = 16; } // Default - if (0 == P113_OPT_CENTER) { P113_OPT_CENTER = 199; } // Optical Center @ Center of sensor. See matrix in documentation + if (0 == P113_OPT_CENTER) { P113_OPT_CENTER = 199; } // Optical Center @ Center of sensor. See matrix in documentation if ((P113_ROI_X > 10) || (P113_ROI_Y > 10)) { P113_OPT_CENTER = 199; } // Driver behavior } diff --git a/src/_P114_VEML6075.ino b/src/_P114_VEML6075.ino index 9d47c8cb68..740bf75832 100644 --- a/src/_P114_VEML6075.ino +++ b/src/_P114_VEML6075.ino @@ -93,7 +93,8 @@ boolean Plugin_114(uint8_t function, struct EventStruct *event, String& string) P114_IT_400, P114_IT_800, }; - addFormSelector(F("Integration Time"), F("it"), 5, optionsMode2, optionValuesMode2, PCONFIG(1)); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); + addFormSelector(F("Integration Time"), F("it"), optionCount, optionsMode2, optionValuesMode2, PCONFIG(1)); } { @@ -101,7 +102,8 @@ boolean Plugin_114(uint8_t function, struct EventStruct *event, String& string) F("Normal Dynamic"), F("High Dynamic") } ; - addFormSelector(F("Dynamic Setting"), F("hd"), 2, optionsMode3, nullptr, PCONFIG(2)); + constexpr size_t optionCount = NR_ELEMENTS(optionsMode3); + addFormSelector(F("Dynamic Setting"), F("hd"), optionCount, optionsMode3, nullptr, PCONFIG(2)); } success = true; @@ -133,9 +135,9 @@ boolean Plugin_114(uint8_t function, struct EventStruct *event, String& string) return success; } - float UVA = 0.0f; - float UVB = 0.0f; - float UVIndex = 0.0f; + float UVA{}; + float UVB{}; + float UVIndex{}; if (P114_data->read_sensor(UVA, UVB, UVIndex)) { UserVar.setFloat(event->TaskIndex, 0, UVA); diff --git a/src/_P115_MAX1704x_v2.ino b/src/_P115_MAX1704x_v2.ino index 0397b1179b..0623f7cc76 100644 --- a/src/_P115_MAX1704x_v2.ino +++ b/src/_P115_MAX1704x_v2.ino @@ -106,7 +106,8 @@ boolean Plugin_115(uint8_t function, struct EventStruct *event, String& string) MAX1704X_MAX17044, MAX1704X_MAX17048, MAX1704X_MAX17049 }; - addFormSelector(F("Device"), F("device"), 4, options, optionValues, choice); + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Device"), F("device"), optionCount, options, optionValues, choice); } addFormNumericBox(F("Alert threshold"), F("threshold"), P115_THRESHOLD, 1, 32); diff --git a/src/_P117_SCD30.ino b/src/_P117_SCD30.ino index b8fad4df6d..307d69172e 100644 --- a/src/_P117_SCD30.ino +++ b/src/_P117_SCD30.ino @@ -128,23 +128,15 @@ boolean Plugin_117(uint8_t function, struct EventStruct *event, String& string) P117_SENSOR_ALTITUDE = alt; P117_TEMPERATURE_OFFSET = getFormItemFloat(F("tmp")); P117_AUTO_CALIBRATION = isFormItemChecked(F("abc")) ? 1 : 0; - uint16_t interval = getFormItemInt(F("pinterval")); - - if (interval < 2) { interval = 2; } - - if (interval > 1800) { interval = 1800; } - P117_MEASURE_INTERVAL = interval; + const uint16_t interval = getFormItemInt(F("pinterval")); + P117_MEASURE_INTERVAL = constrain(interval, 2, 1800); success = true; break; } case PLUGIN_INIT: { - uint16_t interval = P117_MEASURE_INTERVAL; - - if (interval < 2) { interval = 2; } - - if (interval > 1800) { interval = 1800; } - P117_MEASURE_INTERVAL = interval; + const uint16_t interval = P117_MEASURE_INTERVAL; + P117_MEASURE_INTERVAL = constrain(interval, 2, 1800); initPluginTaskData(event->TaskIndex, new (std::nothrow) P117_data_struct(P117_SENSOR_ALTITUDE, P117_TEMPERATURE_OFFSET, P117_AUTO_CALIBRATION == 1, P117_MEASURE_INTERVAL)); @@ -162,10 +154,10 @@ boolean Plugin_117(uint8_t function, struct EventStruct *event, String& string) return success; } - uint16_t scd30_CO2 = 0u; - uint16_t scd30_CO2EAvg = 0u; - float scd30_Humid = 0.0f; - float scd30_Temp = 0.0f; + uint16_t scd30_CO2{}; + uint16_t scd30_CO2EAvg{}; + float scd30_Humid{}; + float scd30_Temp{}; switch (P117_data->read_sensor(&scd30_CO2, &scd30_CO2EAvg, &scd30_Temp, &scd30_Humid)) { @@ -222,7 +214,7 @@ boolean Plugin_117(uint8_t function, struct EventStruct *event, String& string) log += concat(F("Calibration: "), event->Par1 == 1 ? F("auto") : F("manual")); success = true; } else if (equals(command, F("scdsetfrc")) && (event->Par1 >= 400) && (event->Par1 <= 2000)) { - int res = P117_data->setForcedRecalibrationFactor(event->Par1); + const int res = P117_data->setForcedRecalibrationFactor(event->Par1); log += strformat(F("SCD30 Forced calibration: %d, result: %d"), event->Par1, res); success = true; } else if (equals(command, F("scdgetinterval"))) { @@ -230,7 +222,7 @@ boolean Plugin_117(uint8_t function, struct EventStruct *event, String& string) log += concat(F("Interval: "), value); success = true; } else if (equals(command, F("scdsetinterval")) && (event->Par1 >= 2) && (event->Par1 <= 1800)) { - int res = P117_data->setMeasurementInterval(event->Par1); + const int res = P117_data->setMeasurementInterval(event->Par1); P117_MEASURE_INTERVAL = event->Par1; // Update device configuration log += strformat(F("SCD30 Measurement Interval: %d, result: %d"), event->Par1, res); diff --git a/src/_P119_ITG3205_Gyro.ino b/src/_P119_ITG3205_Gyro.ino index c34d3f50ac..1aa867205b 100644 --- a/src/_P119_ITG3205_Gyro.ino +++ b/src/_P119_ITG3205_Gyro.ino @@ -122,8 +122,9 @@ boolean Plugin_119(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *frequencyOptions[] = { F("10"), F("50") }; - const int frequencyValues[] = { P119_FREQUENCY_10, P119_FREQUENCY_50 }; - addFormSelector(F("Measuring frequency"), F("frequency"), 2, frequencyOptions, frequencyValues, P119_FREQUENCY); + const int frequencyValues[] = { P119_FREQUENCY_10, P119_FREQUENCY_50 }; + constexpr size_t optionCount = NR_ELEMENTS(frequencyValues); + addFormSelector(F("Measuring frequency"), F("frequency"), optionCount, frequencyOptions, frequencyValues, P119_FREQUENCY); addUnit(F("Hz")); success = true; diff --git a/src/_P121_HMC5883L.ino b/src/_P121_HMC5883L.ino index d31eaffef9..6da8a55f5e 100644 --- a/src/_P121_HMC5883L.ino +++ b/src/_P121_HMC5883L.ino @@ -22,9 +22,6 @@ */ # include "src/PluginStructs/P121_data_struct.h" -# include -# include -# include # define PLUGIN_121 # define PLUGIN_ID_121 121 diff --git a/src/_P122_SHT2x.ino b/src/_P122_SHT2x.ino index e19b97e414..96402421cd 100644 --- a/src/_P122_SHT2x.ino +++ b/src/_P122_SHT2x.ino @@ -125,8 +125,6 @@ boolean Plugin_122(uint8_t function, struct EventStruct *event, String& string) // The user's selection will be stored in // PCONFIG(x) (custom configuration) - # define P122_RESOLUTION_OPTIONS 4 - const __FlashStringHelper *options[] = { F("Temp 14 bits / RH 12 bits"), F("Temp 13 bits / RH 10 bits"), @@ -139,7 +137,8 @@ boolean Plugin_122(uint8_t function, struct EventStruct *event, String& string) P122_RESOLUTION_12T_08RH, P122_RESOLUTION_11T_11RH, }; - addFormSelector(F("Resolution"), P122_RESOLUTION_LABEL, P122_RESOLUTION_OPTIONS, options, optionValues, P122_RESOLUTION); + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("Resolution"), P122_RESOLUTION_LABEL, optionCount, options, optionValues, P122_RESOLUTION); # ifndef LIMIT_BUILD_SIZE P122_data_struct *P122_data = static_cast(getPluginTaskData(event->TaskIndex)); @@ -150,17 +149,18 @@ boolean Plugin_122(uint8_t function, struct EventStruct *event, String& string) uint32_t eidb; uint8_t firmware; P122_data->getEID(eida, eidb, firmware); - String txt = F("CHIP ID:"); - txt += formatToHex(eida); - txt += ','; - txt += formatToHex(eidb); - txt += F(" firmware="); - txt += String(firmware); -# ifdef PLUGIN_122_DEBUG - txt += F(" userReg= "); - txt += formatToHex(P122_data->getUserReg()); -# endif // ifdef PLUGIN_122_DEBUG - addFormNote(txt); + addFormNote(strformat(F("CHIP ID:%s,%s firmware=%d" + # ifdef PLUGIN_122_DEBUG + " userReg= %s" + # endif // ifdef PLUGIN_122_DEBUG + ), + formatToHex(eida).c_str(), + formatToHex(eidb).c_str(), + firmware + # ifdef PLUGIN_122_DEBUG + , formatToHex(P122_data->getUserReg()).c_str() + # endif // ifdef PLUGIN_122_DEBUG + )); } # endif // ifndef LIMIT_BUILD_SIZE success = true; From 2555ef7d37947e87e3789cf9133f68fa6465567e Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Wed, 8 Jan 2025 21:08:00 +0100 Subject: [PATCH 7/9] [Bugfix] AdaGFX helper [#length.""] and #textheight didn't support period separator --- src/src/Helpers/AdafruitGFX_helper.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/src/Helpers/AdafruitGFX_helper.cpp b/src/src/Helpers/AdafruitGFX_helper.cpp index e858c55dab..fb9171c026 100644 --- a/src/src/Helpers/AdafruitGFX_helper.cpp +++ b/src/src/Helpers/AdafruitGFX_helper.cpp @@ -2176,7 +2176,7 @@ bool AdafruitGFX_helper::processCommand(const String& string) { # if ADAGFX_ARGUMENT_VALIDATION const int16_t curWin = getWindow(); - if (curWin != 0) { selectWindow(0); } // Validate against raw window coordinates + if (curWin != 0) { selectWindow(0); } // Validate against raw window coordinates if (argCount == 6) { setRotation(nParams[5]); } // Use requested rotation @@ -2313,10 +2313,15 @@ bool AdafruitGFX_helper::pluginGetConfigValue(String& string) { case adagfx_getcommands_e::textheight: // length/textheight: get text length or height { - int16_t x1, y1; - uint16_t w1, h1; - String newString = AdaGFXparseTemplate(parseStringToEndKeepCaseNoTrim(string, 2), 0); - _display->getTextBounds(newString, 0, 0, &x1, &y1, &w1, &h1); // Count length and height + int16_t x1{}, y1{}; + uint16_t w1{}, h1{}; + String newString = parseStringToEndKeepCaseNoTrim(string, 2, sep); + + if (!newString.isEmpty()) { + newString = AdaGFXparseTemplate(newString, 0); + + _display->getTextBounds(newString, 0, 0, &x1, &y1, &w1, &h1); // Count length and height + } if (adagfx_getcommands_e::length == cmd) { string = w1; @@ -3358,12 +3363,13 @@ bool AdafruitGFX_helper::showBmp(const String& filename, } constexpr size_t errorcode = (size_t)-1; - size_t pos = file.position(); + size_t pos = file.position(); + if (pos == errorcode) { pos = 0; } - if (pos != bmpPos) { // Need seek? + if (pos != bmpPos) { // Need seek? if (transact && canTransact) { _tft->dmaWait(); _tft->endWrite(); // End TFT SPI transaction From 4a8c4ca4a1350670f6bceba1227b3c72664d1e46 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Wed, 8 Jan 2025 22:49:27 +0100 Subject: [PATCH 8/9] [Build] Small code reductions in .ino files [P123] .. [P176] --- src/_P123_I2CTouch.ino | 3 ++- src/_P124_MultiRelay.ino | 7 ++++--- src/_P126_74HC595.ino | 5 +++-- src/_P129_74HC165.ino | 27 +++++++++++++++----------- src/_P131_NeoPixelMatrix.ino | 2 +- src/_P132_INA3221.ino | 26 ++++++++++++------------- src/_P133_LTR390.ino | 13 ++++++++----- src/_P135_SCD4x.ino | 3 ++- src/_P137_AXP192.ino | 9 ++++++--- src/_P138_IP5306.ino | 3 ++- src/_P141_PCD8544_Nokia5110.ino | 6 +++--- src/_P142_AS5600.ino | 15 +++++++++----- src/_P143_I2C_Rotary.ino | 12 ++++++++---- src/_P146_CacheControllerReader.ino | 6 +++--- src/_P147_SGP4x.ino | 5 +++-- src/_P150_TMP117.ino | 16 ++++++++++++--- src/_P151_Honeywell_pressure.ino | 2 +- src/_P153_SHT4x.ino | 3 ++- src/_P166_GP8403.ino | 3 ++- src/_P168_VEML6030_7700.ino | 12 ++++++++---- src/_P169_AS3935_LightningDetector.ino | 15 ++++++++------ 21 files changed, 118 insertions(+), 75 deletions(-) diff --git a/src/_P123_I2CTouch.ino b/src/_P123_I2CTouch.ino index 667e278a9c..e97b65e21c 100644 --- a/src/_P123_I2CTouch.ino +++ b/src/_P123_I2CTouch.ino @@ -200,9 +200,10 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string) static_cast(P123_TouchType_e::CHSC5816), static_cast(P123_TouchType_e::Automatic), }; + constexpr size_t optionCount = NR_ELEMENTS(touchTypeOptions); addFormSelector(F("Touchscreen type (address)"), F("ttype"), - NR_ELEMENTS(touchTypeOptions), + optionCount, touchTypes, touchTypeOptions, P123_GET_TOUCH_TYPE); diff --git a/src/_P124_MultiRelay.ino b/src/_P124_MultiRelay.ino index e17ae31f9c..8220b8ff55 100644 --- a/src/_P124_MultiRelay.ino +++ b/src/_P124_MultiRelay.ino @@ -110,7 +110,8 @@ boolean Plugin_124(uint8_t function, struct EventStruct *event, String& string) F("4"), F("8") }; const int optionValuesMode2[] { 2, 4, 8 }; - addFormSelector(F("Number of relays"), F("relays"), 3, optionsMode2, optionValuesMode2, P124_CONFIG_RELAY_COUNT, true); + constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); + addFormSelector(F("Number of relays"), F("relays"), optionCount, optionsMode2, optionValuesMode2, P124_CONFIG_RELAY_COUNT, true); addFormSelector_YesNo(F("Initialize relays on startup"), getPluginCustomArgName(P124_FLAGS_INIT_RELAYS), @@ -123,7 +124,7 @@ boolean Plugin_124(uint8_t function, struct EventStruct *event, String& string) addFormNote(F("Disabled: Applied once per restart, Enabled: Applied on every plugin start, like on Submit of this page")); for (int i = 0; i < P124_CONFIG_RELAY_COUNT; ++i) { - const String label = strformat(F("Relay %d initial state (on/off)"), i + 1); + const String label = strformat(F("Relay %d %sstate (on/off)"), i + 1, FsP(F("initial "))); addFormCheckBox(label, getPluginCustomArgName(i), bitRead(P124_CONFIG_FLAGS, i)); } } @@ -134,7 +135,7 @@ boolean Plugin_124(uint8_t function, struct EventStruct *event, String& string) if (bitRead(P124_CONFIG_FLAGS, P124_FLAGS_EXIT_RELAYS)) { for (int i = 0; i < P124_CONFIG_RELAY_COUNT; ++i) { - const String label = strformat(F("Relay %d exit-state (on/off)"), i + 1); + const String label = strformat(F("Relay %d %sstate (on/off)"), i + 1, FsP(F("exit-"))); addFormCheckBox(label, getPluginCustomArgName(i + P124_FLAGS_EXIT_OFFSET), bitRead(P124_CONFIG_FLAGS, i + P124_FLAGS_EXIT_OFFSET)); } addFormNote(F("ATTENTION: These Relay states will be set when the task is enabled and the settings are saved!")); diff --git a/src/_P126_74HC595.ino b/src/_P126_74HC595.ino index bc1e8dd4e5..81bd15365b 100644 --- a/src/_P126_74HC595.ino +++ b/src/_P126_74HC595.ino @@ -165,8 +165,9 @@ boolean Plugin_126(uint8_t function, struct EventStruct *event, String& string) F("Decimal & hex/bin"), F("Decimal only"), F("Hex/bin only") }; - const int outputValues[] = { P126_OUTPUT_BOTH, P126_OUTPUT_DEC_ONLY, P126_OUTPUT_HEXBIN }; - addFormSelector(F("Output selection"), F("output"), 3, outputOptions, outputValues, P126_CONFIG_FLAGS_GET_OUTPUT_SELECTION); + const int outputValues[] = { P126_OUTPUT_BOTH, P126_OUTPUT_DEC_ONLY, P126_OUTPUT_HEXBIN }; + constexpr size_t optionCount = NR_ELEMENTS(outputValues); + addFormSelector(F("Output selection"), F("output"), optionCount, outputOptions, outputValues, P126_CONFIG_FLAGS_GET_OUTPUT_SELECTION); addFormCheckBox(F("Restore Values on warm boot"), F("valrestore"), P126_CONFIG_FLAGS_GET_VALUES_RESTORE); diff --git a/src/_P129_74HC165.ino b/src/_P129_74HC165.ino index 195b090c91..60a7bf5589 100644 --- a/src/_P129_74HC165.ino +++ b/src/_P129_74HC165.ino @@ -178,8 +178,14 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *frequencyOptions[] = { F("10/sec (100 msec)"), F("50/sec (20 msec)") }; - const int frequencyValues[] = { P129_FREQUENCY_10, P129_FREQUENCY_50 }; - addFormSelector(F("Sample frequency"), F("frequency"), 2, frequencyOptions, frequencyValues, P129_CONFIG_FLAGS_GET_READ_FREQUENCY); + const int frequencyValues[] = { P129_FREQUENCY_10, P129_FREQUENCY_50 }; + constexpr size_t optionCount = NR_ELEMENTS(frequencyValues); + addFormSelector(F("Sample frequency"), + F("frequency"), + optionCount, + frequencyOptions, + frequencyValues, + P129_CONFIG_FLAGS_GET_READ_FREQUENCY); addFormSubHeader(F("Display and output")); @@ -191,8 +197,10 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string) F("Decimal & hex/bin"), F("Decimal only"), F("Hex/bin only") }; - const int outputValues[] = { P129_OUTPUT_BOTH, P129_OUTPUT_DEC_ONLY, P129_OUTPUT_HEXBIN }; - addFormSelector(F("Output selection"), F("outputsel"), 3, outputOptions, outputValues, P129_CONFIG_FLAGS_GET_OUTPUT_SELECTION); + const int outputValues[] = { P129_OUTPUT_BOTH, P129_OUTPUT_DEC_ONLY, P129_OUTPUT_HEXBIN }; + constexpr size_t outputCount = NR_ELEMENTS(outputValues); + addFormSelector(F("Output selection"), F("outputsel"), outputCount, outputOptions, outputValues, + P129_CONFIG_FLAGS_GET_OUTPUT_SELECTION); addFormCheckBox(F("Separate events per pin"), F("separate_events"), P129_CONFIG_FLAGS_GET_SEPARATE_EVENTS == 1); @@ -292,13 +300,10 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string) # ifndef P129_DEBUG_LOG if (loglevelActiveFor(LOG_LEVEL_INFO) && ((i % 4 == 3) || (i == P129_CONFIG_CHIP_COUNT))) { - String log = F("74HC165 Writing to: "); - log += (i / 4); - log += F(", offset: "); - log += (off * 8); - log += F(", bits: "); - log += P129_ul2stringFixed(bits, BIN); - addLog(LOG_LEVEL_INFO, log); + addLog(LOG_LEVEL_INFO, strformat(F("74HC165 Writing to: %d, offset: %d, bits: %s"), + i / 4, + off * 8, + P129_ul2stringFixed(bits, BIN).c_str())); } # endif // ifndef P129_DEBUG_LOG off++; diff --git a/src/_P131_NeoPixelMatrix.ino b/src/_P131_NeoPixelMatrix.ino index 38307ec4b5..24371d69d0 100644 --- a/src/_P131_NeoPixelMatrix.ino +++ b/src/_P131_NeoPixelMatrix.ino @@ -350,7 +350,7 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) error += SaveCustomTaskSettings(event->TaskIndex, strings, P131_Nlines, 0); - if (error.length() > 0) { + if (!error.isEmpty()) { addHtmlError(error); } diff --git a/src/_P132_INA3221.ino b/src/_P132_INA3221.ino index 10e2ea5874..314970893a 100644 --- a/src/_P132_INA3221.ino +++ b/src/_P132_INA3221.ino @@ -100,7 +100,6 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { - #define INA3221_var_OPTION 6 { const __FlashStringHelper *varOptions[] = { F("Current channel 1"), @@ -110,31 +109,31 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) F("Current channel 3"), F("Voltage channel 3") }; + constexpr size_t optionCount = NR_ELEMENTS(varOptions); for (uint8_t r = 0; r < VARS_PER_TASK; ++r) { addFormSelector(concat(F("Power value "), r + 1), - getPluginCustomArgName(r), INA3221_var_OPTION, varOptions, NULL, PCONFIG(P132_CONFIG_BASE + r)); + getPluginCustomArgName(r), optionCount, varOptions, NULL, PCONFIG(P132_CONFIG_BASE + r)); } } addFormSubHeader(F("Hardware")); - #define INA3221_shunt_OPTION 3 { const __FlashStringHelper *varshuntptions[] = { F("0.1 ohm"), F("0.01 ohm"), F("0.005 ohm"), }; - const int shuntvalue[] = { 1, 10, 20 }; - addFormSelector(F("Shunt resistor"), F("shunt"), INA3221_shunt_OPTION, varshuntptions, shuntvalue, P132_SHUNT); + const int shuntvalue[] = { 1, 10, 20 }; + constexpr size_t optionCount = NR_ELEMENTS(shuntvalue); + addFormSelector(F("Shunt resistor"), F("shunt"), optionCount, varshuntptions, shuntvalue, P132_SHUNT); addFormNote(F("Select as is installed on the board.")); } addFormSubHeader(F("Measurement")); - #define INA3221_average_OPTION 8 { const __FlashStringHelper *averagingSamples[] = { F("1 (default)"), @@ -146,17 +145,17 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) F("512"), F("1024"), }; - const int averageValue[] = { 0b000, 0b001, 0b010, 0b011, 0b100, 0b101, 0b110, 0b111 }; + const int averageValue[] = { 0b000, 0b001, 0b010, 0b011, 0b100, 0b101, 0b110, 0b111 }; + constexpr size_t optionCount = NR_ELEMENTS(averageValue); addFormSelector(F("Averaging samples"), F("average"), - INA3221_average_OPTION, + optionCount, averagingSamples, averageValue, P132_GET_AVERAGE); addFormNote(F("Samples > 16 then min. Interval: 64= 4, 128= 7, 256= 14, 512= 26, 1024= 52 seconds!")); } - #define INA3221_conversion_OPTION 8 { const __FlashStringHelper *conversionRates[] = { F("140 µsec"), @@ -171,16 +170,17 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) // 140us 204us 332us 588us 1.1ms 2.1ms 4.1ms 8.2ms const int conversionValues[] = { 0b000, 0b001, 0b010, 0b011, 0b100, 0b101, 0b110, 0b111 }; + constexpr size_t optionCount = NR_ELEMENTS(conversionValues); addFormSelector(F("Conversion rate Voltage"), F("conv_v"), - INA3221_conversion_OPTION, + optionCount, conversionRates, conversionValues, P132_GET_CONVERSION_B); addFormSelector(F("Conversion rate Current"), F("conv_c"), - INA3221_conversion_OPTION, + optionCount, conversionRates, conversionValues, P132_GET_CONVERSION_S); @@ -230,11 +230,9 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) return success; } - uint8_t reg; - for (uint8_t r = 0; r < VARS_PER_TASK; ++r) { // VALUES 1..4 - reg = static_cast(PCONFIG(P132_CONFIG_BASE + r) + 1); + const uint8_t reg = static_cast(PCONFIG(P132_CONFIG_BASE + r) + 1); if ((reg == 2) || (reg == 4) || (reg == 6)) { UserVar.setFloat(event->TaskIndex, r, diff --git a/src/_P133_LTR390.ino b/src/_P133_LTR390.ino index f45f408a59..39390ec521 100644 --- a/src/_P133_LTR390.ino +++ b/src/_P133_LTR390.ino @@ -96,7 +96,8 @@ boolean Plugin_133(uint8_t function, struct EventStruct *event, String& string) static_cast(P133_selectMode_e::UVMode), static_cast(P133_selectMode_e::ALSMode) }; - addFormSelector(F("Read mode"), F("mode"), 3, selectModeOptions, selectModeValues, P133_SELECT_MODE, true); + constexpr size_t optionCount = NR_ELEMENTS(selectModeValues); + addFormSelector(F("Read mode"), F("mode"), optionCount, selectModeOptions, selectModeValues, P133_SELECT_MODE, true); } const __FlashStringHelper *gainOptions[] = { F("1x"), F("3x"), F("6x"), F("9x"), F("18x") }; @@ -107,6 +108,7 @@ boolean Plugin_133(uint8_t function, struct EventStruct *event, String& string) LTR390_GAIN_9, LTR390_GAIN_18 }; + constexpr size_t gainCount = NR_ELEMENTS(gainValues); const __FlashStringHelper *resolutionOptions[] = { F("20 bit"), @@ -124,15 +126,16 @@ boolean Plugin_133(uint8_t function, struct EventStruct *event, String& string) LTR390_RESOLUTION_16BIT, LTR390_RESOLUTION_13BIT, }; + constexpr size_t resolutionCount = NR_ELEMENTS(resolutionValues); if (static_cast(P133_SELECT_MODE) != P133_selectMode_e::ALSMode) { - addFormSelector(F("UV Gain"), F("uvgain"), 5, gainOptions, gainValues, P133_UVGAIN); - addFormSelector(F("UV Resolution"), F("uvres"), 6, resolutionOptions, resolutionValues, P133_UVRESOLUTION); + addFormSelector(F("UV Gain"), F("uvgain"), gainCount, gainOptions, gainValues, P133_UVGAIN); + addFormSelector(F("UV Resolution"), F("uvres"), resolutionCount, resolutionOptions, resolutionValues, P133_UVRESOLUTION); } if (static_cast(P133_SELECT_MODE) != P133_selectMode_e::UVMode) { - addFormSelector(F("Ambient Gain"), F("alsgain"), 5, gainOptions, gainValues, P133_ALSGAIN); - addFormSelector(F("Ambient Resolution"), F("alsres"), 6, resolutionOptions, resolutionValues, P133_ALSRESOLUTION); + addFormSelector(F("Ambient Gain"), F("alsgain"), gainCount, gainOptions, gainValues, P133_ALSGAIN); + addFormSelector(F("Ambient Resolution"), F("alsres"), resolutionCount, resolutionOptions, resolutionValues, P133_ALSRESOLUTION); } addFormCheckBox(F("Reset sensor on init"), F("initreset"), P133_INITRESET == 1); diff --git a/src/_P135_SCD4x.ino b/src/_P135_SCD4x.ino index 0a7c6f7f7c..4f5f2d51e8 100644 --- a/src/_P135_SCD4x.ino +++ b/src/_P135_SCD4x.ino @@ -104,7 +104,8 @@ boolean Plugin_135(uint8_t function, struct EventStruct *event, String& string) static_cast(scd4x_sensor_type_e::SCD4x_SENSOR_SCD40), static_cast(scd4x_sensor_type_e::SCD4x_SENSOR_SCD41), }; - addFormSelector(F("Sensor model"), F("ptype"), 2, sensorTypes, sensorTypeOptions, P135_SENSOR_TYPE, true); + constexpr size_t optionCount = NR_ELEMENTS(sensorTypeOptions); + addFormSelector(F("Sensor model"), F("ptype"), optionCount, sensorTypes, sensorTypeOptions, P135_SENSOR_TYPE, true); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Page will reload on change.")); # endif // ifndef LIMIT_BUILD_SIZE diff --git a/src/_P137_AXP192.ino b/src/_P137_AXP192.ino index 3085420459..02b214217a 100644 --- a/src/_P137_AXP192.ino +++ b/src/_P137_AXP192.ino @@ -189,8 +189,9 @@ boolean Plugin_137(uint8_t function, struct EventStruct *event, String& string) static_cast(P137_PredefinedDevices_e::M5Stack_Core2), static_cast(P137_PredefinedDevices_e::LilyGO_TBeam), static_cast(P137_PredefinedDevices_e::UserDefined) }; // keep last and at 99 !! + constexpr size_t optionCount = NR_ELEMENTS(predefinedValues); addFormSelector(F("Predefined device configuration"), F("predef"), - sizeof(predefinedValues) / sizeof(int), + optionCount, predefinedNames, predefinedValues, 0, !Settings.isPowerManagerTask(event->TaskIndex)); if (!Settings.isPowerManagerTask(event->TaskIndex)) { @@ -265,11 +266,12 @@ boolean Plugin_137(uint8_t function, struct EventStruct *event, String& string) F("disabled"), F("disabled"), }; + constexpr size_t optionCount = NR_ELEMENTS(bootStateValues); for (int i = 0; i < 5; ++i) { // GPIO0..4 const String id = concat(F("pgpio"), i); addRowLabel(concat(F("Initial state GPIO"), i)); - addSelector(id, sizeof(bootStateValues) / sizeof(int), + addSelector(id, optionCount, bootStates, bootStateValues, bootStateAttributes, get3BitFromUL(P137_CONFIG_FLAGS, i * 3), false, !bitRead(P137_CONFIG_DISABLEBITS, i + 3), F("") @@ -334,12 +336,13 @@ boolean Plugin_137(uint8_t function, struct EventStruct *event, String& string) static_cast(P137_valueOptions_e::DCDC2), static_cast(P137_valueOptions_e::DCDC3), }; + constexpr size_t optionCount = NR_ELEMENTS(valValues); for (uint8_t i = 0; i < P137_NR_OUTPUT_VALUES; ++i) { sensorTypeHelper_loadOutputSelector(event, P137_CONFIG_BASE + i, i, - sizeof(valValues) / sizeof(int), + optionCount, valOptions, valValues); } diff --git a/src/_P138_IP5306.ino b/src/_P138_IP5306.ino index 6843301b26..25310a0bd3 100644 --- a/src/_P138_IP5306.ino +++ b/src/_P138_IP5306.ino @@ -144,12 +144,13 @@ boolean Plugin_138(uint8_t function, struct EventStruct *event, String& string) static_cast(P138_valueOptions_e::ChargeLevel), static_cast(P138_valueOptions_e::PowerSource), }; + constexpr size_t optionCount = NR_ELEMENTS(valValues); for (uint8_t i = 0; i < P138_NR_OUTPUT_VALUES; i++) { sensorTypeHelper_loadOutputSelector(event, P138_CONFIG_BASE + i, i, - sizeof(valValues) / sizeof(int), + optionCount, valOptions, valValues); } diff --git a/src/_P141_PCD8544_Nokia5110.ino b/src/_P141_PCD8544_Nokia5110.ino index 547a0f0caa..c56f909411 100644 --- a/src/_P141_PCD8544_Nokia5110.ino +++ b/src/_P141_PCD8544_Nokia5110.ino @@ -147,9 +147,10 @@ boolean Plugin_141(uint8_t function, struct EventStruct *event, String& string) static_cast(P141_CommandTrigger::pcd8544), static_cast(P141_CommandTrigger::lcd), }; + constexpr size_t optionCount = NR_ELEMENTS(commandTriggerOptions); addFormSelector(F("Write Command trigger"), F("pcmdtrigger"), - NR_ELEMENTS(commandTriggerOptions), + optionCount, commandTriggers, commandTriggerOptions, P141_CONFIG_FLAG_GET_CMD_TRIGGER); @@ -222,13 +223,12 @@ boolean Plugin_141(uint8_t function, struct EventStruct *event, String& string) P141_CONFIG_FLAGS = lSettings; String strings[P141_Nlines]; - String error; for (uint8_t varNr = 0; varNr < P141_Nlines; ++varNr) { strings[varNr] = web_server.arg(getPluginCustomArgName(varNr)); } - error = SaveCustomTaskSettings(event->TaskIndex, strings, P141_Nlines, 0); + const String error = SaveCustomTaskSettings(event->TaskIndex, strings, P141_Nlines, 0); if (!error.isEmpty()) { addHtmlError(error); diff --git a/src/_P142_AS5600.ino b/src/_P142_AS5600.ino index 21683b0a2a..260d8b27cb 100644 --- a/src/_P142_AS5600.ino +++ b/src/_P142_AS5600.ino @@ -172,9 +172,10 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_MODE_DEGREES, AS5600_MODE_RADIANS, }; + constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); addFormSelector(F("Output range"), F("range"), - NR_ELEMENTS(configurationOptions), + optionCount, configurations, configurationOptions, P142_GET_OUTPUT_MODE); @@ -210,9 +211,10 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_POWERMODE_LOW2, AS5600_POWERMODE_LOW3, }; + constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); addFormSelector(F("Power mode"), F("pow"), - NR_ELEMENTS(configurationOptions), + optionCount, configurations, configurationOptions, P142_GET_POWER_MODE); @@ -234,9 +236,10 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_HYST_LSB2, AS5600_HYST_LSB3, }; + constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); addFormSelector(F("Hysteresis"), F("hyst"), - NR_ELEMENTS(configurationOptions), + optionCount, configurations, configurationOptions, P142_GET_HYSTERESIS); @@ -254,9 +257,10 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_SLOW_FILT_4X, AS5600_SLOW_FILT_2X, }; + constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); addFormSelector(F("Slow filter"), F("sflt"), - NR_ELEMENTS(configurationOptions), + optionCount, configurations, configurationOptions, P142_GET_SLOW_FILTER); @@ -282,9 +286,10 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_FAST_FILT_LSB24, AS5600_FAST_FILT_LSB10, }; + constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); addFormSelector(F("Fast filter"), F("fflt"), - NR_ELEMENTS(configurationOptions), + optionCount, configurations, configurationOptions, P142_GET_FAST_FILTER); diff --git a/src/_P143_I2C_Rotary.ino b/src/_P143_I2C_Rotary.ino index 87d26bd7b9..cfe4748341 100644 --- a/src/_P143_I2C_Rotary.ino +++ b/src/_P143_I2C_Rotary.ino @@ -171,9 +171,10 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) static_cast(P143_DeviceType_e::DFRobotEncoder) # endif // if P143_FEATURE_INCLUDE_DFROBOT }; + constexpr size_t optionCount = NR_ELEMENTS(selectModeValues); addFormSelector(F("Encoder type"), F("pdevice"), - sizeof(selectModeValues) / sizeof(int), + optionCount, selectModeOptions, selectModeValues, P143_ENCODER_TYPE, @@ -239,9 +240,10 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) static_cast(P143_M5StackLed_e::Led1Only), static_cast(P143_M5StackLed_e::Led2Only), }; + constexpr size_t optionCount = NR_ELEMENTS(selectLedModeValues); addFormSelector(F("Color map Leds"), F("pledsel"), - sizeof(selectLedModeValues) / sizeof(int), + optionCount, selectLedModeOptions, selectLedModeValues, P143_M5STACK_SELECTION); @@ -284,9 +286,10 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) static_cast(P143_ButtonAction_e::PushButtonInverted), static_cast(P143_ButtonAction_e::ToggleSwitch), }; + constexpr size_t optionCount = NR_ELEMENTS(selectButtonValues); addFormSelector(F("Button action"), F("pbutton"), - sizeof(selectButtonValues) / sizeof(int), + optionCount, selectButtonOptions, selectButtonValues, P143_PLUGIN_BUTTON_ACTION); @@ -326,9 +329,10 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) static_cast(P143_CounterMapping_e::ColorMapping), static_cast(P143_CounterMapping_e::ColorGradient), }; + constexpr size_t optionCount = NR_ELEMENTS(selectCounterValues); addFormSelector(F("Counter color mapping"), F("pmap"), - sizeof(selectCounterValues) / sizeof(int), + optionCount, selectCounterOptions, selectCounterValues, P143_PLUGIN_COUNTER_MAPPING); diff --git a/src/_P146_CacheControllerReader.ino b/src/_P146_CacheControllerReader.ino index f383daacca..83edccd923 100644 --- a/src/_P146_CacheControllerReader.ino +++ b/src/_P146_CacheControllerReader.ino @@ -220,7 +220,8 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string) ',', ';' }; - addFormSelector(F("Separator"), F("separator"), 3, separatorLabels, separatorOptions, P146_SEPARATOR_CHARACTER); + constexpr size_t optionCount = NR_ELEMENTS(separatorOptions); + addFormSelector(F("Separator"), F("separator"), optionCount, separatorLabels, separatorOptions, P146_SEPARATOR_CHARACTER); } addFormCheckBox(F("Join Samples with same Timestamp"), F("jointimestamp"), P146_GET_JOIN_TIMESTAMP); addFormCheckBox(F("Export only enabled tasks"), F("onlysettasks"), P146_GET_ONLY_SET_TASKS); @@ -268,13 +269,12 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string) P146_SEPARATOR_CHARACTER = getFormItemInt(F("separator")); String strings[P146_Nlines]; - String error; for (uint8_t varNr = 0; varNr < P146_Nlines; varNr++) { strings[varNr] = webArg(getPluginCustomArgName(varNr)); } - error = SaveCustomTaskSettings(event->TaskIndex, strings, P146_Nlines, 0); + const String error = SaveCustomTaskSettings(event->TaskIndex, strings, P146_Nlines, 0); if (!error.isEmpty()) { addHtmlError(error); diff --git a/src/_P147_SGP4x.ino b/src/_P147_SGP4x.ino index cfacd3beb6..98b859b677 100644 --- a/src/_P147_SGP4x.ino +++ b/src/_P147_SGP4x.ino @@ -118,7 +118,8 @@ boolean Plugin_147(uint8_t function, struct EventStruct *event, String& string) static_cast(P147_sensor_e::SGP40), static_cast(P147_sensor_e::SGP41), }; - addFormSelector(F("Sensor model"), F("ptype"), 2, sensorTypes, sensorTypeOptions, P147_SENSOR_TYPE, true); + constexpr size_t optionCount = NR_ELEMENTS(sensorTypeOptions); + addFormSelector(F("Sensor model"), F("ptype"), optionCount, sensorTypes, sensorTypeOptions, P147_SENSOR_TYPE, true); # ifndef BUILD_NO_DEBUG addFormNote(F("Page will reload on change.")); # endif // ifndef BUILD_NO_DEBUG @@ -162,7 +163,7 @@ boolean Plugin_147(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_SAVE: { - int prevSensor = P147_SENSOR_TYPE; + const int prevSensor = P147_SENSOR_TYPE; P147_SENSOR_TYPE = getFormItemInt(F("ptype")); P147_LOW_POWER_MEASURE = isFormItemChecked(F("plow")) ? 1 : 0; P147_SET_USE_COMPENSATION(getFormItemInt(F("comp"))); diff --git a/src/_P150_TMP117.ino b/src/_P150_TMP117.ino index 3c4c6290a8..a0bb743723 100644 --- a/src/_P150_TMP117.ino +++ b/src/_P150_TMP117.ino @@ -134,7 +134,8 @@ boolean Plugin_150(uint8_t function, struct EventStruct *event, String& string) P150_AVERAGING_32_SAMPLES, P150_AVERAGING_64_SAMPLES, }; - addFormSelector(F("Averaging"), F("avg"), 4, averagingCaptions, averagingOptions, P150_GET_CONF_AVERAGING); + constexpr size_t optionCount = NR_ELEMENTS(averagingOptions); + addFormSelector(F("Averaging"), F("avg"), optionCount, averagingCaptions, averagingOptions, P150_GET_CONF_AVERAGING); } { @@ -146,7 +147,14 @@ boolean Plugin_150(uint8_t function, struct EventStruct *event, String& string) P150_CONVERSION_CONTINUOUS, P150_CONVERSION_ONE_SHOT, }; - addFormSelector(F("Conversion mode"), F("conv"), 2, conversionCaptions, conversionOptions, P150_GET_CONF_CONVERSION_MODE, true); + constexpr size_t optionCount = NR_ELEMENTS(conversionOptions); + addFormSelector(F("Conversion mode"), + F("conv"), + optionCount, + conversionCaptions, + conversionOptions, + P150_GET_CONF_CONVERSION_MODE, + true); # ifndef BUILD_NO_DEBUG addFormNote(F("Changing this setting will save and reload this page.")); # endif // ifndef BUILD_NO_DEBUG @@ -173,7 +181,9 @@ boolean Plugin_150(uint8_t function, struct EventStruct *event, String& string) P150_CYCLE_8_SEC, P150_CYCLE_16_SEC, }; - addFormSelector(F("Continuous conversion cycle time"), F("cycle"), 8, cycleCaptions, cycleOptions, P150_GET_CONF_CYCLE_BITS); + constexpr size_t optionCount = NR_ELEMENTS(cycleOptions); + addFormSelector(F("Continuous conversion cycle time"), F("cycle"), optionCount, cycleCaptions, cycleOptions, + P150_GET_CONF_CYCLE_BITS); } addFormSubHeader(F("Output")); diff --git a/src/_P151_Honeywell_pressure.ino b/src/_P151_Honeywell_pressure.ino index 9684963378..019510d404 100644 --- a/src/_P151_Honeywell_pressure.ino +++ b/src/_P151_Honeywell_pressure.ino @@ -71,7 +71,7 @@ boolean Plugin_151(uint8_t function, struct EventStruct *event, String& string) 0x88, 0x98 }; - constexpr size_t addrCount = sizeof(i2cAddressValues) / sizeof(uint8_t); + constexpr size_t addrCount = NR_ELEMENTS(i2cAddressValues); if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { addFormSelectorI2C(F("pi2c"), addrCount, i2cAddressValues, P151_I2C_ADDR); diff --git a/src/_P153_SHT4x.ino b/src/_P153_SHT4x.ino index 7fd10e4ddf..22e2c55626 100644 --- a/src/_P153_SHT4x.ino +++ b/src/_P153_SHT4x.ino @@ -146,9 +146,10 @@ boolean Plugin_153(uint8_t function, struct EventStruct *event, String& string) static_cast(P153_configuration_e::HighResolution20mW1000msec), static_cast(P153_configuration_e::HighResolution20mW100msec), }; + constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); addFormSelector(F("Startup Configuration"), F("startup"), - sizeof(configurationOptions) / sizeof(configurationOptions[0]), + optionCount, configurations, configurationOptions, P153_STARTUP_CONFIGURATION); diff --git a/src/_P166_GP8403.ino b/src/_P166_GP8403.ino index 5280f89540..81c2557e72 100644 --- a/src/_P166_GP8403.ino +++ b/src/_P166_GP8403.ino @@ -126,9 +126,10 @@ boolean Plugin_166(uint8_t function, struct EventStruct *event, String& string) static_cast(DFRobot_GP8403::eOutPutRange_t::eOutputRange5V), static_cast(DFRobot_GP8403::eOutPutRange_t::eOutputRange10V), }; + constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); addFormSelector(F("Output range"), F("range"), - sizeof(configurationOptions) / sizeof(configurationOptions[0]), + optionCount, configurations, configurationOptions, P166_MAX_VOLTAGE); diff --git a/src/_P168_VEML6030_7700.ino b/src/_P168_VEML6030_7700.ino index 85c4dd1703..c5f7e23648 100644 --- a/src/_P168_VEML6030_7700.ino +++ b/src/_P168_VEML6030_7700.ino @@ -113,9 +113,10 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) VEML_LUX_NORMAL_NOWAIT, VEML_LUX_CORRECTED_NOWAIT, }; + constexpr size_t optionCount = NR_ELEMENTS(readMethodOptions); addFormSelector(F("Lux Read-method"), F("rmth"), - NR_ELEMENTS(readMethodOptions), + optionCount, readMethod, readMethodOptions, P168_READLUX_MODE); @@ -134,9 +135,10 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) 0b10, 0b11, }; + constexpr size_t optionCount = NR_ELEMENTS(alsGainOptions); addFormSelector(F("Gain factor"), F("gain"), - NR_ELEMENTS(alsGainOptions), + optionCount, alsGain, alsGainOptions, P168_ALS_GAIN); @@ -158,9 +160,10 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) 0b0010, 0b0011, }; + constexpr size_t optionCount = NR_ELEMENTS(alsIntegrationOptions); addFormSelector(F("Integration time"), F("int"), - NR_ELEMENTS(alsIntegrationOptions), + optionCount, alsIntegration, alsIntegrationOptions, P168_ALS_INTEGRATION); @@ -181,9 +184,10 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) static_cast(P168_power_save_mode_e::Mode3), static_cast(P168_power_save_mode_e::Mode4), }; + constexpr size_t optionCount = NR_ELEMENTS(psmModeOptions); addFormSelector(F("Power Save Mode"), F("psm"), - NR_ELEMENTS(psmModeOptions), + optionCount, psmMode, psmModeOptions, P168_PSM_MODE); diff --git a/src/_P169_AS3935_LightningDetector.ino b/src/_P169_AS3935_LightningDetector.ino index fcabe3e257..7655a70fec 100644 --- a/src/_P169_AS3935_LightningDetector.ino +++ b/src/_P169_AS3935_LightningDetector.ino @@ -88,17 +88,18 @@ boolean Plugin_169(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_I2C_HAS_ADDRESS: case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: { - const uint8_t i2cAddressValues[] = { 0x01, 0x02, 0x03 }; + constexpr uint8_t i2cAddressValues[] = { 0x01, 0x02, 0x03 }; + constexpr size_t i2cOptionCount = NR_ELEMENTS(i2cAddressValues); if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { // addFormSelectorI2C(P169_I2C_ADDRESS_LABEL, 3, i2cAddressValues, P169_I2C_ADDRESS); - addFormSelectorI2C(F("i2c_addr"), NR_ELEMENTS(i2cAddressValues), i2cAddressValues, P169_I2C_ADDRESS); + addFormSelectorI2C(F("i2c_addr"), i2cOptionCount, i2cAddressValues, P169_I2C_ADDRESS); addFormNote(F("Addr: 0-0-0-0-0-A1-A0. Both A0 & A1 low is not valid.")); } else { - success = intArrayContains(NR_ELEMENTS(i2cAddressValues), i2cAddressValues, event->Par1); + success = intArrayContains(i2cOptionCount, i2cAddressValues, event->Par1); } break; } @@ -125,9 +126,10 @@ boolean Plugin_169(uint8_t function, struct EventStruct *event, String& string) AS3935MI::AS3935_MNL_5, AS3935MI::AS3935_MNL_9, AS3935MI::AS3935_MNL_16 }; + constexpr size_t optionCount = NR_ELEMENTS(optionValues); addFormSelector(F("Lightning Threshold"), P169_LIGHTNING_THRESHOLD_LABEL, - NR_ELEMENTS(optionValues), + optionCount, options, optionValues, P169_LIGHTNING_THRESHOLD); @@ -156,8 +158,9 @@ boolean Plugin_169(uint8_t function, struct EventStruct *event, String& string) 17, 18 }; - addFormSelector(F("AFE Gain Min"), P169_AFE_GAIN_LOW_LABEL, NR_ELEMENTS(optionValues), options, optionValues, P169_AFE_GAIN_LOW); - addFormSelector(F("AFE Gain Max"), P169_AFE_GAIN_HIGH_LABEL, NR_ELEMENTS(optionValues), options, optionValues, P169_AFE_GAIN_HIGH); + constexpr size_t optionCount = NR_ELEMENTS(optionValues); + addFormSelector(F("AFE Gain Min"), P169_AFE_GAIN_LOW_LABEL, optionCount, options, optionValues, P169_AFE_GAIN_LOW); + addFormSelector(F("AFE Gain Max"), P169_AFE_GAIN_HIGH_LABEL, optionCount, options, optionValues, P169_AFE_GAIN_HIGH); addFormNote(F("Lower and upper limit for the Analog Frond-End auto gain to use.")); } From ecc413b44ae14801a2f2bf1394869653dc18f571 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Thu, 9 Jan 2025 20:22:48 +0100 Subject: [PATCH 9/9] [Info] Show sketch size and remaining space --- src/src/WebServer/SysInfoPage.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/src/WebServer/SysInfoPage.cpp b/src/src/WebServer/SysInfoPage.cpp index 2d3f3e5b95..232d166653 100644 --- a/src/src/WebServer/SysInfoPage.cpp +++ b/src/src/WebServer/SysInfoPage.cpp @@ -746,19 +746,19 @@ void handle_sysinfo_Storage() { static_cast(RTC.flashCounter))); { - // FIXME TD-er: Must also add this for ESP32. - addRowLabel(LabelType::SKETCH_SIZE); - addHtml(strformat( - F("%d [kB] (%d kB free)"), - getSketchSize() / 1024, - getFreeSketchSpace() / 1024)); - uint32_t maxSketchSize; bool use2step; # if defined(ESP8266) bool otaEnabled = # endif // if defined(ESP8266) OTA_possible(maxSketchSize, use2step); + + addRowLabel(LabelType::SKETCH_SIZE); + addHtml(strformat( + F("%d [kB] (%d kB not used)"), + getSketchSize() / 1024, + (maxSketchSize - getSketchSize()) / 1024)); + addRowLabel(LabelType::MAX_OTA_SKETCH_SIZE); addHtml(strformat( F("%d [kB] (%d bytes)"),