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 SerialCall.printf("updateMenuState(%d) \n", modelKind);
447
448 switch (modelKind)
449 {
451 {
452 //! must save since many preferences are called...
453 char pairedDeviceString[50];
454 char pairedDeviceAddressString[50];
455 //* NEW PLAN..
456 //! the pairedName stored in EPROM can be an Address (eg. 03:34:23:33)
457 //!
458 //!show the BLE connected status at the bottom (G3 if gen3), WIFI, and AP if APmode
459 //! 8.16.25 BLE CLIENT
460 boolean isConnectedBLE = isConnectedBLEClient();
461
462 SerialLots.printf("\nPAIRED_DEVICE_MODEL\n");
463 SerialLots.printf("isConnectedBLE(%d)\n", isConnectedBLE);
464
466 if (gen3Only)
467 SerialLots.printf("gen3Only(%d)\n", gen3Only);
468
469 //! whether the gateway is on.. this isn't using the Gx just BLE or GE3
471 if (gatewayOn)
472 SerialLots.printf("gatewayOn(%d)\n", gatewayOn);
473
474 //! name of paired device (if any) in EPROM
475 char *pairedDeviceTemp = getPairedDevice_mainModule();
476 strcpy(pairedDeviceString, pairedDeviceTemp);
477 SerialLots.printf("pairedDevice(%s)\n", pairedDeviceString);
478
480 strcpy(pairedDeviceAddressString, pairedDeviceAddressTemp);
481
482 SerialLots.printf("pairedDeviceAddress(%s)\n", pairedDeviceAddressString);
483
484 //!name of connected device, or "" if not specified, which means not pairable
485 char *connectedBLEDeviceName = connectedBLEDeviceName_mainModule();
486 SerialLots.printf("connectedBLEDeviceName(%s)\n", connectedBLEDeviceName);
487 //!compare to what's connected ..
488 char *connectedBLEDeviceNameAddress = connectedBLEDeviceNameAddress_mainModule();
489 SerialLots.printf("connectedBLEDeviceNameAddress(%s)\n", connectedBLEDeviceNameAddress);
490
491 //!is paired and connected (to that pair .. if BLECLient working right)
492 boolean pairedAndConnected = false;
493 boolean pairedButNotConnected = false;
494 boolean pairableAndConnected = false;
495 boolean unpaired = false;
496
497 //!if connectedBLE then either paired or not-paired
498 if (isConnectedBLE)
499 {
500 //!if the EPROM's pairedDevice/Address == what's connected, then we are paired and connected
501 if (strcmp(pairedDeviceString,connectedBLEDeviceName)==0 ||
502 strcmp(pairedDeviceAddressString,connectedBLEDeviceNameAddress)==0)
503 //! is paired
504 pairedAndConnected = true;
505 else
506 pairableAndConnected = true;
507 }
508 //! not connected, so paired if a valid paired name/address
509 else if (strlen(pairedDeviceString) > 0 || strlen(pairedDeviceAddressString) > 0)
510 {
511 if (strlen(pairedDeviceString) > 0 && strcmp(pairedDeviceString,(char*)"NONE")==0)
512 unpaired = true;
513 else if (strlen(pairedDeviceAddressString) > 0 && strcmp(pairedDeviceAddressString,(char*)"NONE")==0)
514 unpaired = true;
515 else
516 //!if the EPROM's pairedDevice/Address is set then paired and NOT connected
517 pairedButNotConnected = true;
518 }
519 else
520 {
521 //!unpaired
522 unpaired = true;
523 }
524
525 if (pairedButNotConnected)
526 SerialLots.printf("pairedButNotConnected(%d)\n", pairedButNotConnected);
527 if (pairedAndConnected)
528 SerialLots.printf("pairedAndConnected(%d)\n", pairedAndConnected);
529 if (pairableAndConnected)
530 SerialLots.printf("pairableAndConnected(%d)\n", pairableAndConnected);
531 if (unpaired)
532 SerialLots.printf("unpaired(%d)\n", unpaired);
533
534 if (pairedButNotConnected)
535 {
536 // scan, unpair, gen3
538 deviceState->maxItems = 3;
539 }
540 else if (pairedAndConnected)
541 {
542 // feed, unPair, gen3
544 deviceState->maxItems = 3;
545 }
546 else if (pairableAndConnected)
547 {
548 // feed, skip, pair, gen3only
550 deviceState->maxItems = 4;
551 }
552 else
553 {
554 // scan, gen3Only
556 deviceState->maxItems = 2;
557 }
558
559 break;
560 }
561 case rebootModel:
562
563 //reboot and poweroff, blank, color, semanticMarker, wifiTOO, WIFI Page, next wave page, next wave stream..
564 // 9 = PTClicker, 10 == Uno, 11 = Tumbler
565 deviceState->maxItems = 12;
566 break;
567
568 case menusModel:
569 //!MENUS
570 //! Pairing
571 //! APMode
572 //! Timer
573 //! Advanced
574 //! Status
575 //! WIFI sharing
576 //! Guest Feed
577 //! Settings
578 //! DocFollow
579 //! help
580 //! HomePage
581 //! /WIFI Feed
582 //! WIFI Share
583
584 deviceState->maxItems = MenusModel_Max;
585 break;
586 //updateMenu
587 case timerModel:
588 {
589 SerialCall.printf("updateMenuState timerRunning(%d)\n", deviceState->delayRunning);
590 //! calculate the current second counter..
591 if (deviceState->delayRunning)
592 {
593 //counter.., running
594 deviceState->maxItems = 2;
595
596 /*
597 Design:
598 currentCounterSeconds == the countdown timer
599 The problem is this code isn't guarenteed to be run every second. So we need
600 a way to know the different to subtract seconds from the counter seconds
601
602 delayStartMillis == when the loop started in milis
603 currentTimeMillis == current time
604 diff == number of seconds since first time
605
606 So either diff is subtracted from original (random number) -- or
607
608 */
609
610 long currentTimeMillis = millis();
611 SerialCall.printf("currentTimeMillis = %d\n", currentTimeMillis);
612 SerialCall.printf("delayStartMillis = %d\n", deviceState->delayStartMillis);
613
614 //! the number of seconds since starting the loop
615 float diffSec = (currentTimeMillis - deviceState->delayStartMillis) / 1000;
616 deviceState->currentCounterSeconds = deviceState->counterLoopAbsoluteSeconds - diffSec;
617
618 SerialCall.printf("currentCounterSeconds = %d\n", deviceState->currentCounterSeconds );
619
620 //!if count <=0 then finished..
621 if (deviceState->currentCounterSeconds <= 0)
622 {
623 SerialCall.printf("delayFinished \n");
624
625 //! 11.29.23 use a random
626 //! calculate a new random
628
629 //!if local .. send a command directly to the device..
630 if (deviceState->feedLocalOnly)
631 {
632 //!send the command to the stepper.. not a BLE command
634 }
635 else
636 {
637 //! for now only invoke the feed ... todo mroe things.. STATUS, WIFI FEED, DOCFOLLOW
639 }
640 }
641 }
642 else
643 {
644 // NOT running..
645 //counter.., running, change time..
646 //! added a max delay
647 deviceState->maxItems = 4;
648 }
649 }
650
651
652 break;
653 }
654
655 //!TODO: look at a scrolling idea if > 6 ...
656 if (deviceState->currentItem >= deviceState->maxItems)
657 {
658 // go to first one .. basically the menues changed since last time
659 deviceState->currentItem = 0;
660 }
661 printDeviceState(deviceState);
662}
663
664//!returns the menu string for the deviceState's item number (use woudl go 0..maxItems -1
665char *menuForState(ModelKindEnum modelKind, int item)
666{
667 SerialCall.printf("menuForState(%d,%d)\n", modelKind, item);
668 ModelStateStruct *deviceState = getModel(modelKind);
669 SerialCall.printf("connectedBLEDeviceName_mainModule(%s)\n", connectedBLEDeviceName_mainModule());
670 SerialCall.printf("getFullBLEDeviceName_mainModule(%s)\n", getFullBLEDeviceName_mainModule());
671
672
673 char *menu;
674 switch (modelKind)
675 {
676#ifdef ESP_M5
678 {
679 switch (deviceState->pairedDeviceStateEnum)
680 {
682 switch (item)
683 {
684 case 0:
685 menu = (char*)"scan..";
686 break;
687 case 1:
688 //unpair is to forget and look for others..
689 menu = (char*)"unpair";
690 break;
691 case 2:
693 menu = (char*)"Gen3";
694 else
695 menu = (char*)"AnyBLE";
696 break;
697 default:
698 SerialMin.printf("a.**** Invalid item: %d\n",item);
699 break;
700 }
701 break;
703 switch (item)
704 {
705 case 0:
706 menu = (char*)"feed";
707 break;
708 case 1:
709 menu = (char*)"unpair";
710 break;
711 case 2:
713 menu = (char*)"Gen3";
714 else
715 menu = (char*)"AnyBLE";
716 break;
717 default:
718 SerialMin.printf("b. **** Invalid item: %d\n",item);
719 break;
720 }
721 break;
723 switch (item)
724 {
725 case 0:
726 menu = (char*)"feed";
727 break;
728 case 1:
729 menu = (char*)"skip";
730 break;
731 case 2:
732 menu = (char*)"pair";
733 break;
734 case 3:
736 menu = (char*)"Gen3";
737 else
738 menu = (char*)"AnyBLE";
739 break;
740 default:
741 SerialMin.printf("c. **** Invalid item: %d\n",item);
742 break;
743 }
744 break;
745 case notConnectedEnum:
746 switch (item)
747 {
748 case 0:
749 menu = (char*)"scan..";
750 break;
751 case 1:
753 menu = (char*)"Gen3";
754 else
755 menu = (char*)"AnyBLE";
756 break;
757 default:
758 SerialMin.printf("d. **** Invalid item: %d\n",item);
759 break;
760 }
761 break;
762 }
763 }
764 break;
765 case rebootModel:
766 {
767 //Max for >4 items is 10 characters..
768 switch (item)
769 {
770 case 0:
771 menu = (char*)"reboot";
772 break;
773 case 1:
774 menu = (char*)"poweroff";
775 break;
776 case 2: // blankscreen
777 // poweroff.. but send MQTT first..
778 menu = (char*)"blankscrn";
779 break;
780
781 case 3: // Uno
782 menu = (char *)"Set Uno";
783 break;
784 case 4: //FeedKindTumbler
785 menu = (char *)"Tumbler";
786 break;
787
788 case 5: // change color
789 menu = (char*)"colorscrn";
790 break;
791 case 6: // SemanticMarker
792 menu = (char*)"SemMarker";
793 break;
794 case 7: // Extra sends
796 menu = (char*)"BLE+WIFI";
797 else
798 menu = (char*)"BLEOnly";
799 // .. switch to WIFI too
800 break;
801 case 8: // WIFI Change Page on M5 units..
802 menu = (char*)"CycleScrn";
803 // .. switch to WIFI too
804 break;
805 case 9: // WIFI chage wave page, evetually Wave-Page, Wave+Stream
806 menu = (char*)"Wave+Page";
807 // .. switch to WIFI too
808 break;
809 case 10: // WIFI chage wave page, evetually Wave-Page, Wave+Stream
810 menu = (char*)"Wave+Strm";
811 // .. switch to WIFI too
812 break;
813 case 11: // look for PTClicker
815 menu = (char*)"PTClicker";
816 else
817 menu = (char*)"PTFeeder";
818 break;
819
820 default:
821 SerialMin.printf("e. **** Invalid item: %d\n",item);
822 break;
823 }
824 }
825 break;
826
827 case menusModel:
828 {
829 //!MENUS
830 //! Pairing
831 //! APMode
832 //! Timer
833 //! Advanced
834 //! Status
835 //! WIFI sharing
836 //! Guest Feed
837 //! Settings
838 //! DocFollow
839 //! help
840 //! HomePage
841 //! /WIFI Feed
842 //! WIFI Share
843
844
845 switch (item)
846 {
848 menu = (char*)"BLEPair";
849 break;
851 menu = (char*)"APMode";
852 break;
854 menu = (char*)"WIFIShare";
855 break;
856 case MenusModel_Timer:
857 menu = (char*)"Timer";
858 break;
860 menu = (char*)"Advanced";
861 break;
863 menu = (char*)"Status";
864 break;
866 menu = (char*)"GuestPage";
867 break;
869 menu = (char*)"GuestFeed";
870 break;
872 menu = (char*)"Settings";
873 break;
875 menu = (char*)"DocFollow";
876 break;
877 case MenusModel_Help:
878 menu = (char*)"Help";
879 break;
880
881 default:
882 SerialMin.printf("f. **** Invalid item: %d\n",item);
883 break;
884 }
885 }
886 break;
887#endif //ESP_M5
888 //menuForState. Max == 2 if running (showing STOP , TIME)
889 //! Max == 4 if not running (START, TIME, MAXTIME, DELAY)
890 case timerModel:
891 {
892 switch (item)
893 {
894
895 case 0:
896 //!draw the state we are in..
897 if (deviceState->delayRunning)
898 menu = (char*)"Stop";
899 else
900 menu = (char*) "Start";
901 break;
902 case 1:
903 {
904 //!update menu with seconds countdown
905 if (deviceState->delayRunning)
906 sprintf(_timerBuffer,"%d", deviceState->currentCounterSeconds);
907 else
908 sprintf(_timerBuffer,"%d", deviceState->delaySeconds);
909
910 menu = _timerBuffer;
911 }
912 break;
913
914 //! only if stopped... max == 4, other max == 2
915 case 2:
916 {
917 //!show max
918 sprintf(_timerBuffer,"%d", deviceState->delaySecondsMax);
919 menu = _timerBuffer;
920 }
921 break;
922 case 3:
923 {
924
925 menu = (char*)"Delay";
926 }
927 break;
928 default:
929 SerialMin.printf("g. **** Invalid item: %d\n",item);
930 break;
931 }
932 }
933 break;
934 }
935 return menu;
936}
937
938//!invokes the menu state, return true if the model state has change enough to refreesh your View (such as new menu items)
939//!NOTE: This is the LONG press on the M5 button (the BLUE item)
941{
942 //!default is the view is the same
943 boolean modelChanged = false;
944 //!what model struct to use
945 ModelStateStruct *deviceState = getModel(modelKind);
946 SerialTemp.printf("invokeMenuState(%d, pair=%d) \n", modelKind, deviceState->pairedDeviceStateEnum);
947
948 int item = deviceState->currentItem;
949 switch (modelKind)
950 {
951#ifdef ESP_M5
952 //! the pairdDeviceModel kind
954 {
955 SerialCall.printf("pairedDeviceModel");
956
957 switch (deviceState->pairedDeviceStateEnum)
958 {
959 //paired to a device, but BLE NOT connected right now
961 switch (item)
962 {
963 case 0:
964 //scan .. default
965 break;
966 case 1:
967 //unpair
969 modelChanged = true;
970 break;
971 case 2:
972 //toggle..
974 modelChanged = true;
975 break;
976 }
977 break;
978 //paired to a device, and BLE connected right now
980 switch (item)
981 {
982 case 0:
983 //feed
984 //send BLE feed ... this help figure out which BLE is connected
986 break;
987 case 1:
988 //unpair
990 modelChanged = true;
991 break;
992 case 2:
993 //toggle..
995 modelChanged = true;
996 break;
997 }
998 break;
999 //not paired (but could be paired as it's a named device or address])
1001 switch (item)
1002 {
1003 case 0:
1004 //feed
1006 break;
1007 case 1:
1008 //skip
1010 modelChanged = true;
1011 break;
1012 case 2:
1013 // pair
1015 modelChanged = true;
1016 break;
1017 case 3:
1018 //toggle..
1020 modelChanged = true;
1021 break;
1022 }
1023 break;
1024 //!factory default but not connecte to anything..
1025 case notConnectedEnum:
1026 switch (item)
1027 {
1028 case 0:
1029 //scan
1030 break;
1031 case 1:
1032 //toggle..
1034 modelChanged = true;
1035 break;
1036 }
1037 break;
1038 }
1039 }
1040 break;
1041
1042 case rebootModel:
1043 {
1044 SerialCall.println("*** rebootModel ***");
1045
1046 switch (item)
1047 {
1048 case 0: // reboot
1050 break;
1051 case 1: // poweroff
1052 // poweroff.. but send MQTT first..
1054 break;
1055 case 2: // blankscreen
1057 break;
1058 case 3: // Uno
1059 //! 8.16.25 BLE CLIENT
1061 break;
1062 case 4: //FeedKindTumbler
1063 //! 8.16.25 BLE CLIENT
1065 break;
1066
1067 case 5: //color
1068 //! for now, the color is incremented in the displayModule
1070 break;
1071 case 6: // SemanticMarker
1073 modelChanged = true;
1074 break;
1075 case 7: // extra..
1077 modelChanged = true;
1078 break;
1079 case 8:
1080 //send WIFI to all except this page.. but keep some state.
1081 //! 8.16.25 MQTT
1082 //eg: https://iDogWatch.com/bot/cmddevice/tao49@comcast.net/PASS/dev/sm1
1083 //! BUT at the MQTT level not web page level
1084
1085 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
1086 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
1087 // if (getTransientPreference_mainModule(TRANSIENT_PREFERENCE_SENDWIFI_WITH_BLE))
1088 {
1089 char pubString[60];
1090 //for now .. just send smN
1091 sprintf(pubString,"{'dev':'!%s', 'cmd':'sm%0d'}",deviceName_mainModule(), deviceState->currentPageState);
1093 //incremenet model, wrap around
1094 deviceState->currentPageState = (deviceState->currentPageState +1 ) % deviceState->maxPageState;
1095 }
1096
1097 break;
1098 case 9:
1099 // WIFI chage wave page
1100 //! 8.16.25 MQTT
1101 //eg: https://iDogWatch.com/bot/cmddevice/tao49@comcast.net/PASS/dev/sm1
1102 //! BUT at the MQTT level not web page level
1103
1104 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
1105 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
1106 // if (getTransientPreference_mainModule(TRANSIENT_PREFERENCE_SENDWIFI_WITH_BLE))
1107 {
1108 char pubString[100];
1109 //for now .. just send 'next' on a common wave (TODO: select wave we are in..)'
1110 sprintf(pubString,(char*)"#followMe {AVM=https://SemanticMarker.org/bot/wave/%s?action=next}", deviceState->waveName);
1111 //! this has the # so it is treated slightly different, but tacking on the device for example..
1112 sendMessageMQTT(pubString);
1113
1114 }
1115
1116 break;
1117 case 10:
1118 // WIFI change stream (1..3)
1119 //! 8.16.25 MQTT
1120 //eg: https://iDogWatch.com/bot/cmddevice/tao49@comcast.net/PASS/dev/sm1
1121 //! BUT at the MQTT level not web page level
1122
1123 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
1124 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
1125 // if (getTransientPreference_mainModule(TRANSIENT_PREFERENCE_SENDWIFI_WITH_BLE))
1126 {
1127 char pubString[100];
1128 //for now .. just send 'next' on a common wave (TODO: select wave we are in..)'
1129 //! This just goes to the 0'th page in the stream..
1130 sprintf(pubString,(char*)"#followMe {AVM=https://SemanticMarker.org/bot/wave/%s?stream=%0d&page=0}", deviceState->waveName, deviceState->currentStreamNum+1);
1131 //! 1 based (not 0 based)
1132 //publishMQTTMessageDefaultTopic(pubString);
1133 //! this has the # so it is treated slightly different, but tacking on the device for example..
1134 sendMessageMQTT(pubString);
1135
1136 deviceState->currentStreamNum = (deviceState->currentStreamNum +1 ) % deviceState->maxStream;
1137 }
1138
1139 break;
1140 case 11:
1141 //! set transient look for PTClicker
1143 break;
1144 //! 11.4.22 (after Maggie Bluetic was fed with Pumpking Uno and GreyGoose
1145
1146
1147 default:
1148 SerialMin.println("h, *** invalid item ***");
1149 }
1150 }
1151 break;
1152
1153 case menusModel:
1154 {
1155 modelChanged = true;
1156 SerialCall.println("*** menusModel ***");
1157 //!use lookup
1158 int SMMode = _menuToSMMode[item];
1159 // invoke that page (note now those pages return here on ButB_longpress)
1161
1162 //! Issue: #222 for #206, this sets the current mode to SM_doc_follow, but
1163 //! when at that page in the the current mode (which is now SM_doc_follow) won't let
1164 //! the page go somewhere else (except in this case we are the same page). Only but a
1165 //! physical button click.
1166 //! I THINK THE ANSWER: if current and next are the same an SM_doc_follow, then do the page change..
1167
1168 //! if HELP then printout preferences to the debug window
1169 if (SMMode == SM_help)
1170 //! if HELP .. show the status
1171 //!print the preferences to SerialDebug
1173 }
1174 break;
1175#endif //ESP_M5
1176 case timerModel:
1177 {
1178 //invokeMenuState
1179 SerialTemp.printf("*** timerModel (%d) *** %d\n", item, deviceState->delayRunning);
1180
1181 /*
1182 When running 0 == STOP, and 1 == current time (and a long press will reset it..)
1183 When not running 0 == START, 1 = min, 2 = max , 3 = DELAY ??
1184 */
1185 switch (item)
1186 {
1187 case 0:
1188 // stop the timer..
1189 //start stop..
1190 deviceState->delayRunning = !deviceState->delayRunning;
1191 if (deviceState->delayRunning)
1192 {
1193 // just started..
1195 }
1196 break;
1197 case 1:
1198 if (deviceState->delayRunning)
1199 {
1200 //! This will restart the timer..
1202 break;
1203 }
1204 //otherwise fall through..
1205 case 2:
1206 {
1207 //menu = (char*)"Bounds"; .. change timer 5 .. 30 .. 60 .. 120 .. 5
1208 int currentDelay;
1209 if (item == 1)
1210 currentDelay = deviceState->delaySeconds;
1211 else
1212 currentDelay = deviceState->delaySecondsMax;
1213 //!same login for each
1214 if (currentDelay == 5)
1215 currentDelay = 30;
1216 else if (currentDelay == 30)
1217 currentDelay = 60;
1218 else if (currentDelay == 60)
1219 currentDelay = 120;
1220 else if (currentDelay == 120)
1221 currentDelay = 600;
1222 else
1223 currentDelay = 5;
1224 SerialTemp.printf(".. change delay = %d\n", currentDelay);
1225 if (item == 1)
1226 {
1227 deviceState->delaySeconds = currentDelay;
1228 //save in EPROM
1230
1231 //! make sure the max is >= min
1232 if (deviceState->delaySecondsMax < currentDelay)
1233 {
1234 deviceState->delaySecondsMax = currentDelay;
1235 //save in EPROM
1237 }
1238 }
1239 else
1240 {
1241 //! 11.29.23 add the random feed
1242 if (currentDelay < deviceState->delaySeconds)
1243 currentDelay = deviceState->delaySeconds;
1244 deviceState->delaySecondsMax = currentDelay;
1245 deviceState->currentCounterSeconds = deviceState->delaySeconds;
1246 //save in EPROM
1248 }
1249
1250 //!now use those values to create a new random time..
1251 //!not needed until the START above
1252 //setNextRandomTime();
1253 }
1254 break;
1255 case 3:
1256 //! Delay .. no-opp
1257 break;
1258 default:
1259 SerialMin.println("i2. *** invalid item ***");
1260
1261 }
1262 }
1263 break;
1264 }
1265 return modelChanged;
1266}
1267
1268//!retrieves a semantic marker for the current selected item
1270{
1271 //!default is the view is the same
1272 boolean modelChanged = false;
1273 //!what model struct to use
1274 ModelStateStruct *deviceState = getModel(modelKind);
1275 SerialLots.printf("invokeMenuState(%d, %d) \n", modelKind, deviceState->pairedDeviceStateEnum);
1276
1277 char *semanticMarker = NULL;
1278
1279#ifdef NOTHING_YET_SAVE_SOME_MEMORY
1280 int item = deviceState->currentItem;
1281
1282 switch (modelKind)
1283 {
1284 case rebootModel:
1285 {
1286 switch (item)
1287 {
1288 case 0: // reboot
1289 //REboot the device
1290 //sprintf(_semanticMarkerString,"%s/%s/%s", "https://SemanticMarker.org/bot/reboot", _mqttUserString?_mqttUserString:"NULL", guestPassword?guestPassword:"NULL");
1291 break;
1292 case 1: // poweroff
1293 // poweroff.. but send MQTT first..
1294 break;
1295 case 2: // blankscreen
1296 break;
1297 case 3: //color
1298 //! for now, the color is incremented in the displayModule
1299 break;
1300 case 4: // SemanticMarker
1301 break;
1302 case 5: // none
1303 break;
1304 case 6: // next page .. actually there is one .. later
1305 break;
1306 case 7: // next page .. actually there is one .. later
1307 break;
1308 }
1309 }
1310 }
1311#endif
1312 return semanticMarker;
1313}
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
Definition: MainModule.cpp:844
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
Definition: MainModule.cpp:794
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:381
#define ASYNC_REBOOT
sets the GATEWAY mode off
Definition: MainModule.h:213
#define SM_guest_feed
guest feed
Definition: MainModule.h:379
#define SM_guest_page
guest page
Definition: MainModule.h:372
#define ASYNC_SEND_MQTT_FEED_MESSAGE
sends a message (like FEED) on the users topic
Definition: MainModule.h:203
#define SM_timer
timer .. todo
Definition: MainModule.h:388
#define SM_status
//status
Definition: MainModule.h:368
#define SM_reboot
REboot.
Definition: MainModule.h:390
#define MAX_SM_EXPANDED_MODES
Definition: MainModule.h:396
#define SM_help
HELP.
Definition: MainModule.h:383
#define ASYNC_POWEROFF
sets the GATEWAY mode off
Definition: MainModule.h:215
#define ASYNC_BLANKSCREEN
blank the screen
Definition: MainModule.h:217
#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 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