|
| 1 | +#include "_Plugin_Helper.h" |
| 2 | +#ifdef USES_P164 |
| 3 | + |
| 4 | +// ####################################################################################################### |
| 5 | +// #################################### Plugin-164: Gases - ENS16x (tvoc,eco2) ########################### |
| 6 | +// ####################################################################################################### |
| 7 | +// P164 "GASES - ENS16x (TVOC, eCO2)" |
| 8 | +// Plugin for ENS160 & ENS161 TVOC and eCO2 sensor with I2C interface from ScioSense |
| 9 | +// For documentation of the ENS160 hardware device see |
| 10 | +// https://www.sciosense.com/wp-content/uploads/documents/SC-001224-DS-9-ENS160-Datasheet.pdf |
| 11 | +// |
| 12 | +// PLugin code: |
| 13 | +// 2023 By flashmark |
| 14 | +// ####################################################################################################### |
| 15 | + |
| 16 | +# include "src/PluginStructs/P164_data_struct.h" |
| 17 | + |
| 18 | +# define PLUGIN_164 |
| 19 | +# define PLUGIN_ID_164 164 |
| 20 | +# define PLUGIN_NAME_164 "Gases - ENS16x" |
| 21 | +# define PLUGIN_VALUENAME1_164 "TVOC" |
| 22 | +# define PLUGIN_VALUENAME2_164 "eCO2" |
| 23 | + |
| 24 | +boolean Plugin_164(uint8_t function, struct EventStruct *event, String& string) |
| 25 | +{ |
| 26 | + boolean success = false; |
| 27 | + |
| 28 | + switch (function) |
| 29 | + { |
| 30 | + case PLUGIN_DEVICE_ADD: |
| 31 | + { |
| 32 | + Device[++deviceCount].Number = PLUGIN_ID_164; |
| 33 | + Device[deviceCount].Type = DEVICE_TYPE_I2C; |
| 34 | + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_DUAL; |
| 35 | + Device[deviceCount].Ports = 0; |
| 36 | + Device[deviceCount].PullUpOption = false; |
| 37 | + Device[deviceCount].InverseLogicOption = false; |
| 38 | + Device[deviceCount].FormulaOption = true; |
| 39 | + Device[deviceCount].ValueCount = 2; |
| 40 | + Device[deviceCount].SendDataOption = true; |
| 41 | + Device[deviceCount].TimerOption = true; |
| 42 | + Device[deviceCount].GlobalSyncOption = true; |
| 43 | + Device[deviceCount].PluginStats = true; |
| 44 | + break; |
| 45 | + } |
| 46 | + |
| 47 | + case PLUGIN_GET_DEVICENAME: |
| 48 | + { |
| 49 | + string = F(PLUGIN_NAME_164); |
| 50 | + break; |
| 51 | + } |
| 52 | + |
| 53 | + case PLUGIN_GET_DEVICEVALUENAMES: |
| 54 | + { |
| 55 | + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_164)); |
| 56 | + strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_164)); |
| 57 | + break; |
| 58 | + } |
| 59 | + |
| 60 | + case PLUGIN_I2C_HAS_ADDRESS: |
| 61 | + case PLUGIN_WEBFORM_SHOW_I2C_PARAMS: |
| 62 | + { |
| 63 | + const uint8_t i2cAddressValues[] = { P164_ENS160_I2CADDR_0, P164_ENS160_I2CADDR_1 }; |
| 64 | + constexpr int nrAddressOptions = NR_ELEMENTS(i2cAddressValues); |
| 65 | + |
| 66 | + if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { |
| 67 | + addFormSelectorI2C(F("i2c_addr"), nrAddressOptions, i2cAddressValues, P164_PCONFIG_I2C_ADDR); |
| 68 | + addFormNote(F("ADDR Low=0x52, High=0x53")); |
| 69 | + } else { |
| 70 | + success = intArrayContains(nrAddressOptions, i2cAddressValues, event->Par1); |
| 71 | + } |
| 72 | + |
| 73 | + break; |
| 74 | + } |
| 75 | + |
| 76 | + # if FEATURE_I2C_GET_ADDRESS |
| 77 | + case PLUGIN_I2C_GET_ADDRESS: |
| 78 | + { |
| 79 | + event->Par1 = P164_PCONFIG_I2C_ADDR; |
| 80 | + success = true; |
| 81 | + break; |
| 82 | + } |
| 83 | + # endif // if FEATURE_I2C_GET_ADDRESS |
| 84 | + |
| 85 | + case PLUGIN_SET_DEFAULTS: |
| 86 | + { |
| 87 | + P164_PCONFIG_I2C_ADDR = P164_ENS160_I2CADDR_1; |
| 88 | + success = true; |
| 89 | + break; |
| 90 | + } |
| 91 | + |
| 92 | + case PLUGIN_INIT: |
| 93 | + { |
| 94 | + initPluginTaskData(event->TaskIndex, new (std::nothrow) P164_data_struct(event)); |
| 95 | + P164_data_struct *P164_data = static_cast<P164_data_struct *>(getPluginTaskData(event->TaskIndex)); |
| 96 | + |
| 97 | + success = (nullptr != P164_data && P164_data->begin()); |
| 98 | + break; |
| 99 | + } |
| 100 | + |
| 101 | + case PLUGIN_READ: |
| 102 | + { |
| 103 | + P164_data_struct *P164_data = static_cast<P164_data_struct *>(getPluginTaskData(event->TaskIndex)); |
| 104 | + |
| 105 | + if (nullptr == P164_data) { |
| 106 | + addLogMove(LOG_LEVEL_ERROR, F("P164: plugin_read NULLPTR")); |
| 107 | + break; |
| 108 | + } |
| 109 | + |
| 110 | + float temperature = 20.0f; // A reasonable value in case temperature source task is invalid |
| 111 | + float humidity = 50.0f; // A reasonable value in case humidity source task is invalid |
| 112 | + float tvoc = 0.0f; // tvoc value to be retrieved from device |
| 113 | + float eco2 = 0.0f; // eCO2 value to be retrieved from device |
| 114 | + |
| 115 | + if (validTaskIndex(P164_PCONFIG_TEMP_TASK) && validTaskIndex(P164_PCONFIG_HUM_TASK)) |
| 116 | + { |
| 117 | + // we're checking a value from other tasks |
| 118 | + temperature = UserVar.getFloat(P164_PCONFIG_TEMP_TASK, P164_PCONFIG_TEMP_VAL); // in degrees C |
| 119 | + humidity = UserVar.getFloat(P164_PCONFIG_HUM_TASK, P164_PCONFIG_HUM_VAL); // in % relative |
| 120 | + } |
| 121 | + success = P164_data->read(tvoc, eco2, temperature, humidity); |
| 122 | + UserVar.setFloat(event->TaskIndex, 0, tvoc); |
| 123 | + UserVar.setFloat(event->TaskIndex, 1, eco2); |
| 124 | + break; |
| 125 | + } |
| 126 | + |
| 127 | + case PLUGIN_WEBFORM_LOAD: |
| 128 | + { |
| 129 | + success = P164_data_struct::webformLoad(event); |
| 130 | + break; |
| 131 | + } |
| 132 | + |
| 133 | + case PLUGIN_WEBFORM_SAVE: |
| 134 | + { |
| 135 | + success = P164_data_struct::webformSave(event); |
| 136 | + break; |
| 137 | + } |
| 138 | + |
| 139 | + case PLUGIN_TEN_PER_SECOND: |
| 140 | + { |
| 141 | + P164_data_struct *P164_data = |
| 142 | + static_cast<P164_data_struct *>(getPluginTaskData(event->TaskIndex)); |
| 143 | + if (nullptr == P164_data) { |
| 144 | + break; |
| 145 | + } |
| 146 | + success = P164_data->tenPerSecond(event); |
| 147 | + break; |
| 148 | + } |
| 149 | + } |
| 150 | + return success; |
| 151 | +} |
| 152 | + |
| 153 | +#endif // ifdef USES_P164 |
0 commit comments