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//!@see https://docs.m5stack.com/en/api/core2/lcd_api (for the Core2)
10/**
11 * System:
12 * M5.begin();
13 *
14 * LCD:
15 * M5.Lcd.drawPixel(int16_t x, int16_t y, uint16_t color);
16* M5.Lcd.drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
17* M5.Lcd.fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
18* M5.Lcd.fillScreen(uint16_t color);
19* M5.Lcd.drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
20* M5.Lcd.drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,uint16_t color);
21* M5.Lcd.fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
22* M5.Lcd.fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,int16_t delta, uint16_t color);
23* M5.Lcd.drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
24* M5.Lcd.fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
25* M5.Lcd.drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
26* M5.Lcd.fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
27* M5.Lcd.drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
28* M5.Lcd.drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h),
29* M5.Lcd.drawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg, uint8_t size);
30* M5.Lcd.setCursor(uint16_t x0, uint16_t y0);
31* M5.Lcd.setTextColor(uint16_t color);
32* M5.Lcd.setTextColor(uint16_t color, uint16_t backgroundcolor);
33* M5.Lcd.setTextSize(uint8_t size);
34* M5.Lcd.setTextWrap(boolean w);
35* M5.Lcd.printf();
36* M5.Lcd.print();
37* M5.Lcd.println();
38* M5.Lcd.drawCentreString(const char *string, int dX, int poY, int font);
39* M5.Lcd.drawRightString(const char *string, int dX, int poY, int font);
40 //M5.Lcd.drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x, uint16_t y);
41 //M5.Lcd.drawJpgFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y);
42 //M5.Lcd.drawBmpFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y);
43 *
44 */
45/***************************************************************************************
46 ** Function name: setRotation In
47 ** Description: rotate the screen orientation m = 0-3 or 4-7 for BMP drawing
48 ***************************************************************************************/
49/*
50 void TFT_eSPI::setRotation(uint8_t m)
51 */
52#ifdef ESP_M5_LATER
53
54//!new design for the pairing and dynamic discovery and pairing..
55
56//!defined in icon.c
57//extern const unsigned char bitmap[13424];
58//! draws the bitmap .. for testing
59void drawBitmapIcon()
60{
61 // M5.Lcd.drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
62 // M5.Lcd.drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h),
63
64 M5.Lcd.drawRGBBitmap(0,0, (uint16_t *)bitmap, 135,100);
65}
66#endif //later..
67
68#ifdef M5CORE2_MODULE
69boolean _showScrollingTextWindow = false;
70
71#define SHOW_BIG_BUTTON
72//! the BIG BUTTON is green and says Feed
73/**
74 1.24.24 First attempt at using the M5Core2 display to show something other than the M5 display
75 1. scrolling text
76 */
77#endif
78
79//! 1.24.24 as alternate display windows are introducted,
80//! let others know and don't overright stuff..
82{
83#ifdef M5CORE2_MODULE
84 //! if showing the scrolling window .. don't do the rest ..
85 return _showScrollingTextWindow;
86#else
87 return false;
88#endif
89}
90
91//!prints the text up to the maxLen (the setup of position, etc is already done)
92void printText(String text, int maxLen);
93
94//!default semantic marker (or the current one)
95String _currentSemanticMarkerAddress="https://iDogWatch.com";
96/**
97* \image html IMG_4616.PNG "AR + Semantic Marker"
98*/
99//!returns the current semantic marker (eg. guest page)
101{
102 return _currentSemanticMarkerAddress.c_str();
103}
105//!default semantic title
106String _semanticTitle = "M5 Clicker";
107//!base http address of semantic markers
108String _currentSemanticMarkerAddressBase = "https://iDogWatch.com";
109//!stores the statusFunc (it's a pointer to a function)
110const char* (*_getStatusFunc)(void) = NULL;
111
112//!if blank, then only show something after a click (not a message)
113boolean _semanticMarkerShown = false;
114
115//! 1.26.24 10 seems to be working..
116#define SEMANTIC_MARKER_QR_VERSION 10
117
118//!The type of screen (not the SM_home, etc, but using the SemanticTitle)
119//!NORMAL for normal display .. we can use NORMAL for the first page..
120#define SCREEN_TYPE_NORMAL 0
121//! for home screen
122#define SCREEN_TYPE_HOME 1
123#define SCREEN_TYPE_STATUS 2
124#define SCREEN_TYPE_HELP 3
125#define SCREEN_TYPE_WIFI 4
126#define SCREEN_TYPE_TILT 5
127#define SCREEN_TYPE_BUZZ 6
128#define SCREEN_TYPE_AP 7
129#define SCREEN_TYPE_GUEST_PAGE 8
130#define SCREEN_TYPE_FEED_GUEST 9
131#define SCREEN_TYPE_PAIRED_DEV 10
132#define SCREEN_TYPE_RESET 11
133#define SCREEN_TYPE_REBOOT 12
134//!try simple menu
135#define SCREEN_TYPE_HOME_SIMPLE 13 //tilt
136#define SCREEN_TYPE_HOME_SIMPLE_1 14 //buzz
137#define SCREEN_TYPE_HOME_SIMPLE_2 15 //feed
138#define SCREEN_TYPE_HOME_SIMPLE_3 16 //advanced
139#define SCREEN_TYPE_DOC_FOLLOW 17 //docFollow
140#define SCREEN_TYPE_TIMER 18 //timer
141
142//!the current screen type (a side effect of asking for it)
144
145//!returns the screen type (f0..n) for the title (such as HOME) NOTE: if the name changes .. ramifications
146//! So they match the MQTTNetwork title strings..
148{
149 //!NOTE: All the comparisons are ALL CAPS ...
150 title.toUpperCase();
151 int screenType = SCREEN_TYPE_NORMAL;
152 if (title.compareTo("MINI CLICKER")==0)
153 {
154 screenType = SCREEN_TYPE_HOME_SIMPLE;
155 }
156 else if (title.compareTo("MINI-1")==0)
157 {
158 screenType = SCREEN_TYPE_HOME_SIMPLE_1;
159 }
160 else if (title.compareTo("MINI-2")==0)
161 {
162 screenType = SCREEN_TYPE_HOME_SIMPLE_2;
163 }
164 //!ADD SCREEN_TYPE_HOME
165
166 else if (title.compareTo("MINI-3")==0)
167 {
168 screenType = SCREEN_TYPE_HOME_SIMPLE_3;
169 }
170 //rest are normal
171 else if (title.compareTo("WIFI FEED")==0)
172 {
173 screenType = SCREEN_TYPE_HOME;
174 }
175 else if (title.startsWith("HELP"))
176 {
177 screenType = SCREEN_TYPE_HELP;
178 }
179 else if (title.startsWith("WIFI"))
180 {
181 screenType = SCREEN_TYPE_WIFI;
182 }
183 else if (title.startsWith("TILT"))
184 {
185 screenType = SCREEN_TYPE_TILT;
186 }
187 else if (title.startsWith("BUZZ"))
188 {
189 screenType = SCREEN_TYPE_BUZZ;
190 }
191 else if (title.startsWith("AP"))
192 {
193 screenType = SCREEN_TYPE_AP;
194 }
195 else if (title.startsWith("GUEST PAGE"))
196 {
197 screenType = SCREEN_TYPE_GUEST_PAGE;
198 }
199 else if (title.startsWith("FEED GUEST"))
200 {
201 screenType = SCREEN_TYPE_FEED_GUEST;
202 }
203 else if (title.startsWith("STATUS"))
204 {
205 screenType = SCREEN_TYPE_STATUS;
206 }
207 else if (title.startsWith("RESET"))
208 {
209 screenType = SCREEN_TYPE_RESET;
210 }
211 else if (title.startsWith("DOC FOLLOW"))
212 {
213 screenType = SCREEN_TYPE_DOC_FOLLOW;
214 }
215 else if (title.startsWith("REBOOT"))
216 {
217 screenType = SCREEN_TYPE_REBOOT;
218 }
219 else if (title.startsWith("TIMER"))
220 {
221 screenType = SCREEN_TYPE_TIMER;
222 }
223 //! the "P:" is a special token from the MQTT that denotes this is a pairing feed. The P: is replaced with the paired device
224 else if (title.startsWith("P:"))
225 {
226 screenType = SCREEN_TYPE_PAIRED_DEV;
227 }
228 //set global used by callers of addToTextMessages_displayModule
229 _currentScreenType = screenType;
230 return screenType;
231}
232
233
234
235//!These are when the ESP_M5 isn't used, so the code below compiles..
236#ifdef ESP_M5
237#else
238//!unused .. for now since no display
239#define BLACK 100
240#define WHITE 101
241#define YELLOW 102
242#define BLUE 103
243#define RED 104
244#define ORANGE 105
245
246#endif
247#ifdef M5CORE2_MODULE
248#define WIDTH 320
249#else
250#define WIDTH 135
251#endif
252
253#define HEIGHT_3 20
254#define HEIGHT_3_2LINE 60
255
256#define HEIGHT_4 40
257
258#define HEIGHT_2 10
259#define HEIGHT_1 10
260
261#define ROTATE_0 0
262#define FONT_3 3
263#define FONT_2 2
264#define FONT_1 1
265
266//!defines the position constants
267//!Note some uses below just use the text color and size attributes, (Too much work to make a variable struct)
268//! eg. ORANGE,WHITE,BLACK
269typedef struct TextPosition
270{
271 uint16_t x,y;
272 uint16_t width, height;
273 uint16_t textSize;
274 uint16_t textColor;
276 uint16_t blankColor;
277
278 uint16_t rotation; // 0
279 uint16_t maxLen; // 0
280
282
283//!EG: #actMe (M5) { ksjdfkdsjfk
284//! Feed Guest
285//!based on text size 3
289// the simple title (MINI CLICKER)
295
296//! these are grouped in an array for the color index to use. If index > max then use max.. (-1)
297#define MAX_ACTION_TEXT_HOME_COLORS 5
299{
305};
306
307//! mode is the status of sensors .
310
312 {0,65,WIDTH,HEIGHT_3,FONT_2,ORANGE,BLACK,BLACK,ROTATE_0,22};
313//! Help
316
317#ifdef M5CORE2_MODULE
318//! 2.10.24 on M5Core2 there is a line under "MINI CLICKER" that can show the Device name and pair=
319TextPositionStruct _moduleDeviceNameTextPosition = {0,40,WIDTH,HEIGHT_3,FONT_3,YELLOW,BLUE,BLACK,ROTATE_0,30};
320#endif
321//!status are the state modules (WIFI ON/off, etc)
324
325//! new for the SM_HOME_SIMPLE
327//! new for the SM_HOME_SIMPLE - draws FEED as red if over 13 feeds..
329
330//! the position of "connected" at the bottom on the first 3 screens..
332
333//!new Menu selection (if 4 ..)
336
337
338//top == feed, bottom = semantic marker (or the action of it)..{
339#define BIG_ACTION 0
340#define SM_ACTION 1
341#define SM_ACTION_SMALL 2
342#define QRAVATAR_ACTION 3
343
344#define MAX_ACTIONS 4
345
346#define TRY_SWAPPED_COLORS
347#ifdef TRY_SWAPPED_COLORS
349 {0,145,WIDTH,HEIGHT_3,FONT_3,ORANGE,BLACK,BLACK,ROTATE_0,7},
350 {0,180,WIDTH,HEIGHT_3,FONT_3,WHITE,BLUE,BLACK,ROTATE_0,7},
351
352 //the smaller WIFI words (without feed..)
353 {0,145,WIDTH,HEIGHT_2,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,40},
354 //the avatar character.. not perfect Blue on Yellow -- how about Red
355 {50,150,1,HEIGHT_3,FONT_3,RED,YELLOW,BLACK,ROTATE_0,2}
356};
357#else
359 {0,145,WIDTH,HEIGHT_3,FONT_3,WHITE,BLUE,BLACK,ROTATE_0,7},
360 {0,180,WIDTH,HEIGHT_3,FONT_3,WHITE,BLACK,BLACK,ROTATE_0,7},
361 //!home screens bottom action
362 {0,180,WIDTH,HEIGHT_3,FONT_3,ORANGE,BLACK,BLACK,ROTATE_0,7},
363
364 //the smaller WIFI words (without feed..)
365 {0,145,WIDTH,HEIGHT_2,FONT_2,WHITE,BLACK,BLACK,ROTATE_0,40},
366 //the avatar character.. not perfect Blue on Yellow -- how about Red
367 {50,150,1,HEIGHT_3,FONT_3,RED,YELLOW,BLACK,ROTATE_0,2}
368};
369#endif
370
371//! init the text - but override the text color (stil using the textP.blankCOlor
373{
374 //SerialTemp.printf("setupText(%d,%d,w=%d,h=%d)\n", textP.x, textP.y, textP.width, textP.height);
375#ifdef ESP_M5
376#ifdef M5CORE2_MODULE
377 //! DON"T rotate -- for the M5Core2 display
378#else
379 M5.Lcd.setRotation(textP.rotation);
380#endif
381 M5.Lcd.fillRect(textP.x, textP.y, textP.width, textP.height, textColor.blankColor );
382 M5.Lcd.setTextColor(textColor.textColor, textColor.textColorBackground);
383 M5.Lcd.setCursor(textP.x + 2, textP.y);
384 M5.Lcd.setTextSize(textP.textSize);
385#endif
386}
387
388//!show an OTA message..
390{
391#ifdef ESP_M5
392 // blank the area
393 M5.Lcd.fillRect(0, 60, 135, 140, ORANGE);
394 M5.Lcd.setTextColor(WHITE, BLACK);
395 M5.Lcd.setCursor(10, 90);
396 M5.Lcd.setTextSize(2);
397 M5.Lcd.println("\nStarting \nOTA Update \nPlease Wait\n2-5 minutes");
398#endif
399}
400
401//! set so it can be erased on next loop
403
404//! 4.3.24 show text in big letters
405//!@see https://github.com/konacurrents/ESP_IOT/issues/323
406//!show full screen message..
407void displayFullscreenMessage(String text, boolean turnOn)
408{
409#ifdef ESP_M5
410 if (turnOn)
411 {
413 // M5.Lcd.fillScreen(BLUE);
414
415 // blank the area
416 M5.Lcd.fillRect(0, 0, 135, 240, BLUE);
417 M5.Lcd.setTextColor(WHITE, BLACK);
418 M5.Lcd.setCursor(10, 90);
419 M5.Lcd.setTextSize(3);
420 M5.Lcd.print(text);
421
422 // delay then clear
423 // delay(50);
424 // redrawSemanticMarker_displayModule(false);
425 //wakeupScreen_displayModule();
426 }
427 else
428 {
430
432
433 // M5.blankscreen();
434 }
435#endif
436}
437
438//! init the text
440{
441 //use same color
443
444}
445
446//!use the textPositionStruct - but override the text color
448{
449 setupTextPositionOverrideTextColor(textPosition, textColor);
450 //SerialDebug.printf("'%s'\n", text);
451#ifdef ESP_M5
452 M5.Lcd.print(text);
453#endif
454}
455
456//!use the textPositionStruct
457void printTextAtTextPosition(String text, TextPositionStruct textPosition)
458{
459 setupTextPosition(textPosition);
460#ifdef ESP_M5
461 M5.Lcd.print(text);
462#endif
463}
464
465
466//! SCREEN COLOR
467//!Increment the screen color 0..n cache for getting the screen color 0..max (max provided by sender)
468//!This is implemented by incrementScreenColor_mainModule() since it knows the MAX value of colors
470{
472 screenColor++;
473 if (screenColor >= MAX_ACTION_TEXT_HOME_COLORS)
474 {
475 // change color and store
476 screenColor = 0;
477 }
479
480 SerialCall.printf("incrementScreenColor_displayModule = %d\n", screenColor);
481}
482
483//!cache for getting the screen color 0..n. Will reset the cache as well
485{
486 //normalize
488 if (screenColor < 0 || screenColor >= MAX_ACTION_TEXT_HOME_COLORS)
489 {
490 // normalize the number, and store it..
491 screenColor = screenColor % MAX_ACTION_TEXT_HOME_COLORS;
493 }
494 SerialLots.printf("getScreenColor_displayModule = %d\n", screenColor);
495
496 return screenColor;
497}
498
499//!cache for getting the screen color 0..n. Will reset the cache as well
500void setScreenColor_displayModule(int screenColor)
501{
502 //normalize
503 if (screenColor < 0 || screenColor >= MAX_ACTION_TEXT_HOME_COLORS)
504 {
505 // normalize the number, and store it..
506 screenColor = screenColor % MAX_ACTION_TEXT_HOME_COLORS;
507 }
509 SerialCall.printf("setScreenColor_displayModule = %d\n", screenColor);
510
511}
512
513
514
515//!markerTimer is a semi timer for the number of times before doing anything. Kinda a kludge.
517//! ticks.. when it rest? (show to blank screen)
519//!increment the loop timer
521{
522 _loopTimer = (_loopTimer+1) % 100;
523}
524//!stop the loop timer
526{
527 _loopTimer = 0;
528}
529//!returns the loop timer (just a timer..)
531{
532 return _loopTimer;
533}
534
535//!reset the loop timer .. useful for testing,
537{
538 _loopTimer = 0;
539}
540/**
541* \image html SMStatus1.PNG "Semantic Marker"
542*/
543//!NOTE: need to add dev:deviceName
544//!creates semantic address, and if _getStatusFunc is non nil, call it to add to the address SemanticMarker&trade;
546{
547 //!if there is a status function to call, call it and add to the address (and tack on the _loopTimer)
548 //!Otherwise, just use the provided address (not a status like address)
549 if (_getStatusFunc)
550 {
551 SerialTemp.print("createDynamicSemanticAddress: ");
552
553 //check if this is right (the base)
554 // _currentSemanticMarkerAddress = _currentSemanticMarkerAddressBase + "/" + String((*_getStatusFunc)()) + "&t=" + String(_loopTimer);
555 _currentSemanticMarkerAddress = String((*_getStatusFunc)()) + "&t=" + String(_loopTimer);
556
557 }
558 else
559 {
560 SerialCall.print("createSemanticAddress: ");
562 }
563
564
565 int maxLenForIphone = 250;
566
567 // strip down to 155 .. yanking off each parameter?? or just chop it.. for not just chop it..
568 if (_currentSemanticMarkerAddress.length() > maxLenForIphone)
569 {
570 SerialTemp.printf("1. Truncating chartacters to: %d\n", maxLenForIphone);
571 SerialTemp.println(_currentSemanticMarkerAddress);
573 }
574
575 SerialCall.println(_currentSemanticMarkerAddress);
577}
578
579
580#define USE_TIMER_DELAY_CLASS
581//! 3.29.25 RaiiiinIeeeeR Beer movie
582#ifdef USE_TIMER_DELAY_CLASS
584void startDelay(int seconds)
585{
587}
589{
591}
593{
595}
596#else
597//**** Delay Methods*******
598#define SINGLE_DELAY
599#ifdef SINGLE_DELAY
600//https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html
601//! the time the delay started
602unsigned long _delayStart;
603//! true if still waiting for delay to finish
604boolean _delayRunning = false;
605//! length of delay
606int _delaySeconds;
607//!init the delay starting
608void startDelay(int seconds)
609{
610 SerialCall.printf("startDelay_displayModule: %d\n", seconds);
611
612 _delayStart = millis(); // start delay
613 _delayRunning = true; // not finished yet
614 _delaySeconds = seconds;
615
616}
617//!if finished..
618boolean delayFinished()
619{
620 if (_delayRunning && ((millis() - _delayStart) >= (_delaySeconds * 1000)))
621 {
622 _delayRunning = false;
623 SerialCall.println("delayFinished..");
624 return true;
625 }
626 return false;
627}
628
629//!stop the delay
630void stopDelay()
631{
632 SerialCall.println("stopDelay _delayRunning=false");
633
634 _delayRunning = false;
635}
636#endif //SINGLE_DELAY
637#endif // USE_TIMER_DELAY_CLASS
638
639//****** SCREEN DISPLAY ************
640//!new 12.29.22
641//!
642//! //! https://github.com/Bodmer/TFT_eSPI/issues/226
643//! TRY THIS:
644#define BLK_PWM_CHANNEL 7 // LEDC_CHANNEL_7
645void setBrightness_displayModule(int brightness)
646{
647#ifdef LATER
648 ledcWrite(BLK_PWM_CHANNEL, brightness);
649#endif
650}
651
652//!blanks the screen
654{
655 SerialCall.println("blankScreen_displayModule");
657
658 //!stop the delay which says delay finished .. so don't show anything.. 8.9.22
659 stopDelay();
660
661 //nothing displayed
662 _semanticMarkerShown = false;
663
664#ifdef ESP_M5
665 M5.Lcd.fillScreen(BLACK);
666 //not available.. without M5Stack.h ???
667 // M5.Lcd.setBrightness(0);
668 // M5.Lcd.setBrightness(200);
669
670 //M5.Lcd.sleep();
671
672 // M5.Lcd.fillScreen(ORANGE);
673
674 //get out of all modes..
675 // #issue #144 show something to let know its screen saver not OFF
676
678
679
680
681#define TRY_DEVICES_AND_PAIRED
682#ifdef TRY_DEVICES_AND_PAIRED
683 {
684 char infoString[150];
685 boolean multilineScreenType;
686
687 //!update the model for those drawing Dev and Connected Dev
689
690 multilineScreenType = true;
691 //! just ask the deviceState...
693 switch (model->pairedDeviceStateEnum)
694 {
695 //paired to a device, but BLE NOT connected right now
697 sprintf(infoString,"%s\n+%.*s",deviceName_mainModule(),10,getPairedDeviceOrAddress_mainModule() );
698 break;
699 //paired to a device, and BLE connected right now
701 sprintf(infoString,"%s\n%.*s",deviceName_mainModule(),10,getPairedDeviceOrAddress_mainModule() );
702 break;
703 //not paired (but could be paired as it's a named device])
705 sprintf(infoString,"%s\n-%.*s",deviceName_mainModule(),9,connectedBLEDeviceName_mainModule());
706 break;
707 //!factory default but not connecte to anything..
708 case notConnectedEnum:
709 //sprintf(infoString,"%s\n%s",deviceName_mainModule(),(char*)"scanning..");
710 sprintf(infoString,"%s\n",deviceName_mainModule());
711
712 break;
713 }
714 SerialCall.println(infoString);
715
716 //!use the zoomed amount
718
719 //!draw the text
721 }
722#else
723 //! also show the device name..
724 //! at same location as before.. the small text below the top..
725 //!use the zoomed amount
727
728 //!draw the device name (not including the parired or not paired .. as it can change dynaically...
730#endif
731#endif
732}
733
734//!wakes up the screen
736{
737
738 //clear screen first.. since the KEEP_SAME won't clear the screen..
740
741 // _semanticMarkerShown = true;
742 SerialCall.println("wakeupScreen_displayModule");
743
744 //!see if this works .. vs too flickering.. (if so we have to slow it down..)
746
747}
748
749//!clears the screen (but not a blank screen) and stops the timer..
751{
752 SerialCall.println("clearScreen_displayModule");
753
754 //reset the timer.. NEW!! 8.9.22 (a mini blankScreen)
755 //??
757
758#ifdef ESP_M5
759#ifdef M5CORE2_MODULE
760 //! DON"T rotate -- for the M5Core2 display
761#else
762 M5.Lcd.setRotation(0);
763#endif
764 M5.Lcd.fillScreen(BLACK);
765#endif
766}
767
768//!whether screen is blank (so the button can be a wake, vs action..)
770{
771 SerialLots.print("isBlankScreen_displayModule:");
772#ifdef USE_TIMER_DELAY_CLASS
773 boolean delayRunning = !_timerDelayClass_DisplayModule->delayFinished();
774
775#else
776 boolean delayRunning = _delayRunning;
777#endif
778 SerialLots.println(!delayRunning?"BLANK":"NOT BLANK");
779
780 //! if the delay is running, then not blanked
781 return !delayRunning;
782}
783
784//! whether to display on a blank screen
786{
788}
789
790//! current screen timeout
792{
794 return val;
795}
796
797#ifdef ESP_M5
798//!setup the Lcd, etc..
800{
801 SerialMin.println("setupESP_M5");
802
803#ifdef M5STICKCPLUS2
804//! 4.20.24 add config
805 M5.config();
806#endif
807#ifdef M5CORE2_MODULE
808 /*
809 https://arduino.stackexchange.com/questions/9092/how-do-you-call-a-class-method-with-named-parameters
810 begin(bool LCDEnable = true, bool SDEnable = true, bool SerialEnable = true,
811 bool I2CEnable = false, mbus_mode_t mode = kMBusModeOutput,
812 bool SpeakerEnable = true);
813
814 M5.begin(true, true, true, false);
815 */
816#ifdef DONE_IN_MAIN
817 M5.begin( /*LCDEnable*/true, /*SDEnable*/true, /*SerialEnable*/ true,
818 /*I2CEnable*/ false, /*mode*/ kMBusModeOutput,
819 /*SpeakerEnable*/ true);
820#endif
821 //! see if this lets battery work on M5 Core2 v1.1
822 //! 2.11.24 Super Bowl day
823 //! STILL NOT WORKING on the v1.1 device
824 /*
825 M5.Axp.SetLcdVoltage(3300);
826 M5.Axp.SetBusPowerMode(0);
827 M5.Axp.SetCHGCurrent(AXP192::kCHG_190mA);
828 */
829 /*
830 M5.Power.setPowerBoostOnOff(false); //Change the power on / off method. The power does not turn off when connected via USB. true=Press and hold to turn on / off. false=Turn on / off with two short presses.
831 M5.Power.setPowerBoostSet(false); //Change the power on / off method true=ON / OFF in one short press. false=same as above
832 M5.Power.setPowerVin(true); //When the power supply from USB etc. is cut off, Decide whether to turn on the power again.
833 M5.Power.setPowerBtnEn(true); //Set whether to accept the power button.
834 M5.Power.setPowerBoostKeepOn(false); //Always output power. True= Always output power. False=not Always output power.
835 M5.Power.setAutoBootOnLoad(true); //Set whether to automatically start when power consumption occurs
836 */
837#else
838 //!Init M5StickC Plus. 初始化 M5StickC Plus
839 M5.begin();
840#endif
841
842 //!Set font size.
843 //!Set the font color to yellow. 设置字体颜色为黄色
844 M5.Lcd.setTextColor(WHITE);
845 //!rotate to landscape (vs vertical)
846 //!M5.Lcd.setRotation(3);
847#ifdef M5CORE2_MODULE
848 //! DON"T rotate -- for the M5Core2 display
849 SerialMin.println("M5CORE2_MODULE");
850 M5.Lcd.drawCircle(65,220, 10, WHITE);
851 M5.Lcd.drawCircle(155,220, 10, WHITE);
852 M5.Lcd.drawCircle(255,220, 10, WHITE);
853
854 //! * M5.Lcd.drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
855
856#else
857 //!Rotate the screen. 将屏幕旋转
858 M5.Lcd.setRotation(0);
859#endif
860 //!set the cursor location. 设置光标位置
861
862 //!Set font size.
863
864 M5.Lcd.setTextSize(2);
865 // M5.Lcd.printf("Click Controller v1.0");
866
867 //! STARTUP SCREEN showing VERSION
868 M5.Lcd.printf("%s", VERSION);
869
870 //!Draws a SemanticMarker&trade; (using QR code)
871 //!Create a QR code with a width of 135 QR code at (0, 100). 在(0,0)处创建一个宽为135二维码
872 //!Please select the appropriate QR code version according to the number of characters. 请根据字符数量选择合适的二维码版本
873 M5.Lcd.qrcode("https://iDogWatch.com/bot/help",0,100,135,SEMANTIC_MARKER_QR_VERSION);
874 //try to draw a character in the middle ...
876 //delay so they can read it a little bit..
877 delay(550);
878
879 //blank screen is on..
880}
881#endif //ESP_M5
882
883//!THIS IS the setup() and loop() but using the "component" name, eg MQTTNetworking()
884//!This will perform preference initializtion as well
885//! called from the setup()
887{
888#ifdef ESP_M5
889 setupESP_M5();
890#endif
891
892 //this is supposed to say it's not in blank screen...
893 //stopDelay();
894 startDelay(60);
895
896}
897
898//! used to create a mini
900
901//! called for the loop() of this plugin
903{
904 //! set so it can be erased on next loop
906 {
908 if (_fullscreenLoopCount > 10)
909 {
910 displayFullscreenMessage("", false);
912 }
913 else
914 return;
915
916 }
917#ifdef M5CORE2_MODULE
918 //! 1.24.24 if alternate display then return ..
920 {
921
922 loop_Alternate_displayModule();
923 return;
924 }
925#endif
926
927 //!check if a delay was running..
928 if (delayFinished())
929 {
930 SerialCall.println("loop_displayModule: delayFinished");
932 }
933
934 //TODO:
935 // change sensors, and change any SemanticMarkers using said sensors..
936 // or every second update SM (whatever is shown - and only change if sensors are showing (parms), eg. status
937//either delay or redraw right now.. from loop()
938
939 //4.20.22 (9 pm .. listening to Mike Campbell with drummer talking story about Tom Petty
940 // lets use a counter vs time .. simplier??
941 _markerTimer++;
942//#define LOOP_COUNTER_MICROSECONDS 30
943#define LOOP_COUNTER_MICROSECONDS 20 // 2 seconds it seems.. 11.7.22
944
945 if (_markerTimer > LOOP_COUNTER_MICROSECONDS) //10 was working .. got to 20 how fast it loop across all the modules (their loop() ..
946 {
947
948 //! 9.2.22 new .. update the timer. This is on blank screen as well .. so don't check _semanticMarkerShown
950#define TRY_BLANKSCREEN_IN_LOOP
951#ifdef TRY_BLANKSCREEN_IN_LOOP
952 //!check if a delay was running..
954 {
955 SerialCall.println("loop_displayModule: isBlankScreen");
957 }
958#endif
959 _markerTimer = 0;
961 {
962#pragma mark DEBUG_7_12
963 SerialCall.println("loop_displayModule: redrawSemanticMarker(KEEP_SAME)");
964
965 //!see if this works .. vs too flickering.. (if so we have to slow it down..)
967 }
968 }
969
970#ifdef M5CORE2_MODULE
971 //! try to show where the 3 buttons are below the following box..
972 M5.Lcd.drawRect(50, 235, 10, 3, WHITE);
973 M5.Lcd.drawRect(155,235, 10, 3, WHITE);
974 M5.Lcd.drawRect(258,235, 10, 3, WHITE);
975 //! 240 too low..
976#endif
977}
978
979// ************ Drawing of the Action, Mode and Status ***************
980
981//!prints the text up to the maxLen (the setup of position, etc is already done)
982void printText(String text, int maxLen)
983{
984#ifdef ESP_M5
985 if (text.length() < maxLen)
986 {
987 M5.Lcd.print(text);
988 }
989 else
990 {
991 M5.Lcd.print(text.substring(0,maxLen));
992 }
993#endif
994}
995
996//! print the text, but pad with background color spaces..
997void printTextPadSpaces(String text, TextPositionStruct textColor)
998{
999#ifdef ESP_M5
1000
1001 int maxLen = textColor.maxLen;
1002 printText(text, maxLen);
1003
1004 // now pad with spaces .. using the color provided..
1005 // pad with spaces .., but in the background color..
1006 M5.Lcd.setTextColor(textColor.textColor, textColor.textColorBackground);
1007 for (int i=text.length(); i< maxLen; i++)
1008 {
1009 M5.Lcd.print(" ");
1010 }
1011#endif
1012}
1013
1014//!sets the "ACTION" -- The TOP line
1015void drawAction(String title, int screenType)
1016{
1017
1018 SerialCall.print("drawAction: ");
1019 SerialCall.print(title);
1020 SerialCall.printf(" screenType=%d\n",screenType);
1021
1022 //!setup the position for the Action text
1024 && (screenType != SCREEN_TYPE_HELP))
1025 {
1026 //!only add the CR on the zoomed
1027 title.replace(" ","\r\n");
1028
1029 //!get the color index .. 0..MAX-1, if outside range, pick 0. Use 'mod' == % syntax.
1030 //!This is because the set from the web (MQTT) doesn't know the size.. or have it done here..
1031 int colorIndex = getScreenColor_displayModule();
1032
1033 //!different for home screen
1034 switch (screenType)
1035 {
1037 //!print preferences
1038 //printPreferenceValues_mainModule();
1039 //fall through to same as simple_1/2
1042 case SCREEN_TYPE_AP:
1043
1044 {
1045 //Hard wire back to "MINI CLICKER" since the MQTT code used a name to bind to this code, eg. MINI-2
1048#ifdef M5CORE2_MODULE
1049 setupTextPosition(_moduleDeviceNameTextPosition);
1050 //sprintf(infoString,"%s, %.*s",deviceName_mainModule(),getPairedDeviceOrAddress_mainModule() );
1051 printTextAtTextPosition(deviceName_mainModule(), _moduleDeviceNameTextPosition);
1052#endif
1053 }
1054 break;
1056 {
1057 //Hard wire back to "MINI CLICKER" since the MQTT code used a name to bind to this code, eg. MINI-2
1060 }
1061 break;
1062 //rest are the next set of screens.
1063 case SCREEN_TYPE_HOME:
1064 {
1065 // This now comes in as "FEED ALL" .. so change to SMART CLICKER
1068 break;
1069 //same title.. for now..
1071 {
1072 // the title == P: so replace with the paired name..
1074
1075 //!use the zoomed amount
1077 }
1078 break;
1079 default:
1080 //!use the zoomed amount
1081 //setupTextPosition(_actionTextPositionZoomed);
1084 }
1085 }
1086 else
1087 {
1088 //don't show the P: but rather the paired device name
1089 if (screenType == SCREEN_TYPE_PAIRED_DEV)
1090 {
1091 // the title == P: so replace with the paired name..
1093 //!use the zoomed amount
1095
1096 }
1097 else
1098 {
1100 //printText(title, _actionTextPosition.maxLen);
1101
1103
1104 }
1105 }
1106}
1107
1108//!sets the "Sensor Status"
1109void drawSensorStatus(int screenType)
1110{
1111 char infoString[150];
1112 boolean multilineScreenType = false;
1113
1114#ifdef ESP_M5
1115
1116 //!The "INFO"
1117 //float batVoltage = M5.Axp.GetBatVoltage();
1118 float batPercentage = getBatPercentage_mainModule();
1122 boolean isConnectedBLE =
1123 //! 8.16.25 BLE CLIENT
1125
1126
1127 //!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
1128 String gStatus = "g";
1129 String gStatusHome = "";
1130 if (isConnectedBLE && gatewayOn)
1131 {
1132 gStatus = "G3";
1133 gStatusHome = "G3";
1134 }
1136 {
1137 gStatus = "Gx";
1138 gStatusHome = "Gx";
1139 }
1140 //!Special layout for HELP screen type
1141 switch (screenType)
1142 {
1143
1144 case SCREEN_TYPE_HELP:
1145 multilineScreenType = true;
1146 // sprintf(infoString,inMinMenu?"Show All\nmenus":"Minimize\nmenus");
1147 sprintf(infoString,"Scan Image\nFor Help");
1148
1149 break;
1150 case SCREEN_TYPE_WIFI:
1151 multilineScreenType = true;
1153 {
1154 //! 8.16.25 MQTT
1155
1157 sprintf(infoString,"Swap WIFI");
1158 else
1159 sprintf(infoString,"Swap/Retry\nWIFI");
1160 }
1161 else
1162 {
1163 //! #issue 136 show the WIFI in the semantic marker, and label for scanning
1164 sprintf(infoString,"Scan to\nShare WIFI");
1165 }
1166 break;
1167 case SCREEN_TYPE_AP:
1168 multilineScreenType = true;
1169 //! 8.16.25 WIFI AP
1171 sprintf(infoString,"Enter AP\n192.168.4.1");
1172 else
1173 sprintf(infoString,"In AP\n192.168.4.1");
1174 break;
1176 multilineScreenType = true;
1177 sprintf(infoString,"Share WIFI with Feeder");
1178 break;
1179#ifdef NOMORE
1180 case SCREEN_TYPE_TIMER: //will be it's own with the time values...
1181 {
1182 //printf(infoString,"TIMER...");
1185 sprintf(infoString,"Seconds=%d", model->delaySeconds);
1186
1187 }
1188#endif
1189 break;
1190 case SCREEN_TYPE_TIMER:
1192 //case SCREEN_TYPE_HOME_SIMPLE:
1196 case SCREEN_TYPE_REBOOT:
1197 {
1198 //!update the model for those drawing Dev and Connected Dev
1200
1201 multilineScreenType = true;
1202 //! just ask the deviceState...
1204 switch (model->pairedDeviceStateEnum)
1205 {
1206 //paired to a device, but BLE NOT connected right now
1208 sprintf(infoString,"%s\n+%.*s",deviceName_mainModule(),10,getPairedDeviceOrAddress_mainModule() );
1209 break;
1210 //paired to a device, and BLE connected right now
1212 sprintf(infoString,"%s\n%.*s",deviceName_mainModule(),10,getPairedDeviceOrAddress_mainModule() );
1213 break;
1214 //not paired (but could be paired as it's a named device])
1216 sprintf(infoString,"%s\n-%.*s",deviceName_mainModule(),9,connectedBLEDeviceName_mainModule());
1217 break;
1218 //!factory default but not connecte to anything..
1219 case notConnectedEnum:
1220 sprintf(infoString,"%s\n%s",deviceName_mainModule(),(char*)"scanning..");
1221 break;
1222 }
1223
1224 }
1225 break;
1226
1228 multilineScreenType = true;
1229 sprintf(infoString,"Feed Guest");
1230 break;
1231
1232
1233 case SCREEN_TYPE_HOME:
1236
1237 sprintf(infoString,"Feed=%0d(%0d) Bat=%2.0f%% %s", getFeedCount_mainModule(), feedCountMax_mainModule(), batPercentage,gStatusHome);
1238 //!could add BUZZER (but it's a distributed issue - it can be sent elsewhere..
1239 break;
1240
1241 case SCREEN_TYPE_STATUS:
1242 // case SCREEN_TYPE_REBOOT:
1243 default:
1244 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);
1245 //!could add BUZZER (but it's a distributed issue - it can be sent elsewhere..
1246 break;
1247 }
1248
1249 //!setup the position for the SensorStatus .. HELP is always not-zoomed (show semantic marker)
1251 && !(screenType == SCREEN_TYPE_HELP))
1252 {
1253 //!use the zoomed amount
1255 }
1256 else
1257 {
1259 }
1260
1261 //!draw the text
1263#endif //m5
1264}
1265//!draws the text and differeent if ON or OFF
1266void drawStatusText(String text, boolean isOn)
1267{
1268#ifdef ESP_M5
1269 if (isOn)
1270 M5.Lcd.setTextColor(BLUE, YELLOW);
1271 else
1272 M5.Lcd.setTextColor(WHITE, BLACK);
1273 M5.Lcd.print(text);
1274#endif
1275}
1276
1277//! returns if the modesDesired contains a mode character, but also true if modesDesired in null
1278boolean containsMode(char *modesDesired, char mode)
1279{
1280 if (!modesDesired)
1281 return true;
1282 else return index(modesDesired,mode) != NULL;
1283}
1284
1285//!sets the "Module Status", will show only the modesDesired if non null
1286void drawModuleStatus(char *modesDesired)
1287{
1288 //!setup the position for the SensorStatus
1290 {
1291 //!Zoomed .. setup the position for the ModuleStatus
1293 }
1294 else
1295 {
1296 //!setup the position for the ModuleStatus
1298 }
1299 // would be nice to get the device name.. of our connected BLE..
1300 //!value of WIFI connected
1301 //! 8.16.25 MQTT
1302 if (containsMode(modesDesired,'W'))
1304 if (containsMode(modesDesired,'M'))
1306 //! 8.16.25 BLE CLIENT
1307 //!useBLECLient == it's linked in and running (vs not running)
1308 if (containsMode(modesDesired,'B'))
1310 //! connected == we are connected to another BLEServer
1311 if (containsMode(modesDesired,'C'))
1313 //! 8.16.25 WIFI AP
1314 //!not done is what we look for ..
1315 if (containsMode(modesDesired,'A'))
1317 if (containsMode(modesDesired,'T'))
1319
1320 //! 8.16.25 BLE SERVER
1321 if (containsMode(modesDesired,'S'))
1322 {
1323 //maybe only show if ON..
1325 drawStatusText("S",true);
1326 }
1327 //Buzzer (but only sometimes)
1328 if (containsMode(modesDesired,'Z'))
1330
1331 //! Reset
1332 if (containsMode(modesDesired,'R'))
1333 drawStatusText("R",true);
1334 //! Reboot
1335 if (containsMode(modesDesired,'X'))
1336 drawStatusText("X",true);
1337 //! Help
1338 if (containsMode(modesDesired,'H'))
1339 drawStatusText("H",true);
1340
1341 //! Paired
1342 if (containsMode(modesDesired,'P'))
1343 {
1344 //if the paired device is NONE then
1346 }
1347}
1348
1349//!just draw the simple status at bottom
1351{
1352 //!show the BLE connected status at the bottom (G3 if gen3), WIFI, and AP if APmode
1353 boolean isConnectedBLE =
1354 //! 8.16.25 BLE CLIENT
1356
1357 // whether the gateway is on.. this isn't using the Gx just BLE or GE3
1359 //WIFI means the MQTT is working (not just WIFI)
1360 boolean isConnectedWIFI =
1361 //! 8.16.25 MQTT
1363
1364 char label[30];
1365 String gStatus = " "; //3 characters
1366 if (isConnectedBLE && gatewayOn)
1367 {
1368 gStatus = "GE3";
1369 }
1370 else if (isConnectedBLE)
1371 {
1372 gStatus = "BLE";
1373 }
1374
1375 //! 8.16.25 WIFI AP
1376 sprintf(label,"%s %s %s", gStatus, isConnectedWIFI?"WIFI":" ",!doneWIFI_APModule_Credentials()?"AP":" ");
1378}
1379
1380//!perform a zoom .. of the semantic marker - or it might be something else..
1382{
1383 SerialCall.print("displayZoomedSemanticMarker: ");
1384 SerialCall.println(_semanticTitle);
1385 // use _currentSemanticMarkerAddress
1386
1387 //!used in the new model versions below..
1388 ModelKindEnum modelKind;
1389
1390
1391 //2nd line..
1392 switch (screenType)
1393 {
1394 case SCREEN_TYPE_WIFI:
1395 {
1396 //show the current WIFI..
1397 //TODO: pull out the SSID only...
1398 // {'ssid':<name we want>,'ssidPassword':p}
1399 //try JSON.. NOT WORKING ...
1400 //https://linux.die.net/man/3/strstr
1401 //I'm cheeting, for now .. and grabbing both 1 * 3
1402 char wifi1[100];
1404 char wifi2[100];
1406 char *json = main_JSONStringForWIFICredentials();
1407
1408 SerialTemp.println(wifi1);
1409 SerialTemp.println(wifi2);
1410 boolean wifi1Current = strcmp(json,wifi1)==0;
1411
1412 SerialTemp.printf("wifi1Current == %d\n", wifi1Current);
1413
1414 char buffer[100];
1415
1416 char *json1 = strstr(wifi1,":");
1417 int json1Len = 1;
1418 if (json1 && strlen(json1) > 3)
1419 {
1420 json1 += 2; //move past the ':'"
1421 }
1422 else
1423 json1 = wifi1;
1424 {
1425 //find the '
1426 char *comma = strchr(json1,'\'');
1427 json1Len = comma?((int)(comma - json1)):strlen(json1);
1428 }
1429 SerialTemp.println(json1);
1430
1431 char *json2 = strstr(wifi2,":");
1432 int json2Len = 1;
1433 if (json2 && strlen(json2) > 3)
1434 {
1435 json2 += 2; //move past the ':'"
1436 }
1437 else
1438 json2 = wifi2;
1439 {
1440 //find the '
1441 char *comma = strchr(json2,'\'');
1442 json2Len = comma?((int)(comma - json2)):strlen(json2);
1443 }
1444 SerialTemp.println(json2);
1445
1446 strcpy(buffer,"+");
1447 strncat(buffer, wifi1Current?json1:json2, wifi1Current?json1Len:json2Len );
1448 strcat(buffer,"\n\r");
1450
1451 strcpy(buffer,"-");
1452 strncat(buffer, !wifi1Current?json1:json2, !wifi1Current?json1Len:json2Len );
1453 //make it blue..
1454 M5.Lcd.setTextColor(WHITE, BLUE);
1455 M5.Lcd.print(buffer);
1456
1457 SerialCall.println(buffer);
1458 }
1459 break;
1460
1461 //!ADD SCREEN_TYPE_HOME
1463 {
1464 //Draw the tilt normal, and the buzz as
1465 // new 7.25.22 per issue #126
1466 // This is for the TILT
1467 //THE BIG ACTION == first, but that color is ORANGE, so wap to the SM_ACTION colors
1470 else
1472
1473 //THE BIG ACTION == first, but that color is ORANGE
1476 else
1478 // show the BLE connected status at the bottom
1480 }
1481 break;
1483 {
1484 // This is for the BUZZ
1485 // new 7.25.22 per issue #126
1486 //swap them .. for now .. or TODO: change the zoomText to be swapped colors..
1487 //DRAFT ...
1488 //swap colors, passing the _zoomedTextPositions of the opposite
1491 else
1493
1496 else
1498 // show the BLE connected status at the bottom
1500 }
1501 break;
1503 {
1504 // new 7.25.22 per issue #126, special feeding page
1505 // Feeds left:
1506
1507 char tmpString[30];
1508 //blue as this is an option (for reset counter)
1509 sprintf(tmpString,"%0d(%0d)", getFeedCount_mainModule(), feedCountMax_mainModule());
1511 // battery percent, but orange not selected ..
1512 sprintf(tmpString,"B:%2.0f%%", getBatPercentage_mainModule());
1514 // show the BLE connected status at the bottom
1516 }
1517 break;
1518
1519 case SCREEN_TYPE_AP:
1520 {
1521 //TODO: change the top simple line .. to a messaging
1522 // new 7.25.22 per issue #126
1525 // show the BLE connected status at the bottom
1527 }
1528 break;
1529 case SCREEN_TYPE_TIMER:
1532 case SCREEN_TYPE_REBOOT:
1533 {
1534
1535 if (screenType == SCREEN_TYPE_REBOOT)
1536 modelKind = rebootModel;
1537 else if (screenType == SCREEN_TYPE_PAIRED_DEV)
1538 modelKind = pairedDeviceModel;
1539 else if (screenType == SCREEN_TYPE_HOME_SIMPLE_3)
1540 modelKind = menusModel;
1541 else if (screenType == SCREEN_TYPE_TIMER)
1542 modelKind = timerModel;
1543 else
1544 SerialMin.println(" *** INVALID screenType ***");
1545
1546 char buffer[50];
1547
1548 //!upate the model (done at beginning of loop()
1549 //updateMenuState(modelKind);
1550 //!grab this model.
1551 ModelStateStruct *model = getModel(modelKind);
1552
1553 // empty the 4 lines.. with black characters..
1554 //4 lines max
1555
1556 // blank the area
1557 M5.Lcd.fillRect(0, 80, 135, 130, BLACK);
1558
1559 // start over..
1560 strcpy(buffer,"");
1561 int windowSize = 6;
1562 int textLength = 10;
1563 if (model->perfersBigText)
1564 {
1565 windowSize = 4;
1566 textLength = 6;
1567 }
1568
1569 if (model->maxItems < windowSize)
1570 windowSize = model->maxItems;
1571
1573
1574 //SerialDebug.printf("current = %d, max = %d\n",model->currentItem, model->maxItems);
1575 //get the menu items to draw..
1576 //!try a rolling window..
1577 // current 3 1..8
1578 // if there maxItems > 6 .. then when hit end .. it scrolls to next one..
1579 int startItem = 0;
1580 int maxItems = model->maxItems;
1581 int currentItem = model->currentItem;
1582 if (currentItem >= windowSize)
1583 {
1584 // scrolling time..
1585 // move start the number past maxWindow
1586 // 0..5, 1..6, 2..7 3..8 (and current always last item on scrolling)
1587 //say it's 8: current = 8, start = 8 - windowSize
1588 startItem = currentItem - windowSize + 1;
1589 }
1590 maxItems = startItem + windowSize;
1591 for (int i=startItem; i < maxItems; i++)
1592 {
1593 char *menu = menuForState(modelKind, i);
1594 if (i == model->currentItem)
1595 {
1596 // use blue...
1597 M5.Lcd.setTextColor(WHITE, BLUE);
1598 }
1599 else
1600 {
1601 M5.Lcd.setTextColor(ORANGE, BLACK);
1602 }
1603
1604 sprintf(buffer,"-%.*s\n\r", textLength, menu);
1605 M5.Lcd.print(buffer);
1606 }
1607
1608 // show the BLE connected status at the bottom
1609 // in this case, it's not connected so BLE should be off..
1611 }
1612 break;
1613
1614 default:
1615 {
1616 // FEED ..
1618
1619 String title = "-" + _semanticTitle;
1620 title.replace(" ","\r\n");
1621
1622 switch (screenType)
1623 {
1624 case SCREEN_TYPE_HOME:
1626 break;
1627
1628 //wont get here... the case is above..
1630 break;
1631 case SCREEN_TYPE_HELP:
1632 {
1633 // Instead of "Help Info" show the "MINI CLICKER"
1634 String title = "-MINI\r\nCLICKER";
1636 }
1637 break;
1639 {
1640 //!This sends the M5's WIFI credentials down to the paired device over BLE
1641 // Instead of "Help Info" show the "MINI CLICKER"
1642 String title = "-SHARE\r\nWIFI";
1644 }
1645 break;
1646 default:
1648 }
1649 }
1650 break;
1651 } //switch
1652}
1653
1654//!redraws the image..
1656{
1658
1659 SerialCall.printf("redrawSemanticMarker_displayModule(startNew:%d, ScreenType = %d)\n", startNew, screenType);;
1660 if (startNew)
1661 {
1662 //! resets the preferences so the mini menu is running, and resets other preferences
1663 switch (screenType)
1664 {
1665 //!ADD SCREEN_TYPE_HOME
1667 {
1668 //!set some defaults on boot - that override EPROM this can be called on the HOME screen to set back to normal mode..
1670 }
1671 break;
1675 //DO THIS HERE TOO.. just check if simple_3 lets things still happen..
1676 // setOnboot sets min menu and the zoomedSM
1677 {
1678 //!set some defaults on boot - that override EPROM this can be called on the HOME screen to set back to normal mode..
1680 }
1681 break;
1682 }
1683
1684#define TRY_CLEAR_WITH_RESET_TIMER
1685
1686#ifdef TRY_CLEAR_WITH_RESET_TIMER
1687 //! clears the screen, and resets timer
1689#else
1690 //also resets the loop timer
1692#endif
1693 //empty the lastSM
1694 _lastSemanticMarkerAddress = String("");
1695
1696 }
1697 else
1698 {
1700 }
1701
1702
1703 //!update the model (ModelController.h) for the type of screen displayed (what model)
1704 if (screenType == SCREEN_TYPE_REBOOT)
1705 //!upate the model -- each loop, before drawing stuff (obviously)
1707 else if (screenType == SCREEN_TYPE_PAIRED_DEV)
1709 else if (screenType == SCREEN_TYPE_HOME_SIMPLE_3)
1711 else if (screenType == SCREEN_TYPE_TIMER)
1713
1714 //!sets flag that being shown..
1715 _semanticMarkerShown = true;
1716
1717 //!this re-creates the address (maybe dynamically if the func() callback is defined)
1719
1720 // ** NOTE the zoom is a way to figure out what else to show..
1722 && (screenType != SCREEN_TYPE_HELP))
1723 {
1724 displayZoomedSemanticMarker(screenType);
1725 }
1726 else if (screenType == SCREEN_TYPE_DOC_FOLLOW)
1727 {
1728 //! this draws QR but using the lastDocFollowSemanticMarker
1729#define QRAVATAR
1730#ifdef ESP_M5stepper
1731#ifdef M5CORE2_MODULE
1732 //! DON"T rotate -- for the M5Core2 display
1733#else
1734 M5.Lcd.setRotation(0);
1735#endif
1736 //!Draws a SemanticMarker&trade; (using QR code)
1737 //!Create a QR code with a width of 135 QR code at (0, 100). 在(0,0)处创建一个宽为135二维码
1738 //!Please select the appropriate QR code version according to the number of characters. 请根据字符数量选择合适的二维码版本
1739 //try brightness
1742
1743#ifdef QRAVATAR
1744 //try to draw a character in the middle ... (D, etc)
1746#endif
1747#endif //ESP_M5
1748 }
1749 else
1750 {
1751#ifdef ESP_M5
1752#ifdef M5CORE2_MODULE
1753 //! DON"T rotate -- for the M5Core2 display
1754#else
1755 M5.Lcd.setRotation(0);
1756#endif
1757 SerialLots.print("last vs current: ");
1758 SerialLots.print(_lastSemanticMarkerAddress);
1759 SerialLots.println(" vs ");
1760 SerialLots.println(_currentSemanticMarkerAddress);
1761 //!only redraw if changed ...
1763 {
1764 SerialLots.println(_currentSemanticMarkerAddress);
1765 //try brightness
1767
1768#ifdef ESP_M5_ATOM_S3
1769 //! 7.11.26 Eagles in nest ..
1771
1772#else
1773 //!Draws a SemanticMarker&trade; (using QR code)
1774 //!Create a QR code with a width of 135 QR code at (0, 100). 在(0,0)处创建一个宽为135二维码
1775 //!Please select the appropriate QR code version according to the number of characters. 请根据字符数量选择合适的二维码版本
1777#endif
1778#ifdef QRAVATAR
1779 //try to draw a character in the middle ... (D, etc)
1780 String smChar = _semanticTitle.substring(0,1);
1782#endif
1783 }
1784
1785#endif
1786
1788 }
1789
1790 //!The "ACTION"
1791 drawAction(_semanticTitle, screenType);
1792
1793 //!The "SensorStatus", which uses current info..
1794 drawSensorStatus(screenType);
1795
1796 //!then which modules to draw for the different screens
1797 switch (screenType)
1798 {
1800 //advanced is now ModelController..
1801 break;
1802 //!ADD SCREEN_TYPE_HOME
1806 case SCREEN_TYPE_AP:
1807 {
1808 // 7.25.22
1809 //!Draw FEED in red if the feed count is > 13
1810 if (getFeedCount_mainModule() > 13)
1812 else
1814 // if count > 13 make it red
1815 M5.Lcd.print("+FEED ");
1816 // 1234567
1817 }
1818 break;
1819 //REST are previous..
1820 //NOTE: that the HELP long press also goes home..
1821 case SCREEN_TYPE_HOME:
1822 //!The " ModuleStats"
1823 drawModuleStatus((char*)"WMCTZAS");
1824 break;
1825 case SCREEN_TYPE_TILT:
1826 //!The " ModuleStats"
1827 drawModuleStatus((char*)"T");
1828 break;
1829 case SCREEN_TYPE_BUZZ:
1830 //! module status with BUZZ
1831 drawModuleStatus((char*)"Z");
1832 break;
1833 case SCREEN_TYPE_WIFI:
1834 drawModuleStatus((char*)"WM");
1835 break;
1836// case SCREEN_TYPE_AP:
1837// drawModuleStatus((char*)"WMA");
1838// break;
1839 case SCREEN_TYPE_HELP:
1840 // drawModuleStatus((char*)"H");
1841 // maybe draw text: iDogWatch.com/bot/help
1843
1844 //!draw the text
1845 printText((char*)"iDogWatch.com/bot/help",_helpStatusTextPosition.maxLen);
1846 break;
1847
1848 case SCREEN_TYPE_RESET:
1849 drawModuleStatus((char*)"R");
1850 break;
1851 case SCREEN_TYPE_TIMER:
1852 break;
1853 case SCREEN_TYPE_REBOOT:
1854 break;
1856 break;
1857
1859 drawModuleStatus((char*)"WMC");
1860 break;
1862 drawModuleStatus((char*)"WMC");
1863 break;
1864
1865 case SCREEN_TYPE_STATUS:
1866 default:
1867 //!The " ModuleStats"
1868 //drawModuleStatus((char*)"WMBCATZ");
1869 drawModuleStatus((char*)"WMBCATS");
1870
1871 }
1872 //!startNew is that the screen needs new timeout
1873 if (startNew)
1874 {
1875 // boolean zoomed = getPreferenceBoolean_mainModule( PREFERENCE_SEMANTIC_MARKER_ZOOMED_VALUE);
1876 //if the SemanticMarker is show, delay 50
1877 //!startDelay(zoomed?25: currentScreenTimeout());
1879
1880 //! called by the feed operation to say the device is still running.. and count it as a button click.
1881 //! Issue #145 8.8.22
1883
1884 //!NOTE: this gets called 2 times if buttonB short press .. but not othertimes..
1885
1886 }
1887
1888}
1889
1890
1891//! ISSUE: need to re-generate the SemanticAddress but only for "Status".
1892//! could kluge and use the Title?? == "Status"
1893
1894//**** Specific Methods*******
1895//!displays the Semantic Marker (a super QR code) on the M5 screen (with an N second display)
1896void showSemanticMarker_displayModule(String semanticMarkerAddress, String title)
1897{
1898
1899 SerialTemp.print("showSemanticMarker(nulls func) ");
1900 SerialTemp.print(title);
1901 SerialTemp.print(" SM=");
1902 SerialTemp.println(semanticMarkerAddress);
1903
1904 //!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..
1905 //!cache for the redraw()
1906 _semanticTitle = title;
1907 //!no function, the addresss is the address provided
1908 //!NOTE: we could add our own function .. TODO .. less of a kluge..
1909 _getStatusFunc = NULL;
1910
1911 _currentSemanticMarkerAddressBase = semanticMarkerAddress;
1912 //!save the marker..
1913 _lastSemanticMarkerAddress = String("");
1914
1915 // clearScreen_displayModule();
1916
1917 //!draw a semantic marker (zoomed or not)
1919
1920 //startDelay(20);
1921//issue is another display can show up while this is being shown. like FEED , etc
1922}
1923
1924
1925//UNUSED SO FAR..
1926
1927//!finish the address after calling the function provided, called from MQTT for STATUS
1928void showSemanticMarkerFunc_displayModule(String semanticMarkerAddressBase, String title, const char* (*getStatusFunc)(void))
1929{
1930 SerialCall.print("showSemanticMarkerFunc: ");
1931 SerialCall.print(title);
1932 SerialCall.print(" SM=");
1933 SerialCall.println(semanticMarkerAddressBase);
1934
1935 //!save for use on redraw..
1936 _getStatusFunc = getStatusFunc;
1937 _currentSemanticMarkerAddressBase = semanticMarkerAddressBase;
1938 _semanticTitle = title;
1939 _lastSemanticMarkerAddress = String("");
1940
1941 // clearScreen_displayModule();
1942
1944
1945 //startDelay(20);
1946
1947}
1948
1949
1950//!
1951//! shows a FEED (or whatever) then blanks the screen after N seconds
1952void showText_displayModule(String text)
1953{
1955 // startDelay(10);
1956}
1957
1958
1959
1960
1961
1962//! adds messages that aren't shown unless in message window mode.
1963//! NOTE: This will be a scrolling text as sometime ..
1965{
1966 SerialLots.printf("addToTextMessages_displayModule:(%d)",displayOnBlankScreen());
1967 SerialLots.println(text);
1968
1969#ifdef M5CORE2_MODULE
1970 //! FOR now .. isBlankScreen isn't cared about ..
1971 //! if showing the scrolling window .. don't do the rest ..
1972 if (_showScrollingTextWindow)
1973 {
1974#ifdef SHOW_BIG_BUTTON
1975#else
1976 //! 1.24.24 Adding scrolling text (if that window on the M5Core2 is shown)
1977 addToScrollingText_displayModule(text);
1978#endif
1979 return;
1980 }
1981#endif
1982
1983 //!whether screen is blank (so the button can be a wake, vs action..)
1985 {
1986 SerialLots.println("Not displaying since blank screen");
1987 return;
1988 }
1989
1990
1991 //!different for home screen
1992 switch (_currentScreenType)
1993 {
1994 //!ADD SCREEN_TYPE_HOME
1998 case SCREEN_TYPE_AP:
1999 //don't show anything over the SMART CLICKER at the top
2000 break;
2002 //TODO.. for now..
2003 // draw the title but on the 2nd smaller line
2004 //!use the zoomed amount
2006
2007 //!draw the text
2009 break;
2010 default:
2012
2013
2014 }
2015
2016 //! testing 4.3.24 for large text
2017 if (text.compareTo("FEED")==0)
2018 {
2019 displayFullscreenMessage(text, true);
2020 }
2021}
2022
2023#ifdef M5CORE2_MODULE
2024//! add a loop for the alternate display
2025void loop_Alternate_displayModule()
2026{
2027 //no op for now..
2028}
2029/**
2030 First attempt at using the M5Core2 display to show something other than the M5 display
2031 1. scrolling text
2032 */
2033//! 1.24.24 Adding scrolling text (if that window on the M5Core2 is shown)
2034void addToScrollingText_displayModule(String textString)
2035{
2036 if (_showScrollingTextWindow)
2037 {
2038 M5.Lcd.setTextSize(1);
2039 M5.Lcd.println(textString);
2040 M5.Lcd.println();
2041 int X = M5.Lcd.getCursorX();
2042 int Y = M5.Lcd.getCursorY();
2043 SerialDebug.printf("cursor(%d,%d)\n", X, Y);
2044
2045 if (Y > 213)
2046 M5.Lcd.setCursor(0,0);
2047 }
2048}
2049
2050//! 1.24.24 Goto the scrolling text mode ..
2051void toggleShowingScrollingTextMode_displayModule()
2052{
2053 boolean flag = !_showScrollingTextWindow;
2054 setShowingScrollingTextMode_displayModule(flag);
2055 //! now change perminately ...
2056 //_showScrollingTextWindow = !_showScrollingTextWindow;
2057
2058}
2059
2060//! 2.29.24 Leap Year day
2061//! Returns whether the Scrolling Text window is shown
2062boolean scrollingTextWindowVisible_displayModule()
2063{
2064 return _showScrollingTextWindow;
2065}
2066
2067//! 2.27.24 make the button seem to be touched, if being shown
2068void showButtonTouched_displayModule()
2069{
2070#ifdef SHOW_BIG_BUTTON
2071 //! but only if _showScrollingTextWindow
2072 if (_showScrollingTextWindow)
2073 {
2074 SerialDebug.println("showButtonTouched_displayModule");
2075 delay(200);
2076 //try a blink..
2077 M5.Lcd.fillCircle(150,120,118, BLACK);
2078 M5.Lcd.drawCircle(150,120,118, WHITE);
2079 M5.Lcd.setTextColor(WHITE);
2080 M5.Lcd.setTextSize(5);
2081 M5.Lcd.setCursor(100, 110);
2082 M5.Lcd.print("Feed");
2083
2084 delay(500);
2085 M5.Lcd.fillCircle(150,120,118, GREEN);
2086 M5.Lcd.drawCircle(150,120,118, WHITE);
2087 M5.Lcd.setTextColor(BLACK);
2088 M5.Lcd.setTextSize(5);
2089 M5.Lcd.setCursor(100, 110);
2090 M5.Lcd.print("Feed");
2091 }
2092#endif
2093}
2094
2095//! 1.24.24 Goto the scrolling text mode .. if flag
2096void setShowingScrollingTextMode_displayModule(boolean flag)
2097{
2098 SerialDebug.printf("setShowingScrollingTextMode_displayModule(%d, s=%d)\n", flag,_showScrollingTextWindow );
2099
2100 //! now change perminately ...
2101 _showScrollingTextWindow = flag;
2102
2103 //! only do something if changed state
2104// if (flag == _showScrollingTextWindow)
2105// return;
2106
2107 if (_showScrollingTextWindow)
2108 {
2109 //! stop timers, etc
2110 //!stop the delay which says delay finished .. so don't show anything.. 8.9.22
2112
2113#ifdef SHOW_BIG_BUTTON
2114 // draw big green button.. for the heck of it..
2115 M5.Lcd.fillCircle(150,120,118, GREEN);
2116 M5.Lcd.drawCircle(150,120,118, WHITE);
2117
2118 M5.Lcd.setTextColor(BLACK);
2119 M5.Lcd.setTextSize(5);
2120 M5.Lcd.setCursor(100, 110);
2121 M5.Lcd.print("Feed");
2122
2123 //M5.Lcd.setCursor(0,0);
2124#else
2125 // blank the area
2126 // M5.Lcd.fillRect(0, 60, 135, 140, WHITE);
2127 M5.Lcd.setTextColor(WHITE, BLACK);
2128 M5.Lcd.setCursor(0, 0);
2129 M5.Lcd.setTextSize(1);
2130 M5.Lcd.println("Messages from the Network");
2131 //M5.Lcd.setTextWrap(true);
2132#endif
2133 }
2134 else
2135 {
2136 //! GO back to a normal screen..
2137 //M5.Lcd.setTextWrap(false);
2138
2139 //!wakes up the screen
2140 M5.Lcd.fillScreen(BLACK);
2142
2143 }
2144}
2145
2146//! scrolls the displayed text NOT YET ...
2147void scrollText_displayModule()
2148{
2149 if (_showScrollingTextWindow)
2150 {
2151 //!TODO..
2152 //!for now just clear the text...
2153 M5.Lcd.fillScreen(BLACK);
2154 M5.Lcd.setCursor(0, 0);
2155 //! maybe the text keeps going ... can we ask the cursor location??
2156 }
2157
2158}
2159#endif //M5CORE2_MODULE
2160
2161#else // not DISPLAY_MODULE
2162
2163//!Increment the screen color 0..n cache for getting the screen color 0..max (max provided by sender)
2164//!This is implemented by incrementScreenColor_mainModule() since it knows the MAX value of colors
2166{
2167
2168}
2169
2170
2171//!cache for getting the screen color 0..n. Will reset the cache as well
2172void setScreenColor_displayModule(int screenColor)
2173{
2174
2175}
2176
2177//!THIS IS the setup() and loop() but using the "component" name, eg MQTTNetworking()
2178//!This will perform preference initializtion as well
2179//! called from the setup()
2181{
2182
2183}
2184
2185//! called for the loop() of this plugin
2186void loop_displayModule()
2187{
2188
2189}
2190
2191//! shows a FEED (or whatever) then blanks the screen after N seconds
2192//! NOTE: This will be a scrolling text as sometime ..
2193void showText_displayModule(String text)
2194{
2195
2196}
2197
2198//! adds messages that aren't shown unless in message window mode.
2199//! NOTE: This will be a scrolling text as sometime ..
2200void addToTextMessages_displayModule(String text)
2201{
2202
2203}
2204
2205//!blanks the screen
2207{
2208
2209}
2210
2211//!wakes up the screen
2213{
2214
2215}
2216
2217//!whether screen is blank (so the button can be a wake, vs action..)
2219{
2220 return true;
2221}
2222
2223//!clears the screen
2225{
2226
2227}
2228
2229//!displays the Semantic Marker (a super QR code) on the M5 screen (title = to display)
2230void showSemanticMarker_displayModule(String semanticMarkerAddress, String title)
2231{
2232
2233}
2234
2235//!returns the current semantic marker (eg. guest page)
2237{
2238 return (char*)"unused";
2239}
2240
2241//!the function to call to get the 'status', return char*
2242//char* (*getStatusFunc)(void)
2243//typedef String (*getStatusFunc)(void);
2244
2245//!displays the Semantic Marker (a super QR code) on the M5 screen (title = to display)
2246void showSemanticMarkerFunc_displayModule(String semanticMarkerAddressBase, String title, const char* (*getStatusFunc)(void))
2247{
2248
2249}
2250
2251//!redraws the Semantic Marker image..
2252void redrawSemanticMarker_displayModule(boolean startNew)
2253{
2254
2255}
2256
2257int _loopCounter_displayModule = 0;
2258//!returns the loop timer (just a timer..)
2260{
2261 return _loopCounter_displayModule;
2262}
2263
2264//!reset the loop timer .. useful for testing,
2266{
2267 _loopCounter_displayModule = 0;
2268}
2269//! 1.24.24 Adding scrolling text (if that window on the M5Core2 is shown)
2270void addToScrollingText_displayModule(String textString)
2271{
2272
2273}
2274//! 1.24.24 Goto the scrolling text mode ..
2275void toggleShowingScrollingTextMode_displayModule()
2276{
2277
2278}
2279//! 1.24.24 Goto the scrolling text mode .. if flag -- saves value
2280void setShowingScrollingTextMode_displayModule(boolean flag)
2281{
2282
2283}
2284//! 2.27.24 make the button seem to be touched
2285//void showButtonTouched_displayModule();
2286//! 2.29.24 Leap Year day
2287//! Returns whether the Scrolling Text window is shown
2288//! 1.24.24 as alternate display windows are introducted,
2289//! let others know and don't overright stuff..
2291{
2292 return false;
2293}
2294#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
TextPositionStruct _actionTextPosition
#define BLK_PWM_CHANNEL
#define SCREEN_TYPE_REBOOT
#define SCREEN_TYPE_HOME_SIMPLE_2
void showSemanticMarkerFunc_displayModule(String semanticMarkerAddressBase, String title, const char *(*getStatusFunc)(void))
finish the address after calling the function provided, called from MQTT for STATUS
#define SCREEN_TYPE_WIFI
#define SCREEN_TYPE_RESET
TextPositionStruct _multilineStatusTextPositionZoomed
#define SCREEN_TYPE_DOC_FOLLOW
TextPositionStruct _homeSimpleStatusTextPositionZoomedRED
new for the SM_HOME_SIMPLE - draws FEED as red if over 13 feeds..
boolean containsMode(char *modesDesired, char mode)
returns if the modesDesired contains a mode character, but also true if modesDesired in null
#define FONT_3
TextPositionStruct _actionTextHomeSimplePositionZoomed_2
int currentScreenTimeout()
current screen timeout
void addToTextMessages_displayModule(String text)
void setupTextPosition(TextPositionStruct textP)
init the text
boolean delayFinished()
TextPositionStruct _actionTextPositionZoomed
TextPositionStruct _helpStatusTextPosition
void setupTextPositionOverrideTextColor(TextPositionStruct textP, TextPositionStruct textColor)
init the text - but override the text color (stil using the textP.blankCOlor
void wakeupScreen_displayModule()
wakes up the screen
#define WIDTH
These are when the ESP_M5 isn't used, so the code below compiles..
void showOTAUpdatingMessage()
show an OTA message..
void printTextAtTextPositionOverrideTextColor(String text, TextPositionStruct textPosition, TextPositionStruct textColor)
use the textPositionStruct - but override the text color
void printTextPadSpaces(String text, TextPositionStruct textColor)
print the text, but pad with background color spaces..
#define SCREEN_TYPE_HOME
for home screen
void setup_displayModule()
for types: String, boolean ..
#define SCREEN_TYPE_HOME_SIMPLE_1
TextPositionStruct _menuTextPositionZoomed_4less
new Menu selection (if 4 ..)
void clearScreen_displayModule()
clears the screen (but not a blank screen) and stops the timer..
int _markerTimer
markerTimer is a semi timer for the number of times before doing anything. Kinda a kludge.
void drawSensorStatus(int screenType)
sets the "Sensor Status"
void incrementScreenColor_displayModule()
#define SCREEN_TYPE_STATUS
#define MAX_ACTION_TEXT_HOME_COLORS
these are grouped in an array for the color index to use. If index > max then use max....
#define LOOP_COUNTER_MICROSECONDS
boolean isBlankScreen_displayModule()
whether screen is blank (so the button can be a wake, vs action..)
#define SCREEN_TYPE_HELP
TextPositionStruct _actionTextHomePositionZoomed
boolean displayOnBlankScreen()
whether to display on a blank screen
boolean inAlternateDisplay_displayModule()
String _semanticTitle
default semantic title
void printTextAtTextPosition(String text, TextPositionStruct textPosition)
use the textPositionStruct
void showText_displayModule(String text)
void redrawSemanticMarker_displayModule(boolean startNew)
redraws the image..
TextPositionStruct _actionTextHomeSimplePositionZoomed_4
void incrementLoopTimer()
increment the loop timer
void setScreenColor_displayModule(int screenColor)
cache for getting the screen color 0..n. Will reset the cache as well
void drawModuleStatus(char *modesDesired)
sets the "Module Status", will show only the modesDesired if non null
void displayZoomedSemanticMarker(int screenType)
perform a zoom .. of the semantic marker - or it might be something else..
#define SCREEN_TYPE_HOME_SIMPLE_3
int _currentScreenType
the current screen type (a side effect of asking for it)
void stopLoopTimer()
stop the loop timer
#define HEIGHT_4
#define SCREEN_TYPE_GUEST_PAGE
TextPositionStruct _sensorStatusTextPositionZoomed
void setBrightness_displayModule(int brightness)
TextPositionStruct _connectedStatusTextPositionZoomed
the position of "connected" at the bottom on the first 3 screens..
#define SCREEN_TYPE_AP
String _currentSemanticMarkerAddressBase
base http address of semantic markers
TextPositionStruct _zoomedTextPositions[MAX_ACTIONS]
#define SCREEN_TYPE_TIMER
#define ROTATE_0
#define HEIGHT_2
String _lastSemanticMarkerAddress
TextPositionStruct _homeSimpleStatusTextPositionZoomed
new for the SM_HOME_SIMPLE
boolean _fullScreenMessageDisplayed
set so it can be erased on next loop
TextPositionStruct _menuTextPositionZoomed_4plus
#define SCREEN_TYPE_FEED_GUEST
void showSemanticMarker_displayModule(String semanticMarkerAddress, String title)
displays the Semantic Marker (a super QR code) on the M5 screen (with an N second display)
#define HEIGHT_3
int getScreenColor_displayModule()
cache for getting the screen color 0..n. Will reset the cache as well
const char *(* _getStatusFunc)(void)
stores the statusFunc (it's a pointer to a function)
TextPositionStruct _actionTextHomeSimpleColor[MAX_ACTION_TEXT_HOME_COLORS]
void blankScreen_displayModule()
blanks the screen
TextPositionStruct _actionTextHomeSimplePositionZoomed
int _fullscreenLoopCount
used to create a mini
TextPositionStruct _moduleStatusTextPositionZoomed
#define SM_ACTION
#define MAX_ACTIONS
struct TextPosition TextPositionStruct
TextPositionStruct _multilineStatusTextPosition
Help.
TextPositionStruct _moduleStatusTextPosition
status are the state modules (WIFI ON/off, etc)
void drawAction(String title, int screenType)
sets the "ACTION" – The TOP line
#define SCREEN_TYPE_BUZZ
TextPositionStruct _actionTextHomeSimplePositionZoomed_1
TimerDelayClass * _timerDelayClass_DisplayModule
3.29.25 RaiiiinIeeeeR Beer movie
void printText(String text, int maxLen)
prints the text up to the maxLen (the setup of position, etc is already done)
String _currentSemanticMarkerAddress
default semantic marker (or the current one)
#define FONT_2
#define SCREEN_TYPE_NORMAL
void displayFullscreenMessage(String text, boolean turnOn)
void displaySimpleStatus()
just draw the simple status at bottom
void drawStatusText(String text, boolean isOn)
draws the text and differeent if ON or OFF
#define HEIGHT_3_2LINE
#define SM_ACTION_SMALL
TextPositionStruct _sensorStatusTextPosition
mode is the status of sensors .
const char * currentSemanticMarkerAddress_displayModule()
returns the current semantic marker (eg. guest page)
boolean _semanticMarkerShown
if blank, then only show something after a click (not a message)
int screenTypeForTitle_displayModule(String title)
void stopDelay()
#define SCREEN_TYPE_TILT
TextPositionStruct _actionTextHomeSimplePositionZoomed_3
#define SEMANTIC_MARKER_QR_VERSION
1.26.24 10 seems to be working..
String createSemanticAddress()
int getLoopTimer_displayModule()
returns the loop timer (just a timer..)
void startDelay(int seconds)
#define SCREEN_TYPE_PAIRED_DEV
#define QRAVATAR_ACTION
int _loopTimer
ticks.. when it rest? (show to blank screen)
void resetLoopTimer_displayModule()
reset the loop timer .. useful for testing,
#define SCREEN_TYPE_HOME_SIMPLE
try simple menu
void setupESP_M5()
setup the Lcd, etc..
#define BIG_ACTION
#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
int getFeedCount_mainModule()
feedcount info..
Definition: MainModule.cpp:724
char * main_JSONStringForWIFICredentials()
retrieve a JSON string for the ssid and ssid_password: {'ssid':<ssid>,'ssidPassword':<pass>"}
int feedCountMax_mainModule()
returns the max for this feeder
Definition: MainModule.cpp:706
char * getPairedDeviceOrAddress_mainModule()
returns if the paired device is not NONE .. returns address or device
void refreshDelayButtonTouched_MainModule()
called by the feed operation to say the device is still running.. and count it as a button click.
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)
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
unsigned long millis()
Definition: TinyGPS.cpp:35
boolean doneWIFI_APModule_Credentials()
called to see if the WIFIModule has finished bootstrapping..
An concrete class.
void startDelay(float delayAmountSeconds)
starts delay calculation
boolean delayFinished()
whether the currently delay is finished, false if not running at all
void stopDelay()
stops delay
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
uint16_t blankColor
uint16_t rotation
uint16_t textSize
uint16_t textColor
uint16_t textColorBackground