ESP_IOT v2.5
IOT ESP Coding
DisplayModule.cpp
Go to the documentation of this file.
1#include "DisplayModule.h"
2#ifdef USE_DISPLAY_MODULE
3//! \link DisplayModule
4//!@see https://www.carletonsheets.com/assets/shared/usr/share/doc/doxygen-1.8.5/html/commands.html#cmdlink
5
6//!@see https://docs.m5stack.com/en/api/stickc/lcd_m5stickc
7//!@see https://github.com/m5stack/M5StickC-Plus
8//!@see https://docs.m5stack.com/en/core/m5stickc_plus
9/**
10 * System:
11 * M5.begin();
12 *
13 * LCD:
14 * M5.Lcd.drawPixel(int16_t x, int16_t y, uint16_t color);
15* M5.Lcd.drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
16* M5.Lcd.fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
17* M5.Lcd.fillScreen(uint16_t color);
18* M5.Lcd.drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
19* M5.Lcd.drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,uint16_t color);
20* M5.Lcd.fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
21* M5.Lcd.fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,int16_t delta, uint16_t color);
22* M5.Lcd.drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
23* M5.Lcd.fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
24* M5.Lcd.drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
25* M5.Lcd.fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
26* M5.Lcd.drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
27* M5.Lcd.drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h),
28* M5.Lcd.drawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg, uint8_t size);
29* M5.Lcd.setCursor(uint16_t x0, uint16_t y0);
30* M5.Lcd.setTextColor(uint16_t color);
31* M5.Lcd.setTextColor(uint16_t color, uint16_t backgroundcolor);
32* M5.Lcd.setTextSize(uint8_t size);
33* M5.Lcd.setTextWrap(boolean w);
34* M5.Lcd.printf();
35* M5.Lcd.print();
36* M5.Lcd.println();
37* M5.Lcd.drawCentreString(const char *string, int dX, int poY, int font);
38* M5.Lcd.drawRightString(const char *string, int dX, int poY, int font);
39 //M5.Lcd.drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x, uint16_t y);
40 //M5.Lcd.drawJpgFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y);
41 //M5.Lcd.drawBmpFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y);
42 *
43 */
44/***************************************************************************************
45 ** Function name: setRotation In
46 ** Description: rotate the screen orientation m = 0-3 or 4-7 for BMP drawing
47 ***************************************************************************************/
48/*
49 void TFT_eSPI::setRotation(uint8_t m)
50 */
51#ifdef ESP_M5_LATER
52
53//!new design for the pairing and dynamic discovery and pairing..
54
55//!defined in icon.c
56//extern const unsigned char bitmap[13424];
57//! draws the bitmap .. for testing
58void drawBitmapIcon()
59{
60 // M5.Lcd.drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
61 // M5.Lcd.drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h),
62
63 M5.Lcd.drawRGBBitmap(0,0, (uint16_t *)bitmap, 135,100);
64}
65#endif //later..
66
67
68//!prints the text up to the maxLen (the setup of position, etc is already done)
69void printText(String text, int maxLen);
70
71//!default semantic marker (or the current one)
72String _currentSemanticMarkerAddress="https://iDogWatch.com";
73/**
74* \image html IMG_4616.PNG "AR + Semantic Marker"
75*/
76//!returns the current semantic marker (eg. guest page)
78{
79 return _currentSemanticMarkerAddress.c_str();
80}
81String _lastSemanticMarkerAddress = "";
82//!default semantic title
83String _semanticTitle = "M5 Clicker";
84//!base http address of semantic markers
85String _currentSemanticMarkerAddressBase = "https://iDogWatch.com";
86//!stores the statusFunc (it's a pointer to a function)
87const char* (*_getStatusFunc)(void) = NULL;
88
89//!if blank, then only show something after a click (not a message)
90boolean _semanticMarkerShown = false;
91
92
93//!The type of screen (not the SM_home, etc, but using the SemanticTitle)
94//!NORMAL for normal display .. we can use NORMAL for the first page..
95#define SCREEN_TYPE_NORMAL 0
96//! for home screen
97#define SCREEN_TYPE_HOME 1
98#define SCREEN_TYPE_STATUS 2
99#define SCREEN_TYPE_HELP 3
100#define SCREEN_TYPE_WIFI 4
101#define SCREEN_TYPE_TILT 5
102#define SCREEN_TYPE_BUZZ 6
103#define SCREEN_TYPE_AP 7
104#define SCREEN_TYPE_GUEST_PAGE 8
105#define SCREEN_TYPE_FEED_GUEST 9
106#define SCREEN_TYPE_PAIRED_DEV 10
107#define SCREEN_TYPE_RESET 11
108#define SCREEN_TYPE_REBOOT 12
109//!try simple menu
110#define SCREEN_TYPE_HOME_SIMPLE 13 //tilt
111#define SCREEN_TYPE_HOME_SIMPLE_1 14 //buzz
112#define SCREEN_TYPE_HOME_SIMPLE_2 15 //feed
113#define SCREEN_TYPE_HOME_SIMPLE_3 16 //advanced
114#define SCREEN_TYPE_DOC_FOLLOW 17 //docFollow
115#define SCREEN_TYPE_TIMER 18 //timer
116
117//!the current screen type (a side effect of asking for it)
118int _currentScreenType = SCREEN_TYPE_NORMAL;
119
120//!returns the screen type (f0..n) for the title (such as HOME) NOTE: if the name changes .. ramifications
121//! So they match the MQTTNetwork title strings..
122int screenTypeForTitle_displayModule(String title)
123{
124 //!NOTE: All the comparisons are ALL CAPS ...
125 title.toUpperCase();
126 int screenType = SCREEN_TYPE_NORMAL;
127 if (title.compareTo("MINI CLICKER")==0)
128 {
129 screenType = SCREEN_TYPE_HOME_SIMPLE;
130 }
131 else if (title.compareTo("MINI-1")==0)
132 {
133 screenType = SCREEN_TYPE_HOME_SIMPLE_1;
134 }
135 else if (title.compareTo("MINI-2")==0)
136 {
137 screenType = SCREEN_TYPE_HOME_SIMPLE_2;
138 }
139 //!ADD SCREEN_TYPE_HOME
140
141 else if (title.compareTo("MINI-3")==0)
142 {
143 screenType = SCREEN_TYPE_HOME_SIMPLE_3;
144 }
145 //rest are normal
146 else if (title.compareTo("WIFI FEED")==0)
147 {
148 screenType = SCREEN_TYPE_HOME;
149 }
150 else if (title.startsWith("HELP"))
151 {
152 screenType = SCREEN_TYPE_HELP;
153 }
154 else if (title.startsWith("WIFI"))
155 {
156 screenType = SCREEN_TYPE_WIFI;
157 }
158 else if (title.startsWith("TILT"))
159 {
160 screenType = SCREEN_TYPE_TILT;
161 }
162 else if (title.startsWith("BUZZ"))
163 {
164 screenType = SCREEN_TYPE_BUZZ;
165 }
166 else if (title.startsWith("AP"))
167 {
168 screenType = SCREEN_TYPE_AP;
169 }
170 else if (title.startsWith("GUEST PAGE"))
171 {
172 screenType = SCREEN_TYPE_GUEST_PAGE;
173 }
174 else if (title.startsWith("FEED GUEST"))
175 {
176 screenType = SCREEN_TYPE_FEED_GUEST;
177 }
178 else if (title.startsWith("STATUS"))
179 {
180 screenType = SCREEN_TYPE_STATUS;
181 }
182 else if (title.startsWith("RESET"))
183 {
184 screenType = SCREEN_TYPE_RESET;
185 }
186 else if (title.startsWith("DOC FOLLOW"))
187 {
188 screenType = SCREEN_TYPE_DOC_FOLLOW;
189 }
190 else if (title.startsWith("REBOOT"))
191 {
192 screenType = SCREEN_TYPE_REBOOT;
193 }
194 else if (title.startsWith("TIMER"))
195 {
196 screenType = SCREEN_TYPE_TIMER;
197 }
198 //! the "P:" is a special token from the MQTT that denotes this is a pairing feed. The P: is replaced with the paired device
199 else if (title.startsWith("P:"))
200 {
201 screenType = SCREEN_TYPE_PAIRED_DEV;
202 }
203 //set global used by callers of addToTextMessages_displayModule
204 _currentScreenType = screenType;
205 return screenType;
206}
207
208
209
210//!These are when the ESP_M5 isn't used, so the code below compiles..
211#ifdef ESP_M5
212#else
213//!unused .. for now since no display
214#define BLACK 100
215#define WHITE 101
216#define YELLOW 102
217#define BLUE 103
218#define RED 104
219#define ORANGE 105
220
221#endif
222
223#define WIDTH 135
224#define HEIGHT_3 20
225#define HEIGHT_3_2LINE 60
226
227#define HEIGHT_4 40
228
229#define HEIGHT_2 10
230#define HEIGHT_1 10
231
232#define ROTATE_0 0
233#define FONT_3 3
234#define FONT_2 2
235#define FONT_1 1
236
237//!defines the position constants
238//!Note some uses below just use the text color and size attributes, (Too much work to make a variable struct)
239//! eg. ORANGE,WHITE,BLACK
240typedef struct TextPosition
241{
242 uint16_t x,y;
243 uint16_t width, height;
244 uint16_t textSize;
245 uint16_t textColor;
246 uint16_t textColorBackground;
247 uint16_t blankColor;
248
249 uint16_t rotation; // 0
250 uint16_t maxLen; // 0
251
252} TextPositionStruct;
253
254//!EG: #actMe (M5) { ksjdfkdsjfk
255//! Feed Guest
256//!based on text size 3
257TextPositionStruct _actionTextPosition = {0,2,WIDTH,HEIGHT_2,FONT_2,BLUE,WHITE,BLACK,ROTATE_0,11};
258TextPositionStruct _actionTextPositionZoomed = {0,2,WIDTH,HEIGHT_3_2LINE,FONT_3,BLUE,WHITE,BLACK,ROTATE_0,14};
259TextPositionStruct _actionTextHomePositionZoomed= {0,2,WIDTH,HEIGHT_3_2LINE,FONT_3,ORANGE,BLACK,BLACK,ROTATE_0,14}; //28};
260// the simple title (MINI CLICKER)
261TextPositionStruct _actionTextHomeSimplePositionZoomed = {0,2,WIDTH,HEIGHT_3_2LINE,FONT_3,YELLOW,BLUE,BLACK,ROTATE_0,15}; //28};
262TextPositionStruct _actionTextHomeSimplePositionZoomed_1= {0,2,WIDTH,HEIGHT_3_2LINE,FONT_3,BLUE,YELLOW,BLACK,ROTATE_0,15}; //28};
263TextPositionStruct _actionTextHomeSimplePositionZoomed_2= {0,2,WIDTH,HEIGHT_3_2LINE,FONT_3,BLACK,GREEN,BLACK,ROTATE_0,15}; //28};
264TextPositionStruct _actionTextHomeSimplePositionZoomed_3= {0,2,WIDTH,HEIGHT_3_2LINE,FONT_3,BLACK,WHITE,BLACK,ROTATE_0,15}; //28};
265TextPositionStruct _actionTextHomeSimplePositionZoomed_4= {0,2,WIDTH,HEIGHT_3_2LINE,FONT_3,WHITE,RED,BLACK,ROTATE_0,15}; //28};
266
267//! these are grouped in an array for the color index to use. If index > max then use max.. (-1)
268#define MAX_ACTION_TEXT_HOME_COLORS 5
269TextPositionStruct _actionTextHomeSimpleColor[MAX_ACTION_TEXT_HOME_COLORS] =
270{
271 _actionTextHomeSimplePositionZoomed,
272 _actionTextHomeSimplePositionZoomed_1,
273 _actionTextHomeSimplePositionZoomed_2,
274 _actionTextHomeSimplePositionZoomed_3,
275 _actionTextHomeSimplePositionZoomed_4,
276};
277
278//! mode is the status of sensors .
279TextPositionStruct _sensorStatusTextPosition = {0,27,WIDTH,HEIGHT_2,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,22};
280TextPositionStruct _sensorStatusTextPositionZoomed = {0,65,WIDTH,HEIGHT_3,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,22};
281
282TextPositionStruct _helpStatusTextPosition =
283 {0,65,WIDTH,HEIGHT_3,FONT_2,ORANGE,BLACK,BLACK,ROTATE_0,22};
284//! Help
285TextPositionStruct _multilineStatusTextPosition = {0,27,WIDTH,HEIGHT_4,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,40};
286TextPositionStruct _multilineStatusTextPositionZoomed = {0,65,WIDTH,HEIGHT_4,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,40};
287
288//!status are the state modules (WIFI ON/off, etc)
289TextPositionStruct _moduleStatusTextPosition = {0,67,WIDTH,HEIGHT_3,FONT_3,YELLOW,BLUE,BLACK,ROTATE_0,7};
290TextPositionStruct _moduleStatusTextPositionZoomed = {0,105,WIDTH,HEIGHT_3,FONT_3,YELLOW,BLUE,BLACK,ROTATE_0,7};
291
292//! new for the SM_HOME_SIMPLE
293TextPositionStruct _homeSimpleStatusTextPositionZoomed = {0,105,WIDTH,HEIGHT_3,FONT_3,ORANGE,BLACK,BLACK,ROTATE_0,7};
294//! new for the SM_HOME_SIMPLE - draws FEED as red if over 13 feeds..
295TextPositionStruct _homeSimpleStatusTextPositionZoomedRED = {0,105,WIDTH,HEIGHT_3,FONT_3,RED,BLACK,BLACK,ROTATE_0,7};
296
297//! the position of "connected" at the bottom on the first 3 screens..
298TextPositionStruct _connectedStatusTextPositionZoomed = {0,213,WIDTH,HEIGHT_2,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,11};
299
300//!new Menu selection (if 4 ..)
301TextPositionStruct _menuTextPositionZoomed_4less = {0,105,WIDTH,HEIGHT_3,FONT_3,ORANGE,BLACK,BLACK,ROTATE_0,7};
302TextPositionStruct _menuTextPositionZoomed_4plus = {0,105,WIDTH,HEIGHT_2,FONT_2,ORANGE,BLACK,BLACK,ROTATE_0,22};
303
304
305//top == feed, bottom = semantic marker (or the action of it)..{
306#define BIG_ACTION 0
307#define SM_ACTION 1
308#define SM_ACTION_SMALL 2
309#define QRAVATAR_ACTION 3
310
311#define MAX_ACTIONS 4
312
313#define TRY_SWAPPED_COLORS
314#ifdef TRY_SWAPPED_COLORS
315TextPositionStruct _zoomedTextPositions[MAX_ACTIONS] = {
316 {0,145,WIDTH,HEIGHT_3,FONT_3,ORANGE,BLACK,BLACK,ROTATE_0,7},
317 {0,180,WIDTH,HEIGHT_3,FONT_3,WHITE,BLUE,BLACK,ROTATE_0,7},
318
319 //the smaller WIFI words (without feed..)
320 {0,145,WIDTH,HEIGHT_2,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,40},
321 //the avatar character.. not perfect Blue on Yellow -- how about Red
322 {50,150,1,HEIGHT_3,FONT_3,RED,YELLOW,BLACK,ROTATE_0,2}
323};
324#else
325TextPositionStruct _zoomedTextPositions[MAX_ACTIONS] = {
326 {0,145,WIDTH,HEIGHT_3,FONT_3,WHITE,BLUE,BLACK,ROTATE_0,7},
327 {0,180,WIDTH,HEIGHT_3,FONT_3,WHITE,BLACK,BLACK,ROTATE_0,7},
328 //!home screens bottom action
329 {0,180,WIDTH,HEIGHT_3,FONT_3,ORANGE,BLACK,BLACK,ROTATE_0,7},
330
331 //the smaller WIFI words (without feed..)
332 {0,145,WIDTH,HEIGHT_2,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,40},
333 //the avatar character.. not perfect Blue on Yellow -- how about Red
334 {50,150,1,HEIGHT_3,FONT_3,RED,YELLOW,BLACK,ROTATE_0,2}
335};
336#endif
337
338//! init the text - but override the text color (stil using the textP.blankCOlor
339void setupTextPositionOverrideTextColor(TextPositionStruct textP, TextPositionStruct textColor)
340{
341#ifdef ESP_M5
342 M5.Lcd.setRotation(textP.rotation);
343 M5.Lcd.fillRect(textP.x, textP.y, textP.width, textP.height, textColor.blankColor );
344 M5.Lcd.setTextColor(textColor.textColor, textColor.textColorBackground);
345 M5.Lcd.setCursor(textP.x + 2, textP.y);
346 M5.Lcd.setTextSize(textP.textSize);
347#endif
348}
349
350//!show an OTA message..
352{
353#ifdef ESP_M5
354 // blank the area
355 M5.Lcd.fillRect(0, 60, 135, 140, ORANGE);
356 M5.Lcd.setTextColor(WHITE, BLACK);
357 M5.Lcd.setCursor(10, 90);
358 M5.Lcd.setTextSize(2);
359 M5.Lcd.println("\nStarting \nOTA Update \nPlease Wait\n2-5 minutes");
360#endif
361}
362
363//! init the text
364void setupTextPosition(TextPositionStruct textP)
365{
366 //use same color
367 setupTextPositionOverrideTextColor(textP, textP);
368
369}
370
371//!use the textPositionStruct - but override the text color
372void printTextAtTextPositionOverrideTextColor(String text, TextPositionStruct textPosition, TextPositionStruct textColor)
373{
374 setupTextPositionOverrideTextColor(textPosition, textColor);
375#ifdef ESP_M5
376 M5.Lcd.print(text);
377#endif
378}
379
380//!use the textPositionStruct
381void printTextAtTextPosition(String text, TextPositionStruct textPosition)
382{
383 setupTextPosition(textPosition);
384#ifdef ESP_M5
385 M5.Lcd.print(text);
386#endif
387}
388
389
390//! SCREEN COLOR
391//!Increment the screen color 0..n cache for getting the screen color 0..max (max provided by sender)
392//!This is implemented by incrementScreenColor_mainModule() since it knows the MAX value of colors
394{
396 screenColor++;
397 if (screenColor >= MAX_ACTION_TEXT_HOME_COLORS)
398 {
399 // change color and store
400 screenColor = 0;
401 }
403
404 SerialCall.printf("incrementScreenColor_displayModule = %d\n", screenColor);
405}
406
407//!cache for getting the screen color 0..n. Will reset the cache as well
408int getScreenColor_displayModule()
409{
410 //normalize
412 if (screenColor < 0 || screenColor >= MAX_ACTION_TEXT_HOME_COLORS)
413 {
414 // normalize the number, and store it..
415 screenColor = screenColor % MAX_ACTION_TEXT_HOME_COLORS;
417 }
418 SerialLots.printf("getScreenColor_displayModule = %d\n", screenColor);
419
420 return screenColor;
421}
422
423//!cache for getting the screen color 0..n. Will reset the cache as well
424void setScreenColor_displayModule(int screenColor)
425{
426 //normalize
427 if (screenColor < 0 || screenColor >= MAX_ACTION_TEXT_HOME_COLORS)
428 {
429 // normalize the number, and store it..
430 screenColor = screenColor % MAX_ACTION_TEXT_HOME_COLORS;
431 }
433 SerialCall.printf("setScreenColor_displayModule = %d\n", screenColor);
434
435}
436
437
438
439//!markerTimer is a semi timer for the number of times before doing anything. Kinda a kludge.
440int _markerTimer = 0;
441//! ticks.. when it rest? (show to blank screen)
442int _loopTimer = 0;
443//!increment the loop timer
444void incrementLoopTimer()
445{
446 _loopTimer = (_loopTimer+1) % 100;
447}
448//!stop the loop timer
449void stopLoopTimer()
450{
451 _loopTimer = 0;
452}
453//!returns the loop timer (just a timer..)
455{
456 return _loopTimer;
457}
458
459//!reset the loop timer .. useful for testing,
461{
462 _loopTimer = 0;
463}
464/**
465* \image html SMStatus1.PNG "Semantic Marker"
466*/
467//!NOTE: need to add dev:deviceName
468//!creates semantic address, and if _getStatusFunc is non nil, call it to add to the address SemanticMarker&trade;
469String createSemanticAddress()
470{
471 //!if there is a status function to call, call it and add to the address (and tack on the _loopTimer)
472 //!Otherwise, just use the provided address (not a status like address)
473 if (_getStatusFunc)
474 {
475 SerialTemp.print("createDynamicSemanticAddress: ");
476
477 //check if this is right (the base)
478 // _currentSemanticMarkerAddress = _currentSemanticMarkerAddressBase + "/" + String((*_getStatusFunc)()) + "&t=" + String(_loopTimer);
479 _currentSemanticMarkerAddress = String((*_getStatusFunc)()) + "&t=" + String(_loopTimer);
480
481 }
482 else
483 {
484 SerialCall.print("createSemanticAddress: ");
485 _currentSemanticMarkerAddress = _currentSemanticMarkerAddressBase;
486 }
487
488//#define TEST_LONGER_ADDRESS
489#ifdef TEST_LONGER_ADDRESS
490 //!seems the iPHone QR recognizer breaks after 144 characters .. or so..
491 //! AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:i];
492 //if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode])
493 // NSString *qrValue = [metadataObj stringValue];
494
495 if (_loopTimer > 2)
496 {
497 _currentSemanticMarkerAddress += "&n=";
498
499 // seems that 155 is max (of ability for iPhone to decode a QR but it's still recognized as a QR)
500 if (_currentSemanticMarkerAddress.length() < 130)
501 {
502 for (int i= _currentSemanticMarkerAddress.length(); i< 130; i++)
503 {
504 _currentSemanticMarkerAddress += "_";
505 }
506 }
507 for (int i=0; i< _loopTimer; i++)
508 {
509 _currentSemanticMarkerAddress += String(_loopTimer);
510 }
511 }
512 SerialTemp.printf("Length = %d\n", _currentSemanticMarkerAddress.length());
513
514
515 // test ..
516 if (_loopTimer == 15)
517 {
518 // strip down to 155 .. yanking off each parameter?? or just chop it.. for not just chop it..
519 if (_currentSemanticMarkerAddress.length() > 154)
520 {
521 SerialTemp.println(" Truncating to 154 chartacters...");
522
523 _currentSemanticMarkerAddress = _currentSemanticMarkerAddress.substring(0,154);
524 }
525 }
526#else
527 // strip down to 155 .. yanking off each parameter?? or just chop it.. for not just chop it..
528 if (_currentSemanticMarkerAddress.length() > 154)
529 {
530 SerialTemp.println(" Truncating to 154 chartacters...");
531
532 _currentSemanticMarkerAddress = _currentSemanticMarkerAddress.substring(0,154);
533 }
534#endif
535 SerialLots.println(_currentSemanticMarkerAddress);
536 return _currentSemanticMarkerAddress;
537}
538
539
540//**** Delay Methods*******
541#define SINGLE_DELAY
542#ifdef SINGLE_DELAY
543//https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html
544//! the time the delay started
545unsigned long _delayStart;
546//! true if still waiting for delay to finish
547boolean _delayRunning = false;
548//! length of delay
549int _delaySeconds;
550//!init the delay starting
551void startDelay(int seconds)
552{
553 SerialCall.printf("startDelay_displayModule: %d\n", seconds);
554
555 _delayStart = millis(); // start delay
556 _delayRunning = true; // not finished yet
557 _delaySeconds = seconds;
558
559}
560//!if finished..
561boolean delayFinished()
562{
563 if (_delayRunning && ((millis() - _delayStart) >= (_delaySeconds * 1000)))
564 {
565 _delayRunning = false;
566 SerialCall.println("delayFinished..");
567 return true;
568 }
569 return false;
570}
571
572//!stop the delay
573void stopDelay()
574{
575 SerialCall.println("stopDelay _delayRunning=false");
576
577 _delayRunning = false;
578}
579#endif //SINGLE_DELAY
580
581
582//****** SCREEN DISPLAY ************
583//!new 12.29.22
584//!
585//! //! https://github.com/Bodmer/TFT_eSPI/issues/226
586//! TRY THIS:
587#define BLK_PWM_CHANNEL 7 // LEDC_CHANNEL_7
588void setBrightness_displayModule(int brightness)
589{
590#ifdef LATER
591 ledcWrite(BLK_PWM_CHANNEL, brightness);
592#endif
593}
594
595//!blanks the screen
597{
598 SerialCall.println("blankScreen_displayModule");
599 stopLoopTimer();
600
601 //!stop the delay which says delay finished .. so don't show anything.. 8.9.22
602 stopDelay();
603
604 //nothing displayed
605 _semanticMarkerShown = false;
606
607#ifdef ESP_M5
608 M5.Lcd.fillScreen(BLACK);
609 //not available.. without M5Stack.h ???
610 // M5.Lcd.setBrightness(0);
611 // M5.Lcd.setBrightness(200);
612
613 //M5.Lcd.sleep();
614
615 // M5.Lcd.fillScreen(ORANGE);
616
617 //get out of all modes..
618 // #issue #144 show something to let know its screen saver not OFF
619
620 printTextAtTextPosition(" CLICKER",_connectedStatusTextPositionZoomed);
621
622
623
624#define TRY_DEVICES_AND_PAIRED
625#ifdef TRY_DEVICES_AND_PAIRED
626 {
627 char infoString[150];
628 boolean multilineScreenType;
629
630 //!update the model for those drawing Dev and Connected Dev
632
633 multilineScreenType = true;
634 //! just ask the deviceState...
636 switch (model->pairedDeviceStateEnum)
637 {
638 //paired to a device, but BLE NOT connected right now
640 sprintf(infoString,"%s\n+%.*s",deviceName_mainModule(),10,getPairedDeviceOrAddress_mainModule() );
641 break;
642 //paired to a device, and BLE connected right now
644 sprintf(infoString,"%s\n%.*s",deviceName_mainModule(),10,getPairedDeviceOrAddress_mainModule() );
645 break;
646 //not paired (but could be paired as it's a named device])
648 sprintf(infoString,"%s\n-%.*s",deviceName_mainModule(),9,connectedBLEDeviceName_mainModule());
649 break;
650 //!factory default but not connecte to anything..
651 case notConnectedEnum:
652 //sprintf(infoString,"%s\n%s",deviceName_mainModule(),(char*)"scanning..");
653 sprintf(infoString,"%s\n",deviceName_mainModule());
654
655 break;
656 }
657 SerialCall.println(infoString);
658
659 //!use the zoomed amount
660 setupTextPosition(multilineScreenType?_multilineStatusTextPositionZoomed:_sensorStatusTextPositionZoomed);
661
662 //!draw the text
663 printText(infoString,multilineScreenType?_multilineStatusTextPosition.maxLen:_sensorStatusTextPosition.maxLen);
664 }
665#else
666 //! also show the device name..
667 //! at same location as before.. the small text below the top..
668 //!use the zoomed amount
669 setupTextPosition(_sensorStatusTextPositionZoomed);
670
671 //!draw the device name (not including the parired or not paired .. as it can change dynaically...
672 printTextAtTextPosition(deviceName_mainModule(),_sensorStatusTextPosition);
673#endif
674#endif
675}
676
677//!wakes up the screen
679{
680
681 //clear screen first.. since the KEEP_SAME won't clear the screen..
683
684 // _semanticMarkerShown = true;
685 SerialCall.println("wakeupScreen_displayModule");
686
687 //!see if this works .. vs too flickering.. (if so we have to slow it down..)
689
690}
691
692//!clears the screen (but not a blank screen)
694{
695 SerialCall.println("clearScreen_displayModule");
696
697 //reset the timer.. NEW!! 8.9.22 (a mini blankScreen)
698 //??
699 stopLoopTimer();
700
701#ifdef ESP_M5
702 M5.Lcd.setRotation(0);
703 M5.Lcd.fillScreen(BLACK);
704#endif
705}
706
707//!whether screen is blank (so the button can be a wake, vs action..)
709{
710 SerialLots.print("isBlankScreen_displayModule:");
711 SerialLots.println(!_delayRunning?"BLANK":"NOT BLANK");
712
713 //! if the delay is running, then not blanked
714 return !_delayRunning;
715
716}
717
718//! whether to display on a blank screen
719boolean displayOnBlankScreen()
720{
722}
723
724//! current screen timeout
725int currentScreenTimeout()
726{
728 return val;
729}
730
731#ifdef ESP_M5
732//!setup the Lcd, etc..
733void setupESP_M5()
734{
735 SerialCall.println("setupESP_M5");
736
737 //!Init M5StickC Plus. 初始化 M5StickC Plus
738 M5.begin();
739
740 //!Set font size.
741 //!Set the font color to yellow. 设置字体颜色为黄色
742 M5.Lcd.setTextColor(WHITE);
743 //!rotate to landscape (vs vertical)
744 //!M5.Lcd.setRotation(3);
745 //!Rotate the screen. 将屏幕旋转
746 M5.Lcd.setRotation(0);
747 //!set the cursor location. 设置光标位置
748
749 //!Set font size.
750
751 M5.Lcd.setTextSize(2);
752 // M5.Lcd.printf("Click Controller v1.0");
753
754 //! STARTUP SCREEN showing VERSION
755 M5.Lcd.printf("%s", VERSION);
756
757 //!Draws a SemanticMarker&trade; (using QR code)
758 //!Create a QR code with a width of 135 QR code at (0, 100). 在(0,0)处创建一个宽为135二维码
759 //!Please select the appropriate QR code version according to the number of characters. 请根据字符数量选择合适的二维码版本
760 M5.Lcd.qrcode("https://iDogWatch.com/bot/help",0,100,135);
761 //try to draw a character in the middle ...
762 printTextAtTextPosition("SM",_zoomedTextPositions[QRAVATAR_ACTION]);
763 //delay so they can read it a little bit..
764 delay(550);
765
766 //blank screen is on..
767}
768#endif //ESP_M5
769
770//!THIS IS the setup() and loop() but using the "component" name, eg MQTTNetworking()
771//!This will perform preference initializtion as well
772//! called from the setup()
774{
775#ifdef ESP_M5
776 setupESP_M5();
777#endif
778
779 //this is supposed to say it's not in blank screen...
780 //stopDelay();
781 startDelay(60);
782
783}
784
785//! called for the loop() of this plugin
787{
788 //!check if a delay was running..
789 if (delayFinished())
790 {
791 SerialCall.println("loop_displayModule: delayFinished");
793 }
794
795 //TODO:
796 // change sensors, and change any SemanticMarkers using said sensors..
797 // or every second update SM (whatever is shown - and only change if sensors are showing (parms), eg. status
798//either delay or redraw right now.. from loop()
799
800 //4.20.22 (9 pm .. listening to Mike Campbell with drummer talking story about Tom Petty
801 // lets use a counter vs time .. simplier??
802 _markerTimer++;
803//#define LOOP_COUNTER_MICROSECONDS 30
804#define LOOP_COUNTER_MICROSECONDS 20 // 2 seconds it seems.. 11.7.22
805
806 if (_markerTimer > LOOP_COUNTER_MICROSECONDS) //10 was working .. got to 20 how fast it loop across all the modules (their loop() ..
807 {
808
809 //! 9.2.22 new .. update the timer. This is on blank screen as well .. so don't check _semanticMarkerShown
811#define TRY_BLANKSCREEN_IN_LOOP
812#ifdef TRY_BLANKSCREEN_IN_LOOP
813 //!check if a delay was running..
815 {
816 SerialCall.println("loop_displayModule: isBlankScreen");
818 }
819#endif
820 _markerTimer = 0;
821 if (_semanticMarkerShown)
822 {
823 SerialCall.println("loop_displayModule: redrawSemanticMarker(KEEP_SAME)");
824
825 //!see if this works .. vs too flickering.. (if so we have to slow it down..)
827 }
828 }
829}
830
831// ************ Drawing of the Action, Mode and Status ***************
832
833//!prints the text up to the maxLen (the setup of position, etc is already done)
834void printText(String text, int maxLen)
835{
836#ifdef ESP_M5
837 if (text.length() < maxLen)
838 {
839 M5.Lcd.print(text);
840 }
841 else
842 {
843 M5.Lcd.print(text.substring(0,maxLen));
844 }
845#endif
846}
847
848//! print the text, but pad with background color spaces..
849void printTextPadSpaces(String text, TextPositionStruct textColor)
850{
851#ifdef ESP_M5
852
853 int maxLen = textColor.maxLen;
854 printText(text, maxLen);
855
856 // now pad with spaces .. using the color provided..
857 // pad with spaces .., but in the background color..
858 M5.Lcd.setTextColor(textColor.textColor, textColor.textColorBackground);
859 for (int i=text.length(); i< maxLen; i++)
860 {
861 M5.Lcd.print(" ");
862 }
863#endif
864}
865
866//!sets the "ACTION" -- The TOP line
867void drawAction(String title, int screenType)
868{
869
870 SerialCall.print("drawAction: ");
871 SerialCall.print(title);
872 SerialCall.printf(" screenType=%d\n",screenType);
873
874 //!setup the position for the Action text
876 && (screenType != SCREEN_TYPE_HELP))
877 {
878 //!only add the CR on the zoomed
879 title.replace(" ","\r\n");
880
881 //!get the color index .. 0..MAX-1, if outside range, pick 0. Use 'mod' == % syntax.
882 //!This is because the set from the web (MQTT) doesn't know the size.. or have it done here..
883 int colorIndex = getScreenColor_displayModule();
884
885 //!different for home screen
886 switch (screenType)
887 {
888 case SCREEN_TYPE_HOME_SIMPLE:
889 //!print preferences
890 //printPreferenceValues_mainModule();
891 //fall through to same as simple_1/2
892 case SCREEN_TYPE_HOME_SIMPLE_1:
893 case SCREEN_TYPE_HOME_SIMPLE_2:
894 case SCREEN_TYPE_AP:
895
896 {
897 //Hard wire back to "MINI CLICKER" since the MQTT code used a name to bind to this code, eg. MINI-2
898 setupTextPosition(_actionTextHomeSimpleColor[colorIndex]);
899 printText(" MINI CLICKER", _actionTextHomeSimplePositionZoomed.maxLen);
900 }
901 break;
902 case SCREEN_TYPE_HOME_SIMPLE_3:
903 {
904 //Hard wire back to "MINI CLICKER" since the MQTT code used a name to bind to this code, eg. MINI-2
905 setupTextPosition(_actionTextHomeSimpleColor[colorIndex]);
906 printText("CLICKER MENU ", _actionTextHomeSimplePositionZoomed.maxLen);
907 }
908 break;
909 //rest are the next set of screens.
910 case SCREEN_TYPE_HOME:
911 {
912 // This now comes in as "FEED ALL" .. so change to SMART CLICKER
913 setupTextPosition(_actionTextHomeSimpleColor[colorIndex]);
914 printText(" SMART CLICKER", _actionTextHomeSimplePositionZoomed.maxLen); }
915 break;
916 //same title.. for now..
917 case SCREEN_TYPE_PAIRED_DEV:
918 {
919 // the title == P: so replace with the paired name..
920 setupTextPosition(_actionTextHomeSimpleColor[colorIndex]);
921
922 //!use the zoomed amount
923 printText("PAIR DEVICE ", _actionTextPositionZoomed.maxLen);
924 }
925 break;
926 default:
927 //!use the zoomed amount
928 //setupTextPosition(_actionTextPositionZoomed);
929 setupTextPosition(_actionTextHomeSimpleColor[colorIndex]);
930 printText(title, _actionTextPositionZoomed.maxLen);
931 }
932 }
933 else
934 {
935 //don't show the P: but rather the paired device name
936 if (screenType == SCREEN_TYPE_PAIRED_DEV)
937 {
938 // the title == P: so replace with the paired name..
939 setupTextPosition(_actionTextPosition);
940 //!use the zoomed amount
941 printTextPadSpaces("PAIRDEV", _actionTextPosition);
942
943 }
944 else
945 {
946 setupTextPosition(_actionTextPosition);
947 //printText(title, _actionTextPosition.maxLen);
948
949 printTextPadSpaces(title, _actionTextPosition);
950
951 }
952 }
953}
954
955//!sets the "Sensor Status"
956void drawSensorStatus(int screenType)
957{
958 char infoString[150];
959 boolean multilineScreenType = false;
960
961#ifdef ESP_M5
962
963 //!The "INFO"
964 //float batVoltage = M5.Axp.GetBatVoltage();
965 float batPercentage = getBatPercentage_mainModule();
969 boolean isConnectedBLE =
970#ifdef USE_BLE_CLIENT_NETWORKING
972#else
973 false;
974#endif
975
976 //!add the Gateway status.. Now, if the preference is only GEN3 and not connected, then show a Gx, but if connected then G3, and g if any kind but not connected
977 String gStatus = "g";
978 String gStatusHome = "";
979 if (isConnectedBLE && gatewayOn)
980 {
981 gStatus = "G3";
982 gStatusHome = "G3";
983 }
985 {
986 gStatus = "Gx";
987 gStatusHome = "Gx";
988 }
989 //!Special layout for HELP screen type
990 switch (screenType)
991 {
992
993 case SCREEN_TYPE_HELP:
994 multilineScreenType = true;
995 // sprintf(infoString,inMinMenu?"Show All\nmenus":"Minimize\nmenus");
996 sprintf(infoString,"Scan Image\nFor Help");
997
998 break;
999 case SCREEN_TYPE_WIFI:
1000 multilineScreenType = true;
1002 {
1003#ifdef USE_MQTT_NETWORKING
1004
1006 sprintf(infoString,"Swap WIFI");
1007 else
1008 sprintf(infoString,"Swap/Retry\nWIFI");
1009#endif
1010 }
1011 else
1012 {
1013 //! #issue 136 show the WIFI in the semantic marker, and label for scanning
1014 sprintf(infoString,"Scan to\nShare WIFI");
1015 }
1016 break;
1017 case SCREEN_TYPE_AP:
1018 multilineScreenType = true;
1020 sprintf(infoString,"Enter AP\n192.168.4.1");
1021 else
1022 sprintf(infoString,"In AP\n192.168.4.1");
1023 break;
1024 case SCREEN_TYPE_GUEST_PAGE:
1025 multilineScreenType = true;
1026 sprintf(infoString,"Share WIFI with Feeder");
1027 break;
1028#ifdef NOMORE
1029 case SCREEN_TYPE_TIMER: //will be it's own with the time values...
1030 {
1031 //printf(infoString,"TIMER...");
1034 sprintf(infoString,"Seconds=%d", model->delaySeconds);
1035
1036 }
1037#endif
1038 break;
1039 case SCREEN_TYPE_TIMER:
1040 case SCREEN_TYPE_DOC_FOLLOW:
1041 //case SCREEN_TYPE_HOME_SIMPLE:
1042 case SCREEN_TYPE_HOME_SIMPLE_2:
1043 case SCREEN_TYPE_HOME_SIMPLE_3:
1044 case SCREEN_TYPE_PAIRED_DEV:
1045 case SCREEN_TYPE_REBOOT:
1046 {
1047 //!update the model for those drawing Dev and Connected Dev
1049
1050 multilineScreenType = true;
1051 //! just ask the deviceState...
1053 switch (model->pairedDeviceStateEnum)
1054 {
1055 //paired to a device, but BLE NOT connected right now
1057 sprintf(infoString,"%s\n+%.*s",deviceName_mainModule(),10,getPairedDeviceOrAddress_mainModule() );
1058 break;
1059 //paired to a device, and BLE connected right now
1061 sprintf(infoString,"%s\n%.*s",deviceName_mainModule(),10,getPairedDeviceOrAddress_mainModule() );
1062 break;
1063 //not paired (but could be paired as it's a named device])
1065 sprintf(infoString,"%s\n-%.*s",deviceName_mainModule(),9,connectedBLEDeviceName_mainModule());
1066 break;
1067 //!factory default but not connecte to anything..
1068 case notConnectedEnum:
1069 sprintf(infoString,"%s\n%s",deviceName_mainModule(),(char*)"scanning..");
1070 break;
1071 }
1072
1073 }
1074 break;
1075
1076 case SCREEN_TYPE_FEED_GUEST:
1077 multilineScreenType = true;
1078 sprintf(infoString,"Feed Guest");
1079 break;
1080
1081
1082 case SCREEN_TYPE_HOME:
1083 case SCREEN_TYPE_HOME_SIMPLE:
1084 case SCREEN_TYPE_HOME_SIMPLE_1:
1085
1086 sprintf(infoString,"Feed=%0d(%0d) Bat=%2.0f%% %s", getFeedCount_mainModule(), feedCountMax_mainModule(), batPercentage,gStatusHome);
1087 //!could add BUZZER (but it's a distributed issue - it can be sent elsewhere..
1088 break;
1089
1090 case SCREEN_TYPE_STATUS:
1091 // case SCREEN_TYPE_REBOOT:
1092 default:
1093 sprintf(infoString,"%s|%2.0f%%|%2.0ff c%0d|%c|%s|t%0d",VERSION_SHORT, batPercentage, getTemperature_mainModule(), getFeedCount_mainModule(), buzzerOn?'B':'b', gStatus,_loopTimer);
1094 //!could add BUZZER (but it's a distributed issue - it can be sent elsewhere..
1095 break;
1096 }
1097
1098 //!setup the position for the SensorStatus .. HELP is always not-zoomed (show semantic marker)
1100 && !(screenType == SCREEN_TYPE_HELP))
1101 {
1102 //!use the zoomed amount
1103 setupTextPosition(multilineScreenType?_multilineStatusTextPositionZoomed:_sensorStatusTextPositionZoomed);
1104 }
1105 else
1106 {
1107 setupTextPosition(multilineScreenType?_multilineStatusTextPosition:_sensorStatusTextPosition);
1108 }
1109
1110 //!draw the text
1111 printText(infoString,multilineScreenType?_multilineStatusTextPosition.maxLen:_sensorStatusTextPosition.maxLen);
1112#endif //m5
1113}
1114//!draws the text and differeent if ON or OFF
1115void drawStatusText(String text, boolean isOn)
1116{
1117#ifdef ESP_M5
1118 if (isOn)
1119 M5.Lcd.setTextColor(BLUE, YELLOW);
1120 else
1121 M5.Lcd.setTextColor(WHITE, BLACK);
1122 M5.Lcd.print(text);
1123#endif
1124}
1125
1126//! returns if the modesDesired contains a mode character, but also true if modesDesired in null
1127boolean containsMode(char *modesDesired, char mode)
1128{
1129 if (!modesDesired)
1130 return true;
1131 else return index(modesDesired,mode) != NULL;
1132}
1133
1134//!sets the "Module Status", will show only the modesDesired if non null
1135void drawModuleStatus(char *modesDesired)
1136{
1137 //!setup the position for the SensorStatus
1139 {
1140 //!Zoomed .. setup the position for the ModuleStatus
1141 setupTextPosition(_moduleStatusTextPositionZoomed);
1142 }
1143 else
1144 {
1145 //!setup the position for the ModuleStatus
1146 setupTextPosition(_moduleStatusTextPosition);
1147 }
1148 // would be nice to get the device name.. of our connected BLE..
1149 //!value of WIFI connected
1150#ifdef USE_MQTT_NETWORKING
1151 if (containsMode(modesDesired,'W'))
1152 drawStatusText("W", isConnectedWIFI_MQTTState());
1153 if (containsMode(modesDesired,'M'))
1154 drawStatusText("M", isConnectedMQTT_MQTTState());
1155#endif
1156#ifdef USE_BLE_CLIENT_NETWORKING
1157 //!useBLECLient == it's linked in and running (vs not running)
1158 if (containsMode(modesDesired,'B'))
1159 drawStatusText("B", useBLEClient());
1160 //! connected == we are connected to another BLEServer
1161 if (containsMode(modesDesired,'C'))
1162 drawStatusText("C", isConnectedBLEClient());
1163#endif
1164#ifdef USE_WIFI_AP_MODULE
1165 //!not done is what we look for ..
1166 if (containsMode(modesDesired,'A'))
1167 drawStatusText("A", !doneWIFI_APModule_Credentials());
1168#endif
1169 if (containsMode(modesDesired,'T'))
1171
1172#ifdef USE_BLE_SERVER_NETWORKING
1173 if (containsMode(modesDesired,'S'))
1174 {
1175 //maybe only show if ON..
1177 drawStatusText("S",true);
1178 }
1179#endif
1180 //Buzzer (but only sometimes)
1181 if (containsMode(modesDesired,'Z'))
1183
1184 //! Reset
1185 if (containsMode(modesDesired,'R'))
1186 drawStatusText("R",true);
1187 //! Reboot
1188 if (containsMode(modesDesired,'X'))
1189 drawStatusText("X",true);
1190 //! Help
1191 if (containsMode(modesDesired,'H'))
1192 drawStatusText("H",true);
1193
1194 //! Paired
1195 if (containsMode(modesDesired,'P'))
1196 {
1197 //if the paired device is NONE then
1198 drawStatusText("P",isValidPairedDevice_mainModule());
1199 }
1200}
1201
1202//!just draw the simple status at bottom
1203void displaySimpleStatus()
1204{
1205 //!show the BLE connected status at the bottom (G3 if gen3), WIFI, and AP if APmode
1206 boolean isConnectedBLE =
1207#ifdef USE_BLE_CLIENT_NETWORKING
1209#else
1210 false;
1211#endif
1212 // whether the gateway is on.. this isn't using the Gx just BLE or GE3
1214 //WIFI means the MQTT is working (not just WIFI)
1215 boolean isConnectedWIFI =
1216#ifdef USE_MQTT_NETWORKING
1218#else
1219 false;
1220#endif
1221 char label[30];
1222 String gStatus = " "; //3 characters
1223 if (isConnectedBLE && gatewayOn)
1224 {
1225 gStatus = "GE3";
1226 }
1227 else if (isConnectedBLE)
1228 {
1229 gStatus = "BLE";
1230 }
1231
1232
1233 sprintf(label,"%s %s %s", gStatus, isConnectedWIFI?"WIFI":" ",!doneWIFI_APModule_Credentials()?"AP":" ");
1234 printTextAtTextPosition(label,_connectedStatusTextPositionZoomed);
1235}
1236
1237//!perform a zoom .. of the semantic marker - or it might be something else..
1238void displayZoomedSemanticMarker(int screenType)
1239{
1240 SerialCall.print("displayZoomedSemanticMarker: ");
1241 SerialCall.println(_semanticTitle);
1242 // use _currentSemanticMarkerAddress
1243
1244 //!used in the new model versions below..
1245 ModelKindEnum modelKind;
1246
1247
1248 //2nd line..
1249 switch (screenType)
1250 {
1251 case SCREEN_TYPE_WIFI:
1252 {
1253 //show the current WIFI..
1254 //TODO: pull out the SSID only...
1255 // {'ssid':<name we want>,'ssidPassword':p}
1256 //try JSON.. NOT WORKING ...
1257 //https://linux.die.net/man/3/strstr
1258 //I'm cheeting, for now .. and grabbing both 1 * 3
1259 char wifi1[100];
1261 char wifi2[100];
1263 char *json = main_JSONStringForWIFICredentials();
1264
1265 SerialTemp.println(wifi1);
1266 SerialTemp.println(wifi2);
1267 boolean wifi1Current = strcmp(json,wifi1)==0;
1268
1269 SerialTemp.printf("wifi1Current == %d\n", wifi1Current);
1270
1271 char buffer[100];
1272
1273 char *json1 = strstr(wifi1,":");
1274 int json1Len = 1;
1275 if (json1 && strlen(json1) > 3)
1276 {
1277 json1 += 2; //move past the ':'"
1278 }
1279 else
1280 json1 = wifi1;
1281 {
1282 //find the '
1283 char *comma = strchr(json1,'\'');
1284 json1Len = comma?((int)(comma - json1)):strlen(json1);
1285 }
1286 SerialTemp.println(json1);
1287
1288 char *json2 = strstr(wifi2,":");
1289 int json2Len = 1;
1290 if (json2 && strlen(json2) > 3)
1291 {
1292 json2 += 2; //move past the ':'"
1293 }
1294 else
1295 json2 = wifi2;
1296 {
1297 //find the '
1298 char *comma = strchr(json2,'\'');
1299 json2Len = comma?((int)(comma - json2)):strlen(json2);
1300 }
1301 SerialTemp.println(json2);
1302
1303 strcpy(buffer,"+");
1304 strncat(buffer, wifi1Current?json1:json2, wifi1Current?json1Len:json2Len );
1305 strcat(buffer,"\n\r");
1306 printTextAtTextPosition(buffer,_zoomedTextPositions[SM_ACTION_SMALL]);
1307
1308 strcpy(buffer,"-");
1309 strncat(buffer, !wifi1Current?json1:json2, !wifi1Current?json1Len:json2Len );
1310 //make it blue..
1311 M5.Lcd.setTextColor(WHITE, BLUE);
1312 M5.Lcd.print(buffer);
1313
1314 SerialCall.println(buffer);
1315 }
1316 break;
1317
1318 //!ADD SCREEN_TYPE_HOME
1319 case SCREEN_TYPE_HOME_SIMPLE:
1320 {
1321 //Draw the tilt normal, and the buzz as
1322 // new 7.25.22 per issue #126
1323 // This is for the TILT
1324 //THE BIG ACTION == first, but that color is ORANGE, so wap to the SM_ACTION colors
1326 printTextAtTextPositionOverrideTextColor("TiltOn",_zoomedTextPositions[BIG_ACTION],_zoomedTextPositions[SM_ACTION] );
1327 else
1328 printTextAtTextPositionOverrideTextColor("TiltOff",_zoomedTextPositions[BIG_ACTION], _zoomedTextPositions[SM_ACTION]);
1329
1330 //THE BIG ACTION == first, but that color is ORANGE
1332 printTextAtTextPositionOverrideTextColor("BuzzOn",_zoomedTextPositions[SM_ACTION],_zoomedTextPositions[BIG_ACTION] );
1333 else
1334 printTextAtTextPositionOverrideTextColor("BuzzOff",_zoomedTextPositions[SM_ACTION], _zoomedTextPositions[BIG_ACTION]);
1335 // show the BLE connected status at the bottom
1336 displaySimpleStatus();
1337 }
1338 break;
1339 case SCREEN_TYPE_HOME_SIMPLE_1:
1340 {
1341 // This is for the BUZZ
1342 // new 7.25.22 per issue #126
1343 //swap them .. for now .. or TODO: change the zoomText to be swapped colors..
1344 //DRAFT ...
1345 //swap colors, passing the _zoomedTextPositions of the opposite
1347 printTextAtTextPosition("TiltOn",_zoomedTextPositions[BIG_ACTION]);
1348 else
1349 printTextAtTextPosition("TiltOff",_zoomedTextPositions[BIG_ACTION]);
1350
1352 printTextAtTextPosition("BuzzOn",_zoomedTextPositions[SM_ACTION]);
1353 else
1354 printTextAtTextPosition("BuzzOff",_zoomedTextPositions[SM_ACTION]);
1355 // show the BLE connected status at the bottom
1356 displaySimpleStatus();
1357 }
1358 break;
1359 case SCREEN_TYPE_HOME_SIMPLE_2:
1360 {
1361 // new 7.25.22 per issue #126, special feeding page
1362 // Feeds left:
1363
1364 char tmpString[30];
1365 //blue as this is an option (for reset counter)
1366 sprintf(tmpString,"%0d(%0d)", getFeedCount_mainModule(), feedCountMax_mainModule());
1367 printTextAtTextPositionOverrideTextColor(tmpString,_zoomedTextPositions[BIG_ACTION], _zoomedTextPositions[SM_ACTION]);
1368 // battery percent, but orange not selected ..
1369 sprintf(tmpString,"B:%2.0f%%", getBatPercentage_mainModule());
1370 printTextAtTextPositionOverrideTextColor(tmpString,_zoomedTextPositions[SM_ACTION],_zoomedTextPositions[BIG_ACTION]);
1371 // show the BLE connected status at the bottom
1372 displaySimpleStatus();
1373 }
1374 break;
1375
1376 case SCREEN_TYPE_AP:
1377 {
1378 //TODO: change the top simple line .. to a messaging
1379 // new 7.25.22 per issue #126
1380 printTextAtTextPositionOverrideTextColor("AP",_zoomedTextPositions[BIG_ACTION], _zoomedTextPositions[SM_ACTION]);
1381 printTextAtTextPositionOverrideTextColor("Mode...",_zoomedTextPositions[SM_ACTION],_zoomedTextPositions[SM_ACTION]);
1382 // show the BLE connected status at the bottom
1383 displaySimpleStatus();
1384 }
1385 break;
1386 case SCREEN_TYPE_TIMER:
1387 case SCREEN_TYPE_HOME_SIMPLE_3:
1388 case SCREEN_TYPE_PAIRED_DEV:
1389 case SCREEN_TYPE_REBOOT:
1390 {
1391
1392 if (screenType == SCREEN_TYPE_REBOOT)
1393 modelKind = rebootModel;
1394 else if (screenType == SCREEN_TYPE_PAIRED_DEV)
1395 modelKind = pairedDeviceModel;
1396 else if (screenType == SCREEN_TYPE_HOME_SIMPLE_3)
1397 modelKind = menusModel;
1398 else if (screenType == SCREEN_TYPE_TIMER)
1399 modelKind = timerModel;
1400 else
1401 SerialMin.println(" *** INVALID screenType ***");
1402
1403 char buffer[50];
1404
1405 //!upate the model (done at beginning of loop()
1406 //updateMenuState(modelKind);
1407 //!grab this model.
1408 ModelStateStruct *model = getModel(modelKind);
1409
1410 // empty the 4 lines.. with black characters..
1411 //4 lines max
1412
1413 // blank the area
1414 M5.Lcd.fillRect(0, 80, 135, 130, BLACK);
1415
1416 // start over..
1417 strcpy(buffer,"");
1418 int windowSize = 6;
1419 int textLength = 10;
1420 if (model->perfersBigText)
1421 {
1422 windowSize = 4;
1423 textLength = 6;
1424 }
1425
1426 if (model->maxItems < windowSize)
1427 windowSize = model->maxItems;
1428
1429 printTextAtTextPosition(buffer, (windowSize <= 4)?_menuTextPositionZoomed_4less:_menuTextPositionZoomed_4plus);
1430
1431 //SerialDebug.printf("current = %d, max = %d\n",model->currentItem, model->maxItems);
1432 //get the menu items to draw..
1433 //!try a rolling window..
1434 // current 3 1..8
1435 // if there maxItems > 6 .. then when hit end .. it scrolls to next one..
1436 int startItem = 0;
1437 int maxItems = model->maxItems;
1438 int currentItem = model->currentItem;
1439 if (currentItem >= windowSize)
1440 {
1441 // scrolling time..
1442 // move start the number past maxWindow
1443 // 0..5, 1..6, 2..7 3..8 (and current always last item on scrolling)
1444 //say it's 8: current = 8, start = 8 - windowSize
1445 startItem = currentItem - windowSize + 1;
1446 }
1447 maxItems = startItem + windowSize;
1448 for (int i=startItem; i < maxItems; i++)
1449 {
1450 char *menu = menuForState(modelKind, i);
1451 if (i == model->currentItem)
1452 {
1453 // use blue...
1454 M5.Lcd.setTextColor(WHITE, BLUE);
1455 }
1456 else
1457 {
1458 M5.Lcd.setTextColor(ORANGE, BLACK);
1459 }
1460
1461 sprintf(buffer,"-%.*s\n\r", textLength, menu);
1462 M5.Lcd.print(buffer);
1463 }
1464
1465 // show the BLE connected status at the bottom
1466 // in this case, it's not connected so BLE should be off..
1467 displaySimpleStatus();
1468 }
1469 break;
1470
1471 default:
1472 {
1473 // FEED ..
1474 printTextAtTextPosition("+FEED",_zoomedTextPositions[BIG_ACTION]);
1475
1476 String title = "-" + _semanticTitle;
1477 title.replace(" ","\r\n");
1478
1479 switch (screenType)
1480 {
1481 case SCREEN_TYPE_HOME:
1482 printTextAtTextPosition(title,_zoomedTextPositions[SM_ACTION]);
1483 break;
1484
1485 //wont get here... the case is above..
1486 case SCREEN_TYPE_PAIRED_DEV:
1487 break;
1488 case SCREEN_TYPE_HELP:
1489 {
1490 // Instead of "Help Info" show the "MINI CLICKER"
1491 String title = "-MINI\r\nCLICKER";
1492 printTextAtTextPosition(title,_zoomedTextPositions[SM_ACTION]);
1493 }
1494 break;
1495 case SCREEN_TYPE_GUEST_PAGE:
1496 {
1497 //!This sends the M5's WIFI credentials down to the paired device over BLE
1498 // Instead of "Help Info" show the "MINI CLICKER"
1499 String title = "-SHARE\r\nWIFI";
1500 printTextAtTextPosition(title,_zoomedTextPositions[SM_ACTION]);
1501 }
1502 break;
1503 default:
1504 printTextAtTextPosition(title,_zoomedTextPositions[SM_ACTION]);
1505 }
1506 }
1507 break;
1508 } //switch
1509}
1510
1511//!redraws the image..
1512void redrawSemanticMarker_displayModule(boolean startNew)
1513{
1514 int screenType = screenTypeForTitle_displayModule(_semanticTitle);
1515
1516 SerialLots.printf("redrawSemanticMarker_displayModule(startNew:%d, ScreenType = %d)\n", startNew, screenType);;
1517 if (startNew)
1518 {
1519 //! resets the preferences so the mini menu is running, and resets other preferences
1520 switch (screenType)
1521 {
1522 //!ADD SCREEN_TYPE_HOME
1523 case SCREEN_TYPE_HOME_SIMPLE:
1524 {
1525 //!set some defaults on boot - that override EPROM this can be called on the HOME screen to set back to normal mode..
1527 }
1528 break;
1529 case SCREEN_TYPE_HOME_SIMPLE_1:
1530 case SCREEN_TYPE_HOME_SIMPLE_2:
1531 case SCREEN_TYPE_HOME_SIMPLE_3:
1532 //DO THIS HERE TOO.. just check if simple_3 lets things still happen..
1533 // setOnboot sets min menu and the zoomedSM
1534 {
1535 //!set some defaults on boot - that override EPROM this can be called on the HOME screen to set back to normal mode..
1537 }
1538 break;
1539 }
1540
1541#define TRY_CLEAR_WITH_RESET_TIMER
1542
1543#ifdef TRY_CLEAR_WITH_RESET_TIMER
1544 //! clears the screen, and resets timer
1546#else
1547 //also resets the loop timer
1549#endif
1550 //empty the lastSM
1551 _lastSemanticMarkerAddress = String("");
1552
1553 }
1554 else
1555 {
1556 incrementLoopTimer();
1557 }
1558
1559
1560 //!update the model (ModelController.h) for the type of screen displayed (what model)
1561 if (screenType == SCREEN_TYPE_REBOOT)
1562 //!upate the model -- each loop, before drawing stuff (obviously)
1564 else if (screenType == SCREEN_TYPE_PAIRED_DEV)
1566 else if (screenType == SCREEN_TYPE_HOME_SIMPLE_3)
1568 else if (screenType == SCREEN_TYPE_TIMER)
1570
1571 //!sets flag that being shown..
1572 _semanticMarkerShown = true;
1573
1574 //!this re-creates the address (maybe dynamically if the func() callback is defined)
1575 _currentSemanticMarkerAddress = createSemanticAddress();
1576
1577 // ** NOTE the zoom is a way to figure out what else to show..
1579 && (screenType != SCREEN_TYPE_HELP))
1580 {
1581 displayZoomedSemanticMarker(screenType);
1582 }
1583 else if (screenType == SCREEN_TYPE_DOC_FOLLOW)
1584 {
1585 //! this draws QR but using the lastDocFollowSemanticMarker
1586#define QRAVATAR
1587#ifdef ESP_M5
1588 M5.Lcd.setRotation(0);
1589 //!Draws a SemanticMarker&trade; (using QR code)
1590 //!Create a QR code with a width of 135 QR code at (0, 100). 在(0,0)处创建一个宽为135二维码
1591 //!Please select the appropriate QR code version according to the number of characters. 请根据字符数量选择合适的二维码版本
1592 //try brightness
1593 setBrightness_displayModule(0);
1594#ifdef USE_MQTT_NETWORKING
1595 M5.Lcd.qrcode(getLastDocFollowSemanticMarker_MQTTNetworking(),0,100,135);
1596#else
1597 M5.Lcd.qrcode("https://SemanticMarker.org",0,100,135);
1598
1599#endif
1600#ifdef QRAVATAR
1601 //try to draw a character in the middle ... (D, etc)
1602 printTextAtTextPosition("SM",_zoomedTextPositions[QRAVATAR_ACTION]);
1603#endif
1604#endif //ESP_M5
1605 }
1606 else
1607 {
1608#ifdef ESP_M5
1609 M5.Lcd.setRotation(0);
1610 SerialLots.print("last vs current: ");
1611 SerialLots.print(_lastSemanticMarkerAddress);
1612 SerialLots.println(" vs ");
1613 SerialLots.println(_currentSemanticMarkerAddress);
1614 //!only redraw if changed ...
1615 if (!_lastSemanticMarkerAddress.compareTo(_currentSemanticMarkerAddress)==0)
1616 {
1617 SerialLots.println(_currentSemanticMarkerAddress);
1618 //try brightness
1619 setBrightness_displayModule(0);
1620
1621 //!Draws a SemanticMarker&trade; (using QR code)
1622 //!Create a QR code with a width of 135 QR code at (0, 100). 在(0,0)处创建一个宽为135二维码
1623 //!Please select the appropriate QR code version according to the number of characters. 请根据字符数量选择合适的二维码版本
1624 M5.Lcd.qrcode(_currentSemanticMarkerAddress,0,100,135);
1625#ifdef QRAVATAR
1626 //try to draw a character in the middle ... (D, etc)
1627 String smChar = _semanticTitle.substring(0,1);
1628 printTextAtTextPosition(smChar,_zoomedTextPositions[QRAVATAR_ACTION]);
1629#endif
1630 }
1631
1632#endif
1633
1634 _lastSemanticMarkerAddress = _currentSemanticMarkerAddress;
1635 }
1636
1637 //!The "ACTION"
1638 drawAction(_semanticTitle, screenType);
1639
1640 //!The "SensorStatus", which uses current info..
1641 drawSensorStatus(screenType);
1642
1643 //!then which modules to draw for the different screens
1644 switch (screenType)
1645 {
1646 case SCREEN_TYPE_HOME_SIMPLE_3:
1647 //advanced is now ModelController..
1648 break;
1649 //!ADD SCREEN_TYPE_HOME
1650 case SCREEN_TYPE_HOME_SIMPLE:
1651 case SCREEN_TYPE_HOME_SIMPLE_1:
1652 case SCREEN_TYPE_HOME_SIMPLE_2:
1653 case SCREEN_TYPE_AP:
1654 {
1655 // 7.25.22
1656 //!Draw FEED in red if the feed count is > 13
1657 if (getFeedCount_mainModule() > 13)
1658 setupTextPosition(_homeSimpleStatusTextPositionZoomedRED);
1659 else
1660 setupTextPosition(_homeSimpleStatusTextPositionZoomed);
1661 // if count > 13 make it red
1662 M5.Lcd.print("+FEED ");
1663 // 1234567
1664 }
1665 break;
1666 //REST are previous..
1667 //NOTE: that the HELP long press also goes home..
1668 case SCREEN_TYPE_HOME:
1669 //!The " ModuleStats"
1670 drawModuleStatus((char*)"WMCTZAS");
1671 break;
1672 case SCREEN_TYPE_TILT:
1673 //!The " ModuleStats"
1674 drawModuleStatus((char*)"T");
1675 break;
1676 case SCREEN_TYPE_BUZZ:
1677 //! module status with BUZZ
1678 drawModuleStatus((char*)"Z");
1679 break;
1680 case SCREEN_TYPE_WIFI:
1681 drawModuleStatus((char*)"WM");
1682 break;
1683// case SCREEN_TYPE_AP:
1684// drawModuleStatus((char*)"WMA");
1685// break;
1686 case SCREEN_TYPE_HELP:
1687 // drawModuleStatus((char*)"H");
1688 // maybe draw text: iDogWatch.com/bot/help
1689 setupTextPosition(_helpStatusTextPosition);
1690
1691 //!draw the text
1692 printText((char*)"iDogWatch.com/bot/help",_helpStatusTextPosition.maxLen);
1693 break;
1694
1695 case SCREEN_TYPE_RESET:
1696 drawModuleStatus((char*)"R");
1697 break;
1698 case SCREEN_TYPE_TIMER:
1699 break;
1700 case SCREEN_TYPE_REBOOT:
1701 break;
1702 case SCREEN_TYPE_PAIRED_DEV:
1703 break;
1704
1705 case SCREEN_TYPE_GUEST_PAGE:
1706 drawModuleStatus((char*)"WMC");
1707 break;
1708 case SCREEN_TYPE_FEED_GUEST:
1709 drawModuleStatus((char*)"WMC");
1710 break;
1711
1712 case SCREEN_TYPE_STATUS:
1713 default:
1714 //!The " ModuleStats"
1715 //drawModuleStatus((char*)"WMBCATZ");
1716 drawModuleStatus((char*)"WMBCATS");
1717
1718 }
1719 //!startNew is that the screen needs new timeout
1720 if (startNew)
1721 {
1722 // boolean zoomed = getPreferenceBoolean_mainModule( PREFERENCE_SEMANTIC_MARKER_ZOOMED_VALUE);
1723 //if the SemanticMarker is show, delay 50
1724 //!startDelay(zoomed?25: currentScreenTimeout());
1725 startDelay(currentScreenTimeout());
1726
1727 //! called by the feed operation to say the device is still running.. and count it as a button click.
1728 //! Issue #145 8.8.22
1730
1731 //!NOTE: this gets called 2 times if buttonB short press .. but not othertimes..
1732
1733 }
1734
1735}
1736
1737
1738//! ISSUE: need to re-generate the SemanticAddress but only for "Status".
1739//! could kluge and use the Title?? == "Status"
1740
1741//**** Specific Methods*******
1742//!displays the Semantic Marker (a super QR code) on the M5 screen (with an N second display)
1743void showSemanticMarker_displayModule(String semanticMarkerAddress, String title)
1744{
1745
1746 SerialTemp.print("showSemanticMarker(nulls func) ");
1747 SerialTemp.print(title);
1748 SerialTemp.print(" SM=");
1749 SerialTemp.println(semanticMarkerAddress);
1750
1751 //!NOTE: issue #134 shows that the 'buttonProcessing _currentSMMode isn't getting updated .. Which is only an issue if the message is comming in from outside -- versus a button clik..
1752 //!cache for the redraw()
1753 _semanticTitle = title;
1754 //!no function, the addresss is the address provided
1755 //!NOTE: we could add our own function .. TODO .. less of a kluge..
1756 _getStatusFunc = NULL;
1757
1758 _currentSemanticMarkerAddressBase = semanticMarkerAddress;
1759 //!save the marker..
1760 _lastSemanticMarkerAddress = String("");
1761
1762 // clearScreen_displayModule();
1763
1764 //!draw a semantic marker (zoomed or not)
1766
1767 //startDelay(20);
1768//issue is another display can show up while this is being shown. like FEED , etc
1769}
1770
1771
1772//UNUSED SO FAR..
1773
1774//!finish the address after calling the function provided, called from MQTT for STATUS
1775void showSemanticMarkerFunc_displayModule(String semanticMarkerAddressBase, String title, const char* (*getStatusFunc)(void))
1776{
1777 SerialCall.print("showSemanticMarkerFunc: ");
1778 SerialCall.print(title);
1779 SerialCall.print(" SM=");
1780 SerialCall.println(semanticMarkerAddressBase);
1781
1782 //!save for use on redraw..
1783 _getStatusFunc = getStatusFunc;
1784 _currentSemanticMarkerAddressBase = semanticMarkerAddressBase;
1785 _semanticTitle = title;
1786 _lastSemanticMarkerAddress = String("");
1787
1788 // clearScreen_displayModule();
1789
1791
1792 //startDelay(20);
1793
1794}
1795
1796
1797//!
1798//! shows a FEED (or whatever) then blanks the screen after N seconds
1799void showText_displayModule(String text)
1800{
1801 drawAction(text, _currentScreenType);
1802 // startDelay(10);
1803}
1804
1805//! adds messages that aren't shown unless in message window mode.
1806//! NOTE: This will be a scrolling text as sometime ..
1807void addToTextMessages_displayModule(String text)
1808{
1809 SerialLots.printf("addToTextMessages_displayModule:(%d)",displayOnBlankScreen());
1810 SerialLots.println(text);
1811
1812 //!whether screen is blank (so the button can be a wake, vs action..)
1813 if (isBlankScreen_displayModule() and !displayOnBlankScreen())
1814 {
1815 SerialLots.println("Not displaying since blank screen");
1816 return;
1817 }
1818
1819
1820 //!different for home screen
1821 switch (_currentScreenType)
1822 {
1823 //!ADD SCREEN_TYPE_HOME
1824 case SCREEN_TYPE_HOME_SIMPLE:
1825 case SCREEN_TYPE_HOME_SIMPLE_1:
1826 case SCREEN_TYPE_HOME_SIMPLE_2:
1827 case SCREEN_TYPE_AP:
1828 //don't show anything over the SMART CLICKER at the top
1829 break;
1830 case SCREEN_TYPE_HOME_SIMPLE_3:
1831 //TODO.. for now..
1832 // draw the title but on the 2nd smaller line
1833 //!use the zoomed amount
1834 setupTextPosition(_sensorStatusTextPositionZoomed);
1835
1836 //!draw the text
1837 printText(text,_sensorStatusTextPosition.maxLen);
1838 break;
1839 default:
1840 drawAction(text, _currentScreenType);
1841 }
1842}
1843
1844
1845#else // not DISPLAY_MODULE
1846
1847//!Increment the screen color 0..n cache for getting the screen color 0..max (max provided by sender)
1848//!This is implemented by incrementScreenColor_mainModule() since it knows the MAX value of colors
1850{
1851
1852}
1853
1854
1855//!cache for getting the screen color 0..n. Will reset the cache as well
1856void setScreenColor_displayModule(int screenColor)
1857{
1858
1859}
1860
1861//!THIS IS the setup() and loop() but using the "component" name, eg MQTTNetworking()
1862//!This will perform preference initializtion as well
1863//! called from the setup()
1865{
1866
1867}
1868
1869//! called for the loop() of this plugin
1871{
1872
1873}
1874
1875//! shows a FEED (or whatever) then blanks the screen after N seconds
1876//! NOTE: This will be a scrolling text as sometime ..
1877void showText_displayModule(String text)
1878{
1879
1880}
1881
1882//! adds messages that aren't shown unless in message window mode.
1883//! NOTE: This will be a scrolling text as sometime ..
1885{
1886
1887}
1888
1889//!blanks the screen
1891{
1892
1893}
1894
1895//!wakes up the screen
1897{
1898
1899}
1900
1901//!whether screen is blank (so the button can be a wake, vs action..)
1903{
1904 return true;
1905}
1906
1907//!clears the screen
1909{
1910
1911}
1912
1913//!displays the Semantic Marker (a super QR code) on the M5 screen (title = to display)
1914void showSemanticMarker_displayModule(String semanticMarkerAddress, String title)
1915{
1916
1917}
1918
1919//!returns the current semantic marker (eg. guest page)
1921{
1922 return (char*)"unused";
1923}
1924
1925//!the function to call to get the 'status', return char*
1926//char* (*getStatusFunc)(void)
1927//typedef String (*getStatusFunc)(void);
1928
1929//!displays the Semantic Marker (a super QR code) on the M5 screen (title = to display)
1930void showSemanticMarkerFunc_displayModule(String semanticMarkerAddressBase, String title, const char* (*getStatusFunc)(void))
1931{
1932
1933}
1934
1935//!redraws the Semantic Marker image..
1937{
1938
1939}
1940
1942//!returns the loop timer (just a timer..)
1944{
1946}
1947
1948//!reset the loop timer .. useful for testing,
1950{
1952}
1953#endif
boolean isConnectedBLEClient()
returns whether connected over BLE as a client to a server(like a ESP feeder)
boolean useBLEClient()
returns if the BLEClient is turned on.. note, if connected to a BLE device, then disconnect
void loop_displayModule()
called for the loop() of this plugin
void showSemanticMarkerFunc_displayModule(String semanticMarkerAddressBase, String title, const char *(*getStatusFunc)(void))
the function to call to get the 'status', return char*
void addToTextMessages_displayModule(String text)
void wakeupScreen_displayModule()
wakes up the screen
int _loopCounter_displayModule
void setup_displayModule()
for types: String, boolean ..
void clearScreen_displayModule()
clears the screen
void incrementScreenColor_displayModule()
boolean isBlankScreen_displayModule()
whether screen is blank (so the button can be a wake, vs action..)
void showText_displayModule(String text)
void redrawSemanticMarker_displayModule(boolean startNew)
redraws the Semantic Marker image..
void setScreenColor_displayModule(int screenColor)
cache for getting the screen color 0..n. Will reset the cache as well
void showSemanticMarker_displayModule(String semanticMarkerAddress, String title)
displays the Semantic Marker (a super QR code) on the M5 screen (title = to display)
void blankScreen_displayModule()
blanks the screen
const char * currentSemanticMarkerAddress_displayModule()
returns the current semantic marker (eg. guest page)
int getLoopTimer_displayModule()
returns the loop timer (just a timer..)
void resetLoopTimer_displayModule()
reset the loop timer .. useful for testing,
void showOTAUpdatingMessage()
show an OTA message..
#define START_NEW
Definition: DisplayModule.h:53
#define KEEP_SAME
Definition: DisplayModule.h:54
char * getLastDocFollowSemanticMarker_MQTTNetworking()
boolean isConnectedMQTT_MQTTState()
value of MQTT connected
boolean isConnectedWIFI_MQTTState()
value of WIFI connected
char * deviceName_mainModule()
gets the device name
Definition: MainModule.cpp:607
int getFeedCount_mainModule()
feedcount info..
Definition: MainModule.cpp:155
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
char * getPairedDeviceOrAddress_mainModule()
returns if the paired device is not NONE .. returns address or device
Definition: MainModule.cpp:588
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,...
float getTemperature_mainModule()
retrieves the temperature .
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
float getBatPercentage_mainModule()
start of the sensor updates ... TODO: tie these to the MQTT messaging as well..
void updateMenuState(ModelKindEnum modelKind)
updates the model for the menu state, this sets max etc
char * menuForState(ModelKindEnum modelKind, int item)
returns the menu string for the deviceState's item number (use woudl go 0..maxItems -1
ModelStateStruct * getModel(ModelKindEnum modelKind)
retrieves the state model for the modelKind
ModelKindEnum
a pseudo Class
@ menusModel
@ pairedDeviceModel
@ timerModel
@ rebootModel
@ pairedButNotConnectedEnum
@ notConnectedEnum
factory default but not connecte to anything..
@ pairableAndConnectedEnum
@ pairedAndConnectedEnum
void savePreferenceInt_mainModule(int preferenceID, int val)
sets an int 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 setOnBootPreferences_mainModule()
set some defaults on boot - that override EPROM this can be called on the HOME screen to set back to ...
int getPreferenceInt_mainModule(int preferenceID)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
char * getPreferenceString_mainModule(int preferenceID)
returns the preference but in it's own string buffer. As long as you use it before calling getPrefere...
#define PREFERENCE_SENSOR_TILT_VALUE
Sensor preferences.
#define PREFERENCE_ONLY_GEN3_CONNECT_SETTING
if true, only BLEClient connect to GEN3 feeders..
#define PREFERENCE_SEMANTIC_MARKER_ZOOMED_VALUE
Display preferences (SemanticMarker etc) - boolean.
#define PREFERENCE_WIFI_CREDENTIAL_2_SETTING
#define PREFERENCE_MAIN_BLE_SERVER_VALUE
#define PREFERENCE_STEPPER_BUZZER_VALUE
stepper preferences
#define PREFERENCE_WIFI_CREDENTIAL_1_SETTING
#define PREFERENCE_DISPLAY_SCREEN_TIMEOUT_VALUE
sets the timeout value
#define PREFERENCE_DISPLAY_ON_BLANK_SCREEN_VALUE
Display preferences - show messages on blank screen- boolean.
#define PREFERENCE_IS_MINIMAL_MENU_SETTING
sets the max temp for a poweroff
#define PREFERENCE_SCREEN_COLOR_SETTING
ithe color of the screen 0..n
#define PREFERENCE_MAIN_GATEWAY_VALUE
boolean doneWIFI_APModule_Credentials()
called to see if the WIFIModule has finished bootstrapping..
the struct for the models. Since this isn't straight OO, we are overlaying information....
int currentItem
the current item
boolean perfersBigText
a preference to the View that big text is desired
PairedDeviceStateEnum pairedDeviceStateEnum
int delaySeconds
length of delay (changable..)
int maxItems
the number of items in the model