ESP_IOT v2.5
IOT ESP Coding
ButtonProcessing.cpp
Go to the documentation of this file.
1//! \link ButtonProcessing
2//
3// ButtonProcessing.c
4// M5Stick
5//
6// Created by Scott Moody on 3/9/22.
7//
8
9#include "ButtonProcessing.h"
10#ifdef USE_BUTTON_MODULE
11
12#define USE_TIMER_DELAY_CLASS
13//! 3.29.25 RaiiiinIeeeeR Beer movie
14#ifdef USE_TIMER_DELAY_CLASS
15TimerDelayClass* _timerDelayClass_ButtonModule = new TimerDelayClass(1.0);
16void startDelay_ButtonProcessing(int seconds)
17{
18 _timerDelayClass_ButtonModule->startDelay((float)seconds);
19}
20boolean delayFinished_ButtonProcessing()
21{
22 return _timerDelayClass_ButtonModule->delayFinished();
23}
24void stopDelay_ButtonProcessing()
25{
26 _timerDelayClass_ButtonModule->stopDelay();
27}
28#else
29//! not USE_TIMER_DELAY_CLASS
30//**** Delay Methods*******
31#define SINGLE_DELAY
32#ifdef SINGLE_DELAY
33//https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html
34//! the time the delay started
35unsigned long _delayStart_ButtonProcessing;
36//! true if still waiting for delay to finish
37boolean _delayRunning_ButtonProcessing = false;
38//! length of delay
39int _delaySeconds_ButtonProcessing;
40//!init the delay
41void startDelay_ButtonProcessing(int seconds)
42{
43 SerialCall.printf("startDelay_ButtonProcessing: %d\n", seconds);
44
45 _delayStart_ButtonProcessing = millis(); // start delay
46 _delayRunning_ButtonProcessing = true; // not finished yet
47 _delaySeconds_ButtonProcessing = seconds;
48
49}
50//!if finished..
51boolean delayFinished_ButtonProcessing()
52{
53 if (_delayRunning_ButtonProcessing && ((millis() - _delayStart_ButtonProcessing) >= (_delaySeconds_ButtonProcessing * 1000)))
54 {
55 _delayRunning_ButtonProcessing = false;
56 SerialCall.println("delayFinished_ButtonProcessing..");
57 return true;
58 }
59 return false;
60}
61
62//!stop the delay
63void stopDelay_ButtonProcessing()
64{
65 SerialCall.println("stopDelay_ButtonProcessing _delayRunning=false");
66
67 _delayRunning_ButtonProcessing = false;
68}
69#endif //SINGLE_DELAY
70#endif //USE_TIMER_DELAY_CLASS
71
72//!get the delay values
73int getDelayNoClickPoweroffSetting()
74{
76}
77
78//!set when any button touched..
79void refreshDelayButtonTouched()
80{
81 startDelay_ButtonProcessing(getDelayNoClickPoweroffSetting());
82}
83
84//! called by the feed operation to say the device is still running.. and count it as a button click.
85void refreshDelayButtonTouched_ButtonProcessing()
86{
87 SerialLots.println("refreshDelayButtonTouched_ButtonProcessing");
88 //! call the local implementation
89 refreshDelayButtonTouched();
90}
91
92
93//!checks delay
94void checkDelaySinceButtonTouched()
95{
96 if (delayFinished_ButtonProcessing())
97 {
99 {
100 SerialMin.printf("GATEWAY so no poweroff, but %d seconds with no buttons/feed\n", getDelayNoClickPoweroffSetting());
101 }
102 else if (getDelayNoClickPoweroffSetting() == NO_POWEROFF_AMOUNT_MAIN)
103 {
104 SerialMin.printf("User set no poweroff, but %d seconds with no buttons/feed\n", getDelayNoClickPoweroffSetting());
105 }
106 else
107 {
108
109 //let others know what's happening..
110 sendMessageString_mainModule((char*)"NoButtonActivity.. poweroff");
111
112 SerialMin.printf("buttonProcessor invoking poweroff after %d seconds with no buttons\n", getDelayNoClickPoweroffSetting());
113 // poweroff.. but send MQTT first..
115 }
116
117 }
118}
119
120//#endif //SINGLE_DELAY
121
122//!calls the resetFeed after we figure out the max
123void resetFeedCount()
124{
126}
127
128// ****************** START ESP_M5
129#ifdef ESP_M5
130/**
131 Idea for the 2 buttons: (the side button is the 'select' button, which changes the "state" of the M5. Then the
132 top button is the 'select' on the state. So if the state was "feed" then the top button would be feed.
133
134 But since their are many options for the device, th
135 */
136
137//defaults (mode is incremented on waking)
138char _smMessage[30];
139
140//!toggle the showing of the SemanticMarker and the ZOOM version
141void toggleSM_Zoomed()
142{
144 //now redraw the semantic marker (zoomed or not zoomed)
146}
147
148//!invokes the semantic marker (which changes the display), this uses the getCurrentSMMode_mainModule()
149void invokeCurrentSemanticMarker()
150{
151
152 //! 8.16.25 MQTT
153 //! Ths processJSONMessageMQTT( with cmd:smN } will trigger displaying the SemanticMarker for that page, etc.
154 //!
155 sprintf(_smMessage,"{'cmd':'%s'}",charSMMode_mainModule(getCurrentSMMode_mainModule()));
156 //sends message internally in JSON format.. (same as if message came from MQTT via node-red,
157 // which is where the SemanticMarkers are linked to .. the node-red backend (LinkAndSync)
159
160}
161
162//!process the current command (from some button combination) This is the LONG press on the Big button A
163void performProcessCurrentMode()
164{
165
166 //! long press. This will "select" the mode we are in..
167 //! short press = always feed..
168
169 //!send the async FEED. The logic there determines if BLE or MQTT
170 //! dispatches a call to the command specified. This is run on the next loop()
171 boolean justWakeup = isBlankScreen_displayModule();
172
173 //!debug
174 SerialCall.print("performProcessCurrentMode: blank:");
175 SerialCall.println(justWakeup);
176
177 //!whether screen is blank (so the button can be a wake, vs action..)
178 if (!justWakeup)
179 {
180 SerialTemp.print("currentSMMode: ");
181 SerialTemp.println(getCurrentSMMode_mainModule());
182
183 int currentSMMode = getCurrentSMMode_mainModule();
184 //! see if there is a model..
186 if (model)
187 {
188 //print the model..
189
190 //invoke the operation.. the selection (wrapping around)
191 boolean modelChanged = invokeMenuState(model->modelKindEnum);
192 SerialTemp.printf("modelChanged(%d)\n", modelChanged);
193 //set based on modelChanged
194 int startFlag = modelChanged?START_NEW:KEEP_SAME;
195 //!redraws the Semantic Marker image..
196 // redrawSemanticMarker_displayModule(KEEP_SAME);
197
198 int currentSMModeNow = getCurrentSMMode_mainModule();
199
200 //!basically some of the invocation changes the pages, so if it's different, invoke the current one..
201 SerialTemp.printf("SMmode=%d, now=%d\n", currentSMMode,currentSMModeNow);
202 if (currentSMMode != currentSMModeNow)
203 invokeCurrentSemanticMarker();
204 else
206
207 return;
208 }
209
210 ///the mode is executable now..
212 {
213 case SM_home_simple:
214 SerialCall.println("SM_home_simple");
215
217
218 //long press == tilt toggle..
220 invokeCurrentSemanticMarker();
221
222 break;
223 case SM_home_simple_1:
224 SerialCall.println("SM_home_simple_1");
225
227 //! 8.16.25 BLE CLIENT //!optimized to not send the wrapper around the message
228 // need to send B or b .. depending on result
231 else
233
234 invokeCurrentSemanticMarker();
235
236 //long press == buzz toggle..
237 break;
238 case SM_home_simple_2:
239 {
240 SerialCall.println("SM_home_simple_2");
241
242 //!calls the resetFeed after we figure out the max
243 resetFeedCount();
244
245 //togglePreferenceBoolean_mainModule(PREFERENCE_STEPPER_BUZZER_VALUE);
246 invokeCurrentSemanticMarker();
247 }
248 //long press == buzz toggle..
249 break;
250 case SM_home_simple_3: //trying to mimick the HELP ...
251 //new for the simple homepages..
252 SerialCall.println("SM_home_simple_3");
253 //togglePreferenceBoolean_mainModule(PREFERENCE_IS_MINIMAL_MENU_SETTING);
255
256 //also change to the next item, maybe anothertime popup a message stating what's happening..
258 invokeCurrentSemanticMarker();
259
260 break;
261 //!home page, long pr3ess will be MQTT feed message
263 //! 8.16.25 MQTT
264 ///feed always (done after the code below..)
265// main_dispatchAsyncCommand(ASYNC_SEND_MQTT_FEED_MESSAGE);
266 sendMessageMQTT((char*)"#FEED");
267 break;
268
269 //!guest page. Long press sends our WIFI credentials over BLE to the server (like a feeder)
270 case SM_guest_page:
271 {
272 //!grab the WIFI credentials in JSON format
273 char *credentials = main_JSONStringForWIFICredentials();
274 //!send over BLE
275 //!send an async call with a string parameter. This will set store the value and then async call the command (passing the parameter)
276 //!These are the ASYNC_CALL_PARAMETERS_MAX
277 //!since cannot send over 13 characters lets just sent the swap of network
279 }
280 break;
281 case SM_guest_feed: //guest feed
282 //NO-OP in zoom mode, the SemanticMarker shows the guest feed ..
283 // or make it just feed?
284 //! 8.16.25 MQTT
285 //!create a device name feeding message
286 //!send this as a message, not this tacks on the # in front and other after
287 sendMessageString_mainModule((char*)"FEED");
288 break;
289 //guest feed and wifi ssid both change the credentials..
290 case SM_WIFI_ssid:
291 {
292 //NOTE: this might be where we toggle credentials?? TODO
293 //found other one..
294 char *credentials = main_nextJSONWIFICredential();
295 //! 8.16.25 MQTT
296
297 //!These are the ASYNC_CALL_PARAMETERS_MAX
298 //!NO: just change our credentials ...
299 //send to
300 //main_dispatchAsyncCommandWithString(ASYNC_CALL_BLE_CLIENT_PARAMETER, credentials);
302 //redraw window..
303 invokeCurrentSemanticMarker();
304
305 }
306 break;
307
308 case SM_pair_dev: //pair device
309 {
311 //! 8.16.25 MQTT
312 //!create a device name feeding message
313 sprintf(_smMessage,"FEED {'deviceName':'%s'}",pairDevice);
314 //!send this as a message, not this tacks on the # in front and other after
316 }
317 break;
318 case SM_status: //status
319 {
320 //send this onto the DOCFollow message
323 //! 8.16.25 MQTT
324 //!also send a #STATUS
325 sendMessageMQTT((char*)"#STATUS");
326
327 }
328 break;
329 case SM_help: //help
330 {
331 //!and print any preferences to show
333#ifdef CHANGED_TO_JUST_MIN_MAX
334 //new logic: long press big buton ButA
335 // if in zoomed -- then go to unzoomed (which shows semantic marker)
336 // in unzoomed, also show all the marker (so Min = false)
338 //now what will it be..
340
341 SerialCall.print("Setting MINIMAL_MENU: ");
342 SerialCall.println(isZoomed?"ZOOMED":"UNZOOMED");
343
344 // if zoomed in (then use the short or min setting
346#endif
348
349 //a!lso change to the next item, maybe anothertime popup a message stating what's happening..
351 invokeCurrentSemanticMarker();
352 }
353 break;
354 case SM_ap_mode: //AP MODE
355 //send the async FEED
356 //! dispatches a call to the command specified. This is run on the next loop()
358 break;
359
360 case SM_doc_follow:
361 {
362 //The long press will send A semanticMarker of some kind onto the network..
363 // The getSM is already being shown..
364
365 //This is where options occur.. what to send out?
366 /// FOR NOW lets sed the dynamic status message..
367 //send this onto the DOCFollow message
368 //const char* sm = currentSemanticMarkerAddress_displayModule();
369 char *statusURL = main_currentStatusURL(true);
370
371 SerialTemp.print("SM_doc_follow: ");
372 SerialTemp.println(statusURL);
374
375 }
376 break;
377 case SM_reboot:
378 {
379 SerialMin.println("rebooting..");
381
382 return;
383 }
384 break;
385 default:
386 //these will be just SemanticMarkers to scan..
387 break;
388 } //switch
389 }
390 else
391 {
392 SerialCall.print("currentSMMode: ");
393 SerialCall.println(getCurrentSMMode_mainModule());
394 }
395 //now redraw the semantic marker (zoomed or not zoomed)
397
398}
399
400
401//!defines M5 info: https://docs.rs-online.com/e4eb/A700000008182827.pdf
402
403//!long press on buttonA (top button)
404void buttonA_LongPress()
405{
406 SerialTemp.println("long press.. processMode");
407
408 //!long press
409 performProcessCurrentMode();
410
411}
412
413
414//!short press on buttonA (top button)
415void buttonA_ShortPress()
416{
417 // always feed..
418 SerialTemp.println("buttonA_ShortPress");
419
420 //! see if there is a model..
422 if (model)
423 {
424 boolean justWakeup = isBlankScreen_displayModule();
425 if (justWakeup)
426 {
427 //!redraws the Semantic Marker image..
429 }
430 else
431 {
432 //increment the selection (wrapping around)
434
435 //!redraws the Semantic Marker image..
437 }
438
439 //!no more action .. like no feed
440 return;
441 }
442
443 ///feed always (done after the code below..)
445
446 //! 8.16.25 MQTT
447 //!unfortunately, the incrementFeedCount() is AFTER the redrawSemanticMarker..
448 /// This sets the semantic marker .. which is current SM
449 sprintf(_smMessage,"{'cmd':'%s'}",charSMMode_mainModule(getCurrentSMMode_mainModule()));
450 // processJSONMessageMQTT(charSMMode_mainModule(getCurrentSMMode_mainModule()), TOPIC_TO_SEND);
452
453 //!redraws the Semantic Marker image..
455
456 //shows that we clicked the button... (vs waiting for another to show it..)
457 showText_displayModule("FEED..");
458}
459
460
461//!the long press of the side button
462void buttonB_LongPress()
463{
464
465 SerialCall.println("B.long press.. toggleZoom or incrementColor");
466
468 {
469 case SM_home_simple:
470 case SM_home_simple_1:
471 case SM_home_simple_2:
472 case SM_ap_mode: //AP MODE
473
474 //! for now, the color is incremented in the displayModule
476 //now redraw the semantic marker (zoomed or not zoomed)
478 break;
479 case SM_home_simple_3:
480 // send a STATUS message
481 //! 8.16.25 MQTT
482 //!also send a #STATUS
483 sendMessageMQTT((char*)"#STATUS");
484 break;
485 default:
486 //long press
487 //!toggle the showing of the SemanticMarker and the ZOOM version
488 toggleSM_Zoomed();
489 break;
490 }
491
492
493}
494
495//!the short press of the side button
496void buttonB_ShortPress()
497{
498 //!and print any preferences to show
499 //printPreferenceValues_mainModule();
500 SerialCall.println("buttonB shortPress");
501
502 //!side button.. cycles through choices..
503 //!NOW: for
504
505 boolean justWakeup = isBlankScreen_displayModule();
506 //!whether screen is blank (so the button can be a wake, vs action..)
507 if (!justWakeup)
508 {
509#define NEW_VERSION
510#ifdef NEW_VERSION
512 {
513 // set back to the SM_HOME_SIMPLE_LAST = table of contents..
515 }
516 else
517#endif
519 SerialCall.print("current mode:");
520 SerialCall.println(getCurrentSMMode_mainModule());
521 //not used right now.. min and max are same ..
522
523 }
524
525 //NOTE: starting at SM5, these are groups of 2 (on/off) and the drawing of the semantic marker
526 invokeCurrentSemanticMarker();
527
528}
529#endif //ESP_M5
530// ****************** END ESP_M5
531
532//!the setup for buttonProcessing (extension of ButtonModule)
533//! 在 M5StickC Plus 启动或者复位后,即会开始执行setup()函数中的程序,该部分只会执行一次。
534void setup_ButtonProcessing()
535{
537
538}
539
540boolean _firstLoopProcessing = true;
541//!the loop for buttonProcessing (extension of ButtonModule)
542void loop_ButtonProcessing()
543{
544#ifdef ESP_M5
545 //not sure if MQTT or other running .. but seems like a try
546 if (_firstLoopProcessing)
547 {
548 invokeCurrentSemanticMarker();
549 _firstLoopProcessing = false;
550 }
551#endif //ESP_M5
552 //see if the time is up..
553// checkDelaySinceButtonTouched();
554
555}
556
557#ifdef ESP_M5
558#else
559//!short press on buttonA (top button)
560void buttonA_ShortPress() {}
561//!long press on buttonA (top button)
562void buttonA_LongPress() {}
563//!the long press of the side button
564void buttonB_LongPress() {}
565//!the short press of the side button
566void buttonB_ShortPress() {}
567#endif //ESP_M5
568#endif //USE_BUTTON_MODULE
void sendCommandBLEClient_13orLess(String cmdString)
send a string of 13 characters or less
void incrementScreenColor_displayModule()
boolean isBlankScreen_displayModule()
whether screen is blank (so the button can be a wake, vs action..)
void showText_displayModule(String text)
void redrawSemanticMarker_displayModule(boolean startNew)
redraws the Semantic Marker image..
const char * currentSemanticMarkerAddress_displayModule()
returns the current semantic marker (eg. guest page)
#define START_NEW
Definition: DisplayModule.h:53
#define KEEP_SAME
Definition: DisplayModule.h:54
void sendMessageMQTT(char *message)
boolean processJSONMessageMQTT(char *ascii, char *topic)
process the JSON message (looking for FEED, etc). Note: topic can be nil, or if not,...
void sendSemanticMarkerDocFollow_mainModule(const char *SMDocFollowAddress)
sends the SM on the DOCFOLLOW channel (publish it..)
char * charSMMode_mainModule(int whichSMMode)
returns string form whichSMMode, sg "sm0", sm1 ...
char * main_currentStatusURL(boolean fullStatus)
char * main_JSONStringForWIFICredentials()
retrieve a JSON string for the ssid and ssid_password: {'ssid':<ssid>,'ssidPassword':<pass>"}
Definition: MainModule.cpp:904
void main_dispatchAsyncCommandWithString(int asyncCallCommand, char *parameter)
int getCurrentSMMode_mainModule()
returns the current SM Mode
void resetFeedCount_mainModule()
sets the feed count max
Definition: MainModule.cpp:390
void sendMessageString_mainModule(char *messageString)
adding a synchronous call to send a message over the network (assuming MQTT but not specified),...
void setCurrentSMMode_mainModule(int whichSMMode)
sets the current screen mode .. which can be used by Button and Display processing
void main_dispatchAsyncCommand(int asyncCallCommand)
checks if any async commands are in 'dispatch' mode, and if so, invokes them, and sets their flag to ...
char * main_nextJSONWIFICredential()
! cycle through the next WIFI saved credential
Definition: MainModule.cpp:910
void incrementSMMode_mainModule()
increment the currentSMMode, wrapping and using the max menu
#define SM_home_simple
Definition: MainModule.h:357
#define SM_pair_dev
guest feed device
Definition: MainModule.h:381
#define ASYNC_REBOOT
sets the GATEWAY mode off
Definition: MainModule.h:213
#define ASYNC_CALL_BLE_CLIENT_PARAMETER
these are the async with a string parameter. This sends a BLE command unless MQTT
Definition: MainModule.h:231
#define SM_guest_feed
guest feed
Definition: MainModule.h:379
#define SM_guest_page
guest page
Definition: MainModule.h:372
#define NO_POWEROFF_AMOUNT_MAIN
10000 == no poweroff
Definition: MainModule.h:67
#define ASYNC_SEND_MQTT_FEED_MESSAGE
sends a message (like FEED) on the users topic
Definition: MainModule.h:203
#define SM_HOME_SIMPLE_LAST
Definition: MainModule.h:361
#define SM_home_simple_1
Definition: MainModule.h:358
#define SM_home_simple_2
Definition: MainModule.h:359
#define SM_status
//status
Definition: MainModule.h:368
#define ASYNC_CALL_CLEAN_CREDENTIALS
cleans out the credentials and restarts in AP (Access Point) mode.
Definition: MainModule.h:193
#define SM_reboot
REboot.
Definition: MainModule.h:390
#define SM_help
HELP.
Definition: MainModule.h:383
#define ASYNC_POWEROFF
sets the GATEWAY mode off
Definition: MainModule.h:215
#define SM_home_simple_3
Definition: MainModule.h:360
#define SM_doc_follow
docfollow
Definition: MainModule.h:386
#define SM_smart_clicker_homepage
//! homepage
Definition: MainModule.h:366
#define TOPIC_TO_SEND
Definition: MainModule.h:61
#define SM_WIFI_ssid
WIFI ssid.
Definition: MainModule.h:370
#define SM_ap_mode
AP MODE.
Definition: MainModule.h:375
void incrementMenuState(ModelKindEnum modelKind)
increments the device states deviceState (wrapping around)
boolean invokeMenuState(ModelKindEnum modelKind)
invokes the menu state, return true if the model state has change enough to refreesh your View (such ...
ModelStateStruct * hasModelForSM_Mode(int SM_Mode)
retrieves the state model for the SM_Mode (SM_0 .. SM_LAST) null if none
void savePreferenceBoolean_mainModule(int preferenceID, boolean flag)
save a boolean preference
boolean getPreferenceBoolean_mainModule(int preferenceID)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
void togglePreferenceBoolean_mainModule(int preferenceID)
toggles a preference boolean
int getPreferenceInt_mainModule(int preferenceID)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
char * getPreferenceString_mainModule(int preferenceID)
returns the preference but in it's own string buffer. As long as you use it before calling getPrefere...
void printPreferenceValues_mainModule()
print the preferences to SerialDebug
#define PREFERENCE_SENSOR_TILT_VALUE
Sensor preferences.
#define PREFERENCE_NO_BUTTON_CLICK_POWEROFF_SETTING
#define PREFERENCE_SEMANTIC_MARKER_ZOOMED_VALUE
Display preferences (SemanticMarker etc) - boolean.
#define PREFERENCE_PAIRED_DEVICE_SETTING
the paired device for guest device feeding (6.6.22)
#define PREFERENCE_STEPPER_BUZZER_VALUE
stepper preferences
#define PREFERENCE_IS_MINIMAL_MENU_SETTING
sets the max temp for a poweroff
#define PREFERENCE_MAIN_GATEWAY_VALUE
unsigned long millis()
Definition: TinyGPS.cpp:35
An concrete class.
void startDelay(float delayAmountSeconds)
starts delay calculation
boolean delayFinished()
whether the currently delay is finished, false if not running at all
void stopDelay()
stops delay
the struct for the models. Since this isn't straight OO, we are overlaying information....
ModelKindEnum modelKindEnum
What kind of model.