Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
indexable_behavior.hpp
Go to the documentation of this file.
1
5#ifndef INDEXABLE_BEHAVIOR_MANAGER_H
6#define INDEXABLE_BEHAVIOR_MANAGER_H
7
9
10//
11// note: this code is included as-is by:
12// - user/indexable_functions.h
13//
14
15#include <cstdint>
16namespace lampda::user {
17
18bool button_clicked_default(const uint8_t clicks)
19{
20 // Handle default common behavior
22 {
23 // some event is already handled
24 return true;
25 }
26
27 auto manager = get_context();
28
29 switch (clicks)
30 {
31 case 2: // 2 clicks: next mode
32 {
33 if (manager.state.isInFavoriteMockGroup)
34 {
35 // if in favorite, next favorite
36 manager.state.lastFavoriteStep += 1;
37 // sanity check, if it fails, quit favorites
38 if (not manager.jump_to_favorite(manager.state.lastFavoriteStep, false))
39 {
40 manager.exit_favorite_group(manager.state.beforeFavoriteActiveIndex);
41 }
42 }
43 else
44 {
45 if (manager.state.isLastScrollAGroupChange and manager.lamp.now - manager.state.lastScrollStopped < 2000)
46 {
47 // last action was a group change & timer did not run out yet:
48 // change group
49 manager.next_group();
50
51 // prevent further jumps
52 manager.state.isLastScrollAGroupChange = false;
53 }
54 else
55 {
56 // else: just change mode
57 manager.next_mode();
58 }
59 }
60#ifdef LMBD_SIMULATION
61 {
62 int _groupId = manager.get_active_group();
63 int _modeId = manager.get_active_mode();
64 fprintf(stderr, "group %d *mode %d\n", _groupId, _modeId);
65 if (manager.everySunsetCallback[_groupId][_modeId])
66 fprintf(stderr, " - hasSunsetAnimation\n");
67 if (manager.everyBrightCallback[_groupId][_modeId])
68 fprintf(stderr, " - hasBrightCallback\n");
69 if (manager.everyCustomRamp[_groupId][_modeId])
70 fprintf(stderr, " - hasCustomRamp\n");
71 if (manager.state.rampHandler.animEffect)
72 fprintf(stderr, " - has anim effect\n");
73 if (manager.everyRequireUserThread[_groupId][_modeId])
74 fprintf(stderr, " - requireUserThread\n");
75 if (manager.everySystemCallbacks[_groupId][_modeId])
76 fprintf(stderr, " - hasSystemCallbacks\n");
77 if (manager.everyButtonCustomUI[_groupId][_modeId])
78 fprintf(stderr, " - hasButtonCustomUI\n");
79 }
80#endif
81
82 return true;
83 }
84
85 case 3: // 3 clicks: next group or quit favorite group
86 {
87 if (manager.state.isInFavoriteMockGroup)
88 {
89 // return to previous state
90 manager.exit_favorite_group(manager.state.beforeFavoriteActiveIndex);
91 }
92 else
93 {
94 // true next group
95 manager.next_group();
96 }
97
98#ifdef LMBD_SIMULATION
99 {
100 int _groupId = manager.get_active_group();
101 int _modeId = manager.get_active_mode();
102 fprintf(stderr, "group %d *mode %d\n", _groupId, _modeId);
103 if (manager.everySunsetCallback[_groupId][_modeId])
104 fprintf(stderr, " - hasSunsetAnimation\n");
105 if (manager.everyBrightCallback[_groupId][_modeId])
106 fprintf(stderr, " - hasBrightCallback\n");
107 if (manager.everyCustomRamp[_groupId][_modeId])
108 fprintf(stderr, " - hasCustomRamp\n");
109 if (manager.state.rampHandler.animEffect)
110 fprintf(stderr, " - has anim effect\n");
111 if (manager.everyRequireUserThread[_groupId][_modeId])
112 fprintf(stderr, " - requireUserThread\n");
113 if (manager.everySystemCallbacks[_groupId][_modeId])
114 fprintf(stderr, " - hasSystemCallbacks\n");
115 if (manager.everyButtonCustomUI[_groupId][_modeId])
116 fprintf(stderr, " - hasButtonCustomUI\n");
117 }
118#endif
119 return true;
120 }
121
122 case 4: // 4 clicks: jump to favorite
123 {
124 if (not manager.state.isInFavoriteMockGroup)
125 {
126 // jump and save last used mode
127 manager.jump_to_favorite(manager.state.lastFavoriteStep, true);
128 }
129#ifdef LMBD_SIMULATION
130 {
131 int _groupId = manager.get_active_group();
132 int _modeId = manager.get_active_mode();
133 fprintf(stderr, "group %d *mode %d\n", _groupId, _modeId);
134 if (manager.everySunsetCallback[_groupId][_modeId])
135 fprintf(stderr, " - hasSunsetAnimation\n");
136 if (manager.everyBrightCallback[_groupId][_modeId])
137 fprintf(stderr, " - hasBrightCallback\n");
138 if (manager.everyCustomRamp[_groupId][_modeId])
139 fprintf(stderr, " - hasCustomRamp\n");
140 if (manager.state.rampHandler.animEffect)
141 fprintf(stderr, " - has anim effect\n");
142 if (manager.everyRequireUserThread[_groupId][_modeId])
143 fprintf(stderr, " - requireUserThread\n");
144 if (manager.everySystemCallbacks[_groupId][_modeId])
145 fprintf(stderr, " - hasSystemCallbacks\n");
146 if (manager.everyButtonCustomUI[_groupId][_modeId])
147 fprintf(stderr, " - hasButtonCustomUI\n");
148 }
149#endif
150 return true;
151 }
152 }
153
154 return false;
155}
156
157bool button_hold_default(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
158{
159 // Handle default common behavior
160 if (default_behaviors::button_hold(clicks, isEndOfHoldEvent, holdDuration))
161 {
162 // some event is already handled
163 return true;
164 }
165
166 auto manager = get_context();
167 auto& rampHandler = manager.state.rampHandler;
168
169 switch (clicks)
170 {
171 case 4: // 4 click+hold: configure favorite
172 {
173 if (not isEndOfHoldEvent)
174 {
175 // lock to prevent addition of favorite from favorite & if we are deleting favorites
176 // the second case can happen when the user delete all favorites
177 if (not manager.state.isInFavoriteMockGroup && not manager.state.isInDeleteFavorite)
178 {
179 // no new favorite in favorite
180 manager.animate_favorite_pick(holdDuration, 1500);
181 }
182 else
183 {
184 // remove current favorite
185 manager.animate_favorite_delete(holdDuration, 2000);
186 }
187 }
188 else
189 {
190 manager.state.isInDeleteFavorite = false;
191 }
192 return true;
193 }
194
195 case 6: // 6 click+hold: scroll across modes and group
196 {
197 // no scroll in favorite
198 if (not manager.state.isInFavoriteMockGroup)
199 {
200 // register end of scroll
201 if (isEndOfHoldEvent)
202 {
203 // update release time
204 manager.state.lastScrollStopped = manager.lamp.now;
205 }
206 else
207 {
208 manager.handle_scroll_modes(holdDuration);
209 }
210 }
211 return true;
212 }
213
214 default:
215 break;
216 }
217 return false;
218}
219
220namespace __private {
221
227void handle_pattern_select_command(const uint8_t patternIndex, const uint32_t requestedColor = 0)
228{
229 // ignore if not on
231 return;
232
233 // get manager and execute a mode or group change
234 auto manager = get_context();
235 if (manager.get_hidden_groups_count() <= 0)
236 {
237 bsp::lampda_print("Cannot use bluetooth control without an hidden bluetooth group");
238 return;
239 }
240
241 const auto bluetoothGroup = manager.template get_group_id_of_mode<modes::bluetooth::ColorControlMode>();
242 if (bluetoothGroup < 0)
243 {
244 bsp::lampda_print("Cannot find the bluetooth group and modes");
245 return;
246 }
247
248 const auto availableModes = manager.get_modes_count();
249 if (availableModes <= patternIndex)
250 {
251 bsp::lampda_print("Unimplemented pattern id %d", patternIndex);
252 return;
253 }
254
255 manager.set_active_group(bluetoothGroup);
256 manager.set_active_mode(patternIndex);
257
258 // sanity check
259 const int trueIndex = manager.template get_mode_id<modes::bluetooth::ColorControlMode>();
260 assert(trueIndex == 0 && "Bluetooth group should have the programmable color output as the first group index");
261
262 // handle special programmable group mode
263 if (patternIndex == 0)
264 {
265 auto& modeState = manager.template get_state_of_mode<modes::bluetooth::ColorControlMode>();
266 modeState.color = requestedColor;
267 }
268}
269
274void handle_go_to_favorite_command(const uint8_t favoriteIndex)
275{
276 // ignore if not on
278 return;
279
280 auto manager = get_context();
281
282 // jump and save last used mode
283 manager.jump_to_favorite(favoriteIndex, true);
284}
285
290void handle_set_favorite_command(const uint8_t favoriteIndex)
291{
292 // ignore if not on
294 return;
295
296 auto manager = get_context();
297
298 // Cannot add a favorite mode to te favorite group: we are already here
299 if (manager.state.isInFavoriteMockGroup)
300 return;
301
302 const uint8_t allowedFavorites = manager.get_number_of_allowed_favorites();
303
304 // not enought favorite set
305 if (favoriteIndex >= allowedFavorites)
306 {
307 bsp::lampda_print("Max favorites is [0; %d[, cannot add index %d", allowedFavorites, favoriteIndex);
308 return;
309 }
310
311 // Set the favorite !
312 manager.set_current_mode_as_favorite(favoriteIndex, 1000);
313}
314
315} // namespace __private
316
318{
319 // Handle default common behavior
320 if (default_behaviors::handle_user_command(command))
321 {
322 // some event is already handled
323 return;
324 }
325
326 switch (command.get_type())
327 {
329 {
330 uint32_t color;
332 __private::handle_pattern_select_command(0, color);
333 else
334 bsp::lampda_print("Failed to parse set_ble_custom_color command");
335 return;
336 }
338 {
339 uint8_t index;
340 if (command.parse_set_ble_mode_command(index))
341 __private::handle_pattern_select_command(index);
342 else
343 bsp::lampda_print("Failed to parse set_ble_mode command");
344 return;
345 }
347 {
348 uint8_t index;
349 if (command.parse_go_to_favorite_command(index))
350 __private::handle_go_to_favorite_command(index);
351 else
352 bsp::lampda_print("Failed to parse go_to_favorite command");
353 return;
354 }
356 {
357 uint8_t index;
358 if (command.parse_set_favorite_command(index))
359 __private::handle_set_favorite_command(index);
360 else
361 bsp::lampda_print("Failed to parse set_favorite command");
362 return;
363 }
364 default:
365 break;
366 }
367
368 bsp::lampda_print("Unsupported user command message type");
369}
370
371} // namespace lampda::user
372
373#endif
Define assertions helpers.
Define a command destined to the user layer. Command can only be created by the static make_* methods...
Definition: user_commands.h:21
bool parse_set_favorite_command(uint8_t &index) const
Parse the current command for a set favorite.
Definition: user_commands.cpp:214
bool parse_set_ble_mode_command(uint8_t &index) const
Parse the current command for a set current mode to BLE mode.
Definition: user_commands.cpp:198
bool parse_go_to_favorite_command(uint8_t &index) const
Parse the current command for a go to favorite.
Definition: user_commands.cpp:206
@ SetBleMode
switch to a target BLE mode
@ SetBleCustomColorMode
switch to BLE custom color mode
@ SetFavoriteIndex
Set the current mode to the target favorite index.
@ GoToFavoriteIndex
Go to the target favorite index.
bool parse_set_ble_custom_color_mode_command(uint32_t &color) const
Parse the current command for a set current mode to BLE custom color.
Definition: user_commands.cpp:189
void handle_set_favorite_command(const uint8_t favoriteIndex)
Set the current mode to favorite.
Definition: indexable_behavior.hpp:290
void handle_go_to_favorite_command(const uint8_t favoriteIndex)
Go to the given favorite index if possible.
Definition: indexable_behavior.hpp:274
void handle_pattern_select_command(const uint8_t patternIndex, const uint32_t requestedColor=0)
Handle a pattern change command.
Definition: indexable_behavior.hpp:227
void lampda_print(const char *format,...)
C linkage to print functions.
Definition: text_out.cpp:227
bool is_in_output_state()
return true if the system is in output mode
Definition: behavior.cpp:139
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:247
bool button_clicked(const uint8_t clicks)
must be called by the lampda::user::button_clicked_default
Definition: default_behavior.hpp:219
Contains code handling custom user mode functions for indexable strips.
Definition: default_behavior.hpp:18
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:157
void handle_user_command(const common::UserCommand &command)
Handle user command.
Definition: indexable_behavior.hpp:317