SensESP 3.0.1
Universal Signal K sensor toolkit ESP32
Loading...
Searching...
No Matches
lambda_transform.h
Go to the documentation of this file.
1#ifndef SENSESP_TRANSFORMS_LAMBDA_TRANSFORM_H_
2#define SENSESP_TRANSFORMS_LAMBDA_TRANSFORM_H_
3
5#include "transform.h"
6
7namespace sensesp {
8
9// template snippets for configuration schema
10
14struct ParamInfo {
15 const char* key;
16 const char* description;
17};
18
19// FIXME: This whole implementation should be written with variadic template
20// parameters once the SDK gets updated past GCC 5.2.
21
40template <class IN, class OUT, class P1 = bool, class P2 = bool,
41 class P3 = bool, class P4 = bool, class P5 = bool, class P6 = bool>
42class LambdaTransform : public Transform<IN, OUT> {
43 public:
44 LambdaTransform(std::function<OUT(IN)> function,
45 const String& config_path = "")
46 : Transform<IN, OUT>(config_path), num_params_{0}, function0_{function} {
47 this->load();
48 }
49
50 LambdaTransform(std::function<OUT(IN)> function, const ParamInfo* param_info,
51 const String& config_path = "")
52 : Transform<IN, OUT>(config_path),
53 num_params_{0},
54 function0_{function},
55 param_info_{param_info} {
56 this->load();
57 }
58
59 LambdaTransform(std::function<OUT(IN, P1)> function, P1 param1,
60 const ParamInfo* param_info, const String& config_path = "")
61 : Transform<IN, OUT>(config_path),
62 num_params_{1},
63 function1_{function},
64 param1_{param1},
65 param_info_{param_info} {
66 this->load();
67 }
68
82 LambdaTransform(std::function<OUT(IN, P1, P2)> function, P1 param1, P2 param2,
83 const ParamInfo* param_info, const String& config_path = "")
84 : Transform<IN, OUT>(config_path),
85 num_params_{2},
86 function2_{function},
87 param1_{param1},
88 param2_{param2},
89 param_info_{param_info} {
90 this->load();
91 }
92
93 LambdaTransform(std::function<OUT(IN, P1, P2, P3)> function, P1 param1,
94 P2 param2, P3 param3, const ParamInfo* param_info,
95 const String& config_path = "")
96 : Transform<IN, OUT>(config_path),
97 num_params_{3},
98 function3_{function},
99 param1_{param1},
100 param2_{param2},
101 param3_{param3},
102 param_info_{param_info} {
103 this->load();
104 }
105
106 LambdaTransform(std::function<OUT(IN, P1, P2, P3, P4)> function, P1 param1,
107 P2 param2, P3 param3, P4 param4, const ParamInfo* param_info,
108 const String& config_path = "")
109 : Transform<IN, OUT>(config_path),
110 num_params_{4},
111 function4_{function},
112 param1_{param1},
113 param2_{param2},
114 param3_{param3},
115 param4_{param4},
116 param_info_{param_info} {
117 this->load();
118 }
119
120 LambdaTransform(std::function<OUT(IN, P1, P2, P3, P4, P5)> function,
121 P1 param1, P2 param2, P3 param3, P4 param4, P5 param5,
122 const ParamInfo* param_info, const String& config_path = "")
123 : Transform<IN, OUT>(config_path),
124 num_params_{5},
125 function5_{function},
126 param1_{param1},
127 param2_{param2},
128 param3_{param3},
129 param4_{param4},
130 param5_{param5},
131 param_info_{param_info} {
132 this->load();
133 }
134
135 LambdaTransform(std::function<OUT(IN, P1, P2, P3, P4, P5, P6)> function,
136 P1 param1, P2 param2, P3 param3, P4 param4, P5 param5,
137 P6 param6, const ParamInfo* param_info,
138 const String& config_path = "")
139 : Transform<IN, OUT>(config_path),
140 num_params_{6},
141 function6_{function},
142 param1_{param1},
143 param2_{param2},
144 param3_{param3},
145 param4_{param4},
146 param5_{param5},
147 param6_{param6},
148 param_info_{param_info} {
149 this->load();
150 }
151
152 void set(const IN& input) override {
153 switch (num_params_) {
154 case 0:
155 this->output_ = function0_(input);
156 break;
157 case 1:
158 this->output_ = function1_(input, param1_);
159 break;
160 case 2:
161 this->output_ = function2_(input, param1_, param2_);
162 break;
163 case 3:
164 this->output_ = function3_(input, param1_, param2_, param3_);
165 break;
166 case 4:
167 this->output_ = function4_(input, param1_, param2_, param3_, param4_);
168 break;
169 case 5:
170 this->output_ =
171 function5_(input, param1_, param2_, param3_, param4_, param5_);
172 break;
173 case 6:
174 this->output_ = function6_(input, param1_, param2_, param3_, param4_,
176 break;
177 default:
178 break;
179 }
181 }
182
183 bool to_json(JsonObject& doc) override {
184 switch (num_params_) {
185 case 6:
186 doc[param_info_[5].key] = param6_;
187 case 5:
188 doc[param_info_[4].key] = param5_;
189 case 4:
190 doc[param_info_[3].key] = param4_;
191 case 3:
192 doc[param_info_[2].key] = param3_;
193 case 2:
194 doc[param_info_[1].key] = param2_;
195 case 1:
196 doc[param_info_[0].key] = param1_;
197 default:
198 break;
199 }
200 return true;
201 }
202
203 bool from_json(const JsonObject& config) override {
204 // test that each argument key (as defined by param_info)
205 // exists in the received Json object
206 ESP_LOGD(__FILENAME__, "Preparing to restore configuration from FS.");
207 for (int i = 0; i < num_params_; i++) {
208 const char* expected = param_info_[i].key;
209 if (!config[expected].is<JsonVariant>()) {
210 ESP_LOGD(__FILENAME__, "Didn't find all keys.");
211 return false;
212 }
213 }
214 switch (num_params_) {
215 case 6:
216 param6_ = config[param_info_[5].key];
217 case 5:
218 param5_ = config[param_info_[4].key];
219 case 4:
220 param4_ = config[param_info_[3].key];
221 case 3:
222 param3_ = config[param_info_[2].key];
223 case 2:
224 param2_ = config[param_info_[1].key];
225 case 1:
226 param1_ = config[param_info_[0].key];
227 default:
228 break;
229 }
230 ESP_LOGD(__FILENAME__, "Restored configuration");
231 return true;
232 }
233
234 const ParamInfo* get_param_info() const { return param_info_; }
235
242
243 private:
244 int num_params_;
245
246 std::function<OUT(IN)> function0_;
247 std::function<OUT(IN, P1)> function1_;
248 std::function<OUT(IN, P1, P2)> function2_;
249 std::function<OUT(IN, P1, P2, P3)> function3_;
250 std::function<OUT(IN, P1, P2, P3, P4)> function4_;
251 std::function<OUT(IN, P1, P2, P3, P4, P5)> function5_;
252 std::function<OUT(IN, P1, P2, P3, P4, P5, P6)> function6_;
253
254 const ParamInfo* param_info_;
255};
256
257static const char kLambdaTransformSchemaHead[] = R"({
258 "type": "object",
259 "properties": {
260 )";
261
262static const char kLambdaTransformSchemaTail[] = R"(
263 }
264 })";
265
266static const String format_schema_row(const char key[], const char title[],
267 const char type[], const bool read_only) {
268 char row[1024] = "";
269 const char* read_only_str = read_only ? "true" : "false";
270
271 static const char schema_row[] = R"(
272 "%s": { "title": "%s", "type": "%s", "readOnly": %s }
273)";
274
275 sprintf(row, schema_row, key, title, type, read_only_str);
276
277 return row;
278}
279
280template <class IN, class OUT>
281const String ConfigSchema(const LambdaTransform<IN, OUT>& obj) {
282 return "{}";
283}
284
285// This is stupid. I hope this can be fixed with variadic templates.
286
287template <class IN, class OUT, class P1>
289 String output = kLambdaTransformSchemaHead;
290 const ParamInfo* param_info = obj.get_param_info();
291 output.concat(format_schema_row(param_info[0].key, param_info[0].description,
292 get_schema_type_string(obj.param1_), false));
293 output.concat(kLambdaTransformSchemaTail);
294 return output;
295}
296
297// This is stupid x2
298
299template <class IN, class OUT, class P1, class P2>
301 String output = kLambdaTransformSchemaHead;
302 const ParamInfo* param_info = obj.get_param_info();
303 output.concat(format_schema_row(param_info[0].key,
304 param_info[0].description,
305 get_schema_type_string(obj.param1_), false));
306 output.concat(",");
307 output.concat(format_schema_row(param_info[1].key,
308 param_info[1].description,
309 get_schema_type_string(obj.param2_), false));
310 output.concat(kLambdaTransformSchemaTail);
311 return output;
312}
313
314// This is stupid x3
315
316template <class IN, class OUT, class P1, class P2, class P3>
318 String output = kLambdaTransformSchemaHead;
319 const ParamInfo* param_info = obj.get_param_info();
320
321 output.concat(format_schema_row(param_info[0].key,
322 param_info[0].description,
323 get_schema_type_string(obj.param1_), false));
324 output.concat(",");
325 output.concat(format_schema_row(param_info[1].key,
326 param_info[1].description,
327 get_schema_type_string(obj.param2_), false));
328 output.concat(",");
329 output.concat(format_schema_row(param_info[2].key,
330 param_info[2].description,
331 get_schema_type_string(obj.param3_), false));
332 output.concat(kLambdaTransformSchemaTail);
333 return output;
334}
335
336// This is stupid x4
337
338template <class IN, class OUT, class P1, class P2, class P3, class P4>
340 String output = kLambdaTransformSchemaHead;
341 const ParamInfo* param_info = obj.get_param_info();
342
343 output.concat(format_schema_row(param_info[0].key,
344 param_info[0].description,
345 get_schema_type_string(obj.param1_), false));
346 output.concat(",");
347 output.concat(format_schema_row(param_info[1].key,
348 param_info[1].description,
349 get_schema_type_string(obj.param2_), false));
350 output.concat(",");
351 output.concat(format_schema_row(param_info[2].key,
352 param_info[2].description,
353 get_schema_type_string(obj.param3_), false));
354 output.concat(",");
355 output.concat(format_schema_row(param_info[3].key,
356 param_info[3].description,
357 get_schema_type_string(obj.param4_), false));
358 output.concat(kLambdaTransformSchemaTail);
359 return output;
360}
361
362// This is stupid x5
363
364template <class IN, class OUT, class P1, class P2, class P3, class P4, class P5>
365const String ConfigSchema(
367 String output = kLambdaTransformSchemaHead;
368 const ParamInfo* param_info = obj.get_param_info();
369
370 output.concat(format_schema_row(param_info[0].key,
371 param_info[0].description,
372 get_schema_type_string(obj.param1_), false));
373 output.concat(",");
374 output.concat(format_schema_row(param_info[1].key,
375 param_info[1].description,
376 get_schema_type_string(obj.param2_), false));
377 output.concat(",");
378 output.concat(format_schema_row(param_info[2].key,
379 param_info[2].description,
380 get_schema_type_string(obj.param3_), false));
381 output.concat(",");
382 output.concat(format_schema_row(param_info[3].key,
383 param_info[3].description,
384 get_schema_type_string(obj.param4_), false));
385 output.concat(",");
386 output.concat(format_schema_row(param_info[4].key,
387 param_info[4].description,
388 get_schema_type_string(obj.param5_), false));
389 output.concat(kLambdaTransformSchemaTail);
390 return output;
391}
392
393// This is stupid x6
394
395template <class IN, class OUT, class P1, class P2, class P3, class P4, class P5,
396 class P6>
397const String ConfigSchema(
399 String output = kLambdaTransformSchemaHead;
400 const ParamInfo* param_info = obj.get_param_info();
401
402 output.concat(format_schema_row(param_info[0].key,
403 param_info[0].description,
404 get_schema_type_string(obj.param1_), false));
405 output.concat(",");
406 output.concat(format_schema_row(param_info[1].key,
407 param_info[1].description,
408 get_schema_type_string(obj.param2_), false));
409 output.concat(",");
410 output.concat(format_schema_row(param_info[2].key,
411 param_info[2].description,
412 get_schema_type_string(obj.param3_), false));
413 output.concat(",");
414 output.concat(format_schema_row(param_info[3].key,
415 param_info[3].description,
416 get_schema_type_string(obj.param4_), false));
417 output.concat(",");
418 output.concat(format_schema_row(param_info[4].key,
419 param_info[4].description,
420 get_schema_type_string(obj.param5_), false));
421 output.concat(",");
422 output.concat(format_schema_row(param_info[5].key,
423 param_info[5].description,
424 get_schema_type_string(obj.param6_), false));
425 output.concat(kLambdaTransformSchemaTail);
426 return output;
427}
428
429} // namespace sensesp
430
431#endif
virtual bool load() override
Load and populate the object from a persistent storage.
Definition saveable.cpp:8
Construct a new transform based on a single function.
LambdaTransform(std::function< OUT(IN)> function, const String &config_path="")
LambdaTransform(std::function< OUT(IN, P1, P2, P3)> function, P1 param1, P2 param2, P3 param3, const ParamInfo *param_info, const String &config_path="")
LambdaTransform(std::function< OUT(IN, P1, P2, P3, P4)> function, P1 param1, P2 param2, P3 param3, P4 param4, const ParamInfo *param_info, const String &config_path="")
LambdaTransform(std::function< OUT(IN, P1, P2, P3, P4, P5, P6)> function, P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, const ParamInfo *param_info, const String &config_path="")
LambdaTransform(std::function< OUT(IN, P1)> function, P1 param1, const ParamInfo *param_info, const String &config_path="")
LambdaTransform(std::function< OUT(IN, P1, P2, P3, P4, P5)> function, P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, const ParamInfo *param_info, const String &config_path="")
bool from_json(const JsonObject &config) override
LambdaTransform(std::function< OUT(IN, P1, P2)> function, P1 param1, P2 param2, const ParamInfo *param_info, const String &config_path="")
LambdaTransform constructor for two-parameter function.
bool to_json(JsonObject &doc) override
LambdaTransform(std::function< OUT(IN)> function, const ParamInfo *param_info, const String &config_path="")
const ParamInfo * get_param_info() const
void set(const IN &input) override
The main Transform class. A transform is identified primarily by the type of value that is produces (...
Definition transform.h:53
const String ConfigSchema(const SmartSwitchController &obj)
const char * get_schema_type_string(const int)
const char * description