-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Expand file tree
/
Copy path_Plugin_Helper.cpp
More file actions
305 lines (245 loc) · 8.95 KB
/
_Plugin_Helper.cpp
File metadata and controls
305 lines (245 loc) · 8.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
#include "_Plugin_Helper.h"
#include "ESPEasy_common.h"
#include "src/CustomBuild/ESPEasyLimits.h"
#include "src/DataStructs/PluginTaskData_base.h"
#include "src/DataStructs/SettingsStruct.h"
#include "src/DataStructs/TimingStats.h"
#include "src/Globals/Cache.h"
#include "src/Globals/Plugins.h"
#include "src/Globals/Settings.h"
#include "src/Helpers/Misc.h"
#include "src/Helpers/StringParser.h"
#if FEATURE_PIN_WAKEUP
# include "driver/rtc_io.h"
#endif
PluginTaskData_base *Plugin_task_data[TASKS_MAX] = {};
String PCONFIG_LABEL(int n) {
if (n < PLUGIN_CONFIGVAR_MAX) {
return concat(F("pconf_"), n);
}
return F("error");
}
void resetPluginTaskData() {
for (taskIndex_t i = 0; i < TASKS_MAX; ++i) {
Plugin_task_data[i] = nullptr;
}
}
void clearPluginTaskData(taskIndex_t taskIndex) {
if (validTaskIndex(taskIndex)) {
if (Plugin_task_data[taskIndex] != nullptr) {
delete Plugin_task_data[taskIndex];
Plugin_task_data[taskIndex] = nullptr;
}
}
}
bool initPluginTaskData(taskIndex_t taskIndex, PluginTaskData_base *data) {
if (!validTaskIndex(taskIndex)) {
if (data != nullptr) {
delete data;
}
return false;
}
// 2nd heap may have been active to allocate the PluginTaskData, but here we need to keep the default heap active
#ifdef USE_SECOND_HEAP
HeapSelectDram ephemeral;
#endif // ifdef USE_SECOND_HEAP
clearPluginTaskData(taskIndex);
if (data != nullptr) {
if (Settings.TaskDeviceEnabled[taskIndex]) {
Plugin_task_data[taskIndex] = data;
Plugin_task_data[taskIndex]->_taskdata_pluginID = Settings.getPluginID_for_task(taskIndex);
#if FEATURE_PLUGIN_STATS
const uint8_t valueCount = getValueCountForTask(taskIndex);
for (size_t i = 0; i < valueCount; ++i) {
if (Cache.enabledPluginStats(taskIndex, i)) {
Plugin_task_data[taskIndex]->initPluginStats(i);
}
}
#endif // if FEATURE_PLUGIN_STATS
#if FEATURE_PLUGIN_FILTER
// TODO TD-er: Implement init
#endif // if FEATURE_PLUGIN_FILTER
} else {
delete data;
}
}
return getPluginTaskData(taskIndex) != nullptr;
}
PluginTaskData_base* getPluginTaskData(taskIndex_t taskIndex) {
if (pluginTaskData_initialized(taskIndex)) {
if (!Plugin_task_data[taskIndex]->baseClassOnly()) {
return Plugin_task_data[taskIndex];
}
}
return nullptr;
}
PluginTaskData_base* getPluginTaskDataBaseClassOnly(taskIndex_t taskIndex) {
if (pluginTaskData_initialized(taskIndex)) {
return Plugin_task_data[taskIndex];
}
return nullptr;
}
bool pluginTaskData_initialized(taskIndex_t taskIndex) {
if (!validTaskIndex(taskIndex)) {
return false;
}
return Plugin_task_data[taskIndex] != nullptr &&
(Plugin_task_data[taskIndex]->_taskdata_pluginID == Settings.getPluginID_for_task(taskIndex));
}
String getPluginCustomArgName(int varNr) { return getPluginCustomArgName(F("pc_arg"), varNr); }
String getPluginCustomArgName(const __FlashStringHelper *label, int varNr) { return concat(label, varNr + 1); }
int getFormItemIntCustomArgName(int varNr) { return getFormItemInt(getPluginCustomArgName(varNr)); }
// Helper function to create formatted custom values for display in the devices overview page.
// When called from PLUGIN_WEBFORM_SHOW_VALUES, the last item should add a traling div_br class
// if the regular values should also be displayed.
// The call to PLUGIN_WEBFORM_SHOW_VALUES should only return success = true when no regular values should be displayed
// Note that the varNr of the custom values should not conflict with the existing variable numbers (e.g. start at VARS_PER_TASK)
void pluginWebformShowValue(taskIndex_t taskIndex, uint8_t varNr, const __FlashStringHelper *label, const String& value,
bool addTrailingBreak) {
pluginWebformShowValue(taskIndex, varNr, String(label), value, addTrailingBreak);
}
void pluginWebformShowValue(taskIndex_t taskIndex,
uint8_t varNr,
const String& label,
const String& value,
bool addTrailingBreak) {
if (varNr > 0) {
addHtmlDiv(F("div_br"));
}
String postfix(taskIndex);
postfix += '_';
postfix += varNr;
pluginWebformShowValue(
label, concat(F("valuename_"), postfix),
value, concat(F("value_"), postfix),
addTrailingBreak);
}
void pluginWebformShowValue(const String& valName, const String& value, bool addBR) {
pluginWebformShowValue(valName, EMPTY_STRING, value, EMPTY_STRING, addBR);
}
void pluginWebformShowValue(const String& valName, const String& valName_id, const String& value, const String& value_id, bool addBR) {
String valName_tmp(valName);
if (!valName_tmp.endsWith(F(":"))) {
valName_tmp += ':';
}
addHtmlDiv(F("div_l"), valName_tmp, valName_id);
addHtmlDiv(F("div_r"), value, value_id);
if (addBR) {
addHtmlDiv(F("div_br"));
}
}
bool pluginOptionalTaskIndexArgumentMatch(taskIndex_t taskIndex, const String& string, uint8_t paramNr) {
if (!validTaskIndex(taskIndex)) {
return false;
}
const taskIndex_t found_taskIndex = parseCommandArgumentTaskIndex(string, paramNr);
if (!validTaskIndex(found_taskIndex)) {
// Optional parameter not present
return true;
}
return found_taskIndex == taskIndex;
}
bool pluginWebformShowGPIOdescription(taskIndex_t taskIndex,
const __FlashStringHelper *newline,
String & description)
{
struct EventStruct TempEvent(taskIndex);
TempEvent.String1 = newline;
return PluginCall(PLUGIN_WEBFORM_SHOW_GPIO_DESCR, &TempEvent, description);
}
int getValueCountForTask(taskIndex_t taskIndex) {
struct EventStruct TempEvent(taskIndex);
String dummy;
PluginCall(PLUGIN_GET_DEVICEVALUECOUNT, &TempEvent, dummy);
return TempEvent.Par1;
}
int checkDeviceVTypeForTask(struct EventStruct *event) {
// TD-er: Do not use event->getSensorType() here
if (event->sensorType == Sensor_VType::SENSOR_TYPE_NOT_SET) {
if (validTaskIndex(event->TaskIndex)) {
String dummy;
event->idx = -1;
if (PluginCall(PLUGIN_GET_DEVICEVTYPE, event, dummy)) {
return event->idx; // pconfig_index
}
}
}
return -1;
}
#if FEATURE_PIN_WAKEUP
void setupGpioWakeup(uint64_t ext1_mask) {
// disable wakeup completely if nothin is selected
if (ext1_mask == 0) {
#if FEATURE_PIN_WAKEUP == 1
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT1);
#else
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_GPIO);
#endif
return;
}
#if FEATURE_PIN_WAKEUP == 1
// --- EXT1 Wakeup (supported on classic ESP32/S2/S3) ---
esp_sleep_ext1_wakeup_mode_t new_mode;
if (Settings.wakeOnHigh()) {
new_mode = ESP_EXT1_WAKEUP_ANY_HIGH;
} else {
#if CONFIG_IDF_TARGET_ESP32
new_mode = ESP_EXT1_WAKEUP_ALL_LOW;
#else
new_mode = ESP_EXT1_WAKEUP_ANY_LOW;
#endif
}
// Configure pull-ups/pull-downs for all pins in the mask
for (int gpio = 0; gpio < 64; ++gpio) {
if (ext1_mask & (1ULL << gpio)) {
gpio_num_t rtc_gpio = static_cast<gpio_num_t>(gpio);
if (!Settings.wakeOnHigh()) {
rtc_gpio_pullup_en(rtc_gpio);
rtc_gpio_pulldown_dis(rtc_gpio);
} else {
rtc_gpio_pullup_dis(rtc_gpio);
rtc_gpio_pulldown_en(rtc_gpio);
}
}
}
esp_sleep_enable_ext1_wakeup_io(ext1_mask, new_mode);
#elif FEATURE_PIN_WAKEUP == 2
// --- GPIO-based wakeup for chips without EXT1 (e.g. ESP32-C3) ---
esp_deepsleep_gpio_wake_up_mode_t gpio_mode =
Settings.wakeOnHigh() ? ESP_GPIO_WAKEUP_GPIO_HIGH : ESP_GPIO_WAKEUP_GPIO_LOW;
// Configure all pins in the mask
for (int gpio = 0; gpio < 64; ++gpio) {
if (ext1_mask & (1ULL << gpio)) {
gpio_num_t rtc_gpio = static_cast<gpio_num_t>(gpio);
// if (!Settings.wakeOnHigh()) {
// gpio_pullup_en(rtc_gpio);
// gpio_pulldown_dis(rtc_gpio);
// } else {
// gpio_pullup_dis(rtc_gpio);
// gpio_pulldown_en(rtc_gpio);
// }
}
}
esp_deep_sleep_enable_gpio_wakeup(ext1_mask, gpio_mode);
#endif
}
int8_t getWakeupGPIO() {
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
#if FEATURE_PIN_WAKEUP == 1
if (cause != ESP_SLEEP_WAKEUP_EXT1) {
return -1;
}
uint64_t wakeMask = esp_sleep_get_ext1_wakeup_status();
#else
if (cause != ESP_SLEEP_WAKEUP_GPIO) {
return -1;
}
uint64_t wakeMask = esp_sleep_get_gpio_wakeup_status();
#endif
if (wakeMask == 0) {
return -1;
}
// Return first active GPIO
return __builtin_ctzll(wakeMask);
}
#endif // if FEATURE_PIN_WAKEUP