ESP_IOT v2.5
IOT ESP Coding
ATOM_SM.cpp
Go to the documentation of this file.
1
2//
3// ATOM_SM.cpp
4// M5ATOM_Testing
5//
6// Created by Scott Moody on 12/18/23.
7//
8
9#include "ATOM_SM.h"
10#ifdef ATOM_QRCODE_MODULE
11
12#define DECODE_BASE64
13#ifdef DECODE_BASE64
14
15//! 9.27.23 to decode a base64 string (a Semantic Marker)
16#include <libb64/cdecode.h>
17#endif
18
19//! parse the query args .. ?<arg>=<val>{&<arg>=<val>}
20//! 1.1.24 if useAnyArgs then just create JSON from all the arg-val without remapping
21void parseQueryArgs(char *credentialsStringInput, boolean useAnyArgs);
22
23
24#define MAX_SM 500
27
28//! process the semantic marker (maybe from a click or a scan)
29//! If a SMART button, it will tack on username, password and optionally scannedDevice
30//! 12.15.23
31//! return TRUE if this is a new SemanticMarker to save in _lastSemanticMarker
32//! return FALSE if this is a transient SM so don't override _lastSemanticMarker (eg. /scannedDevice, WIFI, credentials)
33//! Added passing lastSemanticMarker .. this is for the /scannedDevice to recursively call itself
34//! (so parms are substituded)
35boolean ATOM_processSemanticMarker(char *semanticMarker, char *lastSemanticMarker)
36{
37 SerialDebug.printf("ATOM_processSemanticMarker(%s, %s)\n", semanticMarker, lastSemanticMarker);
38 //!NOTE: The _lastSemanticMarker will be replaced with this semanticMarker .. unless
39 //! * scannedDevice - since ethen the long press will re-run the last scanned semantic marker but with the new Device
40
41 //! scannedDevice is a special that is only for the scaner. Syntax:
42 //! https://SemanticMarker.org/bot/scannedDevice/{deviceName}{?queryParms}
43 //! if {deviceName} == "_none" then it empties it..
44 //! NOTE: 12.16.23 The scannedDevice is a temporal feature. It will not replace
45 //! the last scanned SemanticMarker, instead it will be used to set the ScannedDevice (or none)
46 //! That way the longPress can still be used to re-invoke the lastSemanticMarker (such as the feed)
47 //! without having to re-scan it.
48 //! BUT: we will send this on the MQTT network just so others can hear it and decide what to do
49 //! Such as the remote Abilities monitor sees if the user scanned the device first etc..
50 //! FUTURE: decide on a remote ScannedDevice feature.. maybe called that: remoteScannedDevice
51 //! which will be an MQTT message (so a remote handler can set the device..)
52 if (containsSubstring(semanticMarker,"/scannedDevice/"))
53 {
54 char *smartIndex = strstr(semanticMarker,"/scannedDevice/");
55 smartIndex += strlen("/scannedDevice/");
56 //! per issue #286, syntax has been extended to include arguments
57 //! /scannedDevice/DeviceName?kind=AtomSocket&status=socket&valKind=onoff
58 //! HERE we just need to search for the "?" and that will be the device name.
59 char *questionMark = strstr(smartIndex, "?");
60 char scannedDeviceBuffer[50];
61 scannedDeviceBuffer[0] = '\0';
62 int *scannedDeviceLen;
63 //! use the _copyLastSemanticMarker as a placeholder..
64 //! @see https://stackoverflow.com/questions/1453876/why-does-strncpy-not-null-terminate
65 if (questionMark)
66 {
67 int len = questionMark - smartIndex;
68 strncpy(scannedDeviceBuffer, smartIndex, len);
69 scannedDeviceBuffer[len] = '\0';
70 }
71 else
72 strcpy(scannedDeviceBuffer,smartIndex);
73 char *scannedDevice = scannedDeviceBuffer;
74 SerialDebug.printf("scannedDevice = %s\n", scannedDevice);
75 if (strcmp(scannedDevice,"_none")==0)
77 else
78 main_setScannedDeviceName(scannedDevice);
79
80 //! TODO: send MQTT message is it {"scannedDevice",device}
81 //! TODO: implement the remoteScannedDevice MQTT message (or is {set:remoteScannedDevice, val:device}
82 //! or {device:D, set:remoteScannedDevice, val:device} -- only to specified device (in the multicast world)
83
84 strcpy(_copyLastSemanticMarker, lastSemanticMarker);
85 //! this is 2 in one. So call ourself but using the lastSemanticMarker
87 return false;
88 }
89 //! 1.7.24 (snow in mountains and down low .. ski monday)
90 else if (containsSubstring(semanticMarker,"/scannedGroup/"))
91 {
92 char *smartIndex = strstr(semanticMarker,"/scannedGroup/");
93 smartIndex += strlen("/scannedGroup/");
94 //! per issue #286, syntax has been extended to include arguments
95 //! /scannedGroup/GroupName?kind=AtomSocket&status=socket&valKind=onoff
96 //! HERE we just need to search for the "?" and that will be the Group name.
97 char *questionMark = strstr(smartIndex, "?");
98 char scannedGroupBuffer[50];
99 scannedGroupBuffer[0] = '\0';
100 int *scannedGroupLen;
101 //! see if any arguments (which we aren't using yet ..)
102 if (questionMark)
103 {
104 int len = questionMark - smartIndex;
105 strncpy(scannedGroupBuffer, smartIndex, len);
106 scannedGroupBuffer[len] = '\0';
107 }
108 else
109 strcpy(scannedGroupBuffer,smartIndex);
110 char *scannedGroup = scannedGroupBuffer;
111 //! save the group name (withoiut topic path) for use in the smrun below
112 strcpy(_lastScannedGroupName, scannedGroup);
113
114 SerialDebug.printf("scannedGroup = %s\n", scannedGroup);
115 if (strcmp(scannedGroup,"_none")==0)
116 main_setScannedGroupName((char*)"");
117 else
118 main_setScannedGroupName(scannedGroup);
119 return false;
120 }
121 else if (containsSubstring(semanticMarker, "WIFI:"))
122 {
123 //! TODO.. parse this, create a JSON { "ssid" then call processJSONMessageMQTT ..
124 char credentialsJSON[200];
125 char credentialsString[200];
126
127#ifdef ENCODED_URL
128 //! SEEMS the syntax is not to encode vaues (although it's not perfectly clear)
129 //!decode the URL (removing %20 etc)
130 String decoded = String(semanticMarker);
131 decoded = MQTT_urlDecode(decoded);
132 SerialDebug.println(decoded);
133 strcpy(credentialsString, decoded.c_str());
134#else
135 strcpy(credentialsString, semanticMarker);
136#endif
137
138 //!NOTE: the idea of sending this around is kinda catch 22. How can I tell you the SSID
139 //!if you aren't connected to the internet..
140 //!1.1.24 NOTE: these can be in any order.. so start with semanticMarker each time..
141 /*
142 WIFI:S:<SSID>;T:<WEP|WPA|blank>;P:<PASSWORD>;H:<true|false|blank>;
143 */
144 char *ssidIndex = strstr(credentialsString,"S:");
145 ssidIndex += 2;
146 char *semicolon = strstr(ssidIndex, ";");
147 char ssidStr[50];
148 int len = semicolon - ssidIndex;
149 ssidStr[0] = '\0';
150 strncpy(ssidStr, ssidIndex, len);
151 ssidStr[len] = '\0';
152
153 //!start over 1.1.24
154 strcpy(credentialsString, semanticMarker);
155 char *ssidPassIndex = strstr(credentialsString,"P:");
156 ssidPassIndex+= 2;
157 semicolon = strstr(ssidPassIndex, ";");
158 len = semicolon - ssidPassIndex;
159 char ssidPassStr[50];
160 ssidPassStr[0] = '\0';
161 strncpy(ssidPassStr, ssidPassIndex, len);
162 ssidPassStr[len] = '\0';
163
164 ///!put together into JSON. case sensitive..
165 sprintf(credentialsJSON, "{'ssid':'%s','ssidPassword':'%s'}", ssidStr, ssidPassStr);
166 SerialDebug.println(credentialsJSON);
167
168 //! 8.16.25 MQTT
169 processJSONMessageMQTT(credentialsJSON, TOPIC_TO_SEND);
170
171 /*
172 6.16.25 A successful scan look like:
173 ***validScannedSM = 'WIFI:S:SunnyWhiteriver;T:WPA/WPA2;P:sunny2021;H:;'
174 ATOM_processSemanticMarker(WIFI:S:SunnyWhiteriver;T:WPA/WPA2;P:sunny2021;H:;, https://SemanticMarker.org/bot/smart?uuid=QHmwUurxC3&flow=1735086442396&flowCat=Scotty&name=SMART_DeviceM5AtomSocketOutside)
175 {'ssid':'SunnyWhiteriver','ssidPassword':'sunny2021'}
176 processJSONMessageMQTT: '{'ssid':'SunnyWhiteriver','ssidPassword':'sunny2021'}'
177 {
178 "ssid": "SunnyWhiteriver",
179 "ssidPassword": "sunny2021"
180 }
181 */
182 //! Set the credentials for the WIFI using this format
183 return false;
184 }
185
186 else if (containsSubstring(semanticMarker, "/credentials"))
187 {
188 //! ./bot/credentials?ssid=X&ssidpass=Y....
189#ifdef ESP_M5
190 //! currently 9.28.23 no reason for feeder to decode base64 messages. That could change if a stored procedure..
191 //! 12.30.23 .. changing to query parameters
192
193 char *smartIndex = strstr(semanticMarker,"/credentials");
194 smartIndex += strlen("/credentials");
195 char *credentialsString = smartIndex;
196 SerialDebug.printf("credentials = %s\n", credentialsString);
197
198 //! parse .. creating JSON and send it onto the parseJSON
199 parseQueryArgs(credentialsString, false);
200
201
202 // syntax: /bot/credentials/base64JSON or
203 // WIFI convention.. not base64
204//#define DECODE_BASE64_HERE
205#ifdef DECODE_BASE64_HERE
206 char plaintext_out[400];
207 int len = strlen(credentialsString);
208 if (len > 400)
209 {
210 SerialError.println("Length too long to base64 decode: 400");
211 }
212 else
213 {
214 int status = base64_decode_chars(scannedDevice, len, plaintext_out);
215 String decoded = String(plaintext_out);
216 decoded = MQTT_urlDecode(decoded);
217 char *decodedCredentials = (char*)decoded.c_str();
218 SerialDebug.println(decodedCredentials);
219
220 //! ascii and topic
221 processJSONMessageMQTT(decodedCredentials, TOPIC_TO_SEND);
222
223 //! TODO..
224 //! now pass this onto the MQTT processor as JSON (we hope ...)
225 return false;
226 }
227
228#endif //DECODE_BASE64
229#endif //M5
230 return false;
231 }
232 else if (containsSubstring(semanticMarker, "/setJSON"))
233 {
234 //! 1.1.24 support setJSON as well..
235 //! ./bot/setJSON?ssid=X&ssidpass=Y....
236 //! currently 9.28.23 no reason for feeder to decode base64 messages. That could change if a stored procedure..
237 //! 12.30.23 .. changing to query parameters
238
239 char *smartIndex = strstr(semanticMarker,"/setJSON");
240 smartIndex += strlen("/setJSON");
241 char *credentialsString = smartIndex;
242 SerialDebug.printf("setJSON = %s\n", credentialsString);
243
244 //! parse .. creating JSON and send it onto the parseJSON
245 parseQueryArgs(credentialsString, true);
246
247 return false;
248 }
249
250 //! see if connected to a BLE device..
251 char *connectedBLEDeviceName = connectedBLEDeviceName_mainModule()?connectedBLEDeviceName_mainModule():NULL;
252 SerialDebug.printf("connectedBLEDeviceName = %s\n", connectedBLEDeviceName);
253
254 if (containsSubstring(semanticMarker,"feedguestdevice"))
255 {
256 char *device = rindex(semanticMarker,'/');
257 if (device) device++; // skip over the "/"
258
259 if (device && connectedBLEDeviceName && strcmp(device,connectedBLEDeviceName)==0)
260 {
261 // only feed if the device is ours (over BLE)
262 SerialDebug.printf(" *** BLE FEEDING since inside SM (device=%s)\n", device);
263 //! 8.16.25 BLE CLIENT
264 //!send a BLE feed command as we are connected
266 //!perform ACK too
267 //! 8.16.25 MQTT
268 //ack is sent by the caller of this message..??
269 sendMessageMQTT((char *)"#ackMe");
270
271 }
272 else
273 {
274 //! send WIFI feed to only the device decoded..
275
276 SerialDebug.printf("1. *** WIFI FEEDING since inside SM (device=%s)\n", device);
277 if (device)
278 {
279 char pubString[100];
280 //!this should work ..
281 sprintf(pubString,"{'dev':'%s'",device);
282 strcat(pubString,",'cmd':'feed'}");
283 //! 8.16.25 MQTT
285 }
286 else
287 {
288 ///feed always (done after the code below..)
290
291 }
292 }
293 return true;
294 }
295 else if (containsSubstring(semanticMarker,"feeddevice"))
296 {
297 char *device = rindex(semanticMarker,'/');
298 if (device) device++; // skip over the "/"
299 SerialDebug.printf("2. *** WIFI FEEDING since inside SM (device=%s)\n", device);
300
301 ///feed always (done after the code below..)
303 return true;
304 }
305 else if (containsSubstring(semanticMarker,"feedguest"))
306 {
307 SerialDebug.println("3. *** WIFI FEEDING since inside SM");
308
309 ///feed always (done after the code below..)
311 return true;
312 }
313 else if (containsSubstring(semanticMarker,"feed"))
314 {
315 SerialDebug.println("4. *** WIFI FEEDING since inside SM");
316
317 ///feed always (done after the code below..)
319 return true;
320 }
321 //! 1.7.24 if non null then valid group topic eg. /usersP/group/GROUP_NAME
323
324 char getCommand[MAX_SM];
325 char *username = main_getUsername();
326 char *password = main_getPassword();
327 char *scannedDeviceName = main_getScannedDeviceName();
328 SerialDebug.println(username);
329 SerialDebug.println(password);
330 SerialDebug.println(scannedDeviceName);
331
332 //! TODO: syntax for an /optimize?uuid=x&flow=y&cmd=feed
333 //! The MQTT is much faster.. Lets only use MQTT for the 'device' specified (to see this difference)
334 // strcpy(_lastSemanticMarker,"https://SemanticMarker.org/bot/smart?uuid=QHmwUurxC3&flow=1674517131429");
335 boolean scannedDeviceValid = false;
336 //! this will be a cache of commands to try..
337 //! cmd:feed, cmddevice,feed,device
338 if (scannedDeviceName && strlen(scannedDeviceName) > 0)
339 {
340 //! dev: <dev>, cmd: feed
341 //! cmd: feed
342 scannedDeviceValid = true;
343 }
344
345 //! 1.7.24 For now only SMART buttons will use the GROUP feature (and only if local) not the smrun
346 // SMART buttons..
347 if (containsSubstring(semanticMarker,"/smart"))
348 {
349 //! try a call..
350 //! call 'smrun' with URL query parameters, like username/password/device
351 //! /bot/smrun?uuid=x&flownum=y&username=X&password=y&device=z
352 //! HERE .. we add the Username, Password and Device name.. parameters
353
354
355#define TRY_OPTIMIZE
356#ifdef TRY_OPTIMIZE
357
358 //! this is the cached (in code) SMART buton for feed.
359 //! @See https://SemanticMarker.org/bot/smart?uuid=QHmwUurxC3&flow=1674517131429
360 if (containsSubstring(semanticMarker, "QHmwUurxC3") && containsSubstring(semanticMarker,"1674517131429"))
361 {
362 //! this will be a cache of commands to try..
363 //! cmd:feed, cmddevice,feed,device
364 if (scannedDeviceValid)
365 {
366 //! dev: <dev>, cmd: feed
367 //! cmd: feed
368 sprintf(getCommand, "{'dev':'%s', 'cmd':'feed'}", scannedDeviceName);
369 if (groupTopic)
371 else
373 return true;
374
375 }
376 else
377 {
378 // sprintf(getCommand, "{'cmd':'feed'}");
379 return false;
380 }
381 }
382 //! this is the cached (in code) SMART buton for toggle socket power.
383 //! @See https://SemanticMarker.org/bot/smart?uuid=QHmwUurxC3&flow=1703806697279
384 else if (containsSubstring(semanticMarker, "QHmwUurxC3") && containsSubstring(semanticMarker,"1703806697279"))
385 //! SMART_ToggleSocket_Device
386 {
387 //! this is the togglesocket command (versus turn on/off)
388 //! https://iDogWatch.com/bot/cmddevice/USERNAME/PASSWORD/DEVICE_1/togglesocket
389 //! this will be a cache of commands to try..
390 //! cmd:feed, cmddevice,feed,device
391 if (scannedDeviceValid)
392 {
393 //! dev: <dev>, cmd: feed
394 //! cmd: feed
395 sprintf(getCommand, "{'dev':'%s', 'cmd':'togglesocket'}", scannedDeviceName);
396 if (groupTopic)
398 else
400 return true;
401
402 }
403 else
404 {
405 // sprintf(getCommand, "{'cmd':'feed'}");
406 return false;
407 }
408 }
409
410#endif //optimize
411 }
412 //! only here if not optimized
413 if (containsSubstring(semanticMarker,"/smart") || containsSubstring(semanticMarker,"/smflowinfo"))
414 {
415#ifdef USE_REST_MESSAGING
416 //! call the /smrun which an HTTPS call to the SemanticMarker.org/bot site, and then decoded
417 //! .. etc Slower
418 char *smartIndex;
419 if (containsSubstring(semanticMarker,"/smflowinfo"))
420 {
421 smartIndex = strstr(semanticMarker,"/smflowinfo");
422 //! move past /smart
423 smartIndex += strlen("/smflowinfo");
424 }
425 else
426 {
427 smartIndex = strstr(semanticMarker,"/smart");
428 //! move past /smart
429 smartIndex += strlen("/smart");
430 }
431 strcpy(getCommand, "/bot/smrun");
432 strcat(getCommand, smartIndex);
433#else
434 // replace the smart or smflowinfo with smrun
435 strcpy(getCommand, semanticMarker);
436#endif
437 //! NOTE: this assumes smartIndex has parameters like: " /smart?uuid=x&flownum=y"
438 //! WITHOUT the smart/ it's smart?uuid...
439 //TODO: don't add these if already there (in the scanned semantic marker)
440 strcat(getCommand, "&username=");
441 strcat(getCommand, username);
442 strcat(getCommand, "&password=");
443 strcat(getCommand, password);
444 if (scannedDeviceName && strlen(scannedDeviceName) > 0)
445 {
446 strcat(getCommand, "&device=");
447 strcat(getCommand, scannedDeviceName);
448 }
449 //!tack on the raw group name, not the groupTopic which is full path: usersP/group/NAME
450 if (groupTopic)
451 {
452 strcat(getCommand, "&group=");
453 strcat(getCommand, _lastScannedGroupName);
454 }
455
456 //!REST is not working, so now sending to TOMCAT on KnowledgeShark.me:8080 (as HTTP not HTTPS)
457#ifdef USE_REST_MESSAGING
458 //! if REST worked, the message will be "/bot/smrun/..."
459 //! Otherwise, the semantic marker is not changed so it stays as "smart"...
460 //! 3.17.24 no async
461#define TRY_ASYNC
462#ifdef TRY_ASYNC
463 //!send an async call with a string parameter. This will set store the value and then async call the command (passing the parameter)
464 //!These are the ASYNC_CALL_PARAMETERS_MAX
466
467#else
468 sendSecureRESTCall(getCommand);
469#endif //async
470
471#else //no REST
472
473 //! right now it shows smart of smflowinfo ..
474 SerialDebug.println("send as DOCFOLLOW");
475 SerialDebug.println(getCommand);
476 //! 8.16.25 MQTT
477
478#ifdef NOT_NEEDED
479 char buffer[MAX_SM];
480
481 // send as doc follow.. "/bot/smrun...."
482 sprintf(buffer, "https://SemanticMarker.org%s",getCommand);
483 SerialDebug.println(buffer);
484 // sendSemanticMarkerDocFollow_mainModule(buffer);
485 //
486 //! 3.25.24 try the http to tomcat, then it sends https to node-red
487 publishSMRunMessage(buffer);
488#else
489 //! 3.25.24 try the http to tomcat, then it sends https to node-red
490 publishSMRunMessage(getCommand);
491#endif
492
493#endif //use REST
494 return true;
495 }
496 //! already an /smrun so call is..
497 else if (containsSubstring(semanticMarker,"/smrun"))
498 {
499 SerialDebug.println(" ****** SHOULDN't have a smrun ...");
500
501 //! 3.25.24 try the http to tomcat, then it sends https to node-red
502// publishSMRunMessage(semanticMarker);
503 return true;
504 }
505 return true;
506}
507
508//! parse the query args .. ?<arg>=<val>{&<arg>=<val>}
509//! 1.1.24 if useAnyArgs then just create JSON from all the arg-val without remapping
510void parseQueryArgs(char *credentialsStringInput, boolean useAnyArgs)
511{
512 char credentialsJSON[300];
513 //! init the JSON
514 strcpy(credentialsJSON,"{");
515 int countArgs = 0;
516 int bufferLen = 100;
517
518 //! parse the query args .. ?<arg>=<val>{&<arg>=<val>}
519
520
521 char *argNames[] = {(char*)"ssid",(char*)"ssidpass",(char*)"username",(char*)"password", (char*)"location", (char*)"deviceName"};
522 //! mapping to the JSON needed. NOTE: Case sensitive ssidPassword
523 char *argOutputNames[] = {(char*)"ssid",(char*)"ssidPassword",(char*)"mqtt_user",(char*)"mqtt_password", (char*)"location", (char*)"deviceName"};
524 int argNamesLen = sizeof(argNames)/sizeof(char*);
525
526 //!decode the URL (removing %20 etc)
527 String decoded = String(credentialsStringInput);
528 //! 8.16.25 MQTT
529 decoded = MQTT_urlDecode(decoded);
530 SerialDebug.println(decoded);
531 char credentialsStringStorage[MAX_SM];
532 strcpy(credentialsStringStorage, decoded.c_str());
533 char *credentialsString = credentialsStringStorage;
534
535 // eat the & or ?
536 if (credentialsString[0] == '?')
537 credentialsString++;
538 while (credentialsString)
539 {
540 //! keep going while &<arg>
541
542 // look for the next '='
543 char *equalIndex = strstr(credentialsString, "=");
544 if (!equalIndex)
545 {
546 SerialDebug.println("** Bad syntax of URL");
547 // maybe bad syntax.. exit loop
548 exit;
549 }
550 int argLen = equalIndex - credentialsString;
551 char argString[bufferLen];
552 for (int i=0;i<bufferLen;i++) argString[i] = '\0';
553 strncpy(argString,credentialsString,argLen);
554 argString[argLen] = '\0';
555 // step over '='
556 if (equalIndex)
557 equalIndex++;
558
559 // move pointer
560 credentialsString = equalIndex;
561
562 //! look for value (to end of line, or next '&')
563 char *nextAmper = strstr(credentialsString,"&");
564 char valString[bufferLen];
565 for (int i=0;i<bufferLen;i++) valString[i] = '\0';
566 //strcpy(valString,"");
567 if (nextAmper)
568 {
569 // more
570 int valLen = nextAmper - credentialsString;
571 strncpy(valString,credentialsString,valLen);
572 valString[valLen] = '\0';
573
574 //! eat the '&'
575 credentialsString += valLen + 1;
576 }
577 else
578 {
579 strcpy(valString,credentialsString);
580 //! done.. so null
581 credentialsString = NULL;
582 }
583
584 //! if useAnyArgs then
585 if (useAnyArgs)
586 {
587 // if 2nd on put a ',' there
588 if (countArgs > 0)
589 strcat(credentialsJSON, ",");
590
591 char oneArgVal[100];
592 // argOutpuNames might be different (like username => mqtt_user)
593 sprintf(oneArgVal,"'%s':'%s'", argString, valString);
594 // add this oneline
595 strcat(credentialsJSON, oneArgVal);
596
597 countArgs++;
598 }
599 else
600 {
601 // look for matching arg (in any order)
602 for (int i=0; i< argNamesLen; i++)
603 {
604 if (strcmp(argNames[i], argString)==0)
605 {
606 char oneArgVal[100];
607 SerialDebug.printf(" ** Matched %s == %s\n", argNames[i], valString);
608 // argOutpuNames might be different (like username => mqtt_user)
609 sprintf(oneArgVal,"'%s':'%s'", argOutputNames[i], valString);
610
611 // if 2nd on put a ',' there
612 if (countArgs > 0)
613 strcat(credentialsJSON, ",");
614 // add this oneLine
615 strcat(credentialsJSON, oneArgVal);
616
617 countArgs++;
618
619 }
620 }
621 }
622 }
623 if (!useAnyArgs)
624 {
625 //! tack on mqtt_server and mqtt_port
626 strcat(credentialsJSON, ",'mqtt_server':'idogwatch.com'");
627 strcat(credentialsJSON, ",'mqtt_port':'1883'");
628
629 }
630 strcat(credentialsJSON, "}");
631 SerialDebug.printf("JSON = %s\n", credentialsJSON);
632
633 //! 8.16.25 MQTT
634 //! send whatever credentials were created
635 processJSONMessageMQTT(credentialsJSON, TOPIC_TO_SEND);
636}
637
638#endif //ATOM_QRCODE_MODULE
char _lastScannedGroupName[40]
Definition: ATOM_SM.cpp:26
void parseQueryArgs(char *credentialsStringInput, boolean useAnyArgs)
9.27.23 to decode a base64 string (a Semantic Marker)
Definition: ATOM_SM.cpp:510
#define MAX_SM
Definition: ATOM_SM.cpp:24
boolean ATOM_processSemanticMarker(char *semanticMarker, char *lastSemanticMarker)
Definition: ATOM_SM.cpp:35
char _copyLastSemanticMarker[MAX_SM]
Definition: ATOM_SM.cpp:25
void sendFeedCommandBLEClient()
sends the "feed" command over bluetooth to the connected device..
void publishMQTTMessageDefaultTopic(char *message)
Wrapper of the mqttclient publish.
void sendMessageMQTT(char *message)
boolean processJSONMessageMQTT(char *ascii, char *topic)
process the JSON message (looking for FEED, etc). Note: topic can be nil, or if not,...
String MQTT_urlDecode(String input)
Decode the URL (copied from WIFI_APModule. Easier than breaking modules)
@ groupTopic
void publishSMRunMessage(char *smrunMessage)
char * main_getUsername()
Definition: MainModule.cpp:988
void main_setScannedGroupName(char *groupName)
void main_setScannedDeviceName(char *deviceName)
set the scanned device name
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()
char * main_getPassword()
return password
Definition: MainModule.cpp:994
void main_dispatchAsyncCommandWithString(int asyncCallCommand, char *parameter)
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 sendMessageString_mainModule(char *messageString)
adding a synchronous call to send a message over the network (assuming MQTT but not specified),...
void main_dispatchAsyncCommand(int asyncCallCommand)
checks if any async commands are in 'dispatch' mode, and if so, invokes them, and sets their flag to ...
char * connectedBLEDeviceName_mainModule()
returns the connected BLE Device name (the :NAME of advertisment, Address: 01:39:3f:33 part of name,...
char * main_getScannedDeviceName()
return devicename
#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 TOPIC_TO_SEND
Definition: MainModule.h:61