ESP_IOT v2.5
IOT ESP Coding
MainModule.cpp
Go to the documentation of this file.
1//! \link MainModule
2#include "../../Defines.h"
3//#include "MainModule.h"
4
5#define USE_NEW_M5ATOMCLASS
6//! 5.6.25 use the M5Atom ClassType
7#ifdef USE_NEW_M5ATOMCLASS
8//! @see https://www.cs.fsu.edu/~myers/cop3330/notes/dma.html
9#include "../M5AtomClassModule/M5AtomClassType.h"
10
11#include "../M5AtomClassModule/M5Atom_SocketModuleClass.h"
12#include "../M5AtomClassModule/M5Atom_QRCodeModuleClass.h"
13#include "../M5AtomClassModule/M5Atom_HDriverModuleClass.h"
14//! 5.9.25 -- Dead 77
15#include "../M5AtomClassModule/M5Atom_Core2ModuleClass.h"
16//! 7.17.25 - Adding GPS
17#include "../M5AtomClassModule/M5Atom_TinyGPSModuleClass.h"
18//! 8.16.25 bring in the CameraModule from 2022
19#include "../M5AtomClassModule/M5Atom_CameraModuleClass.h"
20
21//! 7.24.25 Hot Day, Ballon last night, Mt Out
22//! for the 'C' option of atom color
23#ifdef USE_FAST_LED
24#include "../ATOM_LED_Module/M5Display.h"
25#endif
26
27//! instances of the M5AtomClassType
28
29//1
31//2
33//3
35//4
37//! 7.17.25 - Adding GPS
38//! 5
40//! 8.16.25 bring in the CameraModule from 2022
41//! 6
43
44//! make sure this is updated.
45//! 8.16.25 == 6
46#define NUM_M5ATOM_CLASS 6
47
48//! 3.31.25 create array of plugs
50
51//! use this one...
53
54#endif //USE_NEW_M5ATOMCLASS
55
56#define USE_SENSOR_CLASS
57#ifdef USE_SENSOR_CLASS
58//! 5.14.25
59#include "../SensorClass/SensorClassType.h"
60#include "../SensorClass/BuzzerSensorClass.h"
61#include "../SensorClass/KeyUnitSensorClass.h"
62
63#define NUM_SENSOR_CLASS 2
66
67//! init will look at those SensorClass known above, and look
68//! to see which ones are defined by the user in the SensorsStruct
69//! A report will show which ones were not found
71{
72 SerialDebug.println(" *** initSensorClassTypeArray ***");
73 //! return the sensor specified or null
75 if (sensorsStruct)
76 {
77 //! all the sensors defined
78 //! sensors is an array of sensor
80 int count = sensorsStruct->count;
81
82 //! go through the defined sensorName and instantiate those classes
83 for (int i=0; i< count; i++)
84 {
85 SensorStruct* sensor = &sensors[i];
86 if (strcmp(sensor->sensorName, "BuzzerSensorClass")==0)
87 {
88 //! init this class
89 _BuzzerSensorClass = new BuzzerSensorClass((char*)"BuzzerSensorClass");
90 //! store the class type instance
92 //! setup and then setPins..
93 _BuzzerSensorClass->setPinValues(sensor->pin1, sensor->pin2);
94
95 //! call setup
97 }
98 }
99 //! find missing sensors
100 //! go throug the defined sensorName and instantiate those classes
101 for (int i=0; i< count; i++)
102 {
103 SensorStruct* sensor = &sensors[i];
104 if (!sensor->sensorClassType)
105 {
106 //! missing instance
107 SerialDebug.printf("Missing class definition: %s\n", sensor->sensorName);
108 }
109 }
110 }
111 SerialDebug.println("Finish initSensorClassTypeArray");
112}
113#endif
114
115//! 6.7.25 hot air balloons over house..
116//! stops the motor
118{
121}
122
123//! gets if PTFeeder a surrogate for the M5Atom class
125{
128 else
129 //!Defines the name of the service of the server, which for M5 will be PTClicker
130 {
131 return containsSubstring(MAIN_BLE_SERVER_SERVICE_NAME, "PTFeeder");
132 }
133 /*
134#ifdef ESP_M5
135#define MAIN_BLE_SERVER_SERVICE_NAME (char*)"PTClicker"
136#else
137#define MAIN_BLE_SERVER_SERVICE_NAME (char*)"PTFeeder"
138#endif
139 */
140}
141
142//! reads the preferences. Save is everytime the savePreference is called
144//!testing..
145boolean _stopAllProcessing = false;
146//!stop all loops... while OTA working..
148{
149 _stopAllProcessing = true;
150}
151//!restart all loops... while OTA working..
153{
154 _stopAllProcessing = false;
155}
156//! if stopped
158{
159 //! try to disconnect..
160 //disconnect_BLEClientNetworking();
161 // return false; //
162 return _stopAllProcessing;
163}
164
165//****** GLOBALS (shows how much memory is allocated.. )
166//!the parameter being sent to those commands passing an argument
168//!global to store credentials when ever they are stored..
170//!global for others to use..
171#define MESSAGE_STORAGE_MAX 500
173//!status string (URL query format)
175//! current smMode
177//! saved deviceName storage..
179
180//!store a big message #MSG_START .. #MSG_END
182char _bigMessage[500];
183//!saved BLE connected name 8.26.22
185//!full: ""Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
187//!full: ""Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
189
190//!init globals strings
192{
193 //!NOTE: this is definitely needed, as grabbing strings willy nilly can bomb or corrupt stuff..
194 strcpy(_connectedBLEDeviceName,(char*)"");
195 strcpy(_bigMessage,(char*)"");
196 strcpy(_deviceNameSave,(char*)"");
197 strcpy(_smMode_MainModule,(char*)"");
198 strcpy(_fullStatusString,(char*)"");
199 strcpy(_messageStorage,(char*)"");
200 strcpy(_JSONStringForWIFICredentials,(char*)"");
201 strcpy(_asyncParameter,(char*)"");
202 strcpy(_fullBLEDeviceName,(char*)"");
203
204 main_setScannedDeviceName((char*)"");
205 //! 1.7.24
206 main_setScannedGroupName((char*)"");
207}
208
209//THIS IS the setup() and loop() but using the "component" name, eg MQTTNetworking()
210//! called from the setup()
212{
213 SerialMin.println("setup_mainModule");
214#ifdef BOOTSTRAP_CLEAN
215 //!cleans the EPROM .. if things are really not working..
217#endif
218
219 //test...
220 //! setup for the token parser (really just for testing) -- an
222
223 //!init globals like strings (but nothing that needs preferences)
225
226 //!read the preferences from EPROM
228
229 //!must initialize the structs NOTE: this has to ber AFTER the preferences are read in..
231
232 //!a first time feature .. to get EPROM changed to a different default
234 {
235
236 //!7.12.22
237 //! {'dev':'m5",'cmd':'bleserveron'} or bleserveroff will work later..
238 //!#issue 116 .. turn off the BLE_Server for the M5
239 SerialMin.println("FIRST TIME TURNING off the BLE_SERVER for the M5");
240#ifdef ESP_M5
241
242#ifdef M5_ATOM
243 //! 5.6.25 use object version
245
246#else // not M5_ATOM
247
248 // 8.28.23 .. not doing this anymore..
250
251 //! not ESP_M5
252#endif // M5_ATOM
253#else // NOT ESP_M5
255#endif
256 //! all ..
258 }
259
260#define NEW_SENSORS
261 //! 5.14.25 use the Sensor types
262 //! first we have N sensors
263 //! then we get which ones the user wants (the SENSORS_SETTING)
264 //! then we instantiate, and provide ping, etc.
266}
267
268#if defined(ESP_M5_CAMERA) || defined(ESP_32)
269//!a couinter to slow down the loop doing things..
270int _mainLoopCounter = 0;
271#endif
272
273//! storage for reading from the serial buffer
274//! 6.20.25 (Sam Sprague grad Western party)
276
277//! called for the loop() of this plugin
279{
280 //no op..
281
282#if defined(ESP_M5_CAMERA) || defined(ESP_32)
283 //!only do this menu update if there is no DisplayModule running the MVC loop
284
285 if (_mainLoopCounter++ > 30)
286 {
287 //! 9.2.22 new .. update the timer. This is on blank screen as well .. so don't check _semanticMarkerShown
289
290 _mainLoopCounter = 0;
291 }
292
293#endif
294
295#pragma mark Serial Input Processor
296 //! 6.20.25 works with full code (JSON, or single commands - with '.' as help)
297 //! 6.19.25 Mt Peak finally (kept to 124 bpm)
298 //! Per ##373 let the serial monitor get some input, and let us set a few features
299 //! see if data on the serial input
300 //! Re-indexed and now command completion works!!!!!! 3 years later.
301 //!@see https://developer.apple.com/documentation/corespotlight/regenerating-your-app-s-indexes-on-demand?language=objc
302 if (Serial.available())
303 {
304 // read string until meet newline character
305 String command = Serial.readStringUntil('\n');
306
307 SerialDebug.println(command);
308 //! save globally for the callback below..
309 strcpy(_serialBuffer, command.c_str());
310
311 if (command == "help")
312 {
313 SerialDebug.println("Enter any Single Char or JSON msg, type '.' for commands");
314 SerialDebug.println("r -- reboot");
315 SerialDebug.println(". -- shows single char commands");
316 SerialDebug.println("Example JSON to change WIFI (copy and modify with your values)");
317 SerialDebug.println(" supports single quotes for values");
318 SerialDebug.println("{'ssid':'Bob', 'ssidPassword':'scott'}");
319
320 }
321 else if (command == "r")
322 {
324 }
325 else
326 {
327 //!call the callback specified from the caller (eg. NimBLE_PetTutor_Server .. or others)
329 }
330 }
331}
332
333
334//! 5.3.22 added a feed count approach.. (NOTE: there is a _feedCount in Dispence.cpp ... and no linker error!!! )
336//!returns the max for this feeder
338{
339 int max = 16;
340 switch (getFeederType_mainModule())
341 {
342 case STEPPER_IS_UNO:
343 max = 16;
344 break;
345 case STEPPER_IS_MINI:
346 max = 55;
347 break;
349 max = 50;
350 break;
351 }
352 return max;
353}
354//!feedcount info..
356{
358}
359
360//!get the feeder type (Sepper 1,2,3 ...)
362{
364 return kind;
365}
366
367//!increments .. and if MAX goes to 0 -- and sends a message on MQTT
369{
370 SerialTemp.println("incrementFeedCount_mainModule");
371
374 {
375 // send a message.
376 //! 8.16.25 MQTT
377 //note needs # or won't send..
378 //!NOTE: don't send "feed" as it might trigger a FEED ...
379 sendMessageMQTT((char*)"#count reached .. resetting");
380
382 }
383
384 //! called by the feed operation to say the device is still running.. and count it as a button click.
385 //! Issue #145 8.8.22
387
388}
389//! sets the feed count max
391{
393}
394
395//!check if the string contains the other string. This is a poor man's grammer checker
396bool containsSubstring(String message, String substring)
397{
398 if (substring.length() == 0 )
399 return false;
400 bool found = strstr(&message[0], &substring[0]);
401 SerialLots.printf("containsSubstring-%d - %s in: %s\n", found, &substring[0], &message[0]);
402 return found;
403}
404
405//! 8.16.25 MQTT
406#include "../MQTTModule/MQTTNetworking.h"
407
408//! 8.16.25 BLE SERVER
409#include "../BLEServerModule/BLEServerNetworking.h"
410
411//! 8.16.25 BLE CLIENT
412#include "../BLEClientModule/BLEClientNetworking.h"
413#ifdef USE_BUTTON_MODULE
414#include "../ButtonModule/ButtonProcessing.h"
415#endif
416
417//! New RegisterCallback that works across a number of callback modules
418//!
419//! callbacksModuleId
420#define CALLBACKS_MQTT 0
421#define CALLBACKS_BUTTON_MODULE 1
422#define CALLBACKS_BLE_CLIENT 2
423#define CALLBACKS_BLE_SERVER 3
424
425
426//!register the callback based on the callbackType. use the callbacksModuleId for which one..
427void registerCallbackMain(int callbacksModuleId, int callbackType, void (*callback)(char*));
428//!performs the indirect callback based on the callbackType
429void callCallbackMain(int callbacksModuleId, int callbackType, char *message);
430
431
432//!make sure these are the number of callbacks.. 0..n
433//! These values are from the respective .h of the modules
434#define CALLBACKS_MAX_MQTT MQTT_MAX_CALLBACKS
435#define CALLBACKS_MAX_BUTTON_MODULE MAX_CALLBACKS_BM
436#define CALLBACKS_MAX_BLE_CLIENT BLE_CLIENT_MAX_CALLBACKS
437#define CALLBACKS_MAX_BLE_SERVER BLE_SERVER_MAX_CALLBACKS
438
439
440//!example callback
441void dummyCallbackMain(char *message)
442{
443 SerialLots.printf("No callback defined .. %s\n", message);
444}
445
446//tricky getting array of arrays (or pointers to arrays), without dynamic memory.. we are going to use calloc()
447//https://www.geeksforgeeks.org/dynamic-memory-allocation-in-c-using-malloc-calloc-free-and-realloc/
448//https://www.tutorialspoint.com/cprogramming/c_pointer_to_pointer.htm
449//https://stackoverflow.com/questions/5573302/pointer-to-an-array-of-function-pointers
450//!the array of callback functions
451//* this means there are arrays of N pointers to functions that take 1 parameter (char*).
452
453
454//! the max of each module .. hard coded (or 0 if module not there)
456
457//!flag for initializing if not yes
459
460//a pointer to a callback function that takes (char*) and returns void
461typedef void (*callbackSignature)(char *);
462//callbackSignature fpar[2] = {&dummyCallbackMain, &dummyCallbackMain};
463
464//!return dyamically created array of max
466{
467 SerialLots.printf("creatingCallbacks %d size: %d\n", max, sizeof(callbackSignature *));
468 callbackSignature *callbackArray = (callbackSignature *)calloc(max,sizeof(callbackSignature *));
469 for (int i=0; i< max; i++)
470 {
471 callbackArray[i] = &dummyCallbackMain;
472 }
473 return callbackArray;
474}
475//!array of known size (CALLBACKS_MODULE_MAX) of callbackSignatures
477
478//!init the callbacks to dummy callbacks
480{
482 {
484
485 // default to 0 callbacks.. in case module not there..
486 for (int i = 0; i < CALLBACKS_MODULE_MAX; i++)
487 {
489 }
490 //! only place for #ifdef (NOTE some can be 0 based on the #ifdef module not being included..
491 //! 8.16.25 MQTT
493 //! 8.16.25 BLE SERVER
495 //! 8.16.25 BLE CLIENT
497#ifdef USE_BUTTON_MODULE
499#endif
500 // initialize the dummy callbacks
501 for (int i = 0; i < CALLBACKS_MODULE_MAX; i++)
502 {
503 //first determine how many are in the array..
504 int max = _callbacksFunctionsMAXS[i];
505 //then create the space which are (void *) pointers
506 _allCallbacks[i] = createMemory(max);
507 }
508 }
509}
510
511//!register the callback based on the callbackType. use the callbacksModuleId for which one..
512void registerCallbackMain(int callbacksModuleId, int callbackType, void (*callback)(char*))
513{
514 SerialDebug.printf("registerCallbackMain %d, %d\n", callbacksModuleId, callbackType);
515
516 //init if not already..
518 int max = _callbacksFunctionsMAXS[callbacksModuleId];
519
520 if (callbackType < 0 || callbackType >= max)
521 {
522 SerialError.printf("#### Error outside callback range - 1, %d\n", callbackType);
523 }
524 else
525 {
526 // array of arrays (or array of pointer to another array)
527 _allCallbacks[callbacksModuleId][callbackType] = callback;
528 }
529}
530//!performs the indirect callback based on the callbackType
531void callCallbackMain(int callbacksModuleId, int callbackType, char *message)
532{
533 //init if not already..
535 int max = _callbacksFunctionsMAXS[callbacksModuleId];
536
537 if (callbackType < 0 || callbackType >= max)
538 {
539 SerialError.printf("#### Error outside callback range - 2, %d\n", callbackType);
540
541 }
542 else {
543 void (*callbackFunction)(char *) = _allCallbacks[callbacksModuleId][callbackType];
544 (*callbackFunction)(message);
545 }
546}
547
548//!whether the string is TRUE, ON, 1
549boolean isTrueString_mainModule(String valCmdString)
550{
551 return valCmdString.equalsIgnoreCase("on") ||
552 valCmdString.equalsIgnoreCase("1") ||
553 valCmdString.equalsIgnoreCase("true");
554};
555
556//! 8.28.23 Adding a way for others to get informed on messages that arrive
557//! for the set,val
558//! 1.10.24 if deviceNameSpecified then this matches this device, otherwise for all.
559//! It's up to the receiver to decide if it has to be specified
560void messageSetVal_mainModule(char *setName, char* valValue, boolean deviceNameSpecified)
561{
562 SerialCall.printf("messageSetVal(%s,%s)\n", setName, valValue);
563 // THE IDEA WOULD be a callback is avaialble..
564 //FOR now.. just ifdef
565#ifdef M5_ATOM
566 //! 5.6.25 use object version
568 _whichM5AtomClassType->messageSetVal_M5AtomClassType(setName, valValue, deviceNameSpecified);
569
570#endif //M5_ATOM
571
572#ifdef M5CORE2_MODULE
573 //! TODO fix this
574 messageSetVal_M5Core2Module(setName, valValue, deviceNameSpecified);
575#endif
576}
577//!TODO: have a callback regist approach
578
579//! 12.28.23, 8.28.23 Adding a way for others to get informed on messages that arrive
580//! for the set,val
581//! 5.21.25 SEND and CMD will be treated the same and put to "send"
582void messageSend_mainModule(char *sendValue, boolean deviceNameSpecified)
583{
584//! 5.21.25 this will overlap with the "cmd" .. so send == cmd
585#ifdef M5_ATOM
586#pragma mark USE_NEW_M5ATOMCLASS
587
588 //! 5.6.25 use object version
590 _whichM5AtomClassType->messageSend_M5AtomClassType(sendValue, deviceNameSpecified);
591
592#endif //M5_ATOM
593
594#ifdef M5CORE2_MODULE
595 //! TODO FIX THIS
596 messageSend_M5Core2Module(sendValue);
597#endif
598}
599
600//! 8.16.25 MQTT
601//!example callback: but the scope would have the pCharacteristic defined, etc..
602//!This is passed just before the setupMQTTNetworking() is called..
603void feedMessageCallback(char *message)
604{
605 SerialTemp.print("feedMessageCallback_main: ");
606 SerialTemp.println(message);
607 char * rxValue = (char*)"c"; //feed (s and 0 work too) MIGHT NOT BE WORKING IF MESSAGE ARRIVES VIA MQTT (and we want to use BLE)
608 //!sends this single character to the StepperModule
610
611 //!increment the feed count .. TODO .. see if this is good place..
612// incrementFeedCount_mainModule();
613
614 //!the FEED was send over MQTT, now what to do?
615 //! WIth the StepperModule -- it just performs the feeding internalls
616 //! if using the BLE_CLIENT then we have the potential to send to over BLE
617 //! to the server (another feeder, GEN3 or ESP32).
618 //! The issue is that ESP32 feeders are receiving the same MQTT message (usually unless MQTT turned off
619 //! So the gatewayMode can be set (or in the EPROM) using {'cmd':'gatewayOn'}
621 {
622 //! 8.16.25 BLE CLIENT
623
624 SerialTemp.print("Paired Device: ");
626
627 SerialTemp.printf("Gateway: Feeding over the BLE CLIENT network .. if connected: %d\n",isConnectedBLEClient());
629 {
630 //!send the feed over the BLE client (if connected)
632 }
633 SerialLots.println("after send feed via ble");
634 }
635}
636
637//!moved here 4.25.22 (entirely from ESP_IOT.ino)
638
639//! April 8, 2022
640//! set that the credentials are set. Called from the MQTT after processJSONMessage() found things were good..
642{
643 // set the done in the WI
644 SerialDebug.println(" *** main_credentialsUpdated .. setDoneWIFI_APModuleFlag **");
645 //! 8.16.25 WIFI AP
647}
648//NOTE: #else not there so this won't link.. on purpose
649
650/*******************************BLE Server*************************************/
651//!The callback for "onWrite" of the bluetooth "onWrite'
652void onBLEServerCallback(char *message)
653{
654 SerialCall.print("onWriteBLEServerCallback: ");
655 SerialCall.println(message);
656
657}
658//! The callback for "status messages" of the bluetooth
660{
661 SerialCall.print("onStatusMessageBLEServerCallback");
662 SerialCall.print(message);
663 //! 2.2.22 send this over bluetooth.. TODO.
664 //
665}
666
667//! The FINISH of callback for "onWrite" of the bluetooth "onWrite'
669{
670
671 SerialDebug.print("onWriteBLEServerCallback_main: ");
672 SerialDebug.println(message);
673
674 //!client never sends these wrapped messages of length 1, so process normally..
675 //!gets us out of potential infinite wait
676 if (strlen(message) == 1)
678
679 if (strcmp(message, "#MSG_START")==0)
680 {
682 strcpy(_bigMessage,"");
683 return;
684 }
686 {
687 if (strcmp(message, "#MSG_END")==0)
688 {
690 //! we are done.. send big message to ourself..
692 }
693 else
694 {
695 strcat(_bigMessage,message);
696 return;
697 }
698 }
700
701 //!Issue: the message is arriving via BLE, but if we call the MQTT process, it might call us back to send
702 //!the message over BLE. This hangs things up!
703 //!So short optimization for 'feed' will be to look for cmd and feed in message {cmd:feed}
704 //!8.19.22 issue #162
705 if (containsSubstring(message,"cmd"))
706 {
707 if (containsSubstring(message,"feed"))
708 {
709 message = (char*)"s";
710 }
711 else if (containsSubstring(message,"buzzOn"))
712 {
713 message = (char*)"B";
714 }
715 else if (containsSubstring(message,"buzzOff"))
716 {
717 message = (char*)"b";
718 }
719
720 }
721
722 //! 8.16.25 MQTT
723 //This should be a 'register' command..
724
725 //!the MQTTNetwork.processJSONMessage()
726 //!will return true if the message was JSON and was processes, false otherwise.
727 if (processJSONMessageMQTT(message, NULL))
728 {
729 //!processed by the MQTTNetworking code..
730 //! 8.16.25 BLE SERVER
732 //pCharacteristic->setValue(0x01); //?? This is the acknowlege(ACK) back to client. Later this should be contigent on a feed completed
733 }
734 else
735 {
736 //!perform feed...
737 SerialDebug.printf("Perform BLE Command '%s'\n", message);
738
739 char cmd = message[0];
740
741 //OOOPS.. we need the ProcessClientCmd .. for other than just step..
742 // for sensors..
743
744 //!look for ** sensor commands..
746
747 //! 8.16.25 BLE SERVER
749
750 }
751 SerialDebug.println("*********");
752
753} //onWriteBLEServerCallback
754
755//! The callback for "onWrite" of the bluetooth "onWrite'
756void onWriteBLEServerCallback(char *message)
757{
758 //TEST:
759#define TRY_ASYNC_BLE_PROCESSING
760#ifdef TRY_ASYNC_BLE_PROCESSING
761
762 //!send an async call with a string parameter. This will set store the value and then async call the command (passing the parameter)
763 //!These are the ASYNC_CALL_PARAMETERS_MAX
765#else
766
767 //! The callback for "onWrite" of the bluetooth "onWrite'
768 onWriteBLEServerCallbackFinish(char *message);
769#endif
770}
771
772//! called by the feed operation to say the device is still running.. and count it as a button click.
774{
775#ifdef USE_BUTTON_MODULE
776 //!calls the button processing control
777 refreshDelayButtonTouched_ButtonProcessing();
778#endif
779}
780//! 3.28.22 .. implemented in ESP_IOT.ino
782//!performs an async OTA update
784{
786}
787//!sets the async OTA flag (for next loop)
789{
791}
792
793//!returns if the paired device is not NONE
795{
797}
798
799//!returns if the paired device is not NONE
801{
803
804}
805//!returns if the paired device is not NONE. Note, the paired Name might be an address now (see below)
807{
808 char *pairedDevice = getPairedDevice_mainModule();
809 //new: now if non ""
810 //return strcmp(pairedDevice,"NONE")!= 0;
811 boolean isValid = pairedDevice && strlen(pairedDevice)>0 && strcmp(pairedDevice,"NONE")!= 0;
812 if (!isValid)
813 {
814 char *pairedDeviceAddress = getPairedDeviceAddress_mainModule();
815 isValid = pairedDeviceAddress && strlen(pairedDeviceAddress)>0 && strcmp(pairedDeviceAddress,"NONE")!= 0;
816 SerialLots.printf("isValidDeviceAddress(%s,%d)\n", pairedDeviceAddress?pairedDeviceAddress:(char*)"NULL", isValid);
817 }
818 SerialLots.printf("isValidPairedDevice_mainModule(%s,%d)\n", pairedDevice?pairedDevice:(char*)"NULL", isValid);
819 return isValid;
820}
821
822//**** dang.. the getPreference reuses the same storage!! ****
823
824//!returns if the paired device is not NONE .. returns address or device
826{
827 char *pairedDevice = getPairedDevice_mainModule();
828 if (pairedDevice && strlen(pairedDevice)>0 && strcmp(pairedDevice,"NONE")!= 0)
829 {
830 SerialLots.printf("getPairedDeviceOrAddress_mainModule(%s)\n", pairedDevice);
831 return pairedDevice;
832 }
833 char *pairedDeviceAddress = getPairedDeviceAddress_mainModule();
834 if (pairedDeviceAddress && strlen(pairedDeviceAddress)>0 && strcmp(pairedDeviceAddress,"NONE")!= 0)
835 {
836 SerialLots.printf("getPairedDeviceOrAddress_mainModule(%s)\n", pairedDeviceAddress);
837 return pairedDeviceAddress;
838 }
839 else
840 return (char*)"";
841}
842
843//!gets the device name
845{
847 strcpy(_deviceNameSave,deviceName);
848 return _deviceNameSave;
849}
850
851//!power of devices
852//!reboot
854{
855 //reboot
856 ESP.restart();
857}
858
859//!power off
861{
862#ifdef ESP_M5
863 //SerialTemp.println(" **** THIS WOULD BE A POWEROFF ***");
864 SerialTemp.println(" **** POWEROFF ***");
865
866#ifndef ESP_M5_CAMERA
867#ifndef M5STICKCPLUS2
868
869#ifndef ESP_M5_ATOM_S3
870 M5.Axp.PowerOff();
871#endif
872#endif
873#endif
874
875#endif
876}
877// ******************* Preference Cleaning ************
878
879//!cleans the EPROM
881{
882 SerialDebug.println("CLEANING EPROM PREFERENCES");
883
884 //4.17.22
886
887 //! 8.16.25 MQTT
889
890 //! 8.16.25 WIFI AP
892 //! 7.29.25 set the FIRST time ..
894
895 SerialDebug.println("REBOOTING...");
896
897 //!reboot
899
900}
901
902
903//!retrieve a JSON string for the ssid and ssid_password: {'ssid':<ssid>,'ssidPassword':<pass>"}
905{
907}
908
909//!! cycle through the next WIFI saved credential
911{
912
913 SerialTemp.printf("WIFI_CREDENTIAL_1: %s\n", getPreference_mainModule(PREFERENCE_WIFI_CREDENTIAL_1_SETTING));
914 SerialTemp.printf("WIFI_CREDENTIAL_2: %s\n", getPreference_mainModule(PREFERENCE_WIFI_CREDENTIAL_2_SETTING));
915
916 //! WIFI_CREDENTIALS_MAX
918 {
919 char* credential = getPreference_mainModule(i);
920 //!jump out of loop if no match.. so index is valid
921 if (strcmp(credential,"NONE")==0)
922 continue;
923 if (strcmp(credential,_JSONStringForWIFICredentials)!= 0)
924 {
925 SerialTemp.print("main_nextJSONWIFICredential:");
926 SerialTemp.println(credential);
927 return credential;
928
929 }
930 }
931 SerialTemp.print("main_nextJSONWIFICredential:");
932 SerialTemp.println(main_JSONStringForWIFICredentials());
934}
935
936//!save the WIFI credential
937void main_saveWIFICredentials(char *ssid, char *ssid_password)
938{
939 //!store the JSON version of these credentials..
940 sprintf(_JSONStringForWIFICredentials, "{'ssid':'%s','ssidPassword':'%s'}", ssid?ssid:"NULL", ssid_password?ssid_password:"NULL");
941 SerialMin.print("main_saveWIFICredentials");
942 SerialMin.println(_JSONStringForWIFICredentials);
943
944 //!look for an non matching slot.. if none, then use the first
947 {
948 char* credential = getPreference_mainModule(index);
949 //!jump out of loop if no match.. so index is valid, or NONE (which is the placeholder)
950 if (strcmp(credential,"NONE")==0)
951 break;;
952 if (strcmp(credential,_JSONStringForWIFICredentials)== 0)
953 {
954 break;
955 }
956 }
957
960
961 SerialDebug.println(_JSONStringForWIFICredentials);
962 //!save in chosen index
964}
965
966//!clean the saved WIFI credential, otherwise the AP mode doesn't work (6.3.22)
968{
969 SerialMin.println("main_cleanSavedWIFICredentials");
970
971 //!go through the saved WIFI credentials and empty them with "" (vs null)
974 {
975 //!cannot null but can make stringlen=0
977 }
978}
979
980//! 12.14.23
981char *_MQTT_Password = (char*)"";
982char *_MQTT_Username = (char*)"";
985
986//! return the username and password
987//! 12.14.23 to support calling the SMART buttons (smrun) with parameters
989{
990 return _MQTT_Username;
991}
992
993//! return password
995{
996 return _MQTT_Password;
997}
998
999//! return devicename
1001{
1002 SerialDebug.printf("main_getScannedDeviceName(%s)\n", _scannedDeviceName);
1003
1004 return _scannedDeviceName;
1005}
1006//! set the scanned device name
1007void main_setScannedDeviceName(char *deviceName)
1008{
1009 strcpy(_scannedDeviceName, deviceName);
1010 SerialDebug.printf("main_setScannedDeviceName(%s)\n", deviceName);
1011}
1012
1013//! set the scanned group name
1014//! 1.7.24
1015void main_setScannedGroupName(char *groupName)
1016{
1017 SerialDebug.printf("main_setScannedGroupName(%s)\n", groupName);
1018
1019 if (groupName && strlen(groupName)>0)
1020 {
1021 char *groupTopic = groupTopicFullName(groupName);
1023 }
1024 else
1025 strcpy(_scannedGroupTopicName, "");
1026}
1027//! return groupname -- returns "" or nil if not set,
1028//! or the FULL group name topic, or nil
1030{
1032 {
1033 SerialDebug.printf("main_getScannedGroupNameTopic(%s)\n", _scannedGroupTopicName);
1035
1036 }
1037 return NULL;
1038}
1039
1040//! sets the WIFI and MQTT user/password. It's up to the code (below, maybe in future a register approach) to decide who needs to know
1041void main_updateMQTTInfo(char *ssid, char *ssid_password, char *username, char *password, char *guestPassword, char *deviceName, char * host, char * port, char *locationString)
1042{
1043 SerialMin.printf("main_updateMQTTInfo(%s,%s,%s,%s,%s, %s, d=%s)\n", ssid?ssid:"NULL", ssid_password?ssid_password:"NULL", username?username:"NULL", password?password:"NULL", guestPassword?guestPassword:"NULL", locationString?locationString:"NULL", deviceName?deviceName:"NULL");
1044
1045 _MQTT_Password = password;
1046 _MQTT_Username = username;
1047
1048 //!store the device name
1050
1051 //!store the JSON version of these credentials..
1052 main_saveWIFICredentials(ssid,ssid_password);
1053
1054 //! 8.16.25 WIFI AP
1055 WIFI_APModule_updateMQTTInfo(ssid, ssid_password, username, password, guestPassword, deviceName, host, port, locationString);
1056}
1057
1058//! 5.16.25 Fountainhead, Raining cold weekend
1059//! start SYNC calls starting with the SYNC_CLICK_SOUND
1060//#define SYNC_CLICK_SOUND 0
1061//#define SYNC_CALL_MAX 1
1062//! the main sync command (no parameters yet)
1063void main_dispatchSyncCommand(int syncCallCommand)
1064{
1065 switch (syncCallCommand)
1066 {
1067 case SYNC_CLICK_SOUND:
1068 {
1070 {
1071 //! 5.15.25 see if the Buzzer class is defined .. if so, then call local message
1072 SensorStruct* buzzerSensor = getSensor_mainModule((char*)"BuzzerSensorClass");
1073
1074 //!perform the click sound..
1075 //!this will be the sensors...
1076 if (buzzerSensor)
1077 {
1078 buzzerSensor->sensorClassType->messageLocal_SensorClassType((char*)"click");
1079 }
1080 else
1081 SerialDebug.println("NO BuzzerSensorClass defined");
1082 }
1083 }
1084 break;
1085 }
1086}
1087
1088//! 3.21.22 these are to setup for the next time the main loop() runs to call these commands..
1089//! The implementation is hard coded in the ESP_IO.ino
1090//! TODO: make this a registeration approach
1091//#define ASYNC_CALL_OTA_UPDATE 0
1092//#define ASYNC_CALL_CLEAN_CREDENTIALS 1
1093//#define ASYNC_CALL_MAX 2
1094
1095//!storage for asyncCallCommands
1097//!array of async flags for the different ASYNC_CALl values
1099
1100//!initialize the async call flags (with and without parameters)
1102{
1103 for (int i = 0; i < ASYNC_CALL_MAX; i++)
1104 {
1105 _asyncCallFlags[i] = false;
1106 }
1107 for (int i = 0; i < ASYNC_CALL_PARAMETERS_MAX; i++)
1108 {
1109 _asyncCallFlagsParameters[i] = false;
1110 }
1111}
1112
1113// ******************* Async Dispatch Processing ************
1114
1115//!checks if any async commands are in 'dispatch' mode, and if so, invokes them, and sets their flag to false
1116
1117//! dispatches a call to the command specified. This is run on the next loop()
1118void main_dispatchAsyncCommand(int asyncCallCommand)
1119{
1120 //! this just sets the flag, it's the next loop that makes the call
1121#ifdef ERROR_CHECKS
1122 if (asyncCallCommand < 0 || asyncCallCommand >= ASYNC_CALL_MAX)
1123 {
1124 SerialError.printf("ERROR: async call out of range: %d\n", asyncCallCommand);
1125 }
1126 else
1127#endif
1128 {
1129 SerialTemp.printf("1.main_dispatchAsyncCommand: %d\n", asyncCallCommand);
1130 _asyncCallFlags[asyncCallCommand] = true;
1131 }
1132}
1133
1134//!send an async call with a string parameter. This will set store the value and then async call the command (passing the parameter)
1135//!These are the ASYNC_CALL_PARAMETERS_MAX
1136void main_dispatchAsyncCommandWithString(int asyncCallCommand, char *parameter)
1137{
1138 //!store in the parameter mailbox
1139 strcpy(_asyncParameter,parameter);
1140 //! this just sets the flag, it's the next loop that makes the call
1141#ifdef ERROR_CHECKS
1142 if (asyncCallCommand < 0 || asyncCallCommand >= ASYNC_CALL_PARAMETERS_MAX)
1143 {
1144 SerialError.printf("ERROR: async call out of range: %d\n", asyncCallCommand);
1145 }
1146 else
1147#endif
1148 {
1149 SerialTemp.print("2.main_dispatchAsyncCommandWithString:");
1150 SerialTemp.print(asyncCallCommand);
1151 SerialTemp.print(": ");
1152 SerialTemp.println(_asyncParameter);
1153 _asyncCallFlagsParameters[asyncCallCommand] = true;
1154
1155 //! 6.15.25 Fathers Day
1156 //! seems issue when a GROVE or other sensor plugged in the main loop isn't working.
1157 //! SO for now, if the command is "r" then do an actual reboot..
1158 if (strlen(_asyncParameter)>1 && _asyncParameter[0] == 'r')
1159 {
1160 SerialDebug.println("SYNC_REBOOT");
1162 }
1163 }
1164}
1165
1166//!checks if any async commands are in 'dispatch' mode, and if so, invokes them, and sets their flag to false
1168{
1169 SerialCall.printf("invokeAsyncCommands(%d)\n", ASYNC_CALL_PARAMETERS_MAX);
1170
1171 for (int i = 0; i < ASYNC_CALL_PARAMETERS_MAX; i++)
1172 {
1173 boolean asyncCallFlag = _asyncCallFlagsParameters[i];
1174 if (asyncCallFlag)
1175 {
1176 SerialCall.printf("invokeAsyncCommands(%d)\n", i);
1177 _asyncCallFlagsParameters[i] = false;
1178 switch (i)
1179 {
1181 SerialTemp.print("ASYNC_CALL_BLE_CLIENT_PARAMETER: ");
1182 SerialTemp.println(_asyncParameter);
1183 //! 8.16.25 BLE CLIENT
1184 if (strlen(_asyncParameter)<=13)
1186 else
1188
1189 break;
1191 SerialTemp.print("ASYNC_CALL_OTA_FILE_UPDATE_PARAMETER: ");
1192 SerialTemp.println(_asyncParameter);
1193 //! 8.16.25 MQTT
1194 {
1195 //look for the host: http://<name>/
1196 // httpAddress is everything after the /
1197 //hostname is without http://
1198 char hostname[100];
1199 char httpAddress[100];
1200 int thirdSlash = 0;
1201 for (int i=0; i< strlen(_asyncParameter);i++)
1202 {
1203 if (_asyncParameter[i] == '/')
1204 {
1205 thirdSlash++;
1206 }
1207 if (thirdSlash == 3)
1208 {
1209 // i == point to 3rd slash
1210 strncpy(hostname,_asyncParameter,i);
1211 //add null
1212 hostname[i] = (char)0;
1213 char *a = &_asyncParameter[i+1];
1214 strcpy(httpAddress,a);
1215 break;
1216 }
1217 }
1218 //todo..
1219 SerialTemp.print("will performOTAUpdate: ");
1220 SerialTemp.print(hostname);
1221 SerialTemp.print(" with httpAddress: ");
1222 SerialTemp.println(httpAddress);
1223 performOTAUpdate(hostname, httpAddress);
1224 }
1225 break;
1227 {
1228 //process the message
1229 SerialDebug.print("ASYNC_JSON_MESSAGE_PARAMETER: ");
1230 SerialDebug.println(_asyncParameter);
1231
1232 //! The FINISH of callback for "onWrite" of the bluetooth "onWrite'
1234 }
1235 break;
1236
1237 //! 1.10.24 add ability to send a MQTT Semantic Marker message
1239 {
1240 //process the message
1241 SerialDebug.print("ASYNC_JSON_MQTT_MESSAGE_PARAMETER: ");
1242 SerialDebug.println(_asyncParameter);
1243
1244 //! This sends a MQTT message. Currently GROUP not supported
1245 //! TODO: add GROUP
1246 char *groupTopic = NULL;
1247 if (groupTopic)
1249 else
1251 }
1252 break;
1253
1254 //! 3.9.24 REST call
1256 {
1257 //process the message
1258 SerialDebug.print("ASYNC_REST_CALL_MESSAGE_PARAMETER: ");
1259 SerialDebug.println(_asyncParameter);
1260#ifdef USE_REST_MESSAGING
1261 sendSecureRESTCall(_asyncParameter);
1262#endif
1263 }
1264 break;
1265 }
1266
1267 }
1268 }
1269
1270 //!now process those that don't have a string parameter
1271 for (int i = 0; i < ASYNC_CALL_MAX; i++)
1272 {
1273 boolean asyncCallFlag = _asyncCallFlags[i];
1274 if (asyncCallFlag)
1275 {
1276 _asyncCallFlags[i] = false;
1277 switch (i)
1278 {
1280 SerialLots.println("ASYNC_CALL_OTA_UPDATE");
1281 //! 8.16.25 MQTT
1283 break;
1285 SerialTemp.println("ASYNC_CALL_CLEAN_CREDENTIALS");
1286 //! 8.16.25 WIFI AP
1288 //this reboots ..
1289 break;
1291 SerialTemp.println("ASYNC_CALL_CLEAN_EPROM");
1293 break;
1295 SerialLots.println("ASYNC_CALL_FEED_COMMAND");
1297 //! 8.16.25 MQTT
1298 //!register the 2 callbacks for now..
1300 break;
1301 //!this is a sending of the message
1303 SerialTemp.println("ASYNC_SEND_MQTT_FEED_MESSAGE");
1304 //incrementFeedCount_mainModule();
1305 SerialCall.println("async_send_feed.1");
1306
1307 //! 8.16.25 MQTT
1308 //! 8.16.25 BLE CLIENT
1309 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
1310 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
1312 {
1313 char pubString[100];
1315 boolean isPaired = paired && strlen(paired)>0;
1316 // cannot save it.. so refresh below.. (Preferences are reused)
1317 SerialTemp.printf("Paired = %s\n", paired?paired:(char*)"none");
1318 SerialTemp.printf("Connected = %s\n", connectedBLEDeviceName_mainModule()?connectedBLEDeviceName_mainModule():(char*)"none");
1319
1321 sprintf(pubString,"{'dev':'!%s & !%s'",deviceName_mainModule(),connectedBLEDeviceName_mainModule());
1322 else if (isPaired)
1323 sprintf(pubString,"{'dev':'!%s & !%s'",deviceName_mainModule(),getPreference_mainModule(PREFERENCE_PAIRED_DEVICE_SETTING));
1324 else
1325 sprintf(pubString,"{'dev':'!%s'",deviceName_mainModule());
1326 strcat(pubString,",'cmd':'feed'}");
1328 //! if not paired, then feed everyone except out device...
1329 }
1330 //! if not BLE connected .. send wifi fee to all below...
1331 //SerialTemp.println("async_send_feed.3");
1332 //TODO: 7.26.22 .. decide if this logic makes sense:
1333 //NO BLECLient, and a message arrives for this device to #FEED. So previously it would sned that onto the network .. but I don't think that's right. (And we weren't in that mode yet).
1334 //sendMessageMQTT((char *)"#FEED");
1335 //! 8.16.25 BLE CLIENT
1336 //! returns whether connected over BLE as a client to a server(like a ESP feeder)
1337 if (!isConnectedBLEClient())
1338 {
1339 //! If not connected over BLE -- then send the MQTT feed message.. ??? WHY??
1340 //! 8.16.25 MQTT
1341
1342 //!only if not WIFI with BLE
1343 //! 8.20.24 put back to MQTT feed to all .. for now..
1344 //! SerialCall.println("async_send_feed.1");
1345 sendMessageMQTT((char *)"#FEED");
1346 SerialTemp.println(" *** NO BLE connected so send wifi ASYNC_SEND_MQTT_FEED_MESSAGE");
1347
1348 }
1349 else
1350 {
1351 SerialCall.println("async_send_feed.2");
1353
1354 //!send a BLE feed command as we are connected
1356
1357 //!perform ACK too
1358 //! 8.16.25 MQTT
1359 //ack is sent by the caller of this message..??
1360 sendMessageMQTT((char *)"#ackMe");
1361 }
1362#ifdef NOT_NOW
1363 //! 8.24.22 (This will redraw the screen - and turn off the blank screen (but not let anyone know)
1364 //! SO: now only the buttons will unlock the blank screen..
1365
1366 //!redraws the Semantic Marker image..
1368#endif //not_now
1369 break;
1370
1371 //!this is a sending of the message
1372 //!5.15.25 Sodbuster Rod plowing/disking in minutes with Mark and Bud
1373 case ASYNC_CLICK_SOUND:
1374 {
1375 SerialTemp.println("ASYNC_CLICK_SOUND");
1377 }
1378 break;
1379
1380 case ASYNC_CALL_BUZZ_ON:
1382 {
1383 boolean isBuzzOn = (i == ASYNC_CALL_BUZZ_ON);
1384 //! set the persistence (Note, this is locally saved. If sending elsewhere .. then they have to set their value)
1386
1387 SerialDebug.printf("ASYNC_CALL_BUZZ %d\n",isBuzzOn);
1388 String cmdToSend;
1389 if (isBuzzOn)
1390 cmdToSend = "{'cmd':'buzzon'}";
1391 else
1392 cmdToSend = "{'cmd':'buzzoff'}";
1393
1394 //!OK: issue.
1395 //! if we are an ESP feeder, the STEPPER is on .. so we're good,
1396 //! if an M5 - then either send over BLE or MQTT
1397#ifdef ESP_M5
1398 //!send via BLE or MQTT ..
1399 //! 8.16.25 BLE CLIENT
1400 //! returns whether connected over BLE as a client to a server(like a ESP feeder)
1401 if (!isConnectedBLEClient())
1402 {
1403 SerialLots.println("async_call_buzz_on/off -- not BLE connected.. send MQTT");
1404 //! If not connected over BLE -- then send the MQTT buzzon message..
1405 //! 8.16.25 MQTT
1406 sendMessageMQTT((char*)cmdToSend.c_str());
1407 }
1408 else
1409 {
1410 //!send over BLE...
1411 sendCommandBLEClient(cmdToSend);
1412 }
1413#else //not M5
1414
1415 //! 8.16.25 BLE CLIENT
1416 //! returns whether connected over BLE as a client to a server(like a ESP feeder)
1417 if (!isConnectedBLEClient())
1418 {
1419 SerialLots.println("async_call_buzz_on -- not BLE connected.. send MQTT");
1420 //! If not connected over BLE -- then send the MQTT buzzon message..
1421 //! 8.16.25 MQTT
1422 sendMessageMQTT((char *)cmdToSend.c_str());
1423 }
1424 else
1425 {
1426 SerialLots.println("async_call_buzz_on -- YES BLE connected.. send BLE");
1427 processClientCommandChar_mainModule(isBuzzOn?'B':'b');
1428
1429 }
1430
1431#endif // ESP_M5
1432 }
1433 break;
1434
1435 //!setGatewayOn/Off called from the processJSON message in MQTT
1436 //! or via the EPROM setting (TODO)
1438 SerialLots.println("ASYNC_SET_GATEWAY_ON");
1440
1441 break;
1442
1444 SerialLots.println("ASYNC_SET_GATEWAY_OFF");
1446
1447 break;
1448
1449 case ASYNC_REBOOT:
1450 SerialDebug.println("ASYNC_REBOOT");
1452
1453 break;
1454
1455 case ASYNC_POWEROFF:
1456 SerialDebug.println("ASYNC_POWEROFF");
1458
1459 break;
1460 case ASYNC_BLANKSCREEN:
1461 SerialDebug.println("ASYNC_BLANKSCREEN");
1463 break;
1465 //!sends the status from the main module URL
1466 //! 8.16.25 MQTT
1467 {
1468#ifdef ESP_M5_CAMERA
1469 char *statusURL = main_currentStatusURL(false);
1470#else
1471 char *statusURL = main_currentStatusURL(true);
1472#endif
1473 SerialDebug.print(" ASYNC_SEND_MQTT_STATUS_URL: ");
1474 SerialDebug.println(statusURL);
1475 /// NO MORE: sendDocFollowMessageMQTT(statusURL);
1476 sendStatusMessageMQTT(statusURL);
1477 }
1478#ifdef M5BUTTON_MODULE
1479 //! 1.23.24 call the status which re-evaluates the sensor ALIVE
1480 //! this status will be called and let the ALIVE re-evaluate
1481 //! Only do this on the STATUS since it might be slow for the LUX
1482 statusM5ButtonModule();
1483#endif
1484 break;
1485
1486 case ASYNC_SWAP_WIFI:
1487 case ASYNC_NEXT_WIFI:
1488 {
1489 //NOTE: this might be where we toggle credentials?? TODO
1490 //found other one..
1491 char *credentials = main_nextJSONWIFICredential();
1492 //! 8.16.25 MQTT
1493
1494 //!These are the ASYNC_CALL_PARAMETERS_MAX
1495 //!NO: just change our credentials ...
1496 //send to
1497 //main_dispatchAsyncCommandWithString(ASYNC_CALL_BLE_CLIENT_PARAMETER, credentials);
1499 }
1500 break;
1502 //! 8.16.25 MQTT
1503 //!Restarts (or attempts) a restart of the WIFI using the existing credentials -- vs the 'n' command
1505 break;
1506 default:
1507 SerialLots.printf("NO COMMAND: %s", i);
1508 }
1509 }
1510 }
1511}
1512//! 2.21.25 add a way to change the button color (if any)
1514{
1515#ifdef M5BUTTON_MODULE
1516 SerialDebug.println("changeButtonColor_MainModule");
1517 // changeButtonColor_M5ButtonModule()
1518#endif
1519}
1520
1521//!3.17.24 the unqiue chip id
1523//! string like: 10311304
1525
1526//! 3.17.24 get the chip id
1527uint32_t getChipId()
1528{
1529 if (_chipID_MainModule == 0)
1530 {
1531 //get chip ID
1532 for (int i = 0; i < 17; i = i + 8) {
1533 _chipID_MainModule |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
1534 }
1536 }
1537 return _chipID_MainModule;
1538
1539}
1540
1541//! 3.17.24 get the chip id as a string
1543{
1544 getChipId();
1546}
1547
1548//! 1.12.24 add a temporary LUX dark
1549//! threshholdKind = 0 (LIGHT), 1=(DARK) .. others might be 2=super dark
1550//#define THRESHOLD_KIND_LIGHT 0
1551//#define THRESHOLD_KIND_DARK 1
1554//! set the threshold val
1555void setLUXThreshold_mainModule(int thresholdKind, int luxVal)
1556{
1557 switch (thresholdKind)
1558 {
1560 _thresholdLUXLight = luxVal;
1561 break;
1563 _thresholdLUXDark = luxVal;
1564 break;
1565 }
1566}
1567//! get the threshold val
1568int getLUXThreshold_mainModule(int thresholdKind)
1569{
1570 switch (thresholdKind)
1571 {
1573 return _thresholdLUXLight;
1574 break;
1576 return _thresholdLUXDark;
1577 break;
1578 }
1579 return 80;
1580}
1581
1582//!storage for the group topic name
1583//!Note NO "/" in the front of the path only "usersP"
1585#define GROUP_TOPIC_TO_SEND (char*)"usersP/groups"
1586//!returns a groupTopic to use as a topic
1587char *groupTopicFullName(char *groupName)
1588{
1589 sprintf(_groupTopicName, "%s/%s",GROUP_TOPIC_TO_SEND, groupName);
1590 return _groupTopicName;
1591}
1592
1593//define a couple lights .. maybe move somewhere else..
1594char* _ON_LIGHT = (char*)"ON";
1595char* _OFF_LIGHT = (char*)"OFF";
1596
1597//!callback for blinking led
1598void blinkMessageCallback(char *message)
1599{
1600
1601#ifdef ESP_M5
1602
1603 //call the already defined blink led
1604 // devined in Dispense.cpp
1605// digitalWrite(LED, HIGH);
1606// delay(150);
1607// digitalWrite(LED, LOW);
1608
1609#else //not M5
1610 //call the already defined blink led
1611 // defined in Dispense.cpp
1612 // stepperModule_BlinkLED();
1614#endif //ESP_M5
1615}
1616
1617//!callback for SOLID blinking led
1618void solidLightMessageCallback(char *message)
1619{
1620 SerialLots.println("solidLightMessageCallback..");
1621#ifdef ESP_M5
1622#else
1623 //!call the already defined solid led
1624 //! defined in Dispense.cpp
1625 boolean lightOn = true;
1626 lightOn = strstr(&message[0], _ON_LIGHT);
1627 solidLightOnOff_UIModule(lightOn);
1628#endif
1629}
1630
1631//!clean the SSID eprom (MQTT_CLEAN_SSID_EPROM)
1633{
1634 //!call the already defined solid led
1635 //! defined in Dispense.cpp
1636 //! 8.16.25 WIFI AP
1637 //!clean_SSID_WIFICredentials();
1638 //!now register an async call..
1640
1641}
1642
1643//!called on single click
1644//!NOTE: with BLE_CLIENT_NETWORKING, the right button and top button send a BLE command for feeding..
1645void singleClickTouched(char *whichButton)
1646{
1647 //! 8.16.25 WIFI AP
1648 //!for now, only send the FEED command via BLE_CLIENT if turned on. No reboot to AP mode yet..
1649 //! 8.16.25 BLE CLIENT
1650 //!send the async FEED
1651
1652 //! dispatches a call to the command specified. This is run on the next loop()
1654}
1655
1656//! shows a FEED (or whatever) then blanks the screen after N seconds
1657//! NOTE: This will be a scrolling text as sometime ..
1658void showText_mainModule(String text)
1659{
1660 //showText_displayModule(text);
1662
1663}
1664
1665//!callback for SOLID blinking led
1666void solidLightOnOff(boolean onOff)
1667{
1668#ifdef ESP_M5
1669#else
1670 SerialLots.println("solidLight..");
1671 //!call the already defined solid led
1672 //! defined in Dispense.cpp
1673 boolean lightOn = onOff;
1674 solidLightOnOff_UIModule(lightOn);
1675#endif
1676}
1677
1678//!prints the module configuration by looking at #defines
1679//! Eventually this might be an object returned letting the code
1680//!know a capability is included for runtime (vs compile time) decisions
1682{
1683 //!Module Configuration
1684 SerialDebug.println(" ** #define Module Configuration **");
1685 SerialDebug.println(PARTITION_SCHEME);
1686 SerialDebug.printf("M5Stack Version = %s\n", (char*)M5STACK_VERSION);
1687
1688 SerialDebug.println(" ** BUILDS **");
1689
1690#ifdef ESP_M5
1691 //![x] ESP_M5
1692 SerialMin.println("[x] ESP_M5");
1693#else
1694 SerialMin.println("[ ] ESP_M5");
1695#endif
1696#ifdef ESP_M5_CAMERA
1697 //![x] ESP_M5
1698 SerialMin.println("[x] ESP_M5_CAMERA");
1699#else
1700 SerialMin.println("[ ] ESP_M5_CAMERA");
1701#endif
1702#ifdef ESP_32
1703 //! [x] ESP_32
1704 SerialMin.println("[x] ESP_32");
1705#else
1706 SerialMin.println("[ ] ESP_32");
1707#endif
1708#ifdef M5CORE2_MODULE
1709 //![x] M5CORE2_MODULE
1710 SerialMin.println(F("[x] M5CORE2_MODULE"));
1711#else
1712 SerialMin.println(F("[ ] M5CORE2_MODULE"));
1713#endif
1714 //Set this if the SMART clicker build is used.
1715#ifdef ESP_M5_SMART_CLICKER_CONFIGURATION
1716 SerialMin.println(F("[x] ESP_M5_SMART_CLICKER_CONFIGURATION"));
1717#else
1718 SerialMin.println(F("[ ] ESP_M5_SMART_CLICKER_CONFIGURATION"));
1719#endif
1720#ifdef ESP_M5_ATOM_LITE
1721 SerialMin.println(F("[x] ESP_M5_ATOM_LITE"));
1722#else
1723 SerialMin.println(F("[ ] ESP_M5_ATOM_LITE"));
1724#endif
1725
1726 SerialDebug.println(F(" ** MQTT BLE NETWORKING **"));
1727
1728 //! 8.16.25 MQTT
1729 //! [x] USE_MQTT_NETWORKING
1730 SerialMin.println("[x] USE_MQTT_NETWORKING");
1731
1732 //! 8.16.25 BLE SERVER
1733 //! [x] USE_BLE_SERVER_NETWORKING
1734 SerialMin.println("[x] USE_BLE_SERVER_NETWORKING");
1735
1736 //! 8.16.25 BLE CLIENT
1737 //! [x] USE_BLE_CLIENT_NETWORKING
1738 SerialMin.println(F("[x] USE_BLE_CLIENT_NETWORKING"));
1739
1740 //! 8.16.25 WIFI AP
1741 //! [x] USE_WIFI_AP_MODULE
1742
1743 SerialMin.println(F("[x] USE_WIFI_AP_MODULE"));
1744
1745
1746#ifdef USE_BUTTON_MODULE
1747 // [x] USE_BUTTON_MODULE
1748 SerialMin.println("[x] USE_BUTTON_MODULE");
1749#else
1750 SerialMin.println("[ ] USE_BUTTON_MODULE");
1751#endif
1752
1753#ifdef M5BUTTON_MODULE
1754 // [x] M5BUTTON_MODULE
1755 SerialMin.println("[x] M5BUTTON_MODULE");
1756#else
1757 SerialMin.println("[ ] M5BUTTON_MODULE");
1758
1759#endif
1760
1761#ifdef USE_STEPPER_MODULE
1762 SerialMin.println("[x] USE_STEPPER_MODULE");
1763#else
1764 SerialMin.println("[ ] USE_STEPPER_MODULE");
1765
1766#endif
1767#ifdef USE_UI_MODULE
1768 SerialMin.println("[x] USE_UI_MODULE");
1769#else
1770 SerialMin.println("[ ] USE_UI_MODULE");
1771
1772#endif
1773#ifdef USE_DISPLAY_MODULE
1774 SerialMin.println("[x] USE_DISPLAY_MODULE");
1775#else
1776 SerialMin.println("[ ] USE_DISPLAY_MODULE");
1777
1778#endif
1779#ifdef BOARD
1780 SerialMin.println(F("[x] BOARD"));
1781#else
1782 SerialMin.println(F("[ ] BOARD"));
1783#endif
1784#ifdef USE_SPIFF_MODULE
1785 SerialMin.printf("[%d] USE_SPIFF_MODULE/_SETTING\n", getPreferenceBoolean_mainModule(PREFERENCE_USE_SPIFF_SETTING));
1786#else
1787 SerialMin.println("[ ] USE_SPIFF_MODULE");
1788#endif
1789#ifdef USE_SPIFF_MQTT_SETTING
1790 SerialMin.printf("[%d] USE_SPIFF_MQTT_SETTING\n",getPreferenceBoolean_mainModule(PREFERENCE_USE_SPIFF_MQTT_SETTING));
1791#endif
1792#ifdef USE_SPIFF_QRATOM_SETTING
1793 SerialMin.printf("[%d] USE_SPIFF_QRATOM_SETTING\n", getPreferenceBoolean_mainModule(PREFERENCE_USE_SPIFF_QRATOM_SETTING));
1794#endif
1795
1796#ifdef USE_FAST_LED
1797 SerialMin.println(F("[x] USE_FAST_LED"));
1798#else
1799 SerialMin.println(F("[ ] USE_FAST_LED"));
1800#endif
1801#ifdef KEY_UNIT_SENSOR_CLASS
1802 SerialMin.println(F("[x] KEY_UNIT_SENSOR_CLASS"));
1803#else
1804 SerialMin.println(F("[ ] KEY_UNIT_SENSOR_CLASS"));
1805#endif
1806#ifdef USE_LED_BREATH
1807 SerialMin.println(F("[x] USE_LED_BREATH"));
1808#else
1809 SerialMin.println(F("[ ] USE_LED_BREATH"));
1810#endif
1811
1812#if (SERIAL_DEBUG_ERROR)
1813 SerialMin.println(F("[x] SERIAL_DEBUG_ERROR"));
1814#endif
1815#if (SERIAL_DEBUG_DEBUG)
1816 SerialMin.println(F("[x] SERIAL_DEBUG_DEBUG"));
1817#endif
1818#if (SERIAL_DEBUG_INFO)
1819 SerialMin.println(F("[x] SERIAL_DEBUG_INFO"));
1820#endif
1821#if (SERIAL_DEBUG_MINIMAL)
1822 SerialMin.println(F("[x] SERIAL_DEBUG_MINIMAL"));
1823#endif
1824
1825 //!and print any preferences to show
1827}
1828
1829//!If nil it create one with just the null, so strlen = 0
1830//!NOTE: the strdup() might be used later..
1831char* createCopy(char * stringA)
1832{
1833 if (stringA)
1834 return strdup(stringA);
1835 else
1836 return strdup("");
1837}
1838
1839//!informs if null or empty string
1840boolean isEmptyString(char *stringA)
1841{
1842 if (!stringA)
1843 {
1844 return true;
1845 }
1846 else if (strlen(stringA) == 0)
1847 {
1848 return true;
1849 }
1850 else
1851 return false;
1852}
1853
1854//!a char* version of startsWith (after skipping spaces)
1855boolean startsWithChar(char *str, char c)
1856{
1857 if (!str) return false;
1858 //!find first non space character, and if not '{' then return false
1859 int i = 0;
1860 while (i < strlen(str))
1861 {
1862 //!jump out if not a space, and 'i' will be the thing to look for
1863 if (str[i] != ' ')
1864 break;
1865 i++;
1866 }
1867
1868 if (str[i] == c)
1869 return true;
1870
1871 return false;
1872}
1873
1874//!start of the sensor updates ... TODO: tie these to the MQTT messaging as well..
1876{
1877 float batVoltage = 1;
1878 float batPercentage = 100; //plugged in
1879#ifdef ESP_M5
1880#ifndef M5STICKCPLUS2
1881
1882#ifdef M5_ATOM
1883 //! the M5.Axp.GetBatVoltage() is VERY slow on the M5 (as there isn't one..)
1884#elif defined(M5CORE2_MODULE)
1885 //!see https://forum.arduino.cc/t/elseif-not-working/565646/12
1886 batVoltage = M5.Axp.GetBatVoltage();
1887 batPercentage = (batVoltage < 3.2) ? 0 : ( batVoltage - 3.2 ) * 100;
1888#else
1889 batVoltage = M5.Axp.GetBatVoltage();
1890 batPercentage = (batVoltage < 3.2) ? 0 : ( batVoltage - 3.2 ) * 100;
1891 //!#Issue 117
1892 //!from: https://community.m5stack.com/topic/1361/ischarging-and-getbatterylevel/9
1893 //!GetVbatdata() is currently depreciated
1894 uint16_t vbatData = M5.Axp.GetVbatData();
1895 double vbat = vbatData * 1.1 / 1000;
1896 batPercentage = 100.0 * ((vbat - 3.0) / (4.07 - 3.0));
1897#endif
1898#endif // M5STICKCPLUS2
1899#endif
1900
1901 if (batPercentage > 100.0)
1902 batPercentage = 100.0;
1903 return batPercentage;
1904}
1905
1906//!adding a synchronous call to send a message over the network (assuming MQTT but not specified), this tacks on {device} and {t:time}
1907void sendMessageString_mainModule(char *messageString)
1908{
1910#ifdef REFACTOR
1911
1912 //! 8.16.25 MQTT
1913 SerialDebug.printf("sendMessageString_mainModule(%s)\n", messageString);
1914 if (strlen(messageString) > 0 && messageString[0] == '{')
1915 {
1916 // JSON Message
1917 //! 12.19.23 Amber in air from Iceland. 50 years since Dead 12.19.73
1918 sendMessageNoChangeMQTT(messageString);
1919 }
1920 else if (strlen(messageString) < MESSAGE_STORAGE_MAX)
1921 {
1922 //!NOTE: the # has to be there, otherwise the sendMessageMQTT ignores it..
1923 sprintf(_messageStorage,"#%s {%s} {t:%d}", messageString, getDeviceNameMQTT(), getTimeStamp_mainModule());
1924 //!send this message over MQTT
1926 }
1927#endif
1928}
1929
1930
1931//!adding a synchronous call to send a message over the network (assuming MQTT but not specified), this tacks on {device} and {t:time}
1932void sendMessageStringTopic_mainModule(char *messageString, char*topicString)
1933{
1934 //! 8.16.25 MQTT
1935 SerialDebug.printf("sendMessageStringTopic_mainModule(%s) - topic=%s\n", messageString, topicString);
1936 if (strlen(messageString) > 0 && messageString[0] == '{')
1937 {
1938 // JSON Message
1939 //! 12.19.23 Amber in air from Iceland. 50 years since Dead 12.19.73
1940 sendMessageNoChangeMQTT_Topic(messageString, topicString);
1941 }
1942 else if (strlen(messageString) < MESSAGE_STORAGE_MAX)
1943 {
1944 //!NOTE: the # has to be there, otherwise the sendMessageMQTT ignores it..
1945 sprintf(_messageStorage,"#%s {%s} {t:%d}", messageString, getDeviceNameMQTT(), getTimeStamp_mainModule());
1946 //!send this message over MQTT
1948 }
1949}
1950
1951//!retrieves the temperature .
1953{
1954#ifdef ESP_M5
1955 //!return celcius
1956 //!float temperature = M5.Axp.GetTempInAXP192();
1957 float temperature;
1958#ifdef M5_ATOM
1959#else
1960#ifndef M5STICKCPLUS2
1961 M5.IMU.getTempData(&temperature);
1962#endif
1963#endif
1964
1965#ifdef USER_THE_MAX_TEMP_FEATURE
1967 if (temperature > maxtemp)
1968 {
1969 //! turn off the device after sending a message..
1970 //! let others know we are powering off..
1971 //! then poweroff
1972 //! 8.16.25 MQTT
1973 sprintf(_messageStorage,"#Temp %f too high > %d - powering off {%s}", temperature, maxtemp, getDeviceNameMQTT());
1974 //!send this message over MQTT
1976 //! now poweroff
1977 SerialTemp.println(" *** This would poweroff .. but you can send message");
1978 //!poweroff_mainModule();
1979
1980 }
1981#endif
1982
1983#else
1984 float temperature = 10.0;
1985#endif
1986 return temperature ;//* 9/5 + 32;
1987}
1988//!NEW: 4.30.22
1989//!returns a string in JSON format, such that {'battery':'84'}, {'buzzon':'off'} .. etc
1990//!as a URL: SemanticMarker.org/bot/sample/scott@name/password/status?BLE:on&numfeeds=8&WIFI:on&AP:off
1991/** Sample format:
1992{"status": [
1993 {
1994 "BLE": "on"
1995 },
1996 {
1997 "numfeeds": "8",
1998 "maxfeeds": "16"
1999 },
2000 {
2001 "battery": "87"
2002 },
2003 {
2004 "buzzon": "on"
2005 },
2006 {
2007 "MQTT": "on"
2008 },
2009 {
2010 "WIFI": "on"
2011 },
2012 {
2013 "AP": "off"
2014 },
2015 {
2016 "tilt": "55"
2017 }
2018]
2019}
2020*/
2021//!status in JSON format, needs to return something as a ',' is already added before calling this..
2023{
2024 //returns a JSON string..
2025// String b = String(getBatPercentage(),0);
2026// return "{'status':[{'BLE':'on'},{'bat':'" + b + "'}]}";
2027 // return (char*)"";
2028
2029 //! 1.4.24 work on ATOM kinds without IFDEF (except to bring in the code)
2030#pragma mark USE_NEW_M5ATOMCLASS
2031
2032 //! 5.6.25 use object version
2035
2036#ifdef M5CORE2_MODULE
2037 //!returns a string in in JSON so: status&battery=84'&buzzon='off' } .. etc
2038 //!starts with "&"*
2040#endif
2041
2042 return (char*)"'tbd':'x'";
2043}
2044
2045//! TODO: fix syntax. If just sensor sensor status: ....
2046//!https://SemanticMarker.org/bot/sensor/scott@konacurrents.com/doggy/status?v=v2&dev=M5Ski&b=68&temp=66&c=0&t=8&W=on&M=on&B=on&C=on&A=off&T=on&S=on&Z=off&t=8
2047//!not working just added Z=on/off length = 157
2048//! going to remove the username/password to shorten..
2049
2050//!adds a query string "&key=value"
2051void addStatusStringFlag(const char *key, char * val)
2052{
2053 char buf[50];
2054 sprintf(buf,"&%s=%s", key, val);
2055 strcat(_fullStatusString, buf);
2056}
2057//!adds to _fullStatusString a query string "&key=value"
2058void addStatusBooleanFlag(const char *key, boolean flag)
2059{
2060 addStatusStringFlag(key, flag?(char*)"on":(char*)"off");
2061
2062}
2063//!sets the "Module Status"
2064//!in queryString == name=val&name=val ...
2066{
2067 //!value of WIFI connected
2068 //! 8.16.25 MQTT
2071 //! 8.16.25 BLE CLIENT
2072 //useBLECLient == it's linked in and running (vs not running)
2074 //! connected == we are connected to another BLEServer
2076
2077 //! 8.16.25 WIFI AP
2078 //!not done is what we look for ..
2080
2081#pragma mark reused
2082#ifdef OVERLOADS_TIME_T
2083 //! 7.20.25 this breaks the T:<time> since there is a dublicate in the URL .. with no error
2085#endif
2086
2087 //! 8.16.25 BLE SERVER
2089 {
2090 //! add a bleS=PTFeeder:name
2091 char *serverBLEName = getServiceName_BLEServerNetworking();
2092 addStatusStringFlag((char*)"bleS",serverBLEName);
2093 }
2094
2095 //!show Z for buZZ
2097
2098 //!show G for gateway
2100
2101 //! 8.10.25
2102 //! #393 add stepper angle
2103 //!show SA for stepper angle float ..
2105
2106
2107 //!P = paired
2110#ifdef NO_MORE_PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
2111
2114#endif
2115 {
2116 addStatusStringFlag("P", pairedDeviceName);
2117 }
2118
2119 //! add the canister and stepper angle per #278
2120#ifdef ESP_32
2125
2126#endif
2127}
2128
2129//!returns a string in in URL so: status?battery=84'&buzzon='off' } .. etc
2130//!if fullStatus, return everything, else just the ATOM stuff
2131char* main_currentStatusURL(boolean fullStatus)
2132{
2133 //!7.20.25 add T too
2134 int time = getTimeStamp_mainModule();
2135 if (fullStatus)
2136 {
2137 //! 8.16.25 MQTT
2138 char *deviceName = getDeviceNameMQTT();
2139 //!TODO: make sure no spaces ... unless escaped
2140
2141 sprintf(_fullStatusString,"status?T=%d&v=%s&dev=%s&b=%02.0f&temp=%02.0f&c=%0d&t=%0d",time, VERSION_SHORT, deviceName, getBatPercentage_mainModule(), getTemperature_mainModule(), getFeedCount_mainModule(), getLoopTimer_displayModule());
2142
2143 }
2144 else
2145 {
2146 //_fullStatusString[0] = '\0';
2147 //! 8.16.25 MQTT
2148 char *deviceName = getDeviceNameMQTT();
2149 //!TODO: make sure no spaces ... unless escaped
2150 sprintf(_fullStatusString,"status?T=%d&v=%s&dev=%s",time, VERSION_SHORT, deviceName);
2151
2152 }
2153#pragma mark USE_NEW_M5ATOMCLASS
2154 //! 5.6.25 use object version
2157
2158 //add to _fullStatusString
2160
2161// //NOTE: any new query from somewhere starts with & (they put it in)
2162
2163 SerialCall.println( _fullStatusString );
2164
2165 //!TODO: put these somewhere somehow (expandable easily..architecturally. eg. setStatus("battery","87") key,val
2166 //!the JSON DB supports db["battery"]=87 like syntax..
2167
2168 //return "status?buzzon=off&AP=off&MQTT=on&WIFI=on&BLE=on&battery=" + String(getBatPercentage(),0);
2169 return _fullStatusString;
2170}
2171
2172#ifdef UNDEFINED
2173//!sets status parts cia a a string in JSON format, such that {'battery':'84'}, {'buzzon':'off'} .. etc
2174void main_setStatusJSON(const char* JSONString)
2175{
2176 //would set the JSON string
2177}
2178//!sets status parts cia a a string in JSON format, such that {'battery':'84'}, {'buzzon':'off'} .. etc
2179void main_setStatusKeyValue(const char* key, const char* value)
2180{
2181 //todo..
2182}
2183#endif
2184
2185//!SemanticMarker events
2186//!This would see a DOCFollow message, and set the value.. then SM10 can display it..
2188//!sed the address to follow
2189void setSemanticMarkerDocFollow_mainModule(char* SMDocFollowAddress)
2190{
2191 _lastSemanticMarkerDocFollow = SMDocFollowAddress;
2194}
2195
2196//!gets the semanticAddress SemanticMarker&trade;
2198{
2200}
2201
2202//!sends the SM on the DOCFOLLOW channel (publish it..)
2203void sendSemanticMarkerDocFollow_mainModule(const char* SMDocFollowAddress)
2204{
2205 //! 8.16.25 MQTT
2206 sendDocFollowMessageMQTT(SMDocFollowAddress);
2207}
2208
2209//! 8.18.24 setting this will check for the factory setting..
2210void setClockwiseMotorDirection_mainModule(boolean isClockwiseFlag)
2211{
2213 SerialDebug.printf("factoryMotorClockwise = %d, isClockwiseFlag = %d\n",factoryMotorClockwise, isClockwiseFlag);
2214
2215 if (factoryMotorClockwise && isClockwiseFlag)
2216 {
2217 SerialDebug.println("setClockwiseMotorDirection -- same so no change");
2218 }
2219 else if (factoryMotorClockwise && !isClockwiseFlag)
2220 {
2221 //!toggle flag and save as that mode..
2222 isClockwiseFlag = !isClockwiseFlag;
2223 //! this says: factory is CW and we want to turn CCW
2224 //! so we have to go the opposite direction (!CW)
2225 }
2226 else if (!factoryMotorClockwise && isClockwiseFlag)
2227 {
2228 //! toggle flag as well,
2229 isClockwiseFlag = !isClockwiseFlag;
2230 //! this says: factory is CCW and we want to turn CW
2231 //! so we have to go the opposite direction (!CW)
2232 }
2233 else if (!factoryMotorClockwise && !isClockwiseFlag)
2234 {
2235 SerialDebug.println("setClockwiseMotorDirection -- same so no change");
2236 }
2237 //! set to what it thinks it is...
2239}
2240
2241//!Keep ProcessClientCmd short to let the callback run. instead change the feeder state flag
2242//! processes a message that might save in the EPROM.. the cmd is still passed onto other (like the stepper module)
2244{
2245 //!the sentToStepper is only needed if there are 'actions' on the command, versus just
2246 //! setting persistent EPROM data. Like feed, buzzer, etc..
2247 //!Thus we don't need to know much of their implementation.. or we just pass anyway!
2248 boolean sendToStepperModule = false;
2249 SerialDebug.printf("***** processClientCommand_mainModule(%c) from client*****\n", cmd);
2250
2251 //char cmd = message[0];
2252 //!only process things that are stored persistently..
2253 //!7.20.25 6 months T
2254 //!Using switch to guarentee unique case of single characters
2255 switch (cmd)
2256 {
2257 case 0x00:
2258 case 's':
2259 case 'c':
2260 {
2261 sendToStepperModule = true;
2262 } break;
2263 case 'a':
2264 {
2265
2266 SerialDebug.println("cmd=a startTimer");
2267 //!start timer..
2269
2270 } break;
2271 case 'A':
2272 {
2273
2274 SerialDebug.println("cmd=A stopTimer");
2275
2276 //!start timer..
2278
2279 } break;
2280 case 'j':
2281 {
2282 sendToStepperModule = true;
2283 SerialLots.println("Setting FeedState = JACKPOT_FEED");
2285
2286 } break;
2287 case 'u':
2288 {
2289 SerialDebug.println("Setting feederType = UNO");
2291
2292 //!Issue #332 8.17.2024
2294 //! set autoRotoate as well..
2296 //! default to clockwise == 0
2297 //! 8.18.24 setting this will check for the factory setting..
2299 } break;
2300 case 'm':
2301 {
2302 SerialDebug.println("Setting feederType = MINI");
2303 //save preference
2305 //!Issue #332 8.17.2024
2307 // turn clockwise..
2308 //! 8.18.24 setting this will check for the factory setting..
2310 } break;
2311 case 'L':
2312 {
2313 SerialDebug.println("Setting feederType = Tumbler");
2314 //save preference
2316 //!Issue #332 8.17.2024
2318 //! set autoRotoate as well..
2320 //! set autoRotoate as well..
2321 //! 8.18.24 setting this will check for the factory setting..
2322 //setClockwiseMotorDirection_mainModule(true);
2323 } break;
2324 case 'B':
2325 {
2326 sendToStepperModule = true;
2327 SerialDebug.println("Setting buzzStatus = BUZZON");
2328 //save pref
2330 } break;
2331 case 'b':
2332 {
2333 sendToStepperModule = true;
2334
2335 SerialDebug.println("Setting buzzStatus = BUZZOFF");
2337 } break;
2338 case 'T':
2339 {
2340 SerialDebug.println("*** Setting tilt = ON");
2342 } break;
2343 case 't':
2344 {
2345 SerialDebug.println("Setting tilt = OFF");
2347 } break;
2348 case 'R':
2349 {
2350 SerialDebug.println("Clean Credentials");
2351 //! dispatches a call to the command specified. This is run on the next loop()
2353 } break;
2354 //!6.20.25
2355#ifdef NOT_SUPPORTED_RIGHT_NOW
2356 case 'O':
2357 {
2358 SerialDebug.println("OTA Update.. ");
2359 //! dispatches a call to the command specified. This is run on the next loop()
2361 } break;
2362#endif
2363 case 'X':
2364 {
2365 SerialDebug.println("Clean EPROM.. ");
2366 //! dispatches a call to the command specified. This is run on the next loop()
2368 } break;
2369 case 'x':
2370 {
2371 SerialDebug.println("Clean SSID from EPROM.. ");
2372 char cleanWIFI[100];
2373 strcpy(cleanWIFI,"{'ssid':'','ssidPassword':''}");
2374 SerialDebug.println(cleanWIFI);
2375 //! 8.16.25 MQTT
2376 //! send to ourself
2377 sendMessageNoChangeMQTT((char*)cleanWIFI);
2378
2379 } break;
2380
2381 //!NOTE: the gateway is auto selected for now. A future version might manually set it in other situations (eg. my iPhone app should have a flag to not be a gateway at time)
2382 case 'G':
2383 {
2384 SerialDebug.println("Setting Gateway = ON");
2386 } break;
2387 case 'g':
2388 {
2389 SerialDebug.println("Setting Gateway = OFF");
2391 } break;
2392 case '_':
2393 {
2394 //This is from the handshake like "_BLEClient_ESP_M5"
2395 SerialDebug.println("unused cmd '_'");
2396 } break;
2397#ifdef OLD_FOR_M5_DISPLAY
2398 case 'Z':
2399 {
2400 sendToStepperModule = false;
2401
2402 SerialDebug.println("Setting SM Zoom = zoomed");
2404 } break;
2405 case 'z':
2406 {
2407 sendToStepperModule = false;
2408
2409 SerialDebug.println("Setting SM Zoom = full SM");
2411 } break;
2412#else
2413 //! 7.25.25 chilly morning, Mt starting to come out.
2414 //! SPIFF
2415 case 'Z':
2416 {
2417 //! clean SPIFF file"
2418
2419 SerialDebug.println("clean SPIFF file");
2421 } break;
2422 case 'z':
2423 {
2424 //! upload SPIFF to web
2425
2426 SerialDebug.println("upload SPIFF to web");
2427 //! number of lines to send
2428 //! TODO: configure thie number of lines to save..
2430 } break;
2431#endif
2432 case 'P':
2433 {
2434 //printout the spiff.. to the serial debug monitor
2435 //!Restarts (or attempts) a restart of the WIFI using the existing credentials -- vs the 'n' command
2437 } break;
2438 //! 7.24.25 use SPIFF
2439 case 'S':
2440 {
2441 //! toggle spiff on/off
2443 spiffFlag = !spiffFlag;
2444
2445 SerialDebug.printf("Changing current USE_SPIFF = %s\n", spiffFlag?"NOYES":"NO");
2447
2448 // reboot
2450
2451 }
2452 //! WIFI credential changes...
2453 case 'N':
2454 {
2455 //NOTE: this might be where we toggle credentials?? TODO
2456 //found other one..
2457 char *credentials = main_JSONStringForWIFICredentials();
2458
2459 //!These are the ASYNC_CALL_PARAMETERS_MAX
2461 } break;
2462 case 'n':
2463 {
2464 //!NOTE: this is almost the same as 'w' except there might be more WIFI than 2 (so swap is different).
2466 } break;
2467 case 'W':
2468 {
2470 } break;
2471 case 'w':
2472 {
2473 SerialDebug.println("w for swapWifi");
2474
2476 } break;
2477
2478 //! 8.16.24 per #332
2479 case 'H':
2480 {
2481 SerialDebug.printf("PREFERENCE_STEPPER_AUTO_MOTOR_DIRECTION_SETTING true");
2482
2483 // autoMotorDirection ON
2485
2486 } break;
2487 //! 8.16.24 per #332
2488
2489 case 'h':
2490 {
2491 SerialDebug.printf("PREFERENCE_STEPPER_AUTO_MOTOR_DIRECTION_SETTING false");
2492
2493 // autoMotorDirection off
2495 } break;
2496 case 'D':
2497 {
2498 SerialDebug.printf("PREFERENCE_STEPPER_CLOCKWISE_MOTOR_DIRECTION_SETTING counter clockwise");
2499
2500 //!NOTE: no current mode to specify CCW or CW dynamically (non factory reset)
2501 // motor direction = counterclockwise
2503 } break;
2504 case 'd':
2505 {
2506 SerialDebug.printf("PREFERENCE_STEPPER_CLOCKWISE_MOTOR_DIRECTION_SETTING clockwise");
2507
2508 // motor direction == (clockwise)
2510 } break;
2511 //! 9.30.23 reverse direction
2512 case 'Q':
2513 {
2514 SerialDebug.printf("PREFERENCE_STEPPER_CLOCKWISE_MOTOR_DIRECTION_SETTING reverse direction");
2515
2516 //! note: reboot not needed as the next time a feed happens, it reads this value
2517 // motor direction == (reverse)
2519 currentDirection = !currentDirection;
2521
2522 } break;
2523 case 'E':
2524 {
2525 SerialDebug.printf("PREFERENCE_BLE_SERVER_USE_DEVICE_NAME_SETTING false");
2526
2527 //!if set, the BLE Server (like PTFeeder) will tack on the device name (or none if not defined).
2529 // reboot
2531 } break;
2532 case 'e':
2533 {
2534 SerialDebug.printf("PREFERENCE_BLE_SERVER_USE_DEVICE_NAME_SETTING true");
2535
2536 //!if set, the BLE Server (like PTFeeder) will tack on the device name (or none if not defined).
2538 // reboot
2540 } break;
2541 case 'r':
2542 {
2543 // reboot
2544 SerialDebug.println("REBOOT ...");
2546 } break;
2547
2548 case 'p':
2549 {
2550 //! poweroff
2551 SerialDebug.printf("(%c) POWEROFF ...", cmd);
2553 } break;
2554 //! 7.12.25
2555 //! 0 == Clear SENSOR definitions
2556 case '0':
2557 {
2558 //! poweroff
2559 SerialDebug.println("Clearing Sensors");
2560 setSensorsString_mainModule((char*)"");
2561
2562 //! reboot .. so the sensors are set..
2564 } break;
2565 //! 7.9.25
2566 //! 1 == Init SENSOR definitions
2567 case '1':
2568 {
2569 //! poweroff
2570 SerialDebug.println("Default L9110S_DCStepperClass");
2571 //resetSensorToDefault_mainModule();
2572 //! 7.30.25 changing to the HDriver's board
2573 setSensorsString_mainModule((char*)"BuzzerSensorClass,19,22,L9110S_DCStepperClass,21,25");
2574 //! 7.31.25 if Scanner or QR then pin 22 used .. so make M5HDriver (basically don't have a sensor)
2576 //! also specify the sensor plug
2578 //! 1 second motor (overloads "angle" field)
2580 //! set tumbler
2582 //! set autoRotoate as well..
2584 //! tumbler
2586
2587 //! reboot .. so the sensors are set..
2589 } break;
2590 //! 7.12.25
2591 //! 2 == default for SMART Button
2592 case '2':
2593 {
2594 /*
2595 #define IN1 22
2596 #define IN2 19
2597 #define IN3 23
2598 #define IN4 33
2599 */
2600 //! poweroff
2601 SerialDebug.println("Default ULN2003_StepperClass");
2602 //resetSensorToDefault_mainModule();
2603 //! 7.30.25 changing to the HDriver's board
2604 setSensorsString_mainModule((char*)"BuzzerSensorClass,21,25,ULN2003_StepperClass,23,33");
2605 //! 7.31.25 if Scanner or QR then pin 22 used .. so make M5HDriver (basically don't have a sensor)
2607 //! also specify the sensor plug
2609 //! 1 second motor (overloads "angle" field)
2610 //! This is the RPM speed
2612 //! @see #390 this is the RPM of the stepper
2614 //! set autoRotoate as well..
2616 //! tumbler
2618
2619 //! reboot .. so the sensors are set..
2621 } break;
2622 //! 7.19.25 add Clear Sensors
2623 case '3':
2624 {
2625
2626 //! poweroff
2627 SerialDebug.println("Default PTStepperClass");
2628 //resetSensorToDefault_mainModule();
2629 //! 7.30.25 changing to the HDriver's board
2630 setSensorsString_mainModule((char*)"BuzzerSensorClass,21,25,PTStepperClass,23,33");
2631 //! 7.31.25 if Scanner or QR then pin 22 used .. so make M5HDriver (basically don't have a sensor)
2633 //! also specify the sensor plug
2635 //! for Tumbler .. use 200
2637 //! @see #390 this is the RPM of the stepper
2638 //savePreferenceFloat_mainModule(PREFERENCE_STEPPER_RPM_SETTING, 15.0);
2639 //! set autoRotoate as well..
2641 //! tumbler
2643
2644 //! reboot .. so the sensors are set..
2646 } break;
2647 //! 7.19.25 BLE Client ON
2648 case '4':
2649 {
2650 //! poweroff
2651 SerialDebug.println("Default M5AtomCamera");
2652 //resetSensorToDefault_mainModule();
2653 //! 7.30.25 changing to the HDriver's board
2654 setSensorsString_mainModule((char*)"");
2655 //! 7.31.25 if Scanner or QR then pin 22 used .. so make M5HDriver (basically don't have a sensor)
2657 //! also specify the sensor plug
2659
2660 //! reboot .. so the sensors are set..
2662 } break;
2663 //! 7.9.25 grabbed from BOOTSTRAP let someone update the atom to the recent OTA
2664 case '5':
2665 {
2666 SerialDebug.println(" *** performing m5atom OTA Update");
2667 //! 8.16.25 MQTT
2668 //!retrieves from constant location
2669 performOTAUpdate((char*)"http://KnowledgeShark.org", (char*)"OTA/TEST/M5Atom/ESP_IOT.ino.m5stick_c_plus.bin");
2670 } break;
2671 //! 7.9.25 grabbed from BOOTSTRAP let someone update the atom to the recent OTA
2672 case '6':
2673 {
2674 SerialDebug.println(" *** performing m5atom OTA Update - DAILY");
2675 //! 8.16.25 MQTT
2676 //!retrieves from constant location
2677 performOTAUpdate((char*)"http://KnowledgeShark.org", (char*)"OTA/TEST/M5Atom/daily/ESP_IOT.ino.m5stick_c_plus.bin");
2678 } break;
2679 case '7':
2680 {
2681 SerialDebug.println(" *** performing m5atom OTA Update - BOOTSTRAP");
2682 //! 8.16.25 MQTT
2683 //!retrieves from constant location
2684 performOTAUpdate((char*)"http://KnowledgeShark.org", (char*)"OTA/Bootstrap/ESP_M5_BOOTSTRAP.ino.m5stack_stickc_plus.bin");
2685 } break;
2686 //! 8.18.25
2687 case '8':
2688 {
2689 //!
2690 SerialDebug.println("Default M5AtomTinyGPS");
2691 //resetSensorToDefault_mainModule();
2692 //! 7.30.25 changing to the HDriver's board
2693 setSensorsString_mainModule((char*)"");
2694 //! 7.31.25 if Scanner or QR then pin 22 used .. so make M5HDriver (basically don't have a sensor)
2696 //! also specify the sensor plug
2698
2699 //! reboot .. so the sensors are set..
2701 } break;
2702 case '9':
2703 {
2704 //! 8.18.25 M5Clicker
2705 SerialDebug.println(" *** performing m5atom OTA Update - M5Clicker");
2706 //! 8.16.25 MQTT
2707 //!retrieves from constant location
2708 performOTAUpdate((char*)"http://KnowledgeShark.org", (char*)"OTA/Bootstrap/ESP_M5_BOOTSTRAP.ino.m5stack_stickc_plus.bin");
2709 } break;
2710 case 'C':
2711 {
2712 SerialDebug.println("'C' change color touched");
2713#ifdef USE_FAST_LED
2714 CRGB randomColor = getRandomColor();
2715 fillpix(randomColor);
2716 delay(50);
2717#endif
2718 }
2719 break;
2720 case 'i':
2721 {
2722 char sendCapture[100];
2723 strcpy(sendCapture,"{'send':'capture'}");
2724 SerialDebug.println(sendCapture);
2725 //! 8.16.25 MQTT
2726 //! send to ourself
2727 sendMessageNoChangeMQTT((char*)sendCapture);
2728
2729 }
2730 break;
2731 case '.':
2732 {
2733
2734 //! returns if the BLEClient is turned on.. note, if connected to a BLE device, then disconnect
2735
2737 //! toggle spiff on/off
2739
2740 SerialMin.println("Valid Commands: ");
2741 SerialMin.println(" . = help, this message");
2742 SerialMin.println(" p = poweroff if can");
2743 SerialMin.println(" 0x0, s, c == Single Feed ");
2744 SerialMin.println(" a == AutoFeed On");
2745 SerialMin.println(" A == AutoFeed Off");
2746 SerialMin.println(" u == UNO ");
2747 SerialMin.println(" m == MINI ");
2748 SerialMin.println(" L == tumbler");
2749 SerialMin.println(" H == autoMotorDirection on");
2750 SerialMin.println(" h == autoMotorDirection off");
2751 SerialMin.println(" D == FACTORY counter clockwise motor direction");
2752 SerialMin.println(" d == FACTORY clockwise motor direction");
2753 SerialMin.println(" Q == change motor direction opposite of current");
2754
2755 SerialMin.println(" B == Buzzer On");
2756 SerialMin.println(" b == Buzzer Off");
2757 SerialMin.println(" G == Gateway On");
2758 SerialMin.println(" g == Gateway Off");
2759 SerialMin.println(" R == clean credentials");
2760 SerialMin.println(" X == clean EPROM");
2761 SerialMin.println(" x == clean SSID from EPROM");
2762 SerialMin.println(" r == reboot ");
2763 //!6.20.25
2764
2765 SerialMin.println(" T == tiltOn");
2766 SerialMin.println(" t == tiltOff");
2767 SerialMin.println(" N == send WIFI Credential to BLEServer");
2768 SerialMin.println(" n == next WIFI Credential");
2769 SerialMin.println(" W == retry WIFI");
2770 SerialMin.println(" w == swap WIFI");
2771 SerialMin.println(" C == change m5 atom to random color");
2772 SerialMin.println(" i == take pic, {send:capture}");
2773
2774 SerialMin.println(" SPIFF internal memory ");
2775#ifndef OLD_FOR_M5_DISPLAY
2776 SerialMin.println(" Z == clean SPIFF file");
2777 SerialMin.println(" z == upload SPIFF to web");
2778#endif
2779 SerialMin.println(" P == print SPIFF");
2780 SerialMin.printf (" S == toggle SPIFF %s\n", spiffFlag?"OFF":"ON");
2781
2782 SerialMin.println(" BLE Naming ");
2783
2784 SerialMin.println(" E == use only PTFeeder naming");
2785 SerialMin.println(" e == use naming PTFeeder:name");
2786#ifdef OLD_FOR_M5_DISPLAY
2787 SerialMin.println(" Z == Setting SM Zoom = zoomed");
2788 SerialMin.println(" z == Setting SM Zoom = full SM");
2789#endif
2790 SerialMin.println(" Configurations of M5Atom ");
2791
2792 SerialMin.println(" 0 == no sensors");
2793 SerialMin.println(" 1 == L9100S_DCStepper (current main)");
2794 SerialMin.println(" 2 == ULN2002 Stepper (new test 8.13.25)");
2795 SerialMin.println(" 3 == *** PTStepperClass (original code - with M5");
2796 SerialMin.printf (" 4 == M5AtomCamera\n");
2797 SerialMin.println(" 8 == M5TinyGPS");
2798
2799#ifdef NOT_SUPPORTED_RIGHT_NOW
2800 SerialMin.println(" O == OTA update");
2801#else
2802 SerialMin.println(" OTA Updates of M5Atom ");
2803 SerialMin.println(" 5 == m5atom DEV OTA update");
2804 SerialMin.println(" 6 == m5atom DAILY TEST DEV OTA update");
2805 SerialMin.println(" 7 == go back to m5atom BOOTSTRAP");
2806
2807#endif
2808 SerialMin.println();
2809 SerialMin.println("Full API at: https://github.com/konacurrents/SemanticMarkerAPI");
2810 SerialMin.println();
2811
2812 //!print out stuff
2814
2815 } break;
2816 break;
2817 default:
2818
2819 {
2820 SerialMin.printf("*****invalid command '%c' from client (use '.' for help) *****\n", cmd);
2821 }
2822 }
2823
2824#ifdef USE_STEPPER_MODULE
2825 if (sendToStepperModule)
2826 {
2828 }
2829#endif
2830}
2831
2832
2833//!On the esp32, sec is all we can handle. We can return as a double if milisecond resolution is needed.
2834//!This is the time since app started..
2835//!https://randomnerdtutorials.com/epoch-unix-time-esp32-arduino/
2837{
2838
2839 time_t now;
2840 struct tm timeinfo;
2841 time(&now);
2842 //! 7.27.25
2843 //! miliseconds .. convert to seconds
2844 //now = now * 1000;
2845 SerialMin.printf("Unix Time: %d\n", now);
2846 return now;
2847}
2848
2849//! ************** SM Mode Processing ***************
2850
2851
2852//!returns an index from 0..max of SM matching cmd, or -1 if none
2854{
2855#ifdef ESP_M5
2856 //https://www.cplusplus.com/reference/cstring
2857 if (strncmp(cmd,"sm",2) == 0)
2858 {
2859 //point to the 'm' in 'sm'
2860 char *p = strchr(cmd,'m');
2861 //then increment
2862 p++;
2863 //convert to a number
2864 int num = atoi(p);
2865 //convert to integer..
2866 SerialLots.print("whichSMMode: ");
2867 SerialLots.print(cmd);
2868 SerialLots.print(" => " );
2869 SerialLots.println(num);
2870 return num;
2871 }
2872 else
2873#endif //ESP_M5
2874 {
2875 return -1;
2876 }
2877}
2878//!returns if a match the mode. whichSMMode is 0..12 and == sm0 .. smn
2879boolean matchesSMMode_mainModule(char *cmd, int whichSMMode)
2880{
2881 char *mode = charSMMode_mainModule(whichSMMode);
2882 return (strcasecmp(cmd,mode)==0);
2883}
2884//!returns string form whichSMMode, sg "sm0", sm1 ...
2885//!This can (and is) called by multiple places (like ButtonProcessing and MainModule
2886char* charSMMode_mainModule(int whichSMMode)
2887{
2888 SerialLots.printf("charSMMode_mainModule: %d\n", whichSMMode);
2889
2890 sprintf(_smMode_MainModule,"sm%0d",whichSMMode);
2891 SerialCall.println(_smMode_MainModule);
2892 return _smMode_MainModule;
2893}
2894
2895//!returns which mode in (min or expanded)
2897{
2899}
2900
2901//!toggles the menu mode
2903{
2905}
2906
2907//! returns the current max of the MIN menu modes (using the setting of min or expanded) to determine
2909{
2910 return MAX_SM_MIN_MODES;
2911}
2912
2913//! returns the current max of the menu modes (using the setting of min or expanded) to determine
2915{
2916 SerialLots.printf("maxMenuModes_mainModule: %s, %d, %d\n", isMinimalMenuMode_mainModule?"1":"0", MAX_SM_MIN_MODES, MAX_SM_EXPANDED_MODES);
2918 return MAX_SM_MIN_MODES;
2919 else
2920 return MAX_SM_EXPANDED_MODES;
2921}
2922
2923//!the saved SMMode
2925//!sets the current screen mode .. which can be used by Button and Display processing
2926void setCurrentSMMode_mainModule(int whichSMMode)
2927{
2928 SerialLots.print("setCurrentSMMode_mainModule:");
2929 SerialLots.println(whichSMMode);
2930
2931 // This version sets the MIN OR MAX
2932 if (whichSMMode >= MAX_SM_MIN_MODES)
2933 {
2934 // change to EXPANDED MODES
2936 }
2937 _saveWhichSMMode = whichSMMode;
2938}
2939//!returns the current SM Mode
2941{
2942 return _saveWhichSMMode;
2943}
2944
2945//!increment the currentSMMode, wrapping and using the max menu
2947{
2949 int max = maxMenuModes_mainModule();
2950 if (_saveWhichSMMode >= max)
2951 {
2952 _saveWhichSMMode = 0;
2953 }
2954 SerialTemp.print("incrementSMMode_mainModule:");
2955 SerialTemp.println(_saveWhichSMMode);
2956}
2957//!increment the currentSMMode, wrapping and using the max menu
2959{
2960 if (_saveWhichSMMode > 0)
2961 {
2963 }
2964}
2965
2966//!full: ""Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
2968{
2969 //! 8.16.25 BLE CLIENT
2971 return _fullBLEDeviceName;
2972 else
2973 {
2974 return (char*)"";
2975 }
2976}
2977
2978//!whether connected GEN3
2979boolean _connecteBLEisGEN3 = false;
2980//!whether the connected is a GEN3 (so the name isn't valid)
2982{
2983 return _connecteBLEisGEN3;
2984}
2985
2986//! BLE Discovery Methods
2987//! Connected to a BLE device with the advertised name. The syntax can include (PTFeeder:NAME) or just PTFeeder
2988//! Being disconnected is already a flag isConnectedBLE ...
2989void setConnectedBLEDevice_mainModule(char *deviceName, boolean isGEN3)
2990{
2991 //!set the isGEN3 flag
2992 _connecteBLEisGEN3 = isGEN3;
2993 //!now set the gateway based on if GEN3
2994 SerialTemp.printf("auto-settingGateway(%d)\n", isGEN3);
2996
2997 strcpy(_fullBLEDeviceName, deviceName);
2998
2999 //!seems device name = "Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead
3000 //!Note: the Address, eg "7c:9e:bd:48:af:92" is unique somehow.. lets use that to skip one..
3001 SerialCall.printf("setConnectedBLEDevice_mainModule: %s\n", deviceName);
3002 strcpy(_connectedBLEDeviceName,"");
3003
3004 if (containsSubstring(deviceName,"PTFeeder:") || containsSubstring(deviceName,"PTClicker:"))
3005 {
3006 //!parse out the 2nd half of name
3007 char *colon = index(deviceName,':');
3008 colon++;
3009 colon = index(colon,':');
3010 //! go past the :
3011 colon++;
3012
3013 while (*colon && *colon != ',')
3014 {
3015 int len = strlen(_connectedBLEDeviceName);
3016 _connectedBLEDeviceName[len] = colon[0];
3017 _connectedBLEDeviceName[len+1] = '\0';
3018 colon++;
3019 }
3020 }
3021 else
3022 {
3023 //! empty name (just PTFeeder)
3024 strcpy(_connectedBLEDeviceName,(char*)"");
3025 }
3026 SerialTemp.print("connectedBLEName= ");
3027 SerialTemp.println(_connectedBLEDeviceName);
3028
3029 //! 8.29.23 send a message saying we connected..
3030#ifdef LATER
3031 seems to be crashing..
3032 {
3033 char connectMessage[300];
3034 sprintf(connectMessage,"#connectedBLE {%s to %s}", getDeviceNameMQTT(), _connectedBLEDeviceName);
3035 SerialTemp.println(connectMessage);
3036 //sendSemanticMarkerDocFollow_mainModule(&fileURL[0]);
3037 //! for now only send if it start message starts with "#"
3038 publishMQTTMessageDefaultTopic(connectMessage);
3039 }
3040#endif
3041 //!parse for the address too..
3042 //! strcpy(_fullBLEDeviceName, deviceName);
3043
3044 //!seems device name = "Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead
3045 //!Note: the Address, eg "7c:9e:bd:48:af:92" is unique somehow.. lets use that to skip one..
3046 strcpy(_connectedBLEDeviceAddress,"");
3047 if (containsSubstring(_fullBLEDeviceName,"Address:"))
3048 {
3049 //!parse out the 2nd half of name
3050 char *colon = strstr(_fullBLEDeviceName,"Address:");
3051 colon += strlen("Address:");
3052 //strip spaces
3053 while (*colon && *colon == ' ')
3054 {
3055 colon++;
3056 }
3057 //now until the , is the address
3058 while (*colon && *colon != ',')
3059 {
3060 int len = strlen(_connectedBLEDeviceAddress);
3061 _connectedBLEDeviceAddress[len] = colon[0];
3062 _connectedBLEDeviceAddress[len+1] = '\0';
3063 colon++;
3064 }
3065 }
3066 else
3067 {
3068 //! empty name (just PTFeeder)
3069 strcpy(_connectedBLEDeviceAddress,(char*)"");
3070 }
3071 SerialTemp.print("_connectedBLEDeviceAddress= ");
3072 SerialTemp.println(_connectedBLEDeviceAddress);
3073}
3074
3075//!ISSUE: if BLE, can only return the address.. it's up to the caller to know it might not match the Paired Name (eg DukeGEN3)
3076//! returns the connected BLE Device name (the :NAME of advertisment, Address: 01:39:3f:33 part of name
3078{
3079 char *nameToUse;
3080 if (strlen(_connectedBLEDeviceName)!= 0)
3081 nameToUse = _connectedBLEDeviceName;
3082 else if (strlen(_connectedBLEDeviceAddress)!= 0)
3083 nameToUse =_connectedBLEDeviceAddress;
3084 else
3085 nameToUse = (char*)"";
3086
3087 //! 8.16.25 BLE CLIENT
3088
3089 //! if connected, return the connected name, otherwise return empty string
3091 {
3092 return nameToUse;
3093 }
3094 else
3095 {
3096 return (char*)"";
3097 }
3098}
3099
3100//!returns address part of name.
3102{
3103 //! 8.16.25 BLE CLIENT
3104
3105 //! if connected, return the connected name, otherwise return empty string
3107 {
3109 }
3110 else
3111 {
3112 return (char*)"";
3113 }
3114}
3115
3116//! 6.6.25 get the current M5AtomClassType
3118{
3119 return _whichM5AtomClassType;
3120}
3121
3122//! 1.22.24 add setup and loop at main so it can call appropriate plugs
3124{
3125#ifdef USE_BUTTON_MODULE
3126 //! the model part of the MVC for buttons
3127 loop_ButtonProcessing();
3128#endif
3129
3130 //! these are the plugin modules .. and only 1 active at a time except for ATOM
3131#ifdef M5CORE2_MODULE
3133#elif defined(M5_ATOM)
3134
3135#pragma mark USE_NEW_M5ATOMCLASS
3136 //! 5.6.25 use object version
3138 {
3139 SerialCall.printf("*** _whichM5AtomClassType %s\n",_whichM5AtomClassType->classIdentity() );
3141 }
3142 else
3143 {
3144 SerialDebug.println("*** _whichM5AtomClassType NULL ***");
3145
3146 }
3147
3148 // end atom
3149
3150#elif defined(M5BUTTON_MODULE)
3151 loop_M5ButtonModule();
3152#endif
3153}
3154
3155//! 1.22.24 setup of buttons
3157{
3158 SerialDebug.println("setup_Sensors_mainModule");
3159#ifdef USE_BUTTON_MODULE
3160 //! the model part of the MVC for buttons
3161 setup_ButtonProcessing();
3162#endif
3163 //! these are the plugin modules .. and only 1 active at a time except for ATOM
3164#ifdef M5_ATOM
3165 SerialDebug.println(" ***** M5_ATOM define ****");
3166#endif
3167#ifdef M5CORE2_MODULE
3169#endif
3170
3171#ifdef M5_ATOM
3172
3173 //! 5.6.25 use the M5Atom ClassType
3174#ifdef USE_NEW_M5ATOMCLASS
3175 //! @see https://www.cs.fsu.edu/~myers/cop3330/notes/dma.html
3176 _M5Atom_SocketModuleClass = new M5Atom_SocketModuleClass((char*)"M5AtomSocket");
3177 _M5Atom_QRCodeModuleClass = new M5Atom_QRCodeModuleClass((char*)"M5AtomScanner");
3178 _M5Atom_HDriverModuleClass = new M5Atom_HDriverModuleClass((char*)"M5HDriver");
3179 //! 7.17.25
3180 _M5Atom_TinyGPSModuleClass = new M5Atom_TinyGPSModuleClass((char*)"M5AtomTinyGPS");
3181 //! 8.16.25 bring in the Camera
3182 _M5Atom_CameraModuleClass = new M5Atom_CameraModuleClass((char*)"M5AtomCamera");
3183
3184 int whichM5AtomIndex = 0;
3185 SerialDebug.println("setup_M5Atoms");
3186
3187 //! 3.31.25 create array of plugs
3188 _M5AtomClassTypes[whichM5AtomIndex++] = _M5Atom_SocketModuleClass;
3189 _M5AtomClassTypes[whichM5AtomIndex++] = _M5Atom_QRCodeModuleClass;
3190 _M5AtomClassTypes[whichM5AtomIndex++] = _M5Atom_HDriverModuleClass;
3191 //! 7.17.25
3192 _M5AtomClassTypes[whichM5AtomIndex++] = _M5Atom_TinyGPSModuleClass;
3193 //! 8.16.25 bring in the Camera
3194 _M5AtomClassTypes[whichM5AtomIndex++] = _M5Atom_CameraModuleClass;
3195
3196 //! add check..
3197 if (whichM5AtomIndex > NUM_M5ATOM_CLASS)
3198 {
3199 SerialDebug.printf("**** sensors are more than max .. FIX CODE");
3200 }
3201 SerialDebug.printf("Created %d M5AtomClassTypes\n", whichM5AtomIndex);
3202
3203
3204 //! use this one...
3205 _whichM5AtomClassType = NULL;
3206 //! find the current atomKind. which is a string
3207 char *atomKind = getPreferenceATOMKind_MainModule();
3208
3209 //! find which one..
3210 for (int i=0; i<NUM_M5ATOM_CLASS; i++)
3211 {
3212 if (!_M5AtomClassTypes[i])
3213 {
3214 SerialDebug.println("NULL M5AtomClassType");
3215 continue;
3216 }
3217 //! check against the identity.. (or make this part of that method?)
3218 if (strcmp(_M5AtomClassTypes[i]->classIdentity(), atomKind) == 0)
3219 {
3220 //! Matched..
3222 break;
3223 }
3224 }
3226 {
3227 SerialDebug.printf("** Found M5AtomClass = %s\n", atomKind);
3228 }
3229 else
3230 {
3231 SerialDebug.printf("****^^^ Cannot find M5AtomClass = %s\n", atomKind);
3232
3233 SerialDebug.println("Defaulting to _M5Atom_HDriverModuleClass");
3235 }
3236#else
3237 SerialDebug.printf("M5AtomKind = %d\n", getM5ATOMKind_MainModule());
3238#endif
3239
3240 //! now the setup() call
3241#pragma mark USE_NEW_M5ATOMCLASS
3242 //! 5.6.25 use object version
3245
3246 // end atom
3247
3248#elif defined(M5BUTTON_MODULE)
3249 setup_M5ButtonModule();
3250#endif
3251}
3252//! BUTTON PROCESSING abstraction
3253//!short press on buttonA (top button)
3255{
3256#ifdef USE_BUTTON_MODULE
3257 buttonA_ShortPress();
3258#endif
3259#ifdef M5CORE2_MODULE
3261#elif defined(M5_ATOM)
3262#pragma mark USE_NEW_M5ATOMCLASS
3263 //! 5.6.25 use object version
3266
3267#elif defined(M5BUTTON_MODULE)
3268 buttonA_ShortPress_M5ButtonModule();
3269#endif
3270
3271}
3272
3273//!long press on buttonA (top button)
3275{
3276#ifdef USE_BUTTON_MODULE
3277 buttonA_LongPress();
3278#endif
3279#ifdef M5CORE2_MODULE
3281#elif defined(M5_ATOM)
3282
3283#pragma mark USE_NEW_M5ATOMCLASS
3284 //! 5.6.25 use object version
3287
3288
3289#elif defined(M5BUTTON_MODULE)
3290 buttonA_LongPress_M5ButtonModule();
3291#endif
3292}
3293
3294
3295//!the long press of the side button
3297{
3298#ifdef USE_BUTTON_MODULE
3299 buttonB_LongPress();
3300#endif
3301#ifdef M5BUTTON_MODULE
3302 //!the long press of the side button
3303 buttonB_LongPress_M5ButtonModule();
3304#endif
3305}
3306//!the short press of the side button
3308{
3309#ifdef USE_BUTTON_MODULE
3310 buttonB_ShortPress();
3311#endif
3312
3313#ifdef M5BUTTON_MODULE
3314 //!the long press of the side button
3315 buttonB_ShortPress_M5ButtonModule();
3316#endif
3317}
3318
3319//!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
3321{
3322 //!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
3324}
3325
3326//! 1.1.24 send status of this device after events..
3328{
3329 //On demand #STATUS send the statusURL as well (if an M5)
3330 //this queues the sending of the StatusURL over MQTT.
3331 // This is async (next loop) since sending 2 MQTT messages can be hard to do in a row ..
3333}
3334
3335//! 3.23.25 rainy weekend
3336//! create a JSON string from the SemanticMarker
3337//! https://semanticmarker.org/bot/setdevice/scott@konacurrents.com/PASS/M5AtomSocket/socket/on}
3338//! Create a JSON knowing the "bot" syntax, eg. setdevice/USER/PASS/device/<set>/<flag>
3339//! defined in TokenParser.h
3340char *semanticMarkerToJSON_mainModule(char* semanticMarker)
3341{
3342 return semanticMarkerToJSON_TokenParser(semanticMarker);
3343}
3344
3345#pragma mark PIN USE to see if overlaps.
3346//! 7.31.25 add this for a status, saw that QRCode was using 22 also .. so buzer didn't work.
3347/**
3348#define PIN_USE_MAX 10
3349struct pinUseStruct {
3350 int pinUseCount;
3351 char *pinUseArray[PIN_USE_MAX];
3352} _pinUseStruct;
3353*/
3354
3355//! global for use
3357//! get the pin use array
3359{
3360 return _pinUseStruct;
3361}
3362
3363//! 7.31.25 store this information.. for STATUS
3364//! 5.3.25 add a central clearing house for defining PIN use
3365//! @see issue #365
3366//! central clearing house for all pins used to we can analyze if there are overlaps
3367//! pin is the actual number, pinName is the local name (eg. IN1_PIN or VIN_PIN).
3368//! moduleName is the module in the code,
3369//! isI2C is whether this is a I2C bus (which we aren't using much yet)
3370void registerPinUse_mainModule(long pin, String pinName, String moduleName, boolean isI2C)
3371{
3372 char pinUseSample[100];
3373 sprintf(pinUseSample,"PIN_USE: %2d = %s, %s %s", pin, pinName.c_str(), moduleName.c_str(), isI2C?"(I2C)":"");
3374 //! 5.3.25 create storage here
3375 char *pinUse = (char*)calloc(strlen(pinUseSample)+1, sizeof(char));
3376 strcpy(pinUse, pinUseSample);
3377 //!store globally
3379 //! increment
3381
3383 {
3384 SerialError.printf("*** ERROR .. too many PINS defined ***");
3386
3387 }
3388
3389 SerialDebug.printf("** PIN_USE: %s = %d, module=%s %s\n", pinName.c_str(), pin, moduleName.c_str(), isI2C?"(I2C)":"");
3390}
void sendCommandBLEClient(String cmdString)
boolean isConnectedBLEClient()
returns whether connected over BLE as a client to a server(like a ESP feeder)
void sendFeedCommandBLEClient()
sends the "feed" command over bluetooth to the connected device..
boolean useBLEClient()
returns if the BLEClient is turned on.. note, if connected to a BLE device, then disconnect
void sendCommandBLEClient_13orLess(String cmdString)
send a string of 13 characters or less
void sendBLEMessageACKMessage()
send ACK over bluetooth, this right now is 0x01
char * getServiceName_BLEServerNetworking()
retrieve the service name (PTFEEDER, PTFeeder:Name, PTClicker:Name, etc)
#define BLE_SERVER_CALLBACK_ONWRITE
void addToTextMessages_displayModule(String text)
void redrawSemanticMarker_displayModule(boolean startNew)
redraws the Semantic Marker image..
void blankScreen_displayModule()
blanks the screen
int getLoopTimer_displayModule()
returns the loop timer (just a timer..)
#define KEEP_SAME
Definition: DisplayModule.h:54
void setup_M5Core2Module()
void loop_M5Core2Module()
called for the loop() of this plugin
char * currentStatusJSON_M5Core2Module()
void messageSend_M5Core2Module(char *sendValue)
void messageSetVal_M5Core2Module(char *setName, char *valValue, boolean deviceNameSpecified)
void buttonA_ShortPress_M5Core2Module()
CRGB getRandomColor()
7.24.25 return a (semi) random color
Definition: M5Display.cpp:78
void fillpix(CRGB Color)
color the button light
Definition: M5Display.cpp:65
void publishMQTTMessageDefaultTopic(char *message)
Wrapper of the mqttclient publish.
void cleanEPROM_MQTTNetworking()
cleans the eprom info
void sendMessageNoChangeMQTT_Topic(char *message, char *topic)
just send a message but without any extras
void sendMessageMQTT(char *message)
void sendStatusMessageMQTT(const char *semanticMarker)
sends the semantic marker as a doc follow message #remoteMe (vs STATUS, as that triggers a status rep...
boolean processJSONMessageMQTT(char *ascii, char *topic)
process the JSON message (looking for FEED, etc). Note: topic can be nil, or if not,...
void sendMessageMQTT_Topic(char *message, char *topic)
for now only send if it start message starts with "#"
void sendDocFollowMessageMQTT(const char *semanticMarker)
sends the semantic marker as a doc follow message
void sendMessageNoChangeMQTT(char *message)
just send a message but without any extras
boolean isConnectedMQTT_MQTTState()
value of MQTT connected
@ groupTopic
char * getDeviceNameMQTT()
called for things like the advertisement
boolean isConnectedWIFI_MQTTState()
value of WIFI connected
void restartWIFI_MQTTState()
restart the WIFI and then MQTT connection
#define MQTT_CALLBACK_FEED
8.16.25 MQTT
void cleanEpromPreferences()
cleans the EPROM
Definition: MainModule.cpp:880
void sendSemanticMarkerDocFollow_mainModule(const char *SMDocFollowAddress)
sends the SM on the DOCFOLLOW channel (publish it..)
void initCallbacksMain()
init the callbacks to dummy callbacks
Definition: MainModule.cpp:479
#define MESSAGE_STORAGE_MAX
global for others to use..
Definition: MainModule.cpp:171
char * _MQTT_Username
Definition: MainModule.cpp:982
boolean _connecteBLEisGEN3
whether connected GEN3
void setAsyncCallOTAUpdate(bool flag)
sets the async OTA flag (for next loop)
Definition: MainModule.cpp:788
void main_cleanSavedWIFICredentials()
clean the saved WIFI credential, otherwise the AP mode doesn't work (6.3.22)
Definition: MainModule.cpp:967
void messageSend_mainModule(char *sendValue, boolean deviceNameSpecified)
TODO: have a callback regist approach.
Definition: MainModule.cpp:582
boolean _asyncCallOTAUpdateFlag
3.28.22 .. implemented in ESP_IOT.ino
Definition: MainModule.cpp:781
boolean _stopAllProcessing
testing..
Definition: MainModule.cpp:145
M5Atom_Core2ModuleClass * _M5Atom_Core2ModuleClass
Definition: MainModule.cpp:36
#define CALLBACKS_MQTT
8.16.25 MQTT
Definition: MainModule.cpp:420
void main_updateMQTTInfo(char *ssid, char *ssid_password, char *username, char *password, char *guestPassword, char *deviceName, char *host, char *port, char *locationString)
sets the WIFI and MQTT user/password. It's up to the code (below, maybe in future a register approach...
void setConnectedBLEDevice_mainModule(char *deviceName, boolean isGEN3)
char _fullBLEDeviceName[100]
full: ""Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
Definition: MainModule.cpp:186
#define CALLBACKS_MAX_BLE_SERVER
Definition: MainModule.cpp:437
KeyUnitSensorClass * _KeyUnitSensorClass
Definition: MainModule.cpp:65
char * connectedBLEDeviceNameAddress_mainModule()
returns address part of name.
void cleanSSID_EPROM_MessageCallback(char *message)
clean the SSID eprom (MQTT_CLEAN_SSID_EPROM)
callbackSignature * createMemory(int max)
return dyamically created array of max
Definition: MainModule.cpp:465
void toggleMinimalMenuMode_mainModule()
toggles the menu mode
char * charSMMode_mainModule(int whichSMMode)
returns string form whichSMMode, sg "sm0", sm1 ...
int _thresholdLUXDark
char * main_getUsername()
Definition: MainModule.cpp:988
char * groupTopicFullName(char *groupName)
returns a groupTopic to use as a topic
char * _OFF_LIGHT
char _smMode_MainModule[10]
current smMode
Definition: MainModule.cpp:176
void loop_mainModule()
called for the loop() of this plugin
Definition: MainModule.cpp:278
char * getSemanticMarkerDocFollow_mainModule()
gets the semanticAddress SemanticMarker™
void main_setScannedGroupName(char *groupName)
void registerCallbackMain(int callbacksModuleId, int callbackType, void(*callback)(char *))
register the callback based on the callbackType. use the callbacksModuleId for which one....
Definition: MainModule.cpp:512
#define NUM_M5ATOM_CLASS
Definition: MainModule.cpp:46
M5Atom_HDriverModuleClass * _M5Atom_HDriverModuleClass
Definition: MainModule.cpp:34
char * deviceName_mainModule()
gets the device name
Definition: MainModule.cpp:844
int getLUXThreshold_mainModule(int thresholdKind)
get the threshold val
void dummyCallbackMain(char *message)
example callback
Definition: MainModule.cpp:441
#define CALLBACKS_MAX_MQTT
Definition: MainModule.cpp:434
void initGlobals_mainModule()
init globals strings
Definition: MainModule.cpp:191
void sendStatusMQTT_mainModule()
1.1.24 send status of this device after events..
PinUseStruct _pinUseStruct
7.31.25 add this for a status, saw that QRCode was using 22 also .. so buzer didn't work.
char _deviceNameSave[50]
saved deviceName storage..
Definition: MainModule.cpp:178
void initSensorClassTypeArray()
Definition: MainModule.cpp:70
boolean connectedBLEDeviceIsGEN3_mainModule()
whether the connected is a GEN3 (so the name isn't valid)
char * semanticMarkerToJSON_mainModule(char *semanticMarker)
char * main_currentStatusURL(boolean fullStatus)
int minMenuModesMax_mainModule()
returns the current max of the MIN menu modes (using the setting of min or expanded) to determine
int _thresholdLUXLight
#define CALLBACKS_BLE_SERVER
Definition: MainModule.cpp:423
boolean _asyncCallFlags[ASYNC_CALL_MAX]
storage for asyncCallCommands
void main_setScannedDeviceName(char *deviceName)
set the scanned device name
void processClientCommandChar_mainModule(char cmd)
single character version of processClientCommand (since many used that already)
char _scannedDeviceName[100]
Definition: MainModule.cpp:983
int getFeedCount_mainModule()
feedcount info..
Definition: MainModule.cpp:355
void onStatusMessageBLEServerCallback(char *message)
The callback for "status messages" of the bluetooth.
Definition: MainModule.cpp:659
char * main_JSONStringForWIFICredentials()
retrieve a JSON string for the ssid and ssid_password: {'ssid':<ssid>,'ssidPassword':<pass>"}
Definition: MainModule.cpp:904
int feedCountMax_mainModule()
returns the max for this feeder
Definition: MainModule.cpp:337
char _scannedGroupTopicName[100]
Definition: MainModule.cpp:984
M5Atom_CameraModuleClass * _M5Atom_CameraModuleClass
Definition: MainModule.cpp:42
void setClockwiseMotorDirection_mainModule(boolean isClockwiseFlag)
8.18.24 setting this will check for the factory setting..
void solidLightOnOff(boolean onOff)
callback for SOLID blinking led
void sendMessageStringTopic_mainModule(char *messageString, char *topicString)
adding a synchronous call to send a message over the network (assuming MQTT but not specified),...
char * main_getScannedGroupNameTopic()
uint32_t _chipID_MainModule
3.17.24 the unqiue chip id
void main_credentialsUpdated()
moved here 4.25.22 (entirely from ESP_IOT.ino)
Definition: MainModule.cpp:641
void setup_mainModule()
called from the setup()
Definition: MainModule.cpp:211
void main_dispatchSyncCommand(int syncCallCommand)
the main sync command (no parameters yet)
boolean stopAllProcesses_mainModule()
if stopped
Definition: MainModule.cpp:157
void restartAllMenuStates_mainModule()
restarts all the menu states to the first one .. useful for getting a clean start....
void setSemanticMarkerDocFollow_mainModule(char *SMDocFollowAddress)
sed the address to follow
boolean isTrueString_mainModule(String valCmdString)
whether the string is TRUE, ON, 1
Definition: MainModule.cpp:549
char * main_getPassword()
return password
Definition: MainModule.cpp:994
int whichSMMode_mainModule(char *cmd)
************** SM Mode Processing ***************
M5Atom_SocketModuleClass * _M5Atom_SocketModuleClass
5.6.25 use the M5Atom ClassType
Definition: MainModule.cpp:30
void main_dispatchAsyncCommandWithString(int asyncCallCommand, char *parameter)
char _bigMessage[500]
Definition: MainModule.cpp:182
void initAsyncCallFlags()
initialize the async call flags (with and without parameters)
void registerPinUse_mainModule(long pin, String pinName, String moduleName, boolean isI2C)
void solidLightMessageCallback(char *message)
callback for SOLID blinking led
M5AtomClassType * _M5AtomClassTypes[NUM_M5ATOM_CLASS]
3.31.25 create array of plugs
Definition: MainModule.cpp:49
M5AtomClassType * _whichM5AtomClassType
use this one...
Definition: MainModule.cpp:52
boolean isEmptyString(char *stringA)
informs if null or empty string
void rebootDevice_mainModule()
Definition: MainModule.cpp:853
void poweroff_mainModule()
power off
Definition: MainModule.cpp:860
int maxMenuModes_mainModule()
returns the current max of the menu modes (using the setting of min or expanded) to determine
void buttonB_ShortPress_mainModule()
the short press of the side button
#define GROUP_TOPIC_TO_SEND
boolean isPTFeeder_mainModule()
gets if PTFeeder a surrogate for the M5Atom class
Definition: MainModule.cpp:124
bool containsSubstring(String message, String substring)
check if the string contains the other string. This is a poor man's grammer checker
Definition: MainModule.cpp:396
void decrementSMMode_mainModule()
increment the currentSMMode, wrapping and using the max menu
M5Atom_QRCodeModuleClass * _M5Atom_QRCodeModuleClass
Definition: MainModule.cpp:32
void onWriteBLEServerCallbackFinish(char *message)
The FINISH of callback for "onWrite" of the bluetooth "onWrite'.
Definition: MainModule.cpp:668
char _serialBuffer[300]
Definition: MainModule.cpp:275
void callCallbackMain(int callbacksModuleId, int callbackType, char *message)
performs the indirect callback based on the callbackType
Definition: MainModule.cpp:531
int getCurrentSMMode_mainModule()
returns the current SM Mode
boolean _waitingForBigMessageEnd
store a big message #MSG_START .. #MSG_END
Definition: MainModule.cpp:181
void stopMotor_mainModule()
added 9.29.22 to support wildcards #196
Definition: MainModule.cpp:117
void stopProcessesForOTAUpdate_mainModule()
stop all loops... while OTA working..
Definition: MainModule.cpp:147
void feedMessageCallback(char *message)
Definition: MainModule.cpp:603
void resetFeedCount_mainModule()
sets the feed count max
Definition: MainModule.cpp:390
boolean asyncCallOTAUpdate()
performs an async OTA update
Definition: MainModule.cpp:783
void sendMessageString_mainModule(char *messageString)
adding a synchronous call to send a message over the network (assuming MQTT but not specified),...
char * main_currentStatusJSON()
status in JSON format, needs to return something as a ',' is already added before calling this....
M5AtomClassType * whichM5AtomClassType()
6.6.25 get the current M5AtomClassType
void(* callbackSignature)(char *)
Definition: MainModule.cpp:461
void changeButtonColor_MainModule()
2.21.25 add a way to change the button color (if any)
void setup_Sensors_mainModule()
1.22.24 setup of buttons
char * getFullBLEDeviceName_mainModule()
full: ""Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
char _groupTopicName[100]
int getFeederType_mainModule()
get the feeder type (Sepper 1,2,3 ...)
Definition: MainModule.cpp:361
char _connectedBLEDeviceName[50]
saved BLE connected name 8.26.22
Definition: MainModule.cpp:184
char * _lastSemanticMarkerDocFollow
char _connectedBLEDeviceAddress[50]
full: ""Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
Definition: MainModule.cpp:188
void addMoreStatusQueryString()
void buttonA_LongPress_mainModule()
long press on buttonA (top button)
void addStatusBooleanFlag(const char *key, boolean flag)
adds to _fullStatusString a query string "&key=value"
void invokeAsyncCommands()
checks if any async commands are in 'dispatch' mode, and if so, invokes them, and sets their flag to ...
#define CALLBACKS_MAX_BLE_CLIENT
Definition: MainModule.cpp:436
boolean startsWithChar(char *str, char c)
a char* version of startsWith (after skipping spaces)
void showText_mainModule(String text)
callbackSignature * _allCallbacks[CALLBACKS_MODULE_MAX]
array of known size (CALLBACKS_MODULE_MAX) of callbackSignatures
Definition: MainModule.cpp:476
void setCurrentSMMode_mainModule(int whichSMMode)
sets the current screen mode .. which can be used by Button and Display processing
char * getPairedDeviceOrAddress_mainModule()
returns if the paired device is not NONE .. returns address or device
Definition: MainModule.cpp:825
char _chipIdString_MainModule[15]
string like: 10311304
char * getPairedDevice_mainModule()
returns if the paired device is not NONE
Definition: MainModule.cpp:794
void onWriteBLEServerCallback(char *message)
The callback for "onWrite" of the bluetooth "onWrite'.
Definition: MainModule.cpp:756
char * _MQTT_Password
12.14.23
Definition: MainModule.cpp:981
void setLUXThreshold_mainModule(int thresholdKind, int luxVal)
set the threshold val
boolean _callbacksInitializedMain
flag for initializing if not yes
Definition: MainModule.cpp:458
#define CALLBACKS_BLE_CLIENT
Definition: MainModule.cpp:422
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 _JSONStringForWIFICredentials[200]
global to store credentials when ever they are stored..
Definition: MainModule.cpp:169
boolean matchesSMMode_mainModule(char *cmd, int whichSMMode)
returns if a match the mode. whichSMMode is 0..12 and == sm0 .. smn
int _feedCount_mainModule
5.3.22 added a feed count approach.. (NOTE: there is a _feedCount in Dispence.cpp ....
Definition: MainModule.cpp:335
BuzzerSensorClass * _BuzzerSensorClass
Definition: MainModule.cpp:64
int _saveWhichSMMode
the saved SMMode
char * getChipIdString()
3.17.24 get the chip id as a string
void refreshDelayButtonTouched_MainModule()
called by the feed operation to say the device is still running.. and count it as a button click.
Definition: MainModule.cpp:773
char * connectedBLEDeviceName_mainModule()
returns the connected BLE Device name (the :NAME of advertisment, Address: 01:39:3f:33 part of name,...
uint32_t getChipId()
3.17.24 get the chip id
boolean isMinimalMenuMode_mainModule()
returns which mode in (min or expanded)
char _asyncParameter[500]
the parameter being sent to those commands passing an argument
Definition: MainModule.cpp:167
void loop_Sensors_mainModule()
1.22.24 add setup and loop at main so it can call appropriate plugs
int getTimeStamp_mainModule()
void buttonB_LongPress_mainModule()
the long press of the side button
void blinkMessageCallback(char *message)
callback for blinking led
void restartProcessesForOTAUpdate_mainModule()
restart all loops... while OTA working..
Definition: MainModule.cpp:152
char * main_getScannedDeviceName()
return devicename
char * createCopy(char *stringA)
#define CALLBACKS_MAX_BUTTON_MODULE
Definition: MainModule.cpp:435
boolean _asyncCallFlagsParameters[ASYNC_CALL_PARAMETERS_MAX]
array of async flags for the different ASYNC_CALl values
char _fullStatusString[500]
status string (URL query format)
Definition: MainModule.cpp:174
void main_printModuleConfiguration()
M5Atom_TinyGPSModuleClass * _M5Atom_TinyGPSModuleClass
Definition: MainModule.cpp:39
void messageSetVal_mainModule(char *setName, char *valValue, boolean deviceNameSpecified)
Definition: MainModule.cpp:560
void singleClickTouched(char *whichButton)
float getTemperature_mainModule()
retrieves the temperature .
void buttonA_ShortPress_mainModule()
boolean isValidPairedDevice_mainModule()
returns if the paired device is not NONE. Note, the paired Name might be an address now (see below)
Definition: MainModule.cpp:806
char * main_nextJSONWIFICredential()
! cycle through the next WIFI saved credential
Definition: MainModule.cpp:910
void onBLEServerCallback(char *message)
The callback for "onWrite" of the bluetooth "onWrite'.
Definition: MainModule.cpp:652
void addStatusStringFlag(const char *key, char *val)
adds a query string "&key=value"
void incrementSMMode_mainModule()
increment the currentSMMode, wrapping and using the max menu
char * _ON_LIGHT
#define CALLBACKS_BUTTON_MODULE
Definition: MainModule.cpp:421
char _messageStorage[MESSAGE_STORAGE_MAX]
Definition: MainModule.cpp:172
void incrementFeedCount_mainModule()
increments .. and if MAX goes to 0 – and sends a message on MQTT
Definition: MainModule.cpp:368
PinUseStruct getPinUseStruct_mainModule()
get the pin use array
void main_saveWIFICredentials(char *ssid, char *ssid_password)
save the WIFI credential
Definition: MainModule.cpp:937
void readPreferences_mainModule()
reads the preferences. Save is everytime the savePreference is called
char * getPairedDeviceAddress_mainModule()
returns if the paired device is not NONE
Definition: MainModule.cpp:800
float getBatPercentage_mainModule()
start of the sensor updates ... TODO: tie these to the MQTT messaging as well..
int _callbacksFunctionsMAXS[CALLBACKS_MODULE_MAX]
the array of callback functions
Definition: MainModule.cpp:455
#define ASYNC_CALL_FEED_COMMAND
sends a 'c' to the BLE end of the code (assuming a feeder is connected). Need to morph if a real feed...
Definition: MainModule.h:197
#define MAX_SM_MIN_MODES
note for now, heep the max the same – so only goes through zoom or not zoom
Definition: MainModule.h:395
void cleanEPROM_mainModule()
cleans the main module EPROM
#define ASYNC_CALL_MAX
the max one greater than last one
Definition: MainModule.h:228
#define THRESHOLD_KIND_DARK
Definition: MainModule.h:74
#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 ASYNC_REST_CALL_MESSAGE_PARAMETER
send REST call
Definition: MainModule.h:239
#define ASYNC_SEND_MQTT_FEED_MESSAGE
sends a message (like FEED) on the users topic
Definition: MainModule.h:203
#define CALLBACKS_MODULE_MAX
Definition: MainModule.h:90
#define ASYNC_JSON_MQTT_MESSAGE_PARAMETER
these are the async with a string parameter
Definition: MainModule.h:237
#define ASYNC_CALL_CLEAN_CREDENTIALS
cleans out the credentials and restarts in AP (Access Point) mode.
Definition: MainModule.h:193
#define ASYNC_SWAP_WIFI
swaps WIFI 'w'
Definition: MainModule.h:220
#define ASYNC_SET_GATEWAY_ON
sets the GATEWAY mode on
Definition: MainModule.h:208
#define MAX_SM_EXPANDED_MODES
Definition: MainModule.h:396
#define ASYNC_RESTART_WIFI_MQTT
restarts the WIFI (after BLE interrupt over)
Definition: MainModule.h:224
#define THRESHOLD_KIND_LIGHT
Definition: MainModule.h:73
#define SYNC_CLICK_SOUND
Definition: MainModule.h:258
#define PIN_USE_MAX
Definition: MainModule.h:494
#define ASYNC_CALL_BUZZ_ON
sends a 'B' to the BLE end of the code (assuming a feeder is connected).
Definition: MainModule.h:199
#define ASYNC_POWEROFF
sets the GATEWAY mode off
Definition: MainModule.h:215
#define ASYNC_CALL_CLEAN_EPROM
cleans the EPROM totally, and reboots
Definition: MainModule.h:195
#define ASYNC_BLANKSCREEN
blank the screen
Definition: MainModule.h:217
#define ASYNC_CALL_PARAMETERS_MAX
the max one greater than last one
Definition: MainModule.h:241
#define ASYNC_SEND_MQTT_STATUS_URL_MESSAGE
sends the status from the main module URL
Definition: MainModule.h:205
#define ASYNC_SET_GATEWAY_OFF
sets the GATEWAY mode off
Definition: MainModule.h:210
#define ASYNC_CALL_OTA_FILE_UPDATE_PARAMETER
these are the async with a string parameter
Definition: MainModule.h:233
#define ASYNC_CALL_OTA_UPDATE
TODO: make this a registeration approach.
Definition: MainModule.h:191
#define TOPIC_TO_SEND
Definition: MainModule.h:61
#define ASYNC_NEXT_WIFI
next WIFI 'n'
Definition: MainModule.h:222
#define ASYNC_CALL_BUZZ_OFF
sends a 'b' to the BLE end of the code (assuming a feeder is connected).
Definition: MainModule.h:201
#define ASYNC_CLICK_SOUND
5.15.25 add a BUZZ command (or CLICK)
Definition: MainModule.h:226
#define ASYNC_JSON_MESSAGE_PARAMETER
these are the async with a string parameter
Definition: MainModule.h:235
void updateMenuState(ModelKindEnum modelKind)
updates the model for the menu state, this sets max etc
void startStopTimer_mainModule(boolean startTimer)
void initModelStructs_ModelController()
initialize the objects
void restartAllMenuStates_ModelController()
restarts all the menu states to the first one .. useful for getting a clean start....
@ timerModel
void performOTAUpdateSimple()
retrieves from constant location
void performOTAUpdate(char *hostname, char *httpAddress)
8.16.25 MQTT
void savePreferenceInt_mainModule(int preferenceID, int val)
sets an int preference
void savePreferenceBoolean_mainModule(int preferenceID, boolean flag)
save a boolean preference
SensorsStruct * getSensors_mainModule()
return the sensors defined
void setSensorsString_mainModule(char *sensorsString)
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
char * getPreferenceATOMKind_MainModule()
new 1.4.24 setting ATOM kind (eg. M5AtomSocket, M5AtomScanner)
void savePreferenceFloat_mainModule(int preferenceID, float val)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
int getM5ATOMKind_MainModule()
new 1.4.24 setting ATOM kind (eg. ATOM_KIND_M5_SCANNER, ATOM_KIND_M5_SOCKET)
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 * getPreference_mainModule(int preferenceID)
SensorStruct * getSensor_mainModule(char *sensorName)
return the sensor specified or null
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_USE_SPIFF_SETTING
8.22.22 to turn on/off SPIFF use (more below..)
#define PREFERENCE_PAIRED_DEVICE_ADDRESS_SETTING
the paired device for guest device feeding (6.6.22) .. but the Address 9.3.22
#define PREFERENCE_STEPPER_KIND_VALUE
uses STEPPER type
#define PREFERENCE_SENSOR_TILT_VALUE
Sensor preferences.
#define PREFERENCE_SENSOR_PLUGS_SETTING
#define PREFERENCE_STEPPER_FACTORY_CLOCKWISE_MOTOR_DIRECTION_SETTING
#define PREFERENCE_BLE_SERVER_USE_DEVICE_NAME_SETTING
if set, the BLE Server (like PTFeeder) will tack on the device name (or none if not defined).
#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_STEPPER_JACKPOT_FEED_VALUE
#define PREFERENCE_WIFI_CREDENTIAL_2_SETTING
#define PREFERENCE_STEPPER_RPM_SETTING
#define PREFERENCE_MAIN_BLE_SERVER_VALUE
#define PREFERENCE_PAIRED_DEVICE_SETTING
the paired device for guest device feeding (6.6.22)
#define PREFERENCE_STEPPER_BUZZER_VALUE
stepper preferences
#define STEPPER_IS_TUMBLER
#define PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
#define PREFERENCE_WIFI_CREDENTIAL_1_SETTING
#define PREFERENCE_USE_SPIFF_MQTT_SETTING
#define STEPPER_IS_UNO
#define WIFI_CREDENTIALS_MAX
for now, save 2 WIFI Credentials
#define PREFERENCE_FIRST_TIME_FEATURE_SETTING
a firsttime feature flag (only 1 per build) 7.12.22 defaulting to TRUE
#define PREFERENCE_IS_MINIMAL_MENU_SETTING
sets the max temp for a poweroff
#define STEPPER_IS_MINI
#define PREFERENCE_USE_SPIFF_QRATOM_SETTING
For MQTT writing to the QRATOM.
#define PREFERENCE_DEVICE_NAME_SETTING
the device name itself (6.6.22)
#define PREFERENCE_HIGH_TEMP_POWEROFF_VALUE
sets the max temp for a poweroff
#define PREFERENCE_STEPPER_ANGLE_FLOAT_SETTING
#define PREFERENCE_STEPPER_AUTO_MOTOR_DIRECTION_SETTING
#define PREFERENCE_MAIN_GATEWAY_VALUE
#define PREFERENCE_STEPPER_CLOCKWISE_MOTOR_DIRECTION_SETTING
#define PREFERENCE_MAIN_BLE_CLIENT_VALUE
#define PREFERENCE_ATOM_KIND_SETTING
1.4.24 What kind of ATOM plug (set, M5AtomKind, val= {M5AtomSocket, M5AtomScanner}
void sendStrings_SPIFFModule(int numberOfLines)
sends SPIFF module strings over MQTT, starting at the number back specified. This will use the curren...
void printFile_SPIFFModule()
prints the spiff file to the SerialDebug output
void deleteFiles_SPIFFModule()
delete the spiff files..
void stepperModule_ProcessClientCmdFinal(char cmd)
the Blink the LED - and it will use the latest BUZZER status (so MQTT could set buzzer on....
void setup_tokenParser_mainModule()
setup a test ..
char * semanticMarkerToJSON_TokenParser(char *semanticMarker)
void blinkLED_UIModule()
blink the LED
Definition: UI.cpp:23
void solidLightOnOff_UIModule(boolean onOff)
turns on/off a solid light
Definition: UI.cpp:20
void clean_SSID_WIFICredentials()
returns true if the SSID is set, false otherwise. If set, then just exit..
void WIFI_APModule_updateMQTTInfo(char *ssid, char *ssid_password, char *username, char *password, char *guestPassword, char *deviceName, char *host, char *port, char *locationString)
sets the MQTT user/password. It's up to the code to decide who needs to know
boolean doneWIFI_APModule_Credentials()
called to see if the WIFIModule has finished bootstrapping..
void cleanEPROM_WIFI_APModule()
cleans the eprom info
void setDoneWIFI_APModuleFlag(boolean flag)
called to set the done flag
void setup()
Pure Virtual Function.
An mostly virtual class.
virtual void messageSend_M5AtomClassType(char *sendValue, boolean deviceNameSpecified)=0
virtual void loop_M5AtomClassType()=0
loop the PTStepper (so timer can run)
boolean isPTFeeder_M5AtomClassType()
virtual void buttonA_ShortPress_M5AtomClassType()=0
virtual char * currentStatusJSON_M5AtomClassType()=0
virtual void buttonA_LongPress_M5AtomClassType()=0
long press on buttonA (top button)
virtual void messageSetVal_M5AtomClassType(char *setName, char *valValue, boolean deviceNameSpecified)=0
these are from the ATOM
virtual void setup_M5AtomClassType()=0
setup the PTStepper
virtual void stop_M5AtomClassType()=0
stop the motor
virtual char * currentStatusURL_M5AtomClassType()=0
void setPinValues(int pin1, int pin2)
virtual void messageLocal_SensorClassType(char *message)
5.15.25 try a special command local to this class
char * pinUseArray[PIN_USE_MAX]
Definition: MainModule.h:497
SensorClassType * sensorClassType
and the pointer to matching SensorClassType
SensorStruct * sensors
array of sensorStruct