ESP_IOT v2.5
IOT ESP Coding
ModelController.cpp
Go to the documentation of this file.
1#include "../../Defines.h"
2#include "ModelController.h"
3
4//*** For the MenuSelection MODEL
5//! a pseudo Class
6
7#define MenusModel_Help 0
8#define MenusModel_Settings 1
9#define MenusModel_Pairing 2
10#define MenusModel_APMode 3
11#define MenusModel_Timer 4
12#define MenusModel_Status 5
13#define MenusModel_Advanced 6
14#define MenusModel_WIFIShare 7
15#define MenusModel_GuestFeed 8
16#define MenusModel_GuestPage 9
17#define MenusModel_DocFollow 10
18#define MenusModel_Max 11
19
20//!retrieves the state model for the modelKind
22
23#ifdef ESP_M5
24//!storage of mapping
26//!init the mapping
28{
29 for (int i=0; i< MenusModel_Max; i++)
30 {
31 switch (i)
32 {
35 break;
38 break;
41 break;
44 break;
47 break;
50 break;
53 break;
56 break;
59 break;
62 break;
63 case MenusModel_Help:
65 break;
66 default:
67 SerialMin.println(" *** invalid menu item");
68 break;
69 }
70 }
71}
72#endif //ESP_M5
73//!
74//!create state variables for the ModelKindEnum entries
75ModelStateStruct _modelStateStructs[ModelKindEnumMax];
76char _timerBuffer[10];
77
78//!initialize the objects
80{
81 strcpy(_timerBuffer,"5");
82#ifdef ESP_M5
84#endif //ESP_M5
85
86 for (int i=0;i< ModelKindEnumMax;i++)
87 {
90 switch (i)
91 {
92#ifdef ESP_M5
96 break;
97 case rebootModel:
100
101 //STATE info..
102 //! for the next page state 0..n
104 // the max before goes back to 0, use SM_LAST from MainModule.h
108 _modelStateStructs[i].waveName = (char*)"KikahaPhotos"; // for now.. TODO .. explain this..
109 break;
110 case menusModel:
113 break;
114#endif //ESP_M5
115 case timerModel:
116 //!initialize the random:
117 //!@see https://www.arduino.cc/reference/en/language/functions/random-numbers/random/
118 randomSeed(101010);
119
122 //! true if still waiting for delay to finish
124 //! length of delay
125 //!get from in EPROM
129 SerialCall.printf("initTimer: sec = %d\n", _modelStateStructs[i].currentCounterSeconds);
130#if defined(ESP_M5_CAMERA) || defined(ESP_32)
131 //! feed local instead of MQTT or BLE..
132 //! if camera then feed local == take a picture..
134#else
135 //! feed local instead of MQTT or BLE..
137#endif //ESP_32 or CAMERA
138 break;
139 }
140 }
141}
142
143//!! TIMER Remote control set delay seconds
144//!MQTT: set: timerdelay, val:seconds
146{
147 SerialDebug.printf("setTimerDelaySeconds_mainModule(%d)\n", delaySeconds);
148
149 ModelStateStruct *timerModelStruct = getModel(timerModel);
150 timerModelStruct->delaySeconds = delaySeconds;
151 timerModelStruct->currentCounterSeconds = delaySeconds;
152 //!save in EPROM
154
155}
156
157//!! TIMER Remote control set delay seconds
158//!MQTT: set: timerdelay,Max val:seconds
160{
161 SerialDebug.printf("setTimerDelaySecondsMax_mainModule(%d)\n", delaySeconds);
162
163 ModelStateStruct *timerModelStruct = getModel(timerModel);
164 timerModelStruct->delaySecondsMax = delaySeconds;
165 timerModelStruct->currentCounterSeconds = delaySeconds;
166 //!save in EPROM
168
169}
170
171//! set the next random time .. since called from a couple places
172//! will set the model->delayStartMillis == currentCounterSeconds
174{
175 ModelStateStruct *timerModelStruct = getModel(timerModel);
176
177 // calculate a random
178 int nextRandomTimeSeconds = random(timerModelStruct->delaySeconds, timerModelStruct->delaySecondsMax);
179 timerModelStruct->delayStartMillis = millis(); // when started
180 timerModelStruct->currentCounterSeconds = nextRandomTimeSeconds;
181
182 //!the value returned from random .. the diff is taken off this number
183 //! but this number doesn't change except next random call
184 timerModelStruct->counterLoopAbsoluteSeconds = nextRandomTimeSeconds;
185
186 SerialCall.printf("nextRandomTimeSeconds(%d,%d) = %d\n", timerModelStruct->delaySeconds, timerModelStruct->delaySecondsMax, nextRandomTimeSeconds);
187}
188
189//!! TIMER Remote control start
190//!MQTT: set: starttimer, val: true/false (true == start timer, false = stop timer)
191void startStopTimer_mainModule(boolean startTimer)
192{
193 ModelStateStruct *timerModelStruct = getModel(timerModel);
194 timerModelStruct->delayRunning = startTimer;
195
196 if (startTimer)
197 {
199 }
200 SerialDebug.printf("startStopTimer_mainModule(%d, %d)\n", startTimer, timerModelStruct->currentCounterSeconds);
201
202}
203
204//!print it out..
206{
207//#define PRINT_THIS
208#ifdef PRINT_THIS
209 ModelKindEnum modelKind = deviceState->modelKindEnum;
210 switch (modelKind)
211 {
213 {
214
215 SerialTemp.print("deviceState->pairedDeviceStateEnum: ");
216 switch (deviceState->pairedDeviceStateEnum)
217 {
218 //paired to a device, but BLE NOT connected right now
220 SerialLots.println("pairedButNotConnectedEnum");
221 break;
222 //paired to a device, and BLE connected right now
224 SerialLots.println("pairedAndConnectedEnum");
225 break;
226 //not paired (but could be paired as it's a named device])
228 SerialLots.println("pairableAndConnectedEnum");
229 break;
230 //!factory default but not connecte to anything..
231 case notConnectedEnum:
232 SerialLots.println("notConnectedEnum");
233 break;
234 }
235 break;
236 }
237 case rebootModel:
238 {
239 SerialTemp.println("deviceState = rebootModel ");
240 }
241 break;
242 case menusModel:
243 {
244 //!MENUS
245 //! WIFI Feed
246 //! Advanced
247 //! Status
248 //! WIFI sharing
249 //! APMode
250 //! Guest Feed
251 //! Settings
252 //! Pairing
253 //! DocFollow
254 //! help
255 //! HomePage
256
257 SerialTemp.println("deviceState = menusModel ");
258 }
259 break;
260 case timerModel:
261 {
262 SerialTemp.println("deviceState = timerModel ");
263 }
264 break;
265 }
266 SerialTemp.printf("deviceState->maxItems (%d) \n", deviceState->maxItems );
267 SerialTemp.printf("deviceState->currentItem (%d) \n", deviceState->currentItem );
268#endif
269}
270
271
272//!retrieves the state model for the modelKind
274{
275 ModelStateStruct *model = &_modelStateStructs[modelKind];
276 SerialCall.printf("getModel(%d) = %d\n", modelKind, model);
277 printDeviceState(model);
278
279 return model;
280}
281
282//!retrieves the state model for the SM_Mode (SM_0 .. SM_LAST) null if none
284{
285 for (int i=0;i< ModelKindEnumMax;i++)
286 {
287 if (_modelStateStructs[i].SM_Mode == SM_Mode)
288 {
289 SerialCall.printf("hasModelForSM_Mode(%d) == yes\n", SM_Mode);
290
292 return &_modelStateStructs[i];
293 }
294 }
295 SerialCall.printf("hasModelForSM_Mode(%d) == NO\n", SM_Mode);
296
297 return NULL;
298}
299
300//!increments the device states deviceState (wrapping around)
302{
303 ModelStateStruct *deviceState = getModel(modelKind);
304
305
306 int item = deviceState->currentItem;
307 int max = deviceState->maxItems;
308 item = (item + 1) % max;
309 deviceState->currentItem = item;
310
311 SerialCall.printf("incrementMenuState(%d) = %d \n", modelKind, item);;
312
313}
314
315//!restarts all the menu states to the first one .. useful for getting a clean start. This doesn't care if the menu is being shown
317{
318 SerialDebug.println("restartAllMenuStates");
319 for (int i=0;i< ModelKindEnumMax;i++)
320 {
321 ModelKindEnum modelKind = (ModelKindEnum)i;
322 ModelStateStruct *deviceState = getModel(modelKind);
323 deviceState->currentItem = 0;
324 }
325}
326
327//!storage..
328//char _smMessage_ModelController[30];
329
330//!send the command to the stepper.. not a BLE command
332{
334}
335
336//!performs the BLE feed
338{
339 char _smMessage_ModelController[30];
340
341 ///feed always (done after the code below..)
343
344 //! 8.16.25 MQTT
345 //!unfortunately, the incrementFeedCount() is AFTER the redrawSemanticMarker..
346 /// This sets the semantic marker .. which is current SM
347 sprintf(_smMessage_ModelController,"{'cmd':'%s'}",charSMMode_mainModule(getCurrentSMMode_mainModule()));
348 // processJSONMessageMQTT(charSMMode_mainModule(getCurrentSMMode_mainModule()), TOPIC_TO_SEND);
349 processJSONMessageMQTT(_smMessage_ModelController, TOPIC_TO_SEND);
350
351}
352
353//! just unpair .. don't skip
354//!performs the unpairing
356{
359
360#ifdef NO_MORE_PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
362#endif
363 //!also unset the main storage..
364 setConnectedBLEDevice_mainModule((char *)"",false);
365
366}
367//! just unpair .. don't skip
368//!performs the unpairing
370{
371 //!refactored base
373
374 //! 8.16.25 BLE CLIENT
376}
377
378//!performs the unpairing
379void invokeUnpair_ModelController(char *nameOrAddress)
380{
381 //!refactored base
383
384 //! 8.16.25 BLE CLIENT
387
388}
389//!performs the pairing.. to whatever is currently connected, this means a message could make that happen
390//!for a device (ESP-32) with no user interface.
392{
393 char *deviceName = connectedBLEDeviceName_mainModule();
394 char *deviceNameAddress = connectedBLEDeviceNameAddress_mainModule();
395 boolean isGEN3 = connectedBLEDeviceIsGEN3_mainModule();
396
397 SerialLots.printf("invokePair(%s, gen3=%d)\n", deviceName, isGEN3);
398
399 //TODO...
400
401 //!this is where it needs to know if GEN3. If so, then if their is a paired name .. If GEN3, don't overreight the device name
402 //!in case it was set by the user..
403 if (!isGEN3)
405
406 //! always set the ADDRESS
408
409 //!This means the name
410#ifdef NO_MORE_PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
412#endif
413}
414
415//!performs skip
416void invokeSkip_ModelController(char *nameOrAddress)
417{
418 //! 8.16.25 BLE CLIENT
419
421
422 //TODO: look to see if the Address can be used to not connect right away to same one...
424}
425
426//! toggles the GEN3 setting
428{
429 //!change GEN3 preference
431
432 //!if connected and not a GEN3 but want only GEN3 .. then disconnect, otherwise keep connected
434 {
435 SerialTemp.println(" *** GEN3 only but connected to a non GEN3 .. so unpair **");
436 //!also unpair..
438 }
439}
440
441
442//!updates the model for the menu state, this sets max etc
444{
445 ModelStateStruct *deviceState = getModel(modelKind);
446#pragma mark DEBUG_7_12
447 SerialCall.printf("updateMenuState(%d) \n", modelKind);
448
449 switch (modelKind)
450 {
452 {
453 //! must save since many preferences are called...
454 char pairedDeviceString[50];
455 char pairedDeviceAddressString[50];
456 //* NEW PLAN..
457 //! the pairedName stored in EPROM can be an Address (eg. 03:34:23:33)
458 //!
459 //!show the BLE connected status at the bottom (G3 if gen3), WIFI, and AP if APmode
460 //! 8.16.25 BLE CLIENT
461 boolean isConnectedBLE = isConnectedBLEClient();
462
463 SerialLots.printf("\nPAIRED_DEVICE_MODEL\n");
464 SerialLots.printf("isConnectedBLE(%d)\n", isConnectedBLE);
465
467 if (gen3Only)
468 SerialLots.printf("gen3Only(%d)\n", gen3Only);
469
470 //! whether the gateway is on.. this isn't using the Gx just BLE or GE3
472 if (gatewayOn)
473 SerialLots.printf("gatewayOn(%d)\n", gatewayOn);
474
475 //! name of paired device (if any) in EPROM
476 char *pairedDeviceTemp = getPairedDevice_mainModule();
477 strcpy(pairedDeviceString, pairedDeviceTemp);
478 SerialLots.printf("pairedDevice(%s)\n", pairedDeviceString);
479
481 strcpy(pairedDeviceAddressString, pairedDeviceAddressTemp);
482
483 SerialLots.printf("pairedDeviceAddress(%s)\n", pairedDeviceAddressString);
484
485 //!name of connected device, or "" if not specified, which means not pairable
486 char *connectedBLEDeviceName = connectedBLEDeviceName_mainModule();
487 SerialLots.printf("connectedBLEDeviceName(%s)\n", connectedBLEDeviceName);
488 //!compare to what's connected ..
489 char *connectedBLEDeviceNameAddress = connectedBLEDeviceNameAddress_mainModule();
490 SerialLots.printf("connectedBLEDeviceNameAddress(%s)\n", connectedBLEDeviceNameAddress);
491
492 //!is paired and connected (to that pair .. if BLECLient working right)
493 boolean pairedAndConnected = false;
494 boolean pairedButNotConnected = false;
495 boolean pairableAndConnected = false;
496 boolean unpaired = false;
497
498 //!if connectedBLE then either paired or not-paired
499 if (isConnectedBLE)
500 {
501 //!if the EPROM's pairedDevice/Address == what's connected, then we are paired and connected
502 if (strcmp(pairedDeviceString,connectedBLEDeviceName)==0 ||
503 strcmp(pairedDeviceAddressString,connectedBLEDeviceNameAddress)==0)
504 //! is paired
505 pairedAndConnected = true;
506 else
507 pairableAndConnected = true;
508 }
509 //! not connected, so paired if a valid paired name/address
510 else if (strlen(pairedDeviceString) > 0 || strlen(pairedDeviceAddressString) > 0)
511 {
512 if (strlen(pairedDeviceString) > 0 && strcmp(pairedDeviceString,(char*)"NONE")==0)
513 unpaired = true;
514 else if (strlen(pairedDeviceAddressString) > 0 && strcmp(pairedDeviceAddressString,(char*)"NONE")==0)
515 unpaired = true;
516 else
517 //!if the EPROM's pairedDevice/Address is set then paired and NOT connected
518 pairedButNotConnected = true;
519 }
520 else
521 {
522 //!unpaired
523 unpaired = true;
524 }
525
526 if (pairedButNotConnected)
527 SerialLots.printf("pairedButNotConnected(%d)\n", pairedButNotConnected);
528 if (pairedAndConnected)
529 SerialLots.printf("pairedAndConnected(%d)\n", pairedAndConnected);
530 if (pairableAndConnected)
531 SerialLots.printf("pairableAndConnected(%d)\n", pairableAndConnected);
532 if (unpaired)
533 SerialLots.printf("unpaired(%d)\n", unpaired);
534
535 if (pairedButNotConnected)
536 {
537 // scan, unpair, gen3
539 deviceState->maxItems = 3;
540 }
541 else if (pairedAndConnected)
542 {
543 // feed, unPair, gen3
545 deviceState->maxItems = 3;
546 }
547 else if (pairableAndConnected)
548 {
549 // feed, skip, pair, gen3only
551 deviceState->maxItems = 4;
552 }
553 else
554 {
555 // scan, gen3Only
557 deviceState->maxItems = 2;
558 }
559
560 break;
561 }
562 case rebootModel:
563
564 //reboot and poweroff, blank, color, semanticMarker, wifiTOO, WIFI Page, next wave page, next wave stream..
565 // 9 = PTClicker, 10 == Uno, 11 = Tumbler
566 deviceState->maxItems = 12;
567 break;
568
569 case menusModel:
570 //!MENUS
571 //! Pairing
572 //! APMode
573 //! Timer
574 //! Advanced
575 //! Status
576 //! WIFI sharing
577 //! Guest Feed
578 //! Settings
579 //! DocFollow
580 //! help
581 //! HomePage
582 //! /WIFI Feed
583 //! WIFI Share
584
585 deviceState->maxItems = MenusModel_Max;
586 break;
587 //updateMenu
588 case timerModel:
589 {
590 SerialCall.printf("updateMenuState timerRunning(%d)\n", deviceState->delayRunning);
591 //! calculate the current second counter..
592 if (deviceState->delayRunning)
593 {
594 //counter.., running
595 deviceState->maxItems = 2;
596
597 /*
598 Design:
599 currentCounterSeconds == the countdown timer
600 The problem is this code isn't guarenteed to be run every second. So we need
601 a way to know the different to subtract seconds from the counter seconds
602
603 delayStartMillis == when the loop started in milis
604 currentTimeMillis == current time
605 diff == number of seconds since first time
606
607 So either diff is subtracted from original (random number) -- or
608
609 */
610
611 long currentTimeMillis = millis();
612 SerialCall.printf("currentTimeMillis = %d\n", currentTimeMillis);
613 SerialCall.printf("delayStartMillis = %d\n", deviceState->delayStartMillis);
614
615 //! the number of seconds since starting the loop
616 float diffSec = (currentTimeMillis - deviceState->delayStartMillis) / 1000;
617 deviceState->currentCounterSeconds = deviceState->counterLoopAbsoluteSeconds - diffSec;
618
619 SerialCall.printf("currentCounterSeconds = %d\n", deviceState->currentCounterSeconds );
620
621 //!if count <=0 then finished..
622 if (deviceState->currentCounterSeconds <= 0)
623 {
624 SerialCall.printf("delayFinished \n");
625
626 //! 11.29.23 use a random
627 //! calculate a new random
629
630 //!if local .. send a command directly to the device..
631 if (deviceState->feedLocalOnly)
632 {
633 //!send the command to the stepper.. not a BLE command
635 }
636 else
637 {
638 //! for now only invoke the feed ... todo mroe things.. STATUS, WIFI FEED, DOCFOLLOW
640 }
641 }
642 }
643 else
644 {
645 // NOT running..
646 //counter.., running, change time..
647 //! added a max delay
648 deviceState->maxItems = 4;
649 }
650 }
651
652
653 break;
654 }
655
656 //!TODO: look at a scrolling idea if > 6 ...
657 if (deviceState->currentItem >= deviceState->maxItems)
658 {
659 // go to first one .. basically the menues changed since last time
660 deviceState->currentItem = 0;
661 }
662 printDeviceState(deviceState);
663}
664
665//!returns the menu string for the deviceState's item number (use woudl go 0..maxItems -1
666char *menuForState(ModelKindEnum modelKind, int item)
667{
668 SerialCall.printf("menuForState(%d,%d)\n", modelKind, item);
669 ModelStateStruct *deviceState = getModel(modelKind);
670 SerialCall.printf("connectedBLEDeviceName_mainModule(%s)\n", connectedBLEDeviceName_mainModule());
671 SerialCall.printf("getFullBLEDeviceName_mainModule(%s)\n", getFullBLEDeviceName_mainModule());
672
673
674 char *menu;
675 switch (modelKind)
676 {
677#ifdef ESP_M5
679 {
680 switch (deviceState->pairedDeviceStateEnum)
681 {
683 switch (item)
684 {
685 case 0:
686 menu = (char*)"scan..";
687 break;
688 case 1:
689 //unpair is to forget and look for others..
690 menu = (char*)"unpair";
691 break;
692 case 2:
694 menu = (char*)"Gen3";
695 else
696 menu = (char*)"AnyBLE";
697 break;
698 default:
699 SerialMin.printf("a.**** Invalid item: %d\n",item);
700 break;
701 }
702 break;
704 switch (item)
705 {
706 case 0:
707 menu = (char*)"feed";
708 break;
709 case 1:
710 menu = (char*)"unpair";
711 break;
712 case 2:
714 menu = (char*)"Gen3";
715 else
716 menu = (char*)"AnyBLE";
717 break;
718 default:
719 SerialMin.printf("b. **** Invalid item: %d\n",item);
720 break;
721 }
722 break;
724 switch (item)
725 {
726 case 0:
727 menu = (char*)"feed";
728 break;
729 case 1:
730 menu = (char*)"skip";
731 break;
732 case 2:
733 menu = (char*)"pair";
734 break;
735 case 3:
737 menu = (char*)"Gen3";
738 else
739 menu = (char*)"AnyBLE";
740 break;
741 default:
742 SerialMin.printf("c. **** Invalid item: %d\n",item);
743 break;
744 }
745 break;
746 case notConnectedEnum:
747 switch (item)
748 {
749 case 0:
750 menu = (char*)"scan..";
751 break;
752 case 1:
754 menu = (char*)"Gen3";
755 else
756 menu = (char*)"AnyBLE";
757 break;
758 default:
759 SerialMin.printf("d. **** Invalid item: %d\n",item);
760 break;
761 }
762 break;
763 }
764 }
765 break;
766 case rebootModel:
767 {
768 //Max for >4 items is 10 characters..
769 switch (item)
770 {
771 case 0:
772 menu = (char*)"reboot";
773 break;
774 case 1:
775 menu = (char*)"poweroff";
776 break;
777 case 2: // blankscreen
778 // poweroff.. but send MQTT first..
779 menu = (char*)"blankscrn";
780 break;
781
782 case 3: // Uno
783 menu = (char *)"Set Uno";
784 break;
785 case 4: //FeedKindTumbler
786 menu = (char *)"Tumbler";
787 break;
788
789 case 5: // change color
790 menu = (char*)"colorscrn";
791 break;
792 case 6: // SemanticMarker
793 menu = (char*)"SemMarker";
794 break;
795 case 7: // Extra sends
797 menu = (char*)"BLE+WIFI";
798 else
799 menu = (char*)"BLEOnly";
800 // .. switch to WIFI too
801 break;
802 case 8: // WIFI Change Page on M5 units..
803 menu = (char*)"CycleScrn";
804 // .. switch to WIFI too
805 break;
806 case 9: // WIFI chage wave page, evetually Wave-Page, Wave+Stream
807 menu = (char*)"Wave+Page";
808 // .. switch to WIFI too
809 break;
810 case 10: // WIFI chage wave page, evetually Wave-Page, Wave+Stream
811 menu = (char*)"Wave+Strm";
812 // .. switch to WIFI too
813 break;
814 case 11: // look for PTClicker
816 menu = (char*)"PTClicker";
817 else
818 menu = (char*)"PTFeeder";
819 break;
820
821 default:
822 SerialMin.printf("e. **** Invalid item: %d\n",item);
823 break;
824 }
825 }
826 break;
827
828 case menusModel:
829 {
830 //!MENUS
831 //! Pairing
832 //! APMode
833 //! Timer
834 //! Advanced
835 //! Status
836 //! WIFI sharing
837 //! Guest Feed
838 //! Settings
839 //! DocFollow
840 //! help
841 //! HomePage
842 //! /WIFI Feed
843 //! WIFI Share
844
845
846 switch (item)
847 {
849 menu = (char*)"BLEPair";
850 break;
852 menu = (char*)"APMode";
853 break;
855 menu = (char*)"WIFIShare";
856 break;
857 case MenusModel_Timer:
858 menu = (char*)"Timer";
859 break;
861 menu = (char*)"Advanced";
862 break;
864 menu = (char*)"Status";
865 break;
867 menu = (char*)"GuestPage";
868 break;
870 menu = (char*)"GuestFeed";
871 break;
873 menu = (char*)"Settings";
874 break;
876 menu = (char*)"DocFollow";
877 break;
878 case MenusModel_Help:
879 menu = (char*)"Help";
880 break;
881
882 default:
883 SerialMin.printf("f. **** Invalid item: %d\n",item);
884 break;
885 }
886 }
887 break;
888#endif //ESP_M5
889 //menuForState. Max == 2 if running (showing STOP , TIME)
890 //! Max == 4 if not running (START, TIME, MAXTIME, DELAY)
891 case timerModel:
892 {
893 switch (item)
894 {
895
896 case 0:
897 //!draw the state we are in..
898 if (deviceState->delayRunning)
899 menu = (char*)"Stop";
900 else
901 menu = (char*) "Start";
902 break;
903 case 1:
904 {
905 //!update menu with seconds countdown
906 if (deviceState->delayRunning)
907 sprintf(_timerBuffer,"%d", deviceState->currentCounterSeconds);
908 else
909 sprintf(_timerBuffer,"%d", deviceState->delaySeconds);
910
911 menu = _timerBuffer;
912 }
913 break;
914
915 //! only if stopped... max == 4, other max == 2
916 case 2:
917 {
918 //!show max
919 sprintf(_timerBuffer,"%d", deviceState->delaySecondsMax);
920 menu = _timerBuffer;
921 }
922 break;
923 case 3:
924 {
925
926 menu = (char*)"Delay";
927 }
928 break;
929 default:
930 SerialMin.printf("g. **** Invalid item: %d\n",item);
931 break;
932 }
933 }
934 break;
935 }
936 return menu;
937}
938
939//!invokes the menu state, return true if the model state has change enough to refreesh your View (such as new menu items)
940//!NOTE: This is the LONG press on the M5 button (the BLUE item)
942{
943 //!default is the view is the same
944 boolean modelChanged = false;
945 //!what model struct to use
946 ModelStateStruct *deviceState = getModel(modelKind);
947 SerialTemp.printf("invokeMenuState(%d, pair=%d) \n", modelKind, deviceState->pairedDeviceStateEnum);
948
949 int item = deviceState->currentItem;
950 switch (modelKind)
951 {
952#ifdef ESP_M5
953 //! the pairdDeviceModel kind
955 {
956 SerialCall.printf("pairedDeviceModel");
957
958 switch (deviceState->pairedDeviceStateEnum)
959 {
960 //paired to a device, but BLE NOT connected right now
962 switch (item)
963 {
964 case 0:
965 //scan .. default
966 break;
967 case 1:
968 //unpair
970 modelChanged = true;
971 break;
972 case 2:
973 //toggle..
975 modelChanged = true;
976 break;
977 }
978 break;
979 //paired to a device, and BLE connected right now
981 switch (item)
982 {
983 case 0:
984 //feed
985 //send BLE feed ... this help figure out which BLE is connected
987 break;
988 case 1:
989 //unpair
991 modelChanged = true;
992 break;
993 case 2:
994 //toggle..
996 modelChanged = true;
997 break;
998 }
999 break;
1000 //not paired (but could be paired as it's a named device or address])
1002 switch (item)
1003 {
1004 case 0:
1005 //feed
1007 break;
1008 case 1:
1009 //skip
1011 modelChanged = true;
1012 break;
1013 case 2:
1014 // pair
1016 modelChanged = true;
1017 break;
1018 case 3:
1019 //toggle..
1021 modelChanged = true;
1022 break;
1023 }
1024 break;
1025 //!factory default but not connecte to anything..
1026 case notConnectedEnum:
1027 switch (item)
1028 {
1029 case 0:
1030 //scan
1031 break;
1032 case 1:
1033 //toggle..
1035 modelChanged = true;
1036 break;
1037 }
1038 break;
1039 }
1040 }
1041 break;
1042
1043 case rebootModel:
1044 {
1045 SerialCall.println("*** rebootModel ***");
1046
1047 switch (item)
1048 {
1049 case 0: // reboot
1051 break;
1052 case 1: // poweroff
1053 // poweroff.. but send MQTT first..
1055 break;
1056 case 2: // blankscreen
1058 break;
1059 case 3: // Uno
1060 //! 8.16.25 BLE CLIENT
1062 break;
1063 case 4: //FeedKindTumbler
1064 //! 8.16.25 BLE CLIENT
1066 break;
1067
1068 case 5: //color
1069 //! for now, the color is incremented in the displayModule
1071 break;
1072 case 6: // SemanticMarker
1074 modelChanged = true;
1075 break;
1076 case 7: // extra..
1078 modelChanged = true;
1079 break;
1080 case 8:
1081 //send WIFI to all except this page.. but keep some state.
1082 //! 8.16.25 MQTT
1083 //eg: https://iDogWatch.com/bot/cmddevice/tao49@comcast.net/PASS/dev/sm1
1084 //! BUT at the MQTT level not web page level
1085
1086 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
1087 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
1088 // if (getTransientPreference_mainModule(TRANSIENT_PREFERENCE_SENDWIFI_WITH_BLE))
1089 {
1090 char pubString[60];
1091 //for now .. just send smN
1092 sprintf(pubString,"{'dev':'!%s', 'cmd':'sm%0d'}",deviceName_mainModule(), deviceState->currentPageState);
1094 //incremenet model, wrap around
1095 deviceState->currentPageState = (deviceState->currentPageState +1 ) % deviceState->maxPageState;
1096 }
1097
1098 break;
1099 case 9:
1100 // WIFI chage wave page
1101 //! 8.16.25 MQTT
1102 //eg: https://iDogWatch.com/bot/cmddevice/tao49@comcast.net/PASS/dev/sm1
1103 //! BUT at the MQTT level not web page level
1104
1105 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
1106 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
1107 // if (getTransientPreference_mainModule(TRANSIENT_PREFERENCE_SENDWIFI_WITH_BLE))
1108 {
1109 char pubString[100];
1110 //for now .. just send 'next' on a common wave (TODO: select wave we are in..)'
1111 sprintf(pubString,(char*)"#followMe {AVM=https://SemanticMarker.org/bot/wave/%s?action=next}", deviceState->waveName);
1112 //! this has the # so it is treated slightly different, but tacking on the device for example..
1113 sendMessageMQTT(pubString);
1114
1115 }
1116
1117 break;
1118 case 10:
1119 // WIFI change stream (1..3)
1120 //! 8.16.25 MQTT
1121 //eg: https://iDogWatch.com/bot/cmddevice/tao49@comcast.net/PASS/dev/sm1
1122 //! BUT at the MQTT level not web page level
1123
1124 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
1125 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
1126 // if (getTransientPreference_mainModule(TRANSIENT_PREFERENCE_SENDWIFI_WITH_BLE))
1127 {
1128 char pubString[100];
1129 //for now .. just send 'next' on a common wave (TODO: select wave we are in..)'
1130 //! This just goes to the 0'th page in the stream..
1131 sprintf(pubString,(char*)"#followMe {AVM=https://SemanticMarker.org/bot/wave/%s?stream=%0d&page=0}", deviceState->waveName, deviceState->currentStreamNum+1);
1132 //! 1 based (not 0 based)
1133 //publishMQTTMessageDefaultTopic(pubString);
1134 //! this has the # so it is treated slightly different, but tacking on the device for example..
1135 sendMessageMQTT(pubString);
1136
1137 deviceState->currentStreamNum = (deviceState->currentStreamNum +1 ) % deviceState->maxStream;
1138 }
1139
1140 break;
1141 case 11:
1142 //! set transient look for PTClicker
1144 break;
1145 //! 11.4.22 (after Maggie Bluetic was fed with Pumpking Uno and GreyGoose
1146
1147
1148 default:
1149 SerialMin.println("h, *** invalid item ***");
1150 }
1151 }
1152 break;
1153
1154 case menusModel:
1155 {
1156 modelChanged = true;
1157 SerialCall.println("*** menusModel ***");
1158 //!use lookup
1159 int SMMode = _menuToSMMode[item];
1160 // invoke that page (note now those pages return here on ButB_longpress)
1162
1163 //! Issue: #222 for #206, this sets the current mode to SM_doc_follow, but
1164 //! when at that page in the the current mode (which is now SM_doc_follow) won't let
1165 //! the page go somewhere else (except in this case we are the same page). Only but a
1166 //! physical button click.
1167 //! I THINK THE ANSWER: if current and next are the same an SM_doc_follow, then do the page change..
1168
1169 //! if HELP then printout preferences to the debug window
1170 if (SMMode == SM_help)
1171 //! if HELP .. show the status
1172 //!print the preferences to SerialDebug
1174 }
1175 break;
1176#endif //ESP_M5
1177 case timerModel:
1178 {
1179 //invokeMenuState
1180 SerialTemp.printf("*** timerModel (%d) *** %d\n", item, deviceState->delayRunning);
1181
1182 /*
1183 When running 0 == STOP, and 1 == current time (and a long press will reset it..)
1184 When not running 0 == START, 1 = min, 2 = max , 3 = DELAY ??
1185 */
1186 switch (item)
1187 {
1188 case 0:
1189 // stop the timer..
1190 //start stop..
1191 deviceState->delayRunning = !deviceState->delayRunning;
1192 if (deviceState->delayRunning)
1193 {
1194 // just started..
1196 }
1197 break;
1198 case 1:
1199 if (deviceState->delayRunning)
1200 {
1201 //! This will restart the timer..
1203 break;
1204 }
1205 //otherwise fall through..
1206 case 2:
1207 {
1208 //menu = (char*)"Bounds"; .. change timer 5 .. 30 .. 60 .. 120 .. 5
1209 int currentDelay;
1210 if (item == 1)
1211 currentDelay = deviceState->delaySeconds;
1212 else
1213 currentDelay = deviceState->delaySecondsMax;
1214 //!same login for each
1215 if (currentDelay == 5)
1216 currentDelay = 30;
1217 else if (currentDelay == 30)
1218 currentDelay = 60;
1219 else if (currentDelay == 60)
1220 currentDelay = 120;
1221 else if (currentDelay == 120)
1222 currentDelay = 600;
1223 else
1224 currentDelay = 5;
1225 SerialTemp.printf(".. change delay = %d\n", currentDelay);
1226 if (item == 1)
1227 {
1228 deviceState->delaySeconds = currentDelay;
1229 //save in EPROM
1231
1232 //! make sure the max is >= min
1233 if (deviceState->delaySecondsMax < currentDelay)
1234 {
1235 deviceState->delaySecondsMax = currentDelay;
1236 //save in EPROM
1238 }
1239 }
1240 else
1241 {
1242 //! 11.29.23 add the random feed
1243 if (currentDelay < deviceState->delaySeconds)
1244 currentDelay = deviceState->delaySeconds;
1245 deviceState->delaySecondsMax = currentDelay;
1246 deviceState->currentCounterSeconds = deviceState->delaySeconds;
1247 //save in EPROM
1249 }
1250
1251 //!now use those values to create a new random time..
1252 //!not needed until the START above
1253 //setNextRandomTime();
1254 }
1255 break;
1256 case 3:
1257 //! Delay .. no-opp
1258 break;
1259 default:
1260 SerialMin.println("i2. *** invalid item ***");
1261
1262 }
1263 }
1264 break;
1265 }
1266 return modelChanged;
1267}
1268
1269//!retrieves a semantic marker for the current selected item
1271{
1272 //!default is the view is the same
1273 boolean modelChanged = false;
1274 //!what model struct to use
1275 ModelStateStruct *deviceState = getModel(modelKind);
1276 SerialLots.printf("invokeMenuState(%d, %d) \n", modelKind, deviceState->pairedDeviceStateEnum);
1277
1278 char *semanticMarker = NULL;
1279
1280#ifdef NOTHING_YET_SAVE_SOME_MEMORY
1281 int item = deviceState->currentItem;
1282
1283 switch (modelKind)
1284 {
1285 case rebootModel:
1286 {
1287 switch (item)
1288 {
1289 case 0: // reboot
1290 //REboot the device
1291 //sprintf(_semanticMarkerString,"%s/%s/%s", "https://SemanticMarker.org/bot/reboot", _mqttUserString?_mqttUserString:"NULL", guestPassword?guestPassword:"NULL");
1292 break;
1293 case 1: // poweroff
1294 // poweroff.. but send MQTT first..
1295 break;
1296 case 2: // blankscreen
1297 break;
1298 case 3: //color
1299 //! for now, the color is incremented in the displayModule
1300 break;
1301 case 4: // SemanticMarker
1302 break;
1303 case 5: // none
1304 break;
1305 case 6: // next page .. actually there is one .. later
1306 break;
1307 case 7: // next page .. actually there is one .. later
1308 break;
1309 }
1310 }
1311 }
1312#endif
1313 return semanticMarker;
1314}
boolean isConnectedBLEClient()
returns whether connected over BLE as a client to a server(like a ESP feeder)
void disconnect_BLEClientNetworking()
try to disconnect..
void skipNameOrAddress_BLEClientNetworking(char *nameOrAddress)
an address or name to skip (for at least 1 time)
void sendCommandBLEClient_13orLess(String cmdString)
send a string of 13 characters or less
void incrementScreenColor_displayModule()
void publishMQTTMessageDefaultTopic(char *message)
Wrapper of the mqttclient publish.
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 setConnectedBLEDevice_mainModule(char *deviceName, boolean isGEN3)
char * connectedBLEDeviceNameAddress_mainModule()
returns address part of name.
char * charSMMode_mainModule(int whichSMMode)
returns string form whichSMMode, sg "sm0", sm1 ...
char * deviceName_mainModule()
gets the device name
boolean connectedBLEDeviceIsGEN3_mainModule()
whether the connected is a GEN3 (so the name isn't valid)
void processClientCommandChar_mainModule(char cmd)
single character version of processClientCommand (since many used that already)
int getCurrentSMMode_mainModule()
returns the current SM Mode
char * getFullBLEDeviceName_mainModule()
full: ""Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
void setCurrentSMMode_mainModule(int whichSMMode)
sets the current screen mode .. which can be used by Button and Display processing
char * getPairedDevice_mainModule()
returns if the paired device is not NONE
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 * connectedBLEDeviceName_mainModule()
returns the connected BLE Device name (the :NAME of advertisment, Address: 01:39:3f:33 part of name,...
#define SM_pair_dev
guest feed device
Definition: MainModule.h:391
#define ASYNC_REBOOT
sets the GATEWAY mode off
Definition: MainModule.h:223
#define SM_guest_feed
guest feed
Definition: MainModule.h:389
#define SM_guest_page
guest page
Definition: MainModule.h:382
#define ASYNC_SEND_MQTT_FEED_MESSAGE
sends a message (like FEED) on the users topic
Definition: MainModule.h:213
#define SM_timer
timer .. todo
Definition: MainModule.h:398
#define SM_status
//status
Definition: MainModule.h:378
#define SM_reboot
REboot.
Definition: MainModule.h:400
#define MAX_SM_EXPANDED_MODES
Definition: MainModule.h:406
#define SM_help
HELP.
Definition: MainModule.h:393
#define ASYNC_POWEROFF
sets the GATEWAY mode off
Definition: MainModule.h:225
#define ASYNC_BLANKSCREEN
blank the screen
Definition: MainModule.h:227
#define SM_home_simple_3
Definition: MainModule.h:370
#define SM_doc_follow
docfollow
Definition: MainModule.h:396
#define SM_smart_clicker_homepage
//! homepage
Definition: MainModule.h:376
#define TOPIC_TO_SEND
Definition: MainModule.h:65
#define SM_WIFI_ssid
WIFI ssid.
Definition: MainModule.h:380
#define SM_ap_mode
AP MODE.
Definition: MainModule.h:385
void updateMenuState(ModelKindEnum modelKind)
updates the model for the menu state, this sets max etc
void invokeUnpairNoNameBASE_ModelController()
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 ...
void initMenuToSMMode()
init the mapping
void setTimerDelaySecondsMax_mainModule(int delaySeconds)
void invokeUnpair_ModelController(char *nameOrAddress)
performs the unpairing
void invokeFeed_ModelController()
performs the BLE feed
void invokePair_ModelController()
#define MenusModel_WIFIShare
void setTimerDelaySeconds_mainModule(int delaySeconds)
void invokeSkip_ModelController(char *nameOrAddress)
performs skip
void printDeviceState(ModelStateStruct *deviceState)
print it out..
#define MenusModel_Help
a pseudo Class
void startStopTimer_mainModule(boolean startTimer)
#define MenusModel_Status
char _timerBuffer[10]
char * menuForState(ModelKindEnum modelKind, int item)
returns the menu string for the deviceState's item number (use woudl go 0..maxItems -1
#define MenusModel_DocFollow
#define MenusModel_GuestFeed
#define MenusModel_Settings
void invokeUnpairNoName_ModelController()
void setNextRandomTime()
ModelStateStruct * hasModelForSM_Mode(int SM_Mode)
retrieves the state model for the SM_Mode (SM_0 .. SM_LAST) null if none
#define MenusModel_Max
#define MenusModel_Timer
#define MenusModel_Advanced
int _menuToSMMode[MenusModel_Max]
storage of mapping
char * getModelSemanticMarker(ModelKindEnum modelKind)
retrieves a semantic marker for the current selected item
ModelStateStruct * getModel(ModelKindEnum modelKind)
retrieves the state model for the modelKind
void initModelStructs_ModelController()
initialize the objects
void invokeFeedLocally()
storage..
#define MenusModel_APMode
#define MenusModel_GuestPage
#define MenusModel_Pairing
void invokeToggleGen3_ModelController()
toggles the GEN3 setting
void restartAllMenuStates_ModelController()
restarts all the menu states to the first one .. useful for getting a clean start....
ModelStateStruct _modelStateStructs[ModelKindEnumMax]
ModelKindEnum
a pseudo Class
@ menusModel
@ pairedDeviceModel
@ timerModel
@ rebootModel
@ pairedButNotConnectedEnum
@ notConnectedEnum
factory default but not connecte to anything..
@ pairableAndConnectedEnum
@ pairedAndConnectedEnum
#define ModelKindEnumMax
void savePreferenceInt_mainModule(int preferenceID, int val)
sets an int preference
boolean getDiscoverM5PTClicker()
get option
void savePreferenceBoolean_mainModule(int preferenceID, boolean flag)
save a boolean preference
void setDiscoverM5PTClicker(boolean flag)
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
void savePreference_mainModule(int preferenceID, String preferenceValue)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
#define PREFERENCE_PAIRED_DEVICE_ADDRESS_SETTING
the paired device for guest device feeding (6.6.22) .. but the Address 9.3.22
#define PREFERENCE_ONLY_GEN3_CONNECT_SETTING
if true, only BLEClient connect to GEN3 feeders..
#define PREFERENCE_SENDWIFI_WITH_BLE
sends the WIFI to all except current device if set
#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_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
#define PREFERENCE_TIMER_MAX_INT_SETTING
the preference timer MAX (pairs with PREFERENCE_TIMER_INT_SETTING)
#define PREFERENCE_MAIN_GATEWAY_VALUE
#define PREFERENCE_TIMER_INT_SETTING
the preference timer
unsigned long millis()
Definition: TinyGPS.cpp:35
the struct for the models. Since this isn't straight OO, we are overlaying information....
ModelKindEnum modelKindEnum
What kind of model.
int currentCounterSeconds
current seconds (<= delaySeconds)
int currentPageState
for the next page state 0..n
boolean feedLocalOnly
feed local instead of MQTT or BLE..
int delaySecondsMax
11.29.23 max Delay Seconds .. if different than delay then next delay will be random() * (max-min) + ...
int delayStartMillis
Timer info - When the timer was started.
int currentItem
the current item
int currentStreamNum
the stream number
char * waveName
which wave
int SM_Mode
which SM mode 0.. SM_LAST
boolean perfersBigText
a preference to the View that big text is desired
PairedDeviceStateEnum pairedDeviceStateEnum
boolean delayRunning
true if still waiting for delay to finish
int delaySeconds
length of delay (changable..)
int maxItems
the number of items in the model