Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
default_behavior.hpp
Go to the documentation of this file.
1
5#ifndef DEFAULT_BEHAVIOR_MANAGER_HPP
6#define DEFAULT_BEHAVIOR_MANAGER_HPP
7
8//
9// note: this code is included as-is by:
10// - src/modes/user/indexable_behavior.hpp
11// - src/modes/user/simple_behavior.hpp
12//
13
14#include "src/system/component/time_handling.h"
15
16#include <cstdint>
17namespace lampda::user {
18
19//
20// These are defined in src/modes/user/{flavor}_behavior.hpp
21//
22
23bool button_clicked_default(const uint8_t);
24
25bool button_hold_default(const uint8_t, const bool, const uint32_t);
26
27//
28// These callbacks are the same for all lamp flavors*
29//
30
31// *meaning: LampTy is the one doing the "polyfill" between flavors
32
34{
35 auto manager = get_context();
36
37 // initialize the lamp object
38 manager.lamp.startup();
39
40 // callbacks
41 manager.power_on_sequence();
42}
43
45{
46 // callbacks
47 auto manager = get_context();
48 manager.power_off_sequence();
49
50 // clear lamp on power-off
51 manager.lamp.clear();
52 manager.lamp.show_now();
53
54 // (no-op) internal symbol used during build
55 ensure_build_canary();
56}
57
58void brightness_update(const brightness_t brightness)
59{
60 auto manager = get_context();
61
62 // dont handle invalid commands
63 if (brightness <= ::lampda::brightness::absoluteMaximumBrightness)
64 {
65 // force update of the internal references
66 manager.lamp.align_internal_to_system_brightness();
67
68 // set brightness for underlying object (w/o re-entry in update_brightness)
69 manager.lamp.setBrightness(brightness, true, true);
70
71 // callbacks
72 manager.brightness_update(brightness);
73 }
74 else
75 {
76 // this call could be just a max brightness update
77 manager.lamp.enforce_internal_brightness_limits();
78 }
79}
80
81void sunset_timer_update(const float progress)
82{
83 auto manager = get_context();
84
85 // callbacks
86 manager.sunset_update(progress);
87}
88
90{
91 auto manager = get_context();
92 manager.write_parameters();
93}
94
96{
97 auto manager = get_context();
98 manager.read_parameters();
99}
100
101bool button_start_click_default(const uint8_t clicks) { return false; }
102
103bool button_start_hold_default(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
104{
105 switch (clicks)
106 {
107 case 5:
108 {
109 if (not isEndOfHoldEvent and holdDuration > 0)
110 {
111 // sunset timer !
112 auto manager = get_context();
113 if (manager.overlay_animate_ramp(
114 holdDuration, 1000, modes::colors::PaletteGradient<modes::colors::White, modes::colors::Red>))
115 {
116 // update the sunset timing
117 manager.state.isSunsetTimingPending = 2;
118 }
119
120 return true;
121 }
122 break;
123 }
124 }
125
126 return false;
127}
128
129bool button_clicked_usermode(const uint8_t clicks)
130{
131 auto manager = get_context();
132 return manager.custom_click(clicks);
133}
134
135bool button_hold_usermode(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
136{
137 auto manager = get_context();
138 return manager.custom_hold(clicks, isEndOfHoldEvent, holdDuration);
139}
140
141void loop()
142{
143 auto manager = get_context();
144 manager.loop();
145
146 // signal display update every loop
147 manager.lamp.signal_display();
148}
149
151{
152#ifdef LMBD_LAMP_TYPE__INDEXABLE
154 return true;
155#else
156 auto manager = get_context();
157 return manager.should_spawn_thread();
158#endif
159}
160
162{
163 auto manager = get_context();
164 manager.lamp.show();
165
166 if (manager.should_spawn_thread())
167 manager.user_thread();
168}
169
171namespace default_behaviors {
172
174bool button_clicked(const uint8_t clicks)
175{
176 auto manager = get_context();
177
178 switch (clicks)
179 {
180 case 6: // 6 clicks: jump to first mode of first category
181 {
182 if (manager.state.isInFavoriteMockGroup)
183 { // reset favorite indicator
184 manager.state.isInFavoriteMockGroup = false;
185 }
186 // return to first state
187 manager.set_active_group(0);
188 manager.set_active_mode(0);
189 manager.blip(250);
190 return true;
191 }
192 }
193
194 // nothing
195 return false;
196}
197
199bool button_hold(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
200{
201 auto manager = get_context();
202 auto& rampHandler = manager.state.rampHandler;
203
204 switch (clicks)
205 {
206 case 3: // 3 click+hold: configure custom ramp
207 // no ramps in favorite group
208 if (not manager.state.isInFavoriteMockGroup)
209 {
210 rampHandler.update_ramp(manager.get_active_custom_ramp(), holdDuration, [&](uint8_t rampValue) {
211 manager.custom_ramp_update(rampValue);
212 manager.set_active_custom_ramp(rampValue);
213 });
214 return true;
215 }
216 break;
217
218 // 5 click+hold: Add 5 minutes to sunset timer
219 case 5:
220 {
221 if (not isEndOfHoldEvent and holdDuration > 0 and logic::sunset::is_enabled())
222 {
223 // sunset timer !
224 auto manager = get_context();
225 if (manager.overlay_animate_ramp(
226 holdDuration, 1000, modes::colors::PaletteGradient<modes::colors::White, modes::colors::Red>))
227 {
228 // update the sunset timing
229 manager.state.isSunsetTimingPending = 2;
230 }
231 }
232 break;
233 }
234
235 case 13: // 13 clicks + hold: reset the whole system and stored parameters
236 {
237 if (not isEndOfHoldEvent and holdDuration > 0)
238 {
239 auto manager = get_context();
240 if (manager.overlay_animate_ramp(
241 holdDuration, 5000, modes::colors::PaletteGradient<modes::colors::Red, modes::colors::Red>))
242 {
243 // reset the file system and memory
244 bsp::lampda_print("clearing the whole file format");
246
247 // shutdown the lamp
248 const bool shouldSaveUserParameters = false;
249 logic::behavior::internal::handle_shutdown_state(shouldSaveUserParameters);
250 }
251 }
252 break;
253 }
254
255 case 20: // 20 clicks + hold: reset the whole system and stored parameters
256 {
257 if (not isEndOfHoldEvent and holdDuration > 0)
258 {
259 auto manager = get_context();
260 if (manager.overlay_animate_ramp(
261 holdDuration, 5000, modes::colors::PaletteGradient<modes::colors::Red, modes::colors::Red>))
262 {
263 // reset the file system and memory
264 bsp::lampda_print("clearing the whole file format");
266
267 // shutdown the lamp
268 const bool shouldSaveUserParameters = false;
269 const bool shouldSaveSystemParameters = false;
270 logic::behavior::internal::handle_shutdown_state(shouldSaveUserParameters, shouldSaveSystemParameters);
271 }
272 }
273 break;
274 }
275 }
276
277 return false;
278}
279
280namespace __private {
281
283void handle_brightness_control(const brightness_t requiredbrightness)
284{
285 // ignore if not on
287 return;
288
290 // update brightness
291 const brightness_t desiredBrightness =
292 min<brightness_t>(::lampda::brightness::absoluteMaximumBrightness, requiredbrightness);
293 // Update the system brightness for real, not the temporary. We want the changes to be saved
294 logic::brightness::update_brightness(desiredBrightness);
295 // update saved brightness
298
299 // and change the sunset timer if needed
301}
302
304void handle_on_off_command(const bool shouldBeOn)
305{
306 // turn on
307 if (shouldBeOn)
308 {
311 }
312 // turn off
313 else
314 {
317 }
318}
319
324void handle_ramp_command(const uint8_t ramp)
325{
326 // ignore if not on
328 return;
329
330 auto manager = get_context();
331
332 // update ramp value in modes
333 manager.custom_ramp_update(ramp, 1000);
334 // override user choice
335 manager.set_active_custom_ramp(ramp);
336}
337
342{
343 if (not time.is_valid())
344 {
345 bsp::lampda_print("Refusing set_time command %d %dh %dm %ds. Invalid values.",
346 time.dayOfTheWeek,
347 time.hour,
348 time.minutes,
349 time.seconds);
350 return;
351 }
352 const bool isValid = component::time::set_real_time(time);
354 "set time %d %dh %dm %ds (validity: %d)", time.dayOfTheWeek, time.hour, time.minutes, time.seconds, isValid);
355}
356
361{
362 if (not time.is_valid())
363 {
364 bsp::lampda_print("Refusing sunset command %d %dh %dm %ds. Invalid values.",
365 time.dayOfTheWeek,
366 time.hour,
367 time.minutes,
368 time.seconds);
369 return;
370 }
371 const auto& realTime = component::time::get_real_time();
372 if (not realTime.is_valid())
373 {
374 bsp::lampda_print("Refusing sunset command %d %dh %dm %ds : Time is not synchronized yet.",
375 time.dayOfTheWeek,
376 time.hour,
377 time.minutes,
378 time.seconds);
379 return;
380 }
381
382 const uint32_t internalLampActionTime = component::time::get_platform_time_from_target_time(time);
383 if (internalLampActionTime <= 0)
384 {
385 bsp::lampda_print("Refusing sunset command %d %dh %dm %ds: Target time is incoherent",
386 time.dayOfTheWeek,
387 time.hour,
388 time.minutes,
389 time.seconds);
390 return;
391 }
392
393 // lamp will turn on if not already turned on
396
397 logic::sunset::set_deadline(internalLampActionTime);
398}
399
400void handle_mode_control(const uint8_t groupIndex, const uint8_t modeIndex)
401{
402 // lamp will turn on if not already turned on
405
406 auto manager = get_context();
407
408 if (groupIndex >= manager.get_groups_count())
409 {
410 bsp::lampda_print("Group id %d is greater than max group id %d", groupIndex, manager.get_groups_count());
411 return;
412 }
413 manager.set_active_group(groupIndex);
414
415 if (modeIndex >= manager.get_modes_count())
416 {
417 bsp::lampda_print("Mode id %d is greater than max mode id %d", modeIndex, manager.get_modes_count());
418 return;
419 }
420 manager.set_active_mode(modeIndex);
421 manager.blip(250);
422}
423
424} // namespace __private
425
426bool handle_user_command(const common::UserCommand& command)
427{
428 switch (command.get_type())
429 {
431 {
432 uint8_t ramp;
433 if (command.parse_ramp(ramp))
434 __private::handle_ramp_command(ramp);
435 else
436 bsp::lampda_print("Failed to parse set_user_ramp command");
437 return true;
438 }
440 {
441 brightness_t brgt;
442 if (command.parse_brightness(brgt))
443 __private::handle_brightness_control(brgt);
444 else
445 bsp::lampda_print("Failed to parse brightness command");
446 return true;
447 }
449 {
450 uint8_t groupId;
451 uint8_t modeId;
452 if (command.parse_set_mode(groupId, modeId))
453 __private::handle_mode_control(groupId, modeId);
454 else
455 bsp::lampda_print("Failed to parse set_mode command");
456 return true;
457 }
459 {
460 bool shouldTurnOn;
461 if (command.parse_turn_onoff(shouldTurnOn))
462 __private::handle_on_off_command(shouldTurnOn);
463 else
464 bsp::lampda_print("Failed to parse onoff command");
465 return true;
466 }
468 {
469 component::time::RealTime time;
470 if (command.parse_set_real_time_command(time))
471 __private::handle_set_time_command(time);
472 else
473 bsp::lampda_print("Failed to parse set_real_time command");
474 return true;
475 }
477 {
478 component::time::RealTime time;
479 if (command.parse_set_sunset_to_time_command(time))
480 __private::handle_sunset_to_time_command(time);
481 else
482 bsp::lampda_print("Failed to parse set_sunset_time command");
483 return true;
484 }
485
486 default:
487 break;
488 }
489 return false;
490}
491
492} // namespace default_behaviors
493
494} // namespace lampda::user
495
496#endif
@ SetSunsetToTime
set the sunset to a target real time
@ SetRealTime
set the system real time
@ SetUserRamp
set the user ramp value
void clear(const Type type)
Clear an alert.
Definition: alerts.cpp:902
void handle_sunset_to_time_command(const component::time::RealTime &time)
Handle the timing command.
Definition: default_behavior.hpp:360
void handle_on_off_command(const bool shouldBeOn)
handle the On or Off command
Definition: default_behavior.hpp:304
void handle_brightness_control(const brightness_t requiredbrightness)
handle the brightness command
Definition: default_behavior.hpp:283
void handle_set_time_command(const component::time::RealTime &time)
Handle the set time command.
Definition: default_behavior.hpp:341
void handle_ramp_command(const uint8_t ramp)
Handle the ramp command.
Definition: default_behavior.hpp:324
void lampda_print(const char *format,...)
C linkage to print functions.
Definition: text_out.cpp:206
void clear_internal_fs()
hard clean of the whole filesystem, you will loose all stored data.
Definition: fileSystem.cpp:90
uint32_t get_platform_time_from_target_time(const RealTime &time)
Given a real time, return the expected platform time in seconds at wich it will be reached.
Definition: time_handling.cpp:92
RealTime get_real_time()
Return a real time value, only valid if it was set first.
Definition: time_handling.cpp:90
bool set_real_time(const RealTime &realTime)
Set the real time in the lamp, only valid until the next shutdown.
Definition: time_handling.cpp:75
void set_power_on()
set system state to "output on"
Definition: behavior.cpp:125
void set_power_off()
set system state to "output off". Can be ignored
Definition: behavior.cpp:126
bool is_in_output_state()
return true if the system is in output mode
Definition: behavior.cpp:139
void update_brightness(const brightness_t newBrightness, const bool shouldCallUserBrightnessCallback)
update the internal brightness values
Definition: brightness_handle.cpp:66
void update_saved_brightness()
Update the saved brightness value with the current brightness.
Definition: brightness_handle.cpp:58
void lock_brightness_update(bool shouldLock)
Lock the hability of the sunset timer to control the brightness.
Definition: sunset_timer.cpp:245
void set_deadline(const uint32_t timeshutdown_s)
Set the sunset timer to a known clock deadline, replacing existing timers. Start the timer,...
Definition: sunset_timer.cpp:128
void bump_timer()
signal to the timer that some time may be added. Only add time if the timer is in the fadeout phase
Definition: sunset_timer.cpp:204
bool is_enabled()
Indicate if the sunset is set.
Definition: sunset_timer.cpp:24
bool button_hold(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
must be called by the lampda::user::button_hold_default
Definition: default_behavior.hpp:199
bool button_clicked(const uint8_t clicks)
must be called by the lampda::user::button_clicked_default
Definition: default_behavior.hpp:174
Contains code handling custom user mode functions for indexable strips.
Definition: default_behavior.hpp:17
bool button_clicked_default(const uint8_t)
Called to handle button click events for default user mode behaviors.
Definition: indexable_behavior.hpp:18
bool button_hold_default(const uint8_t, const bool, const uint32_t)
Called to handle button click+hold events for user mode behaviors.
Definition: indexable_behavior.hpp:168
void brightness_update(const brightness_t brightness)
Called when the system changes the LED strip brightness.
Definition: default_behavior.hpp:58
void user_thread()
Called at each tick of the secondary thread.
Definition: default_behavior.hpp:161
bool button_hold_usermode(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
Called to handle button click+hold events if "usermode UI" is on.
Definition: default_behavior.hpp:135
bool button_start_hold_default(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
Called to handle button hold on lamp start.
Definition: default_behavior.hpp:103
void read_parameters()
Called when system wants to read parameters from filesystem.
Definition: default_behavior.hpp:95
void power_on_sequence()
Called when the system powers on (must be non blocking function!)
Definition: default_behavior.hpp:33
void sunset_timer_update(const float progress)
Called when the sunset timer progresses [0; 1].
Definition: default_behavior.hpp:81
bool button_start_click_default(const uint8_t clicks)
Called to handle button click on lamp start.
Definition: default_behavior.hpp:101
bool should_spawn_thread()
Determine if a second user_thread() loop thread should be spawned.
Definition: default_behavior.hpp:150
void write_parameters()
Called when system wants to write parameters to filesystem.
Definition: default_behavior.hpp:89
void power_off_sequence()
Called when the system powers off (must be non blocking function!)
Definition: default_behavior.hpp:44
void loop()
Called at each tick of the main loop.
Definition: default_behavior.hpp:141
bool button_clicked_usermode(const uint8_t clicks)
Called to handle button click events if "usermode UI" is active.
Definition: default_behavior.hpp:129
uint16_t brightness_t
Define the type of the brightness parameters.
Definition: constants.h:147
Store a real time reference.
Definition: time_handling.h:18
uint8_t minutes
minutes, in the [0; 59]
Definition: time_handling.h:30
uint8_t dayOfTheWeek
[0; 6] the index of the day of the week. Monday is 0, sunday is 6
Definition: time_handling.h:28
uint8_t hour
hour of the day, in the [0; 23]
Definition: time_handling.h:29
uint8_t seconds
seconds, in the [0; 59]
Definition: time_handling.h:31