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
6//! reads the preferences. Save is everytime the savePreference is called
8//!testing..
9boolean _stopAllProcessing = false;
10//!stop all loops... while OTA working..
12{
13 _stopAllProcessing = true;
14}
15//!restart all loops... while OTA working..
17{
18 _stopAllProcessing = false;
19}
20//! if stopped
22{
23 //! try to disconnect..
24 //disconnect_BLEClientNetworking();
25 // return false; //
26 return _stopAllProcessing;
27}
28
29//****** GLOBALS (shows how much memory is allocated.. )
30//!the parameter being sent to those commands passing an argument
32//!global to store credentials when ever they are stored..
34//!global for others to use..
35#define MESSAGE_STORAGE_MAX 400
37//!status string (URL query format)
39//! current smMode
41//! saved deviceName storage..
43
44//!store a big message #MSG_START .. #MSG_END
46char _bigMessage[500];
47//!saved BLE connected name 8.26.22
49//!full: ""Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
51//!full: ""Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
53
54//!init globals strings
56{
57 //!NOTE: this is definitely needed, as grabbing strings willy nilly can bomb or corrupt stuff..
58 strcpy(_connectedBLEDeviceName,(char*)"");
59 strcpy(_bigMessage,(char*)"");
60 strcpy(_deviceNameSave,(char*)"");
61 strcpy(_smMode_MainModule,(char*)"");
62 strcpy(_fullStatusString,(char*)"");
63 strcpy(_messageStorage,(char*)"");
64 strcpy(_JSONStringForWIFICredentials,(char*)"");
65 strcpy(_asyncParameter,(char*)"");
66 strcpy(_fullBLEDeviceName,(char*)"");
67
68}
69
70//THIS IS the setup() and loop() but using the "component" name, eg MQTTNetworking()
71//! called from the setup()
73{
74 SerialMin.println("setup_mainModule");
75
76 //test...
77 //! setup for the token parser (really just for testing) -- an
79
80 //!init globals like strings (but nothing that needs preferences)
82
83 //!read the preferences from EPROM
85
86 //!must initialize the structs NOTE: this has to ber AFTER the preferences are read in..
88
89 //!a first time feature .. to get EPROM changed to a different default
91 {
92
93 //!7.12.22
94 //! {'dev':'m5",'cmd':'bleserveron'} or bleserveroff will work later..
95 //!#issue 117 .. turn off the BLE_Server for the M5
96 SerialMin.println("FIRST TIME TURNING off the BLE_SERVER for the M5");
97#ifdef ESP_M5
99#else
101#endif
103
104 }
105
106}
107
108#if defined(ESP_M5_CAMERA) || defined(ESP_32)
109//!a couinter to slow down the loop doing things..
111#endif
112
113//! called for the loop() of this plugin
115{
116 //no op..
117
118#if defined(ESP_M5_CAMERA) || defined(ESP_32)
119 //!only do this menu update if there is no DisplayModule running the MVC loop
120
121 if (_mainLoopCounter++ > 30)
122 {
123 //! 9.2.22 new .. update the timer. This is on blank screen as well .. so don't check _semanticMarkerShown
125
127 }
128
129#endif
130
131}
132
133
134//! 5.3.22 added a feed count approach.. (NOTE: there is a _feedCount in Dispence.cpp ... and no linker error!!! )
136//!returns the max for this feeder
138{
139 int max = 16;
140 switch (getFeederType_mainModule())
141 {
142 case STEPPER_IS_UNO:
143 max = 16;
144 break;
145 case STEPPER_IS_MINI:
146 max = 55;
147 break;
149 max = 50;
150 break;
151 }
152 return max;
153}
154//!feedcount info..
156{
158}
159
160//!get the feeder type (Sepper 1,2,3 ...)
162{
164 return kind;
165}
166
167//!increments .. and if MAX goes to 0 -- and sends a message on MQTT
169{
170 SerialTemp.println("incrementFeedCount_mainModule");
171
174 {
175 // send a message.
176#ifdef USE_MQTT_NETWORKING
177 //note needs # or won't send..
178 //!NOTE: don't send "feed" as it might trigger a FEED ...
179 sendMessageMQTT((char*)"#count reached .. resetting");
180#endif
182 }
183
184 //! called by the feed operation to say the device is still running.. and count it as a button click.
185 //! Issue #145 8.8.22
187
188}
189//! sets the feed count max
191{
193}
194
195//!check if the string contains the other string. This is a poor man's grammer checker
196bool containsSubstring(String message, String substring)
197{
198 if (substring.length() == 0 )
199 return false;
200 bool found = strstr(&message[0], &substring[0]);
201 SerialLots.printf("containsSubstring-%d - %s in: %s\n", found, &substring[0], &message[0]);
202 return found;
203}
204
205#ifdef USE_MQTT_NETWORKING
206#include "../MQTTModule/MQTTNetworking.h"
207#endif
208#ifdef USE_BLE_SERVER_NETWORKING
209#include "../BLEServerModule/BLEServerNetworking.h"
210#endif
211#ifdef USE_BLE_CLIENT_NETWORKING
212#include "../BLEClientModule/BLEClientNetworking.h"
213#endif
214#ifdef USE_BUTTON_MODULE
215#include "../ButtonModule/ButtonModule.h"
216#endif
217
218//! New RegisterCallback that works across a number of callback modules
219//!
220//! callbacksModuleId
221#define CALLBACKS_MQTT 0
222#define CALLBACKS_BUTTON_MODULE 1
223#define CALLBACKS_BLE_CLIENT 2
224#define CALLBACKS_BLE_SERVER 3
225
226
227//!register the callback based on the callbackType. use the callbacksModuleId for which one..
228void registerCallbackMain(int callbacksModuleId, int callbackType, void (*callback)(char*));
229//!performs the indirect callback based on the callbackType
230void callCallbackMain(int callbacksModuleId, int callbackType, char *message);
231
232
233//!make sure these are the number of callbacks.. 0..n
234//! These values are from the respective .h of the modules
235#define CALLBACKS_MAX_MQTT MQTT_MAX_CALLBACKS
236#define CALLBACKS_MAX_BUTTON_MODULE MAX_CALLBACKS_BM
237#define CALLBACKS_MAX_BLE_CLIENT BLE_CLIENT_MAX_CALLBACKS
238#define CALLBACKS_MAX_BLE_SERVER BLE_SERVER_MAX_CALLBACKS
239
240
241//!example callback
242void dummyCallbackMain(char *message)
243{
244 SerialLots.printf("No callback defined .. %s\n", message);
245}
246
247//tricky getting array of arrays (or pointers to arrays), without dynamic memory.. we are going to use calloc()
248//https://www.geeksforgeeks.org/dynamic-memory-allocation-in-c-using-malloc-calloc-free-and-realloc/
249//https://www.tutorialspoint.com/cprogramming/c_pointer_to_pointer.htm
250//https://stackoverflow.com/questions/5573302/pointer-to-an-array-of-function-pointers
251//!the array of callback functions
252//* this means there are arrays of N pointers to functions that take 1 parameter (char*).
253
254
255//! the max of each module .. hard coded (or 0 if module not there)
257
258//!flag for initializing if not yes
260
261//a pointer to a callback function that takes (char*) and returns void
262typedef void (*callbackSignature)(char *);
263//callbackSignature fpar[2] = {&dummyCallbackMain, &dummyCallbackMain};
264
265//!return dyamically created array of max
267{
268 SerialLots.printf("creatingCallbacks %d size: %d\n", max, sizeof(callbackSignature *));
269 callbackSignature *callbackArray = (callbackSignature *)calloc(max,sizeof(callbackSignature *));
270 for (int i=0; i< max; i++)
271 {
272 callbackArray[i] = &dummyCallbackMain;
273 }
274 return callbackArray;
275}
276//!array of known size (CALLBACKS_MODULE_MAX) of callbackSignatures
278
279//!init the callbacks to dummy callbacks
281{
283 {
285
286 // default to 0 callbacks.. in case module not there..
287 for (int i = 0; i < CALLBACKS_MODULE_MAX; i++)
288 {
290 }
291 //! only place for #ifdef (NOTE some can be 0 based on the #ifdef module not being included..
292#ifdef USE_MQTT_NETWORKING
294#endif
295#ifdef USE_BLE_SERVER_NETWORKING
297#endif
298#ifdef USE_BLE_CLIENT_NETWORKING
300#endif
301#ifdef USE_BUTTON_MODULE
303#endif
304 // initialize the dummy callbacks
305 for (int i = 0; i < CALLBACKS_MODULE_MAX; i++)
306 {
307 //first determine how many are in the array..
308 int max = _callbacksFunctionsMAXS[i];
309 //then create the space which are (void *) pointers
310 _allCallbacks[i] = createMemory(max);
311 }
312 }
313}
314
315//!register the callback based on the callbackType. use the callbacksModuleId for which one..
316void registerCallbackMain(int callbacksModuleId, int callbackType, void (*callback)(char*))
317{
318 //init if not already..
320 int max = _callbacksFunctionsMAXS[callbacksModuleId];
321
322 if (callbackType < 0 || callbackType >= max)
323 {
324 SerialError.println("#### Error outside callback range");
325 }
326 else
327 {
328 // array of arrays (or array of pointer to another array)
329 _allCallbacks[callbacksModuleId][callbackType] = callback;
330 }
331}
332//!performs the indirect callback based on the callbackType
333void callCallbackMain(int callbacksModuleId, int callbackType, char *message)
334{
335 //init if not already..
337 int max = _callbacksFunctionsMAXS[callbacksModuleId];
338
339 if (callbackType < 0 || callbackType >= max)
340 {
341 SerialError.println("#### Error outside callback range");
342 }
343 else {
344 void (*callbackFunction)(char *) = _allCallbacks[callbacksModuleId][callbackType];
345 (*callbackFunction)(message);
346 }
347}
348
349#ifdef USE_MQTT_NETWORKING
350//!example callback: but the scope would have the pCharacteristic defined, etc..
351//!This is passed just before the setupMQTTNetworking() is called..
352void feedMessageCallback(char *message)
353{
354 SerialTemp.print("feedMessageCallback_main: ");
355 SerialTemp.println(message);
356 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)
357 //!sends this single character to the StepperModule
359
360 //!increment the feed count .. TODO .. see if this is good place..
361// incrementFeedCount_mainModule();
362
363 //!the FEED was send over MQTT, now what to do?
364 //! WIth the StepperModule -- it just performs the feeding internalls
365 //! if using the BLE_CLIENT then we have the potential to send to over BLE
366 //! to the server (another feeder, GEN3 or ESP32).
367 //! The issue is that ESP32 feeders are receiving the same MQTT message (usually unless MQTT turned off
368 //! So the gatewayMode can be set (or in the EPROM) using {'cmd':'gatewayOn'}
370 {
371#ifdef USE_BLE_CLIENT_NETWORKING
372
373 SerialTemp.print("Paired Device: ");
375
376 SerialTemp.printf("Gateway: Feeding over the BLE CLIENT network .. if connected: %d\n",isConnectedBLEClient());
378 {
379 //!send the feed over the BLE client (if connected)
381 }
382 SerialLots.println("after send feed via ble");
383#endif
384 }
385}
386#endif //USE_MQTT_NETWORKING
387
388//!moved here 4.25.22 (entirely from ESP_IOT.ino)
389
390//! April 8, 2022
391//! set that the credentials are set. Called from the MQTT after processJSONMessage() found things were good..
393{
394 // set the done in the WI
395 SerialDebug.println(" *** main_credentialsUpdated .. setDoneWIFI_APModuleFlag **");
396#ifdef USE_WIFI_AP_MODULE
398#endif
399}
400//NOTE: #else not there so this won't link.. on purpose
401
402/*******************************BLE Server*************************************/
403//!The callback for "onWrite" of the bluetooth "onWrite'
404void onBLEServerCallback(char *message)
405{
406 SerialCall.print("onWriteBLEServerCallback: ");
407 SerialCall.println(message);
408
409}
410//! The callback for "status messages" of the bluetooth
412{
413 SerialCall.print("onStatusMessageBLEServerCallback");
414 SerialCall.print(message);
415 //! 2.2.22 send this over bluetooth.. TODO.
416 //
417}
418
419//! The FINISH of callback for "onWrite" of the bluetooth "onWrite'
421{
422
423 SerialDebug.print("onWriteBLEServerCallback_main: ");
424 SerialDebug.println(message);
425
426 //!client never sends these wrapped messages of length 1, so process normally..
427 //!gets us out of potential infinite wait
428 if (strlen(message) == 1)
430
431 if (strcmp(message, "#MSG_START")==0)
432 {
434 strcpy(_bigMessage,"");
435 return;
436 }
438 {
439 if (strcmp(message, "#MSG_END")==0)
440 {
442 //! we are done.. send big message to ourself..
444 }
445 else
446 {
447 strcat(_bigMessage,message);
448 return;
449 }
450 }
452
453 //!Issue: the message is arriving via BLE, but if we call the MQTT process, it might call us back to send
454 //!the message over BLE. This hangs things up!
455 //!So short optimization for 'feed' will be to look for cmd and feed in message {cmd:feed}
456 //!8.19.22 issue #162
457 if (containsSubstring(message,"cmd"))
458 {
459 if (containsSubstring(message,"feed"))
460 {
461 message = (char*)"s";
462 }
463 else if (containsSubstring(message,"buzzOn"))
464 {
465 message = (char*)"B";
466 }
467 else if (containsSubstring(message,"buzzOff"))
468 {
469 message = (char*)"b";
470 }
471
472 }
473
474#ifdef USE_MQTT_NETWORKING
475 //This should be a 'register' command..
476
477 //!the MQTTNetwork.processJSONMessage()
478 //!will return true if the message was JSON and was processes, false otherwise.
479 if (processJSONMessageMQTT(message, NULL))
480 {
481 //!processed by the MQTTNetworking code..
482#ifdef USE_BLE_SERVER_NETWORKING
484#endif
485 //pCharacteristic->setValue(0x01); //?? This is the acknowlege(ACK) back to client. Later this should be contigent on a feed completed
486 }
487 else
488 {
489 //!perform feed...
490 SerialDebug.printf("Perform BLE Command '%s'\n", message);
491
492 char cmd = message[0];
493
494 //OOOPS.. we need the ProcessClientCmd .. for other than just step..
495 // for sensors..
496
497 //!look for ** sensor commands..
499
500#ifdef USE_BLE_SERVER_NETWORKING
502#endif
503
504 }
505 SerialDebug.println("*********");
506
507#endif
508} //onWriteBLEServerCallback
509
510//! The callback for "onWrite" of the bluetooth "onWrite'
511void onWriteBLEServerCallback(char *message)
512{
513 //TEST:
514#define TRY_ASYNC_BLE_PROCESSING
515#ifdef TRY_ASYNC_BLE_PROCESSING
516
517 //!send an async call with a string parameter. This will set store the value and then async call the command (passing the parameter)
518 //!These are the ASYNC_CALL_PARAMETERS_MAX
520#else
521
522 //! The callback for "onWrite" of the bluetooth "onWrite'
523 onWriteBLEServerCallbackFinish(char *message);
524#endif
525}
526
527//!take a picture (calls the camera module).. what to do with picture??? TODO
529{
530#ifdef USE_CAMERA_MODULE
531 takePicture_CameraModule();
532#endif
533}
534
535//! called by the feed operation to say the device is still running.. and count it as a button click.
537{
538#ifdef USE_BUTTON_MODULE
539 //!calls the button processing control
541#endif
542}
543//! 3.28.22 .. implemented in ESP_IOT.ino
545//!performs an async OTA update
547{
549}
550//!sets the async OTA flag (for next loop)
552{
554}
555
556//!returns if the paired device is not NONE
558{
560}
561
562//!returns if the paired device is not NONE
564{
566
567}
568//!returns if the paired device is not NONE. Note, the paired Name might be an address now (see below)
570{
571 char *pairedDevice = getPairedDevice_mainModule();
572 //new: now if non ""
573 //return strcmp(pairedDevice,"NONE")!= 0;
574 boolean isValid = pairedDevice && strlen(pairedDevice)>0 && strcmp(pairedDevice,"NONE")!= 0;
575 if (!isValid)
576 {
577 char *pairedDeviceAddress = getPairedDeviceAddress_mainModule();
578 isValid = pairedDeviceAddress && strlen(pairedDeviceAddress)>0 && strcmp(pairedDeviceAddress,"NONE")!= 0;
579 SerialDebug.printf("isValidDeviceAddress(%s,%d)\n", pairedDeviceAddress, isValid);
580 }
581 SerialDebug.printf("isValidPairedDevice_mainModule(%s,%d)\n", pairedDevice, isValid);
582 return isValid;
583}
584
585//**** dang.. the getPreference reuses the same storage!! ****
586
587//!returns if the paired device is not NONE .. returns address or device
589{
590 char *pairedDevice = getPairedDevice_mainModule();
591 if (pairedDevice && strlen(pairedDevice)>0 && strcmp(pairedDevice,"NONE")!= 0)
592 {
593 SerialLots.printf("getPairedDeviceOrAddress_mainModule(%s)\n", pairedDevice);
594 return pairedDevice;
595 }
596 char *pairedDeviceAddress = getPairedDeviceAddress_mainModule();
597 if (pairedDeviceAddress && strlen(pairedDeviceAddress)>0 && strcmp(pairedDeviceAddress,"NONE")!= 0)
598 {
599 SerialLots.printf("getPairedDeviceOrAddress_mainModule(%s)\n", pairedDeviceAddress);
600 return pairedDeviceAddress;
601 }
602 else
603 return (char*)"";
604}
605
606//!gets the device name
608{
610 strcpy(_deviceNameSave,deviceName);
611 return _deviceNameSave;
612}
613
614//!power of devices
615//!reboot
617{
618 //reboot
619 ESP.restart();
620}
621
622//!power off
624{
625#ifdef ESP_M5
626 //SerialTemp.println(" **** THIS WOULD BE A POWEROFF ***");
627 SerialTemp.println(" **** POWEROFF ***");
628
629#ifndef ESP_M5_CAMERA
630 M5.Axp.PowerOff();
631#endif
632
633#endif
634}
635// ******************* Preference Cleaning ************
636
637//!cleans the EPROM
639{
640 SerialDebug.println("CLEANING EPROM PREFERENCES");
641
642 //4.17.22
644
645#ifdef USE_MQTT_NETWORKING
647#endif
648
649#ifdef USE_WIFI_AP_MODULE
651#endif
652
653
654 SerialDebug.println("REBOOTING...");
655
656 //!reboot
658
659}
660
661
662//!retrieve a JSON string for the ssid and ssid_password: {'ssid':<ssid>,'ssidPassword':<pass>"}
664{
666}
667
668//!! cycle through the next WIFI saved credential
670{
671
672 SerialTemp.printf("WIFI_CREDENTIAL_1: %s\n", getPreference_mainModule(PREFERENCE_WIFI_CREDENTIAL_1_SETTING));
673 SerialTemp.printf("WIFI_CREDENTIAL_2: %s\n", getPreference_mainModule(PREFERENCE_WIFI_CREDENTIAL_2_SETTING));
674
675 //! WIFI_CREDENTIALS_MAX
677 {
678 char* credential = getPreference_mainModule(i);
679 //!jump out of loop if no match.. so index is valid
680 if (strcmp(credential,"NONE")==0)
681 continue;
682 if (strcmp(credential,_JSONStringForWIFICredentials)!= 0)
683 {
684 SerialTemp.print("main_nextJSONWIFICredential:");
685 SerialTemp.println(credential);
686 return credential;
687
688 }
689 }
690 SerialTemp.print("main_nextJSONWIFICredential:");
691 SerialTemp.println(main_JSONStringForWIFICredentials());
693}
694
695//!save the WIFI credential
696void main_saveWIFICredentials(char *ssid, char *ssid_password)
697{
698 //!store the JSON version of these credentials..
699 sprintf(_JSONStringForWIFICredentials, "{'ssid':'%s','ssidPassword':'%s'}", ssid?ssid:"NULL", ssid_password?ssid_password:"NULL");
700 SerialMin.print("main_saveWIFICredentials");
701 SerialMin.println(_JSONStringForWIFICredentials);
702
703 //!look for an non matching slot.. if none, then use the first
706 {
707 char* credential = getPreference_mainModule(index);
708 //!jump out of loop if no match.. so index is valid, or NONE (which is the placeholder)
709 if (strcmp(credential,"NONE")==0)
710 break;;
711 if (strcmp(credential,_JSONStringForWIFICredentials)== 0)
712 {
713 break;
714 }
715 }
716
719
720 SerialDebug.println(_JSONStringForWIFICredentials);
721 //!save in chosen index
723}
724
725//!clean the saved WIFI credential, otherwise the AP mode doesn't work (6.3.22)
727{
728 SerialMin.println("main_cleanSavedWIFICredentials");
729
730 //!go through the saved WIFI credentials and empty them with "" (vs null)
733 {
734 //!cannot null but can make stringlen=0
736 }
737}
738
739
740//! 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
741void main_updateMQTTInfo(char *ssid, char *ssid_password, char *username, char *password, char *guestPassword, char *deviceName, char * host, char * port, char *locationString)
742{
743 SerialMin.printf("main_updateMQTTInfo(%s,%s,%s,%s,%s, %s)\n", ssid?ssid:"NULL", ssid_password?ssid_password:"NULL", username?username:"NULL", password?password:"NULL", guestPassword?guestPassword:"NULL", locationString?locationString:"NULL");
744
745 //!store the device name
747
748 //!store the JSON version of these credentials..
749 main_saveWIFICredentials(ssid,ssid_password);
750
751#ifdef USE_WIFI_AP_MODULE
752 WIFI_APModule_updateMQTTInfo(ssid, ssid_password, username, password, guestPassword, deviceName, host, port, locationString);
753#endif
754}
755
756//! 3.21.22 these are to setup for the next time the main loop() runs to call these commands..
757//! The implementation is hard coded in the ESP_IO.ino
758//! TODO: make this a registeration approach
759//#define ASYNC_CALL_OTA_UPDATE 0
760//#define ASYNC_CALL_CLEAN_CREDENTIALS 1
761//#define ASYNC_CALL_MAX 2
762
763//!storage for asyncCallCommands
765//!array of async flags for the different ASYNC_CALl values
767
768
769//!initialize the async call flags (with and without parameters)
771{
772 for (int i = 0; i < ASYNC_CALL_MAX; i++)
773 {
774 _asyncCallFlags[i] = false;
775 }
776 for (int i = 0; i < ASYNC_CALL_PARAMETERS_MAX; i++)
777 {
778 _asyncCallFlagsParameters[i] = false;
779 }
780}
781
782// ******************* Async Dispatch Processing ************
783
784
785
786//!checks if any async commands are in 'dispatch' mode, and if so, invokes them, and sets their flag to false
787
788//! dispatches a call to the command specified. This is run on the next loop()
789void main_dispatchAsyncCommand(int asyncCallCommand)
790{
791 //! this just sets the flag, it's the next loop that makes the call
792#ifdef ERROR_CHECKS
793 if (asyncCallCommand < 0 || asyncCallCommand >= ASYNC_CALL_MAX)
794 {
795 SerialError.printf("ERROR: async call out of range: %d\n", asyncCallCommand);
796 }
797 else
798#endif
799 {
800 SerialLots.printf("main_dispatchAsyncCommand: %d\n", asyncCallCommand);
801 _asyncCallFlags[asyncCallCommand] = true;
802 }
803}
804
805//!send an async call with a string parameter. This will set store the value and then async call the command (passing the parameter)
806//!These are the ASYNC_CALL_PARAMETERS_MAX
807void main_dispatchAsyncCommandWithString(int asyncCallCommand, char *parameter)
808{
809 //!store in the parameter mailbox
810 strcpy(_asyncParameter,parameter);
811 //! this just sets the flag, it's the next loop that makes the call
812#ifdef ERROR_CHECKS
813 if (asyncCallCommand < 0 || asyncCallCommand >= ASYNC_CALL_PARAMETERS_MAX)
814 {
815 SerialError.printf("ERROR: async call out of range: %d\n", asyncCallCommand);
816 }
817 else
818#endif
819 {
820 SerialTemp.print("main_dispatchAsyncCommandWithString:");
821 SerialTemp.print(asyncCallCommand);
822 SerialTemp.print(": ");
823 SerialTemp.println(_asyncParameter);
824 _asyncCallFlagsParameters[asyncCallCommand] = true;
825 }
826}
827
828//!checks if any async commands are in 'dispatch' mode, and if so, invokes them, and sets their flag to false
830{
831 for (int i = 0; i < ASYNC_CALL_PARAMETERS_MAX; i++)
832 {
833 boolean asyncCallFlag = _asyncCallFlagsParameters[i];
834 if (asyncCallFlag)
835 {
836 _asyncCallFlagsParameters[i] = false;
837 switch (i)
838 {
840 SerialTemp.print("ASYNC_CALL_BLE_CLIENT_PARAMETER: ");
841 SerialTemp.println(_asyncParameter);
842#ifdef USE_BLE_CLIENT_NETWORKING
843 if (strlen(_asyncParameter)<=13)
845 else
847#endif
848
849 break;
851 SerialTemp.print("ASYNC_CALL_OTA_FILE_UPDATE_PARAMETER: ");
852 SerialTemp.println(_asyncParameter);
853#ifdef USE_MQTT_NETWORKING
854 {
855 //look for the host: http://<name>/
856 // httpAddress is everything after the /
857 //hostname is without http://
858 char hostname[100];
859 char httpAddress[100];
860 int thirdSlash = 0;
861 for (int i=0; i< strlen(_asyncParameter);i++)
862 {
863 if (_asyncParameter[i] == '/')
864 {
865 thirdSlash++;
866 }
867 if (thirdSlash == 3)
868 {
869 // i == point to 3rd slash
870 strncpy(hostname,_asyncParameter,i);
871 //add null
872 hostname[i] = (char)0;
873 char *a = &_asyncParameter[i+1];
874 strcpy(httpAddress,a);
875 break;
876 }
877 }
878 //todo..
879 SerialTemp.print("will performOTAUpdate: ");
880 SerialTemp.print(hostname);
881 SerialTemp.print(" with httpAddress: ");
882 SerialTemp.println(httpAddress);
883 performOTAUpdate(hostname, httpAddress);
884
885 }
886#endif
887 break;
889 {
890 //process the message
891 SerialDebug.print("ASYNC_JSON_MESSAGE_PARAMETER: ");
892 SerialDebug.println(_asyncParameter);
893
894 //! The FINISH of callback for "onWrite" of the bluetooth "onWrite'
896 }
897 break;
898
899 }
900
901 }
902 }
903
904 //!now process those that don't have a string parameter
905 for (int i = 0; i < ASYNC_CALL_MAX; i++)
906 {
907 boolean asyncCallFlag = _asyncCallFlags[i];
908 if (asyncCallFlag)
909 {
910 _asyncCallFlags[i] = false;
911 switch (i)
912 {
914 SerialLots.println("ASYNC_CALL_OTA_UPDATE");
915#ifdef USE_MQTT_NETWORKING
917#endif
918 break;
920 SerialTemp.println("ASYNC_CALL_CLEAN_CREDENTIALS");
921#ifdef USE_WIFI_AP_MODULE
923 //this reboots ..
924#endif
925 break;
927 SerialTemp.println("ASYNC_CALL_CLEAN_EPROM");
929 break;
931 SerialLots.println("ASYNC_CALL_FEED_COMMAND");
933#ifdef USE_MQTT_NETWORKING
934 //!register the 2 callbacks for now..
936
937#endif //USE_MQTT_NETWORKING
938 break;
939
940#define TRY_WIFI_FIRST
941#ifdef TRY_WIFI_FIRST
942 //!this is a sending of the message
944 SerialTemp.println("ASYNC_SEND_MQTT_FEED_MESSAGE");
945 //incrementFeedCount_mainModule();
946 SerialCall.println("async_send_feed.0");
947
948
949#ifdef USE_MQTT_NETWORKING
950
951 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
952 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
954 {
955 char pubString[100];
957 boolean isPaired = paired && strlen(paired)>0;
958 // cannot save it.. so refresh below.. (Preferences are reused)
959 SerialTemp.printf("Paired = %s\n", paired?paired:(char*)"none");
960 SerialTemp.printf("Connected = %s\n", connectedBLEDeviceName_mainModule()?connectedBLEDeviceName_mainModule():(char*)"none");
961
963 sprintf(pubString,"{'dev':'!%s & !%s'",deviceName_mainModule(),connectedBLEDeviceName_mainModule());
964 else if (isPaired)
966 else
967 sprintf(pubString,"{'dev':'!%s'",deviceName_mainModule());
968 strcat(pubString,",'cmd':'feed'}");
970 }
971
972
973 //SerialTemp.println("async_send_feed.3");
974 //TODO: 7.26.22 .. decide if this logic makes sense:
975 //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).
976 //sendMessageMQTT((char *)"#FEED");
977#endif // USE_MQTT_NETWORKING
978#ifdef USE_BLE_CLIENT_NETWORKING
979 //! returns whether connected over BLE as a client to a server(like a ESP feeder)
981 {
982 //! If not connected over BLE -- then send the MQTT feed message.. ??? WHY??
983#ifdef USE_MQTT_NETWORKING_NOT_NOW
984 SerialCall.println("async_send_feed.1");
985 sendMessageMQTT((char *)"#FEED");
986 SerialTemp.println(" *** NO BLE connected so send wifi ASYNC_SEND_MQTT_FEED_MESSAGE");
987#endif //use_MQTT_not_now
988 }
989 else
990 {
991 SerialCall.println("async_send_feed.2");
993
994 //!send a BLE feed command as we are connected
996
997 //!perform ACK too
998#ifdef USE_MQTT_NETWORKING
999 //ack is sent by the caller of this message..??
1000 sendMessageMQTT((char *)"#ackMe");
1001
1002#endif //useMQTT
1003 }
1004#ifdef NOT_NOW
1005 //! 8.24.22 (This will redraw the screen - and turn off the blank screen (but not let anyone know)
1006 //! SO: now only the buttons will unlock the blank screen..
1007
1008 //!redraws the Semantic Marker image..
1010#endif //not_now
1011#endif //using BLE_CLIENT
1012 break;
1013#else //BLE_FIRST
1014 //!this is a sending of the message
1015 case ASYNC_SEND_MQTT_FEED_MESSAGE:
1016 SerialTemp.println("ASYNC_SEND_MQTT_FEED_MESSAGE");
1017 //incrementFeedCount_mainModule();
1018 SerialCall.println("async_send_feed.0");
1019
1020#ifdef USE_BLE_CLIENT_NETWORKING
1021 //! returns whether connected over BLE as a client to a server(like a ESP feeder)
1022 if (!isConnectedBLEClient())
1023 {
1024 //! If not connected over BLE -- then send the MQTT feed message.. ??? WHY??
1025#ifdef USE_MQTT_NETWORKING_NOT_NOW
1026 SerialCall.println("async_send_feed.1");
1027 sendMessageMQTT((char *)"#FEED");
1028 SerialTemp.println(" *** NO BLE connected so send wifi ASYNC_SEND_MQTT_FEED_MESSAGE");
1029#endif //use_MQTT_not_now
1030 }
1031 else
1032 {
1033 SerialCall.println("async_send_feed.2");
1035
1036 //!send a BLE feed command as we are connected
1038
1039 //!perform ACK too
1040#ifdef USE_MQTT_NETWORKING
1041 //ack is sent by the caller of this message..??
1042 sendMessageMQTT((char *)"#ackMe");
1043
1044#endif //useMQTT
1045 }
1046#ifdef NOT_NOW
1047 //! 8.24.22 (This will redraw the screen - and turn off the blank screen (but not let anyone know)
1048 //! SO: now only the buttons will unlock the blank screen..
1049
1050 //!redraws the Semantic Marker image..
1052#endif //not_now
1053#endif //using BLE_CLIENT
1054#ifdef USE_MQTT_NETWORKING
1055
1056 //!9.30.22 IF SET .. send a feed but to all devices except ours and our pair (if any)
1057 //! uses new wildcard syntax either ! OUR NAME [ & ! OUR_CONNECTED_NAME
1059 {
1060 char pubString[100];
1062 boolean isPaired = paired && strlen(paired)>0;
1063 // cannot save it.. so refresh below.. (Preferences are reused)
1064 SerialTemp.printf("Paired = %s\n", paired?paired:(char*)"none");
1065 SerialTemp.printf("Connected = %s\n", connectedBLEDeviceName_mainModule()?connectedBLEDeviceName_mainModule():(char*)"none");
1066
1068 sprintf(pubString,"{'dev':'!%s & !%s'",deviceName_mainModule(),connectedBLEDeviceName_mainModule());
1069 else if (isPaired)
1070 sprintf(pubString,"{'dev':'!%s & !%s'",deviceName_mainModule(),getPreference_mainModule(PREFERENCE_PAIRED_DEVICE_SETTING));
1071 else
1072 sprintf(pubString,"{'dev':'!%s'",deviceName_mainModule());
1073 strcat(pubString,",'cmd':'feed'}");
1075 }
1076
1077
1078 //SerialTemp.println("async_send_feed.3");
1079//TODO: 7.26.22 .. decide if this logic makes sense:
1080 //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).
1081 //sendMessageMQTT((char *)"#FEED");
1082#endif // USE_MQTT_NETWORKING
1083 break;
1084#endif
1085
1086 case ASYNC_CALL_BUZZ_ON:
1088 {
1089 boolean isBuzzOn = (i == ASYNC_CALL_BUZZ_ON);
1090 //! set the persistence (Note, this is locally saved. If sending elsewhere .. then they have to set their value)
1092
1093 SerialDebug.printf("ASYNC_CALL_BUZZ %d\n",isBuzzOn);
1094 String cmdToSend;
1095 if (isBuzzOn)
1096 cmdToSend = "{'cmd':'buzzon'}";
1097 else
1098 cmdToSend = "{'cmd':'buzzoff'}";
1099
1100 //!OK: issue.
1101 //! if we are an ESP feeder, the STEPPER is on .. so we're good,
1102 //! if an M5 - then either send over BLE or MQTT
1103#ifdef ESP_M5
1104 //!send via BLE or MQTT ..
1105#ifdef USE_BLE_CLIENT_NETWORKING
1106 //! returns whether connected over BLE as a client to a server(like a ESP feeder)
1107 if (!isConnectedBLEClient())
1108 {
1109 SerialLots.println("async_call_buzz_on/off -- not BLE connected.. send MQTT");
1110 //! If not connected over BLE -- then send the MQTT buzzon message..
1111#ifdef USE_MQTT_NETWORKING
1112 sendMessageMQTT((char*)cmdToSend.c_str());
1113#endif
1114 }
1115 else
1116 {
1117 //!send over BLE...
1118 sendCommandBLEClient(cmdToSend);
1119 }
1120#endif //USE_BLE_CLIENT
1121#else //not M5
1122
1123#ifdef USE_BLE_CLIENT_NETWORKING
1124 //! returns whether connected over BLE as a client to a server(like a ESP feeder)
1125 if (!isConnectedBLEClient())
1126 {
1127 SerialLots.println("async_call_buzz_on -- not BLE connected.. send MQTT");
1128 //! If not connected over BLE -- then send the MQTT buzzon message..
1129#ifdef USE_MQTT_NETWORKING
1130 sendMessageMQTT((char *)cmdToSend.c_str());
1131#endif
1132 }
1133 else
1134 {
1135 SerialLots.println("async_call_buzz_on -- YES BLE connected.. send BLE");
1136 processClientCommandChar_mainModule(isBuzzOn?'B':'b');
1137
1138 }
1139#else //(so we are a feeder.. or another bridge .. doit)
1140 //! we are not BLE_CLIENT .. so local
1141 SerialDebug.println("Local, doit");
1142 processClientCommandChar_mainModule(isBuzzOn?'B':'b');
1143
1144#endif //USE_BLE_CLIENT_NETWORKING
1145#endif // ESP_M5
1146 }
1147 break;
1148
1149 //!setGatewayOn/Off called from the processJSON message in MQTT
1150 //! or via the EPROM setting (TODO)
1152 SerialLots.println("ASYNC_SET_GATEWAY_ON");
1154
1155 break;
1156
1158 SerialLots.println("ASYNC_SET_GATEWAY_OFF");
1160
1161 break;
1162
1163 case ASYNC_REBOOT:
1164 SerialLots.println("ASYNC_REBOOT");
1166
1167 break;
1168
1169 case ASYNC_POWEROFF:
1170 SerialLots.println("ASYNC_POWEROFF");
1172
1173 break;
1174 case ASYNC_BLANKSCREEN:
1175 SerialDebug.println("ASYNC_BLANKSCREEN");
1177 break;
1179 //!sends the status from the main module URL
1180#ifdef USE_MQTT_NETWORKING
1181 {
1182 char *statusURL = main_currentStatusURL();
1183 SerialDebug.print(" ASYNC_SEND_MQTT_STATUS_URL: ");
1184 SerialDebug.println(statusURL);
1185 /// NO MORE: sendDocFollowMessageMQTT(statusURL);
1186 sendStatusMessageMQTT(statusURL);
1187 }
1188#endif
1189 break;
1190
1191 case ASYNC_SWAP_WIFI:
1192 case ASYNC_NEXT_WIFI:
1193 {
1194 //NOTE: this might be where we toggle credentials?? TODO
1195 //found other one..
1196 char *credentials = main_nextJSONWIFICredential();
1197#ifdef USE_MQTT_NETWORKING
1198
1199 //!These are the ASYNC_CALL_PARAMETERS_MAX
1200 //!NO: just change our credentials ...
1201 //send to
1202 //main_dispatchAsyncCommandWithString(ASYNC_CALL_BLE_CLIENT_PARAMETER, credentials);
1204#endif
1205 }
1206 break;
1208#ifdef USE_MQTT_NETWORKING
1209 //!Restarts (or attempts) a restart of the WIFI using the existing credentials -- vs the 'n' command
1211#endif
1212 break;
1213 default:
1214 SerialLots.printf("NO COMMAND: %s", i);
1215 }
1216 }
1217 }
1218}
1219
1220
1221//define a couple lights .. maybe move somewhere else..
1222char* _ON_LIGHT = (char*)"ON";
1223char* _OFF_LIGHT = (char*)"OFF";
1224
1225//!callback for blinking led
1226void blinkMessageCallback(char *message)
1227{
1228
1229#ifdef ESP_M5
1230
1231 //call the already defined blink led
1232 // devined in Dispense.cpp
1233// digitalWrite(LED, HIGH);
1234// delay(150);
1235// digitalWrite(LED, LOW);
1236
1237#else //not M5
1238 //call the already defined blink led
1239 // defined in Dispense.cpp
1240 // stepperModule_BlinkLED();
1242#endif //ESP_M5
1243}
1244
1245//!callback for SOLID blinking led
1246void solidLightMessageCallback(char *message)
1247{
1248 SerialLots.println("solidLightMessageCallback..");
1249#ifdef ESP_M5
1250#else
1251 //!call the already defined solid led
1252 //! defined in Dispense.cpp
1253 boolean lightOn = true;
1254 lightOn = strstr(&message[0], _ON_LIGHT);
1255 solidLightOnOff_UIModule(lightOn);
1256#endif
1257}
1258
1259//!clean the SSID eprom (MQTT_CLEAN_SSID_EPROM)
1261{
1262 //!call the already defined solid led
1263 //! defined in Dispense.cpp
1264#ifdef USE_WIFI_AP_MODULE
1265 //!clean_SSID_WIFICredentials();
1266 //!now register an async call..
1268#endif //USE_WIFI_AP_MODULE
1269
1270}
1271
1272//!called on single click
1273//!NOTE: with BLE_CLIENT_NETWORKING, the right button and top button send a BLE command for feeding..
1274void singleClickTouched(char *whichButton)
1275{
1276#ifdef USE_WIFI_AP_MODULE
1277 //!for now, only send the FEED command via BLE_CLIENT if turned on. No reboot to AP mode yet..
1278#ifdef USE_BLE_CLIENT_NETWORKING
1279 //!send the async FEED
1280
1281 //! dispatches a call to the command specified. This is run on the next loop()
1283
1284#else
1285 //TODO.. if M5 do this differently..
1287#endif
1288#else //not USE_WIFI_AP_MODULE // never sure of the #elsif syntax..
1289#ifdef USE_BLE_CLIENT_NETWORKING
1290 //send the async FEED
1291 //! dispatches a call to the command specified. This is run on the next loop()
1293#endif
1294#endif //USE_WIFI_AP_MODULE
1295
1296}
1297
1298//!callback for SOLID blinking led
1299void solidLightOnOff(boolean onOff)
1300{
1301#ifdef ESP_M5
1302#else
1303 SerialLots.println("solidLight..");
1304 //!call the already defined solid led
1305 //! defined in Dispense.cpp
1306 boolean lightOn = onOff;
1307 solidLightOnOff_UIModule(lightOn);
1308#endif
1309}
1310
1311
1312
1313//!prints the module configuration by looking at #defines
1314//! Eventually this might be an object returned letting the code
1315//!know a capability is included for runtime (vs compile time) decisions
1317{
1318 //!Module Configuration
1319 SerialDebug.println(" ** #define Module Configuration **");
1320#ifdef ESP_M5
1321 //![x] ESP_M5
1322 SerialMin.println("[x] ESP_M5");
1323#else
1324 SerialInfo.println("[ ] ESP_M5");
1325#endif
1326#ifdef ESP_M5_CAMERA
1327 //![x] ESP_M5
1328 SerialMin.println("[x] ESP_M5_CAMERA");
1329#endif
1330#ifdef ESP_32
1331 //! [x] ESP_32
1332 SerialMin.println("[x] ESP_32");
1333#else
1334 SerialInfo.println("[ ] ESP_32");
1335#endif
1336#ifdef USE_MQTT_NETWORKING
1337 //! [x] USE_MQTT_NETWORKING
1338 SerialMin.println("[x] USE_MQTT_NETWORKING");
1339#else
1340 SerialInfo.println("[ ] USE_MQTT_NETWORKING");
1341#endif
1342#ifdef USE_BLE_SERVER_NETWORKING
1343 //! [x] USE_BLE_SERVER_NETWORKING
1344 SerialMin.println("[x] USE_BLE_SERVER_NETWORKING");
1345#else
1346 SerialInfo.println("[ ] USE_BLE_SERVER_NETWORKING");
1347#endif
1348#ifdef USE_BLE_CLIENT_NETWORKING
1349 //! [x] USE_BLE_CLIENT_NETWORKING
1350 SerialMin.println("[x] USE_BLE_CLIENT_NETWORKING");
1351#else
1352 SerialInfo.println("[ ] USE_BLE_CLIENT_NETWORKING");
1353
1354#endif
1355#ifdef USE_BUTTON_MODULE
1356 // [x] USE_BUTTON_MODULE
1357 SerialMin.println("[x] USE_BUTTON_MODULE");
1358#else
1359 SerialInfo.println("[ ] USE_BUTTON_MODULE");
1360
1361#endif
1362#ifdef USE_WIFI_AP_MODULE
1363 //! [x] USE_WIFI_AP_MODULE
1364
1365 SerialMin.println("[x] USE_WIFI_AP_MODULE");
1366#else
1367 SerialInfo.println("[ ] USE_WIFI_AP_MODULE");
1368
1369#endif
1370#ifdef USE_STEPPER_MODULE
1371 SerialMin.println("[x] USE_STEPPER_MODULE");
1372#else
1373 SerialInfo.println("[ ] USE_STEPPER_MODULE");
1374
1375#endif
1376#ifdef USE_UI_MODULE
1377 SerialMin.println("[x] USE_UI_MODULE");
1378#else
1379 SerialInfo.println("[ ] USE_UI_MODULE");
1380
1381#endif
1382#ifdef USE_DISPLAY_MODULE
1383 SerialMin.println("[x] USE_DISPLAY_MODULE");
1384#else
1385 SerialInfo.println("[ ] USE_DISPLAY_MODULE");
1386
1387#endif
1388#ifdef BOARD
1389 SerialMin.println("[x] BOARD");
1390#else
1391 SerialInfo.println("[ ] BOARD");
1392#endif
1393#ifdef USE_SPIFF_MODULE
1394 SerialMin.println("[x] USE_SPIFF_MODULE");
1395#else
1396 SerialInfo.println("[ ] USE_SPIFF_MODULE");
1397#endif
1398//#ifdef PROTO
1399// SerialMin.println("[x] PROTO");
1400//#else
1401// SerialInfo.println("[ ] PROTO");
1402//#endif
1403
1404 //Set this if the SMART clicker build is used.
1405#ifdef USE_SMART_CLICKER
1406 SerialMin.println("[x] USE_SMART_CLICKER");
1407#else
1408 SerialInfo.println("[ ] USE_SMART_CLICKER");
1409#endif
1410
1411#if (SERIAL_DEBUG_ERROR)
1412 SerialMin.println("[x] SERIAL_DEBUG_ERROR");
1413#endif
1414#if (SERIAL_DEBUG_DEBUG)
1415 SerialMin.println("[x] SERIAL_DEBUG_DEBUG");
1416#endif
1417#if (SERIAL_DEBUG_INFO)
1418 SerialMin.println("[x] SERIAL_DEBUG_INFO");
1419#endif
1420#if (SERIAL_DEBUG_MINIMAL)
1421 SerialMin.println("[x] SERIAL_DEBUG_MINIMAL");
1422#endif
1423
1424 //!and print any preferences to show
1426}
1427
1428
1429//!If nil it create one with just the null, so strlen = 0
1430//!NOTE: the strdup() might be used later..
1431char* createCopy(char * stringA)
1432{
1433 if (stringA)
1434 return strdup(stringA);
1435 else
1436 return strdup("");
1437}
1438
1439//!informs if null or empty string
1440boolean isEmptyString(char *stringA)
1441{
1442 if (!stringA)
1443 {
1444 return true;
1445 }
1446 else if (strlen(stringA) == 0)
1447 {
1448 return true;
1449 }
1450 else
1451 return false;
1452}
1453
1454//!a char* version of startsWith (after skipping spaces)
1455boolean startsWithChar(char *str, char c)
1456{
1457 if (!str) return false;
1458 //!find first non space character, and if not '{' then return false
1459 int i = 0;
1460 while (i < strlen(str))
1461 {
1462 //!jump out if not a space, and 'i' will be the thing to look for
1463 if (str[i] != ' ')
1464 break;
1465 i++;
1466 }
1467
1468 if (str[i] == c)
1469 return true;
1470
1471 return false;
1472}
1473
1474//!start of the sensor updates ... TODO: tie these to the MQTT messaging as well..
1476{
1477#ifdef ESP_M5
1478 float batVoltage = M5.Axp.GetBatVoltage();
1479 float batPercentage = (batVoltage < 3.2) ? 0 : ( batVoltage - 3.2 ) * 100;
1480#else
1481 float batPercentage = 87.0;
1482#endif
1483
1484#ifdef ESP_M5
1485 //!#Issue 117
1486 //!from: https://community.m5stack.com/topic/1361/ischarging-and-getbatterylevel/9
1487 //!GetVbatdata() is currently depreciated
1488 uint16_t vbatData = M5.Axp.GetVbatData();
1489 double vbat = vbatData * 1.1 / 1000;
1490 batPercentage = 100.0 * ((vbat - 3.0) / (4.07 - 3.0));
1491#endif
1492 if (batPercentage > 100.0)
1493 batPercentage = 100.0;
1494 return batPercentage;
1495}
1496
1497
1498
1499//!adding a synchronous call to send a message over the network (assuming MQTT but not specified), this tacks on {device} and {t:time}
1500void sendMessageString_mainModule(char *messageString)
1501{
1502#ifdef USE_MQTT_NETWORKING
1503 if (strlen(messageString) < MESSAGE_STORAGE_MAX)
1504 {
1505 //!NOTE: the # has to be there, otherwise the sendMessageMQTT ignores it..
1506 sprintf(_messageStorage,"#%s {%s} {t:%d}", messageString, getDeviceNameMQTT(), getTimeStamp_mainModule());
1507 //!send this message over MQTT
1509 }
1510#endif
1511}
1512
1513//!retrieves the temperature .
1515{
1516#ifdef ESP_M5
1517 //!return celcius
1518 //!float temperature = M5.Axp.GetTempInAXP192();
1519 float temperature;
1520 M5.IMU.getTempData(&temperature);
1521
1523 if (temperature > maxtemp)
1524 {
1525 //! turn off the device after sending a message..
1526 //! let others know we are powering off..
1527 //! then poweroff
1528#ifdef USE_MQTT_NETWORKING
1529 sprintf(_messageStorage,"#Temp %f too high > %d - powering off {%s}", temperature, maxtemp, getDeviceNameMQTT());
1530 //!send this message over MQTT
1532#endif
1533 //! now poweroff
1534 SerialTemp.println(" *** This would poweroff .. but you can send message");
1535 //!poweroff_mainModule();
1536
1537 }
1538
1539#else
1540 float temperature = 10.0;
1541#endif
1542 return temperature ;//* 9/5 + 32;
1543}
1544//!NEW: 4.30.22
1545//!returns a string in JSON format, such that {'battery':'84'}, {'buzzon':'off'} .. etc
1546//!as a URL: SemanticMarker.org/bot/sample/scott@name/password/status?BLE:on&numfeeds=8&WIFI:on&AP:off
1547/** Sample format:
1548{"status": [
1549 {
1550 "BLE": "on"
1551 },
1552 {
1553 "numfeeds": "8",
1554 "maxfeeds": "16"
1555 },
1556 {
1557 "battery": "87"
1558 },
1559 {
1560 "buzzon": "on"
1561 },
1562 {
1563 "MQTT": "on"
1564 },
1565 {
1566 "WIFI": "on"
1567 },
1568 {
1569 "AP": "off"
1570 },
1571 {
1572 "tilt": "55"
1573 }
1574]
1575}
1576*/
1578{
1579 //returns a JSON string..
1580// String b = String(getBatPercentage(),0);
1581// return "{'status':[{'BLE':'on'},{'bat':'" + b + "'}]}";
1582 return NULL;
1583}
1584
1585//! TODO: fix syntax. If just sensor sensor status: ....
1586//!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
1587//!not working just added Z=on/off length = 157
1588//! going to remove the username/password to shorten..
1589
1590
1591//!adds a query string "&key=value"
1592void addStatusStringFlag(const char *key, char * val)
1593{
1594 char buf[50];
1595 sprintf(buf,"&%s=%s", key, val);
1596 strcat(_fullStatusString, buf);
1597}
1598//!adds to _fullStatusString a query string "&key=value"
1599void addStatusBooleanFlag(const char *key, boolean flag)
1600{
1601 addStatusStringFlag(key, flag?(char*)"on":(char*)"off");
1602
1603}
1604//!sets the "Module Status"
1605//!in queryString == name=val&name=val ...
1607{
1608 //!value of WIFI connected
1609#ifdef USE_MQTT_NETWORKING
1612#endif
1613#ifdef USE_BLE_CLIENT_NETWORKING
1614 //useBLECLient == it's linked in and running (vs not running)
1616 //! connected == we are connected to another BLEServer
1618
1619#endif
1620#ifdef USE_WIFI_AP_MODULE
1621 //!not done is what we look for ..
1623#endif
1625
1626#ifdef USE_BLE_SERVER_NETWORKING
1628 {
1629 //! add a bleS=PTFeeder:name
1630 char *serverBLEName = getServiceName_BLEServerNetworking();
1631 addStatusStringFlag((char*)"bleS",serverBLEName);
1632 }
1633#endif
1634
1635 //!show Z for buZZ
1637
1638 //!show G for gateway
1640
1641 //!P = paired
1644#ifdef NO_MORE_PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
1645
1648#endif
1649 {
1650 addStatusStringFlag("P", pairedDeviceName);
1651 }
1652}
1653
1654//!returns a string in in URL so: status?battery=84'&buzzon='off' } .. etc
1656{
1657
1658#ifdef USE_MQTT_NETWORKING
1659 char *deviceName = getDeviceNameMQTT();
1660 //!TODO: make sure no spaces ... unless escaped
1661 sprintf(_fullStatusString,"status?v=%s&dev=%s&b=%2.0f&temp=%2.0f&c=%0d&t=%0d",VERSION_SHORT, deviceName, getBatPercentage_mainModule(), getTemperature_mainModule(), getFeedCount_mainModule(), getLoopTimer_displayModule());
1662
1663#else
1664 //!TODO: make sure no spaces ... unless escaped
1665 sprintf(_fullStatusString,"status?v=%s&b=%2.0f&temp=%2.0f&c=%0d&t=%0d",VERSION_SHORT, getBatPercentage_mainModule(), getTemperature_mainModule(), getFeedCount_mainModule(), getLoopTimer_displayModule());
1666#endif
1667
1668 //add to _fullStatusString
1670
1671// //NOTE: any new query from somewhere starts with & (they put it in)
1672
1673 SerialCall.println( _fullStatusString );
1674
1675 //!TODO: put these somewhere somehow (expandable easily..architecturally. eg. setStatus("battery","87") key,val
1676 //!the JSON DB supports db["battery"]=87 like syntax..
1677
1678 //return "status?buzzon=off&AP=off&MQTT=on&WIFI=on&BLE=on&battery=" + String(getBatPercentage(),0);
1679 return _fullStatusString;
1680}
1681
1682#ifdef UNDEFINED
1683//!sets status parts cia a a string in JSON format, such that {'battery':'84'}, {'buzzon':'off'} .. etc
1684void main_setStatusJSON(const char* JSONString)
1685{
1686 //would set the JSON string
1687}
1688//!sets status parts cia a a string in JSON format, such that {'battery':'84'}, {'buzzon':'off'} .. etc
1689void main_setStatusKeyValue(const char* key, const char* value)
1690{
1691 //todo..
1692}
1693#endif
1694
1695//!SemanticMarker events
1696//!This would see a DOCFollow message, and set the value.. then SM10 can display it..
1698//!sed the address to follow
1699void setSemanticMarkerDocFollow_mainModule(char* SMDocFollowAddress)
1700{
1701 _lastSemanticMarkerDocFollow = SMDocFollowAddress;
1704}
1705//!gets the semanticAddress SemanticMarker&trade;
1707{
1709}
1710
1711
1712//!sends the SM on the DOCFOLLOW channel (publish it..)
1713void sendSemanticMarkerDocFollow_mainModule(const char* SMDocFollowAddress)
1714{
1715#ifdef USE_MQTT_NETWORKING
1716 sendDocFollowMessageMQTT(SMDocFollowAddress);
1717#endif
1718
1719}
1720
1721//!Keep ProcessClientCmd short to let the callback run. instead change the feeder state flag
1722//! processes a message that might save in the EPROM.. the cmd is still passed onto other (like the stepper module)
1724{
1725 //!the sentToStepper is only needed if there are 'actions' on the command, versus just
1726 //! setting persistent EPROM data. Like feed, buzzer, etc..
1727 //!Thus we don't need to know much of their implementation.. or we just pass anyway!
1728 boolean sendToStepperModule = false;
1729 SerialDebug.printf("***** processClientCommand_mainModule(%c) from client*****\n", cmd);
1730
1731 //char cmd = message[0];
1732 //!only process things that are stored persistently..
1733 if ((cmd == 0x00) || (cmd == 's') || (cmd == 'c'))
1734 {
1735 sendToStepperModule = true;
1736 }
1737 else if (cmd == 'a')
1738 {
1739
1740 SerialDebug.println("cmd=a startTimer");
1741 //!start timer..
1743
1744 }
1745 else if (cmd == 'A')
1746 {
1747
1748 SerialDebug.println("cmd=A stopTimer");
1749
1750 //!start timer..
1752
1753 }
1754 else if (cmd == 'j')
1755 {
1756 sendToStepperModule = true;
1757 SerialLots.println("Setting FeedState = JACKPOT_FEED");
1759
1760 }
1761 else if (cmd == 'u')
1762 {
1763 SerialLots.println("Setting feederType = UNO");
1765 }
1766 else if (cmd == 'm')
1767 {
1768 SerialLots.println("Setting feederType = MINI");
1769 //save preference
1771 }
1772 else if (cmd == 'L')
1773 {
1774 SerialLots.println("Setting feederType = Tumbler");
1775 //save preference
1777 }
1778 else if (cmd == 'B')
1779 {
1780 sendToStepperModule = true;
1781 SerialDebug.println("Setting buzzStatus = BUZZON");
1782 //save pref
1784 }
1785 else if (cmd == 'b')
1786 {
1787 sendToStepperModule = true;
1788
1789 SerialDebug.println("Setting buzzStatus = BUZZOFF");
1791 }
1792 else if (cmd == 'T')
1793 {
1794 SerialDebug.println("*** Setting tilt = ON");
1796 }
1797 else if (cmd == 't')
1798 {
1799 SerialDebug.println("Setting tilt = OFF");
1801 }
1802 else if (cmd == 'R')
1803 {
1804 SerialLots.println("Clean Credentials");
1805 //! dispatches a call to the command specified. This is run on the next loop()
1807 }
1808 else if (cmd == 'O')
1809 {
1810 SerialLots.println("OTA Update.. ");
1811 //! dispatches a call to the command specified. This is run on the next loop()
1813 }
1814 else if (cmd == 'X')
1815 {
1816 SerialLots.println("Clean EPROM.. ");
1817 //! dispatches a call to the command specified. This is run on the next loop()
1819 }
1820
1821 //!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)
1822 else if (cmd == 'G')
1823 {
1824 SerialLots.println("Setting Gateway = ON");
1826 }
1827 else if (cmd == 'g')
1828 {
1829 SerialLots.println("Setting Gateway = OFF");
1831 }
1832 else if (cmd == '_')
1833 {
1834 //This is from the handshake like "_BLEClient_ESP_M5"
1835 SerialLots.println("unused cmd '_'");
1836 }
1837 else if (cmd == 'Z')
1838 {
1839 sendToStepperModule = false;
1840
1841 SerialLots.println("Setting SM Zoom = zoomed");
1843 }
1844 else if (cmd == 'z')
1845 {
1846 sendToStepperModule = false;
1847
1848 SerialLots.println("Setting SM Zoom = full SM");
1850 }
1851 else if (cmd == 'N')
1852 {
1853 //NOTE: this might be where we toggle credentials?? TODO
1854 //found other one..
1855 char *credentials = main_JSONStringForWIFICredentials();
1856
1857 //!These are the ASYNC_CALL_PARAMETERS_MAX
1859 }
1860 else if (cmd == 'n')
1861 {
1862 //!NOTE: this is almost the same as 'w' except there might be more WIFI than 2 (so swap is different).
1864 }
1865 else if (cmd == 'W')
1866 {
1868 }
1869 else if (cmd == 'w')
1870 {
1871 SerialTemp.println("w for swapWifi");
1872
1874 }
1875 else if (cmd == 'P')
1876 {
1877 //printout the spiff.. to the serial debug monitor
1878 //!Restarts (or attempts) a restart of the WIFI using the existing credentials -- vs the 'n' command
1880 }
1881 else if (cmd == 'D')
1882 {
1883 // motor direction = counterclockwise
1885 }
1886 else if (cmd == 'd')
1887 {
1888 // motor direction == (clockwise)
1890 }
1891 else if (cmd == 'E')
1892 {
1893 //!if set, the BLE Server (like PTFeeder) will tack on the device name (or none if not defined).
1895 // reboot
1897 }
1898 else if (cmd == 'e')
1899 {
1900 //!if set, the BLE Server (like PTFeeder) will tack on the device name (or none if not defined).
1902 // reboot
1904 }
1905 else if (cmd == 'r')
1906 {
1907 // reboot
1909 }
1910 else if (cmd == 'H')
1911 {
1912
1913 SerialLots.println("Valid Commands: ");
1914 SerialLots.println(" H == help, this message");
1915 SerialLots.println(" 0x0, s, c == Single Feed ");
1916 SerialLots.println(" a == AutoFeed On");
1917 SerialLots.println(" A == AutoFeed Off");
1918 SerialLots.println(" u == UNO ");
1919 SerialLots.println(" m == MINI ");
1920 SerialLots.println(" L == tumbler");
1921 SerialLots.println(" D == counterclockwise motor direction");
1922 SerialLots.println(" d == clockwise motor direction");
1923
1924 SerialLots.println(" B == Buzzer On");
1925 SerialLots.println(" b == Buzzer Off");
1926 SerialLots.println(" G == Gateway On");
1927 SerialLots.println(" g == Gateway Off");
1928 SerialLots.println(" R == clean credentials");
1929 SerialLots.println(" X == clean EPROM");
1930 SerialLots.println(" r == reboot ");
1931 SerialLots.println(" O == OTA update");
1932 SerialLots.println(" T == tiltOn");
1933 SerialLots.println(" t == tiltOff");
1934 SerialLots.println(" N == send WIFI Credential to BLEServer");
1935 SerialLots.println(" n == next WIFI Credential");
1936 SerialLots.println(" W == retry WIFI");
1937 SerialLots.println(" w == swap WIFI");
1938 SerialLots.println(" P == print SPIFF");
1939 SerialLots.println(" E == use only PTFeeder naming");
1940 SerialLots.println(" e == use naming PTFeeder:name");
1941 SerialLots.println(" Z == Setting SM Zoom = zoomed");
1942 SerialLots.println(" z == Setting SM Zoom = full SM");
1943
1944 //!print out stuff
1946
1947 }
1948 else
1949 {
1950 SerialLots.printf("*****invalid command '%c' from client*****\n", cmd);
1951 }
1952
1953#ifdef USE_STEPPER_MODULE
1954 if (sendToStepperModule)
1955 {
1957 }
1958#endif
1959}
1960
1961
1962//!On the esp32, sec is all we can handle. We can return as a double if milisecond resolution is needed.
1963//!This is the time since app started..
1964//!https://randomnerdtutorials.com/epoch-unix-time-esp32-arduino/
1966{
1967
1968 time_t now;
1969 struct tm timeinfo;
1970 time(&now);
1971 SerialLots.printf("Unix Time: %d\n", now);
1972 return now;
1973}
1974
1975//! ************** SM Mode Processing ***************
1976
1977
1978//!returns an index from 0..max of SM matching cmd, or -1 if none
1980{
1981 //https://www.cplusplus.com/reference/cstring
1982 if (strncmp(cmd,"sm",2) == 0)
1983 {
1984 //point to the 'm' in 'sm'
1985 char *p = strchr(cmd,'m');
1986 //then increment
1987 p++;
1988 //convert to a number
1989 int num = atoi(p);
1990 //convert to integer..
1991 SerialLots.print("whichSMMode: ");
1992 SerialLots.print(cmd);
1993 SerialLots.print(" => " );
1994 SerialLots.println(num);
1995 return num;
1996 }
1997 else
1998 {
1999 return -1;
2000 }
2001}
2002//!returns if a match the mode. whichSMMode is 0..12 and == sm0 .. smn
2003boolean matchesSMMode_mainModule(char *cmd, int whichSMMode)
2004{
2005 char *mode = charSMMode_mainModule(whichSMMode);
2006 return (strcasecmp(cmd,mode)==0);
2007}
2008//!returns string form whichSMMode, sg "sm0", sm1 ...
2009//!This can (and is) called by multiple places (like ButtonProcessing and MainModule
2010char* charSMMode_mainModule(int whichSMMode)
2011{
2012 SerialLots.printf("charSMMode_mainModule: %d\n", whichSMMode);
2013
2014 sprintf(_smMode_MainModule,"sm%0d",whichSMMode);
2015 SerialCall.println(_smMode_MainModule);
2016 return _smMode_MainModule;
2017}
2018
2019//!returns which mode in (min or expanded)
2021{
2023}
2024
2025//!toggles the menu mode
2027{
2029}
2030
2031//! returns the current max of the MIN menu modes (using the setting of min or expanded) to determine
2033{
2034 return MAX_SM_MIN_MODES;
2035}
2036
2037//! returns the current max of the menu modes (using the setting of min or expanded) to determine
2039{
2040 SerialLots.printf("maxMenuModes_mainModule: %s, %d, %d\n", isMinimalMenuMode_mainModule?"1":"0", MAX_SM_MIN_MODES, MAX_SM_EXPANDED_MODES);
2042 return MAX_SM_MIN_MODES;
2043 else
2044 return MAX_SM_EXPANDED_MODES;
2045
2046}
2047
2048//!the saved SMMode
2050//!sets the current screen mode .. which can be used by Button and Display processing
2051void setCurrentSMMode_mainModule(int whichSMMode)
2052{
2053 SerialLots.print("setCurrentSMMode_mainModule:");
2054 SerialLots.println(whichSMMode);
2055
2056 // This version sets the MIN OR MAX
2057 if (whichSMMode >= MAX_SM_MIN_MODES)
2058 {
2059 // change to EXPANDED MODES
2061 }
2062 _saveWhichSMMode = whichSMMode;
2063}
2064//!returns the current SM Mode
2066{
2067 return _saveWhichSMMode;
2068}
2069
2070//!increment the currentSMMode, wrapping and using the max menu
2072{
2074 int max = maxMenuModes_mainModule();
2075 if (_saveWhichSMMode >= max)
2076 {
2077 _saveWhichSMMode = 0;
2078 }
2079 SerialTemp.print("incrementSMMode_mainModule:");
2080 SerialTemp.println(_saveWhichSMMode);
2081}
2082//!increment the currentSMMode, wrapping and using the max menu
2084{
2085 if (_saveWhichSMMode > 0)
2086 {
2088 }
2089}
2090
2091
2092//!full: ""Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
2094{
2095#ifdef USE_BLE_CLIENT_NETWORKING
2096
2098 return _fullBLEDeviceName;
2099 else
2100#endif
2101 {
2102 return (char*)"";
2103 }
2104}
2105
2106//!whether connected GEN3
2107boolean _connecteBLEisGEN3 = false;
2108//!whether the connected is a GEN3 (so the name isn't valid)
2110{
2111 return _connecteBLEisGEN3;
2112}
2113
2114//! BLE Discovery Methods
2115//! Connected to a BLE device with the advertised name. The syntax can include (PTFeeder:NAME) or just PTFeeder
2116//! Being disconnected is already a flag isConnectedBLE ...
2117void setConnectedBLEDevice_mainModule(char *deviceName, boolean isGEN3)
2118{
2119 //!set the isGEN3 flag
2120 _connecteBLEisGEN3 = isGEN3;
2121 //!now set the gateway based on if GEN3
2122 SerialTemp.printf("auto-settingGateway(%d)\n", isGEN3);
2124
2125 strcpy(_fullBLEDeviceName, deviceName);
2126
2127 //!seems device name = "Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead
2128 //!Note: the Address, eg "7c:9e:bd:48:af:92" is unique somehow.. lets use that to skip one..
2129 SerialCall.printf("setConnectedBLEDevice_mainModule: %s\n", deviceName);
2130 strcpy(_connectedBLEDeviceName,"");
2131
2132 if (containsSubstring(deviceName,"PTFeeder:") || containsSubstring(deviceName,"PTClicker:"))
2133 {
2134 //!parse out the 2nd half of name
2135 char *colon = index(deviceName,':');
2136 colon++;
2137 colon = index(colon,':');
2138 //! go past the :
2139 colon++;
2140
2141 while (*colon && *colon != ',')
2142 {
2143 int len = strlen(_connectedBLEDeviceName);
2144 _connectedBLEDeviceName[len] = colon[0];
2145 _connectedBLEDeviceName[len+1] = '\0';
2146 colon++;
2147 }
2148 }
2149 else
2150 {
2151 //! empty name (just PTFeeder)
2152 strcpy(_connectedBLEDeviceName,(char*)"");
2153 }
2154 SerialTemp.print("connectedBLEName= ");
2155 SerialTemp.println(_connectedBLEDeviceName);
2156
2157
2158 //!parse for the address too..
2159 //! strcpy(_fullBLEDeviceName, deviceName);
2160
2161 //!seems device name = "Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead
2162 //!Note: the Address, eg "7c:9e:bd:48:af:92" is unique somehow.. lets use that to skip one..
2163 strcpy(_connectedBLEDeviceAddress,"");
2164 if (containsSubstring(_fullBLEDeviceName,"Address:"))
2165 {
2166 //!parse out the 2nd half of name
2167 char *colon = strstr(_fullBLEDeviceName,"Address:");
2168 colon += strlen("Address:");
2169 //strip spaces
2170 while (*colon && *colon == ' ')
2171 {
2172 colon++;
2173 }
2174 //now until the , is the address
2175 while (*colon && *colon != ',')
2176 {
2177 int len = strlen(_connectedBLEDeviceAddress);
2178 _connectedBLEDeviceAddress[len] = colon[0];
2179 _connectedBLEDeviceAddress[len+1] = '\0';
2180 colon++;
2181 }
2182 }
2183 else
2184 {
2185 //! empty name (just PTFeeder)
2186 strcpy(_connectedBLEDeviceAddress,(char*)"");
2187 }
2188 SerialTemp.print("_connectedBLEDeviceAddress= ");
2189 SerialTemp.println(_connectedBLEDeviceAddress);
2190}
2191
2192//!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)
2193//! returns the connected BLE Device name (the :NAME of advertisment, Address: 01:39:3f:33 part of name
2195{
2196 char *nameToUse;
2197 if (strlen(_connectedBLEDeviceName)!= 0)
2198 nameToUse = _connectedBLEDeviceName;
2199 else if (strlen(_connectedBLEDeviceAddress)!= 0)
2200 nameToUse =_connectedBLEDeviceAddress;
2201 else
2202 nameToUse = (char*)"";
2203
2204#ifdef USE_BLE_CLIENT_NETWORKING
2205
2206 //! if connected, return the connected name, otherwise return empty string
2208 {
2209 return nameToUse;
2210 }
2211 else
2212#endif
2213 {
2214 return (char*)"";
2215 }
2216}
2217
2218//!returns address part of name.
2220{
2221#ifdef USE_BLE_CLIENT_NETWORKING
2222
2223 //! if connected, return the connected name, otherwise return empty string
2225 {
2227 }
2228 else
2229#endif
2230 {
2231 return (char*)"";
2232 }
2233}
2234
2235
2236//! BUTTON PROCESSING abstraction
2237//!short press on buttonA (top button)
2239{
2240#ifdef USE_BUTTON_MODULE
2242#endif
2243}
2244//!long press on buttonA (top button)
2246{
2247#ifdef USE_BUTTON_MODULE
2249#endif
2250}
2251//!the long press of the side button
2253{
2254#ifdef USE_BUTTON_MODULE
2256#endif
2257}
2258//!the short press of the side button
2260{
2261#ifdef USE_BUTTON_MODULE
2263#endif
2264}
2265
2266//!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
2268{
2269 //!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
2271}
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)
void buttonB_ShortPress_ButtonModule()
the short press of the side button
void buttonB_LongPress_ButtonModule()
the long press of the side button
void buttonA_ShortPress_ButtonModule()
void refreshDelayButtonTouched_ButtonModule()
called by the feed operation to say the device is still running.. and count it as a button click.
void buttonA_LongPress_ButtonModule()
long press on buttonA (top button)
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 publishMQTTMessageDefaultTopic(char *message)
Wrapper of the mqttclient publish.
void cleanEPROM_MQTTNetworking()
cleans the eprom info
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 sendDocFollowMessageMQTT(const char *semanticMarker)
sends the semantic marker as a doc follow message
boolean isConnectedMQTT_MQTTState()
value of MQTT connected
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
void cleanEpromPreferences()
cleans the EPROM
Definition: MainModule.cpp:638
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:280
#define MESSAGE_STORAGE_MAX
global for others to use..
Definition: MainModule.cpp:35
boolean _connecteBLEisGEN3
whether connected GEN3
void setAsyncCallOTAUpdate(bool flag)
sets the async OTA flag (for next loop)
Definition: MainModule.cpp:551
void main_cleanSavedWIFICredentials()
clean the saved WIFI credential, otherwise the AP mode doesn't work (6.3.22)
Definition: MainModule.cpp:726
char _fullStatusString[300]
status string (URL query format)
Definition: MainModule.cpp:38
boolean _asyncCallOTAUpdateFlag
3.28.22 .. implemented in ESP_IOT.ino
Definition: MainModule.cpp:544
boolean _stopAllProcessing
testing..
Definition: MainModule.cpp:9
void takePicture_MainModule()
take a picture (calls the camera module).. what to do with picture??? TODO
Definition: MainModule.cpp:528
#define CALLBACKS_MQTT
Definition: MainModule.cpp:221
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...
Definition: MainModule.cpp:741
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:50
#define CALLBACKS_MAX_BLE_SERVER
Definition: MainModule.cpp:238
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:266
void toggleMinimalMenuMode_mainModule()
toggles the menu mode
char * charSMMode_mainModule(int whichSMMode)
returns string form whichSMMode, sg "sm0", sm1 ...
char * _OFF_LIGHT
char _smMode_MainModule[10]
current smMode
Definition: MainModule.cpp:40
void loop_mainModule()
called for the loop() of this plugin
Definition: MainModule.cpp:114
char * getSemanticMarkerDocFollow_mainModule()
gets the semanticAddress SemanticMarker™
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:316
char * deviceName_mainModule()
gets the device name
Definition: MainModule.cpp:607
void dummyCallbackMain(char *message)
example callback
Definition: MainModule.cpp:242
#define CALLBACKS_MAX_MQTT
Definition: MainModule.cpp:235
void initGlobals_mainModule()
init globals strings
Definition: MainModule.cpp:55
char _deviceNameSave[50]
saved deviceName storage..
Definition: MainModule.cpp:42
boolean connectedBLEDeviceIsGEN3_mainModule()
whether the connected is a GEN3 (so the name isn't valid)
int minMenuModesMax_mainModule()
returns the current max of the MIN menu modes (using the setting of min or expanded) to determine
#define CALLBACKS_BLE_SERVER
Definition: MainModule.cpp:224
boolean _asyncCallFlags[ASYNC_CALL_MAX]
storage for asyncCallCommands
Definition: MainModule.cpp:764
void processClientCommandChar_mainModule(char cmd)
single character version of processClientCommand (since many used that already)
int getFeedCount_mainModule()
feedcount info..
Definition: MainModule.cpp:155
void onStatusMessageBLEServerCallback(char *message)
The callback for "status messages" of the bluetooth.
Definition: MainModule.cpp:411
char * main_currentStatusURL()
returns a string in in URL so: status?battery=84'&buzzon='off' } .. etc
char * main_JSONStringForWIFICredentials()
retrieve a JSON string for the ssid and ssid_password: {'ssid':<ssid>,'ssidPassword':<pass>"}
Definition: MainModule.cpp:663
int feedCountMax_mainModule()
returns the max for this feeder
Definition: MainModule.cpp:137
void solidLightOnOff(boolean onOff)
callback for SOLID blinking led
void main_credentialsUpdated()
moved here 4.25.22 (entirely from ESP_IOT.ino)
Definition: MainModule.cpp:392
void setup_mainModule()
called from the setup()
Definition: MainModule.cpp:72
boolean stopAllProcesses_mainModule()
if stopped
Definition: MainModule.cpp:21
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
int whichSMMode_mainModule(char *cmd)
************** SM Mode Processing ***************
int _mainLoopCounter
a couinter to slow down the loop doing things..
Definition: MainModule.cpp:110
void main_dispatchAsyncCommandWithString(int asyncCallCommand, char *parameter)
Definition: MainModule.cpp:807
char _bigMessage[500]
Definition: MainModule.cpp:46
void initAsyncCallFlags()
initialize the async call flags (with and without parameters)
Definition: MainModule.cpp:770
void solidLightMessageCallback(char *message)
callback for SOLID blinking led
boolean isEmptyString(char *stringA)
informs if null or empty string
void rebootDevice_mainModule()
Definition: MainModule.cpp:616
void poweroff_mainModule()
power off
Definition: MainModule.cpp:623
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
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:196
void decrementSMMode_mainModule()
increment the currentSMMode, wrapping and using the max menu
void onWriteBLEServerCallbackFinish(char *message)
The FINISH of callback for "onWrite" of the bluetooth "onWrite'.
Definition: MainModule.cpp:420
void callCallbackMain(int callbacksModuleId, int callbackType, char *message)
performs the indirect callback based on the callbackType
Definition: MainModule.cpp:333
int getCurrentSMMode_mainModule()
returns the current SM Mode
boolean _waitingForBigMessageEnd
store a big message #MSG_START .. #MSG_END
Definition: MainModule.cpp:45
void stopProcessesForOTAUpdate_mainModule()
stop all loops... while OTA working..
Definition: MainModule.cpp:11
void feedMessageCallback(char *message)
Definition: MainModule.cpp:352
void resetFeedCount_mainModule()
sets the feed count max
Definition: MainModule.cpp:190
boolean asyncCallOTAUpdate()
performs an async OTA update
Definition: MainModule.cpp:546
void sendMessageString_mainModule(char *messageString)
adding a synchronous call to send a message over the network (assuming MQTT but not specified),...
char * main_currentStatusJSON()
returns a string in JSON format, such that {'battery':'84'}, {'buzzon':'off'} .. etc
void(* callbackSignature)(char *)
Definition: MainModule.cpp:262
char * getFullBLEDeviceName_mainModule()
full: ""Name: PTFeeder:HowieFeeder, Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
int getFeederType_mainModule()
get the feeder type (Sepper 1,2,3 ...)
Definition: MainModule.cpp:161
char _connectedBLEDeviceName[50]
saved BLE connected name 8.26.22
Definition: MainModule.cpp:48
char * _lastSemanticMarkerDocFollow
char _connectedBLEDeviceAddress[50]
full: ""Address: 7c:9e:bd:48:af:92, serviceUUID: 0xdead"
Definition: MainModule.cpp:52
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 ...
Definition: MainModule.cpp:829
#define CALLBACKS_MAX_BLE_CLIENT
Definition: MainModule.cpp:237
boolean startsWithChar(char *str, char c)
a char* version of startsWith (after skipping spaces)
callbackSignature * _allCallbacks[CALLBACKS_MODULE_MAX]
array of known size (CALLBACKS_MODULE_MAX) of callbackSignatures
Definition: MainModule.cpp:277
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:588
char * getPairedDevice_mainModule()
returns if the paired device is not NONE
Definition: MainModule.cpp:557
void onWriteBLEServerCallback(char *message)
The callback for "onWrite" of the bluetooth "onWrite'.
Definition: MainModule.cpp:511
boolean _callbacksInitializedMain
flag for initializing if not yes
Definition: MainModule.cpp:259
#define CALLBACKS_BLE_CLIENT
Definition: MainModule.cpp:223
void main_dispatchAsyncCommand(int asyncCallCommand)
checks if any async commands are in 'dispatch' mode, and if so, invokes them, and sets their flag to ...
Definition: MainModule.cpp:789
char _JSONStringForWIFICredentials[200]
global to store credentials when ever they are stored..
Definition: MainModule.cpp:33
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:135
int _saveWhichSMMode
the saved SMMode
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:536
char * connectedBLEDeviceName_mainModule()
returns the connected BLE Device name (the :NAME of advertisment, Address: 01:39:3f:33 part of name,...
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:31
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:16
char * createCopy(char *stringA)
#define CALLBACKS_MAX_BUTTON_MODULE
Definition: MainModule.cpp:236
boolean _asyncCallFlagsParameters[ASYNC_CALL_PARAMETERS_MAX]
array of async flags for the different ASYNC_CALl values
Definition: MainModule.cpp:766
void main_printModuleConfiguration()
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:569
char * main_nextJSONWIFICredential()
! cycle through the next WIFI saved credential
Definition: MainModule.cpp:669
void onBLEServerCallback(char *message)
The callback for "onWrite" of the bluetooth "onWrite'.
Definition: MainModule.cpp:404
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:222
char _messageStorage[MESSAGE_STORAGE_MAX]
Definition: MainModule.cpp:36
void incrementFeedCount_mainModule()
increments .. and if MAX goes to 0 – and sends a message on MQTT
Definition: MainModule.cpp:168
void main_saveWIFICredentials(char *ssid, char *ssid_password)
save the WIFI credential
Definition: MainModule.cpp:696
void readPreferences_mainModule()
MainModule
char * getPairedDeviceAddress_mainModule()
returns if the paired device is not NONE
Definition: MainModule.cpp:563
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:256
#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:147
#define MAX_SM_MIN_MODES
note for now, heep the max the same – so only goes through zoom or not zoom
Definition: MainModule.h:322
void cleanEPROM_mainModule()
cleans the main module EPROM
#define ASYNC_CALL_MAX
the max one greater than last one
Definition: MainModule.h:176
#define ASYNC_REBOOT
sets the GATEWAY mode off
Definition: MainModule.h:163
#define ASYNC_CALL_BLE_CLIENT_PARAMETER
these are the async with a string parameter. This sends a BLE command
Definition: MainModule.h:179
#define ASYNC_SEND_MQTT_FEED_MESSAGE
sends a message (like FEED) on the users topic
Definition: MainModule.h:153
#define CALLBACKS_MODULE_MAX
Definition: MainModule.h:61
#define ASYNC_CALL_CLEAN_CREDENTIALS
cleans out the credentials and restarts in AP (Access Point) mode.
Definition: MainModule.h:143
#define ASYNC_SWAP_WIFI
swaps WIFI 'w'
Definition: MainModule.h:170
#define ASYNC_SET_GATEWAY_ON
sets the GATEWAY mode on
Definition: MainModule.h:158
#define MAX_SM_EXPANDED_MODES
Definition: MainModule.h:323
#define ASYNC_RESTART_WIFI_MQTT
restarts the WIFI (after BLE interrupt over)
Definition: MainModule.h:174
#define ASYNC_CALL_BUZZ_ON
sends a 'B' to the BLE end of the code (assuming a feeder is connected).
Definition: MainModule.h:149
#define ASYNC_POWEROFF
sets the GATEWAY mode off
Definition: MainModule.h:165
#define ASYNC_CALL_CLEAN_EPROM
cleans the EPROM totally, and reboots
Definition: MainModule.h:145
#define ASYNC_BLANKSCREEN
blank the screen
Definition: MainModule.h:167
#define ASYNC_CALL_PARAMETERS_MAX
the max one greater than last one
Definition: MainModule.h:185
#define ASYNC_SEND_MQTT_STATUS_URL_MESSAGE
sends the status from the main module URL
Definition: MainModule.h:155
#define ASYNC_SET_GATEWAY_OFF
sets the GATEWAY mode off
Definition: MainModule.h:160
#define ASYNC_CALL_OTA_FILE_UPDATE_PARAMETER
these are the async with a string parameter
Definition: MainModule.h:181
#define ASYNC_CALL_OTA_UPDATE
TODO: make this a registeration approach.
Definition: MainModule.h:141
#define TOPIC_TO_SEND
Definition: MainModule.h:41
#define ASYNC_NEXT_WIFI
next WIFI 'n'
Definition: MainModule.h:172
#define ASYNC_CALL_BUZZ_OFF
sends a 'b' to the BLE end of the code (assuming a feeder is connected).
Definition: MainModule.h:151
#define ASYNC_JSON_MESSAGE_PARAMETER
these are the async with a string parameter
Definition: MainModule.h:183
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)
connects to host and grabs the http file and tries to update the binary (OTA)
void savePreferenceInt_mainModule(int preferenceID, int val)
sets an int preference
void savePreferenceBoolean_mainModule(int preferenceID, boolean flag)
save a boolean preference
boolean getPreferenceBoolean_mainModule(int preferenceID)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
void togglePreferenceBoolean_mainModule(int preferenceID)
toggles a preference boolean
int getPreferenceInt_mainModule(int preferenceID)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
char * getPreference_mainModule(int preferenceID)
char * getPreferenceString_mainModule(int preferenceID)
returns the preference but in it's own string buffer. As long as you use it before calling getPrefere...
void printPreferenceValues_mainModule()
print the preferences to SerialDebug
void savePreference_mainModule(int preferenceID, String preferenceValue)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
#define PREFERENCE_PAIRED_DEVICE_ADDRESS_SETTING
the paired device for guest device feeding (6.6.22) .. but the Address 9.3.22
#define PREFERENCE_STEPPER_KIND_VALUE
uses STEPPER type
#define PREFERENCE_SENSOR_TILT_VALUE
Sensor preferences.
#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_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 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_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_MAIN_GATEWAY_VALUE
#define PREFERENCE_STEPPER_CLOCKWISE_MOTOR_DIRECTION_SETTING
void printFile_SPIFFModule()
prints the spiff file to the SerialDebug output
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 ..
void blinkLED_UIModule()
blink the LED
Definition: UI.cpp:137
void solidLightOnOff_UIModule(boolean onOff)
callback for SOLID blinking led
Definition: UI.cpp:128
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