muwerk mupplet Core Library
muwerk applets; mupplets: functional units that support specific hardware or reusable applications
Loading...
Searching...
No Matches
light_controller.h
1// light_controller.h - controller for light related operations
2
3#pragma once
4
5#include "ustd_platform.h"
6#include "mupplet_core.h"
7
8namespace ustd {
9
17 public:
19 enum Mode {
20 Passive,
26 Pattern
27 };
28
41#if defined(__ESP__) || defined(__UNIXOID__)
42 typedef std::function<void(bool state, double level, bool control, bool notify)> T_CONTROL;
43#elif defined(__ATTINY__)
44 typedef void (*T_CONTROL)(bool state, double level, bool control, bool notify);
45#else
46 typedef ustd::function<void(bool state, double level, bool control, bool notify)> T_CONTROL;
47#endif
48
49 private:
50 // controller state
51 Mode mode;
52 bool state;
53 double brightlevel;
54 // configuration
55 T_CONTROL controller;
56 unsigned long interval = 1000;
57 double phase = 0.0;
58 double minWaveBrightness = 0.0;
59 double maxWaveBrightness = 1.0;
60 String pattern = "";
61 // runtime
62 unsigned long uPhase = 0;
63 unsigned long oPeriod = 0;
64 unsigned long startPulse = 0;
65 unsigned int patternPointer = 0;
66
67 public:
73 }
74
75 void begin(T_CONTROL controller, bool initialState = false) {
82 this->controller = controller;
83 mode = Passive;
84 state = !initialState;
85 set(initialState);
86 }
87
88 void loop() {
93 if (mode == Mode::Passive)
94 return;
95 unsigned long period = (millis() + uPhase) % (2 * interval);
96 if (mode == Mode::Pulse) {
97 if (millis() - startPulse < interval) {
98 set(true, true);
99 } else {
100 set(false, true);
101 setMode(Mode::Passive);
102 }
103 }
104 if (mode == Mode::Blink) {
105 if (period < oPeriod) {
106 set(false, true);
107 } else {
108 if (period > interval && oPeriod < interval) {
109 set(true, true);
110 }
111 }
112 }
113 if (mode == Mode::Wave) {
114 unsigned long period = (millis() + uPhase) % (2 * interval);
115 double br = 0.0;
116 if (period < interval) {
117 br = (double)period / (double)interval;
118 } else {
119 br = (double)(2 * interval - period) / (double)interval;
120 }
121 br = br * (maxWaveBrightness - minWaveBrightness) + minWaveBrightness;
122 brightness(br, true);
123 }
124 if (mode == Mode::Pattern) {
125 if (period < oPeriod) {
126 if (patternPointer < pattern.length()) {
127 char c = pattern[patternPointer];
128 if (c == 'r') {
129 patternPointer = 0;
130 c = pattern[patternPointer];
131 }
132 if (c == '+') {
133 set(true, true);
134 }
135 if (c == '-') {
136 set(false, true);
137 }
138 if (c >= '0' && c <= '9') {
139 double br = (double)(c - '0') * 0.1111;
140 brightness(br, true);
141 }
142 ++patternPointer;
143 } else {
144 patternPointer = 0;
145 set(false, true);
146 setMode(Mode::Passive);
147 }
148 }
149 }
150 oPeriod = period;
151 }
152
153 bool commandParser(String command, String args) {
196 if (command == "set") {
197 double br;
198 br = parseUnitLevel(args);
199 brightness(br);
200 return true;
201 }
202 if (command == "mode/set") {
203 char msgbuf[128];
204 memset(msgbuf, 0, 128);
205 strncpy(msgbuf, args.c_str(), 127);
206 char *p = strchr(msgbuf, ' ');
207 char *p2 = nullptr;
208 char *p3 = nullptr;
209 if (p) {
210 *p = 0;
211 ++p;
212 p2 = strchr(p, ',');
213 if (p2) {
214 *p2 = 0;
215 ++p2;
216 p3 = strchr(p2, ',');
217 if (p3) {
218 *p3 = 0;
219 ++p3;
220 }
221 }
222 }
223 int t = 1000;
224 double phs = 0.0;
225 if (!strcmp(msgbuf, "passive")) {
226 setMode(Mode::Passive);
227 } else if (!strcmp(msgbuf, "pulse")) {
228 if (p)
229 t = atoi(p);
231 } else if (!strcmp(msgbuf, "blink")) {
232 if (p)
233 t = atoi(p);
234 if (p2)
235 phs = atof(p2);
236 setMode(Mode::Blink, t, phs);
237 } else if (!strcmp(msgbuf, "wave")) {
238 if (p)
239 t = atoi(p);
240 if (p2)
241 phs = atof(p2);
242 setMode(Mode::Wave, t, phs);
243 } else if (!strcmp(msgbuf, "pattern")) {
244 if (p && strlen(p) > 0) {
245 if (p2)
246 t = atoi(p2);
247 if (p3)
248 phs = atof(p3);
249 setMode(Mode::Pattern, t, phs, p);
250 }
251 }
252 return true;
253 }
254 if (command == "unitbrightness/get") {
255 controller(state, brightlevel, false, true);
256 return true;
257 }
258 return false;
259 }
260
261 void set(bool state) {
262 // clang-format off
271 // clang-format on
272 set(state, false);
273 }
274
275 void brightness(double level) {
279 brightness(level, false);
280 }
281
282 void setMode(Mode mode, unsigned int interval_ms = 1000, double phase_unit = 0.0,
283 String pattern = "") {
299 this->mode = mode;
300 if (mode == Mode::Passive)
301 return;
302 phase = phase_unit;
303 if (phase < 0.0)
304 phase = 0.0;
305 if (phase > 1.0)
306 phase = 1.0;
307 interval = interval_ms;
308 if (interval < 100)
309 interval = 100;
310 if (interval > 100000)
311 interval = 100000;
312 startPulse = millis();
313 uPhase = (unsigned long)(2.0 * (double)interval * phase);
314 oPeriod = (millis() + uPhase) % interval;
315 if (mode == Mode::Pattern) {
316 this->pattern = pattern;
317 patternPointer = 0;
318 }
319 }
320
321 void setMinMaxWaveBrightness(double minBrightness, double maxBrightness) {
327 if (minBrightness < 0.0 || minBrightness > 1.0)
328 minBrightness = 0.0;
329 if (maxBrightness < 0.0 || maxBrightness > 1.0)
330 maxBrightness = 1.0;
331 if (minBrightness >= maxBrightness) {
332 minBrightness = 0.0;
333 maxBrightness = 1.0;
334 }
335 minWaveBrightness = minBrightness;
336 maxWaveBrightness = maxBrightness;
337 }
338
339 void forceState(bool state, double brightlevel) {
367 this->state = state;
368 this->brightlevel = brightlevel < 0.0 ? 0.0 : brightlevel > 1.0 ? 1.0
369 : brightlevel;
370 }
371
372 private:
373 void set(bool _state, bool _automatic) {
374 if (_state == state)
375 return;
376 if (!_automatic)
377 mode = Mode::Passive;
378 // if we want to preserve the brightness level, we need to change this
379 brightlevel = _state ? 1.0 : 0.0;
380 state = _state;
381 controller(state, brightlevel, true, !_automatic);
382 }
383
384 void brightness(double _brightlevel, bool _automatic) {
385 if (_brightlevel < 0.0)
386 _brightlevel = 0.0;
387 if (_brightlevel > 1.0)
388 _brightlevel = 1.0;
389 if (brightlevel == _brightlevel)
390 return;
391 if (!_automatic)
392 mode = Mode::Passive;
393 brightlevel = _brightlevel;
394 state = _brightlevel > 0.0;
395 controller(state, brightlevel, true, !_automatic);
396 }
397};
398
399} // namespace ustd
The Light Controller Class.
Definition: light_controller.h:16
void setMinMaxWaveBrightness(double minBrightness, double maxBrightness)
Definition: light_controller.h:321
void set(bool state)
Definition: light_controller.h:261
void brightness(double level)
Definition: light_controller.h:275
std::function< void(bool state, double level, bool control, bool notify)> T_CONTROL
Hardware Control Function.
Definition: light_controller.h:42
bool commandParser(String command, String args)
Definition: light_controller.h:153
void forceState(bool state, double brightlevel)
Definition: light_controller.h:339
void begin(T_CONTROL controller, bool initialState=false)
Definition: light_controller.h:75
void loop()
Definition: light_controller.h:88
Mode
Definition: light_controller.h:19
@ Pattern
Definition: light_controller.h:26
@ Blink
Definition: light_controller.h:22
@ Pulse
Definition: light_controller.h:25
@ Wave
Definition: light_controller.h:24
void setMode(Mode mode, unsigned int interval_ms=1000, double phase_unit=0.0, String pattern="")
Definition: light_controller.h:282
LightController()
Definition: light_controller.h:68
The muwerk namespace.
Definition: home_assistant.h:10
double parseUnitLevel(String arg)
Definition: mupplet_core.h:154