-
Notifications
You must be signed in to change notification settings - Fork 175
/
completeLambda.ino
544 lines (464 loc) · 24.1 KB
/
completeLambda.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
/**
* @file completeExample.cpp
* @author Ian Gray @iangray1000
*
* This is an example GUI to show off all of the features of ESPUI.
* This can be built using the Arduino IDE, or PlatformIO.
*
* ---------------------------------------------------------------------------------------
* If you just want to see examples of the ESPUI code, jump down to the setUpUI() function
* ---------------------------------------------------------------------------------------
*
* When this program boots, it will load an SSID and password from the EEPROM.
* The SSID is a null-terminated C string stored at EEPROM addresses 0-31
* The password is a null-terminated C string stored at EEPROM addresses 32-95.
* If these credentials do not work for some reason, the ESP will create an Access
* Point wifi with the SSID HOSTNAME (defined below). You can then connect and use
* the controls on the "Wifi Credentials" tab to store credentials into the EEPROM.
*
* Version with lambdas. Comparing to version with only callbacks:
* diff -u ../completeExample/completeExample.cpp completeLambda.ino|less
*
*/
#include <Arduino.h>
#include <EEPROM.h>
#include <ESPUI.h>
#if defined(ESP32)
#include <WiFi.h>
#include <ESPmDNS.h>
#else
// esp8266
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <umm_malloc/umm_heap_select.h>
#ifndef CORE_MOCK
#ifndef MMU_IRAM_HEAP
#warning Try MMU option '2nd heap shared' in 'tools' IDE menu (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#option-summary)
#warning use decorators: { HeapSelectIram doAllocationsInIRAM; ESPUI.addControl(...) ... } (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#how-to-select-heap)
#warning then check http://<ip>/heap
#endif // MMU_IRAM_HEAP
#ifndef DEBUG_ESP_OOM
#error on ESP8266 and ESPUI, you must define OOM debug option when developping
#endif
#endif
#endif
//Settings
#define SLOW_BOOT 0
#define HOSTNAME "ESPUITest"
#define FORCE_USE_HOTSPOT 0
//Function Prototypes
void connectWifi();
void setUpUI();
void textCallback(Control *sender, int type);
void generalCallback(Control *sender, int type);
void randomString(char *buf, int len);
void paramCallback(Control* sender, int type, int param);
//UI handles
uint16_t wifi_ssid_text, wifi_pass_text;
uint16_t mainLabel, mainSwitcher, mainSlider, mainText, mainNumber, mainScrambleButton, mainTime;
uint16_t styleButton, styleLabel, styleSwitcher, styleSlider, styleButton2, styleLabel2, styleSlider2;
uint16_t graph;
volatile bool updates = false;
// This is the main function which builds our GUI
void setUpUI() {
#ifdef ESP8266
{ HeapSelectIram doAllocationsInIRAM;
#endif
//Turn off verbose debugging
ESPUI.setVerbosity(Verbosity::Quiet);
//Make sliders continually report their position as they are being dragged.
ESPUI.sliderContinuous = true;
//This GUI is going to be a tabbed GUI, so we are adding most controls using ESPUI.addControl
//which allows us to set a parent control. If we didn't need tabs we could use the simpler add
//functions like:
// ESPUI.button()
// ESPUI.label()
/*
* Tab: Basic Controls
* This tab contains all the basic ESPUI controls, and shows how to read and update them at runtime.
*-----------------------------------------------------------------------------------------------------------*/
auto maintab = ESPUI.addControl(Tab, "", "Basic controls");
ESPUI.addControl(Separator, "General controls", "", None, maintab);
ESPUI.addControl(Button, "Button", "Button 1", Alizarin, maintab, [](Control *sender, int type){ paramCallback(sender, type, 19); });
mainLabel = ESPUI.addControl(Label, "Label", "Label text", Emerald, maintab, generalCallback);
mainSwitcher = ESPUI.addControl(Switcher, "Switcher", "", Sunflower, maintab, generalCallback);
//Sliders default to being 0 to 100, but if you want different limits you can add a Min and Max control
mainSlider = ESPUI.addControl(Slider, "Slider", "200", Turquoise, maintab, generalCallback);
ESPUI.addControl(Min, "", "10", None, mainSlider);
ESPUI.addControl(Max, "", "400", None, mainSlider);
//These are the values for the selector's options. (Note that they *must* be declared static
//so that the storage is allocated in global memory and not just on the stack of this function.)
static String optionValues[] {"Value 1", "Value 2", "Value 3", "Value 4", "Value 5"};
auto mainselector = ESPUI.addControl(Select, "Selector", "Selector", Wetasphalt, maintab, generalCallback);
for(auto const& v : optionValues) {
ESPUI.addControl(Option, v.c_str(), v, None, mainselector);
}
mainText = ESPUI.addControl(Text, "Text Input", "Initial value", Alizarin, maintab, generalCallback);
//Number inputs also accept Min and Max components, but you should still validate the values.
mainNumber = ESPUI.addControl(Number, "Number Input", "42", Emerald, maintab, generalCallback);
ESPUI.addControl(Min, "", "10", None, mainNumber);
ESPUI.addControl(Max, "", "50", None, mainNumber);
ESPUI.addControl(Separator, "Updates", "", None, maintab);
//This button will update all the updatable controls on this tab to random values
mainScrambleButton = ESPUI.addControl(Button, "Scramble Values", "Scramble Values", Carrot, maintab,
//This callback updates the "values" of a bunch of controls
[](Control *sender, int type) {
static char rndString1[10];
static char rndString2[20];
static bool scText = false;
if(type == B_UP) { //Button callbacks generate events for both UP and DOWN.
//Generate some random text
randomString(rndString1, 10);
randomString(rndString2, 20);
//Set the various controls to random value to show how controls can be updated at runtime
ESPUI.updateLabel(mainLabel, String(rndString1));
ESPUI.updateSwitcher(mainSwitcher, ESPUI.getControl(mainSwitcher)->value.toInt() ? false : true);
ESPUI.updateSlider(mainSlider, random(10, 400));
ESPUI.updateText(mainText, String(rndString2));
ESPUI.updateNumber(mainNumber, random(100000));
ESPUI.updateButton(mainScrambleButton, scText ? "Scrambled!" : "Scrambled.");
scText = !scText;
}
});
ESPUI.addControl(Switcher, "Constant updates", "0", Carrot, maintab,
[](Control *sender, int type) {
updates = (sender->value.toInt() > 0);
});
mainTime = ESPUI.addControl(Time, "", "", None, 0, generalCallback);
ESPUI.addControl(Button, "Get Time", "Get Time", Carrot, maintab,
[](Control *sender, int type) {
if(type == B_UP) {
ESPUI.updateTime(mainTime);
}
});
ESPUI.addControl(Separator, "Control Pads", "", None, maintab);
ESPUI.addControl(Pad, "Normal", "", Peterriver, maintab, generalCallback);
ESPUI.addControl(PadWithCenter, "With center", "", Peterriver, maintab, generalCallback);
/*
* Tab: Colours
* This tab shows all the basic colours
*-----------------------------------------------------------------------------------------------------------*/
auto colourtab = ESPUI.addControl(Tab, "", "Colours");
ESPUI.addControl(Button, "Alizarin", "Alizarin", Alizarin, colourtab, generalCallback);
ESPUI.addControl(Button, "Turquoise", "Turquoise", Turquoise, colourtab, generalCallback);
ESPUI.addControl(Button, "Emerald", "Emerald", Emerald, colourtab, generalCallback);
ESPUI.addControl(Button, "Peterriver", "Peterriver", Peterriver, colourtab, generalCallback);
ESPUI.addControl(Button, "Wetasphalt", "Wetasphalt", Wetasphalt, colourtab, generalCallback);
ESPUI.addControl(Button, "Sunflower", "Sunflower", Sunflower, colourtab, generalCallback);
ESPUI.addControl(Button, "Carrot", "Carrot", Carrot, colourtab, generalCallback);
ESPUI.addControl(Button, "Dark", "Dark", Dark, colourtab, generalCallback);
/*
* Tab: Styled controls
* This tab shows off how inline CSS styles can be applied to elements and panels in order
* to customise the look of the UI.
*-----------------------------------------------------------------------------------------------------------*/
auto styletab = ESPUI.addControl(Tab, "", "Styled controls");
styleButton = ESPUI.addControl(Button, "Styled Button", "Button", Alizarin, styletab, generalCallback);
styleLabel = ESPUI.addControl(Label, "Styled Label", "This is a label", Alizarin, styletab, generalCallback);
styleSwitcher = ESPUI.addControl(Switcher, "Styled Switcher", "1", Alizarin, styletab, generalCallback);
styleSlider = ESPUI.addControl(Slider, "Styled Slider", "0", Alizarin, styletab, generalCallback);
//This button will randomise the colours of the above controls to show updating of inline styles
ESPUI.addControl(Button, "Randomise Colours", "Randomise Colours", Sunflower, styletab,
//This callback generates and applies inline styles to a bunch of controls to change their colour.
//The styles created are of the form:
// "border-bottom: #999 3px solid; background-color: #aabbcc;"
// "background-color: #aabbcc;"
[](Control *sender, int type) {
//Declare space for style strings. These have to be static so that they are always available
//to the websocket layer. If we'd not made them static they'd be allocated on the heap and
//will be unavailable when we leave this function.
static char stylecol1[60], stylecol2[30];
if(type == B_UP) {
//Generate two random HTML hex colour codes, and print them into CSS style rules
sprintf(stylecol1, "border-bottom: #999 3px solid; background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
sprintf(stylecol2, "background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF));
//Apply those styles to various elements to show how controls react to styling
ESPUI.setPanelStyle(styleButton, stylecol1);
ESPUI.setElementStyle(styleButton, stylecol2);
ESPUI.setPanelStyle(styleLabel, stylecol1);
ESPUI.setElementStyle(styleLabel, stylecol2);
ESPUI.setPanelStyle(styleSwitcher, stylecol1);
ESPUI.setElementStyle(styleSwitcher, stylecol2);
ESPUI.setPanelStyle(styleSlider, stylecol1);
ESPUI.setElementStyle(styleSlider, stylecol2);
}
});
ESPUI.addControl(Separator, "Other styling examples", "", None, styletab);
styleButton2 = ESPUI.addControl(Button, "Styled Button", "Button", Alizarin, styletab, generalCallback);
ESPUI.setPanelStyle(styleButton2, "background: linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(252,176,69,1) 100%); border-bottom: #555;");
ESPUI.setElementStyle(styleButton2, "border-radius: 2em; border: 3px solid black; width: 30%; background-color: #8df;");
styleSlider2 = ESPUI.addControl(Slider, "Styled Slider", "0", Dark, styletab, generalCallback);
ESPUI.setElementStyle(styleSlider2, "background: linear-gradient(to right, red, orange, yellow, green, blue);");
styleLabel2 = ESPUI.addControl(Label, "Styled Label", "This is a label", Dark, styletab, generalCallback);
ESPUI.setElementStyle(styleLabel2, "text-shadow: 3px 3px #74b1ff, 6px 6px #c64ad7; font-size: 60px; font-variant-caps: small-caps; background-color: unset; color: #c4f0bb; -webkit-text-stroke: 1px black;");
/*
* Tab: Grouped controls
* This tab shows how multiple control can be grouped into the same panel through the use of the
* parentControl value. This also shows how to add labels to grouped controls, and how to use vertical controls.
*-----------------------------------------------------------------------------------------------------------*/
auto grouptab = ESPUI.addControl(Tab, "", "Grouped controls");
//The parent of this button is a tab, so it will create a new panel with one control.
auto groupbutton = ESPUI.addControl(Button, "Button Group", "Button A", Dark, grouptab, generalCallback);
//However the parent of this button is another control, so therefore no new panel is
//created and the button is added to the existing panel.
ESPUI.addControl(Button, "", "Button B", Alizarin, groupbutton, generalCallback);
ESPUI.addControl(Button, "", "Button C", Alizarin, groupbutton, generalCallback);
//Sliders can be grouped as well
//To label each slider in the group, we are going add additional labels and give them custom CSS styles
//We need this CSS style rule, which will remove the label's background and ensure that it takes up the entire width of the panel
String clearLabelStyle = "background-color: unset; width: 100%;";
//First we add the main slider to create a panel
auto groupsliders = ESPUI.addControl(Slider, "Slider Group", "10", Dark, grouptab, generalCallback);
//Then we add a label and set its style to the clearLabelStyle. Here we've just given it the name "A"
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, groupsliders), clearLabelStyle);
//We can now continue to add additional sliders and labels
ESPUI.addControl(Slider, "", "20", None, groupsliders, generalCallback);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, groupsliders), clearLabelStyle);
ESPUI.addControl(Slider, "", "30", None, groupsliders, generalCallback);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, groupsliders), clearLabelStyle);
//We can also usefully group switchers.
auto groupswitcher = ESPUI.addControl(Switcher, "Switcher Group", "0", Dark, grouptab, generalCallback);
ESPUI.addControl(Switcher, "", "1", Sunflower, groupswitcher, generalCallback);
ESPUI.addControl(Switcher, "", "0", Sunflower, groupswitcher, generalCallback);
ESPUI.addControl(Switcher, "", "1", Sunflower, groupswitcher, generalCallback);
//To label these switchers we need to first go onto a "new line" below the line of switchers
//To do this we add an empty label set to be clear and full width (with our clearLabelStyle)
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, groupswitcher), clearLabelStyle);
//We will now need another label style. This one sets its width to the same as a switcher (and turns off the background)
String switcherLabelStyle = "width: 60px; margin-left: .3rem; margin-right: .3rem; background-color: unset;";
//We can now just add the styled labels.
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, groupswitcher), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, groupswitcher), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, groupswitcher), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, groupswitcher), switcherLabelStyle);
//You can mix and match different control types, but the results might sometimes
//need additional styling to lay out nicely.
auto grouplabel = ESPUI.addControl(Label, "Mixed Group", "Main label", Dark, grouptab);
auto grouplabel2 = ESPUI.addControl(Label, "", "Secondary label", Emerald, grouplabel);
ESPUI.addControl(Button, "", "Button D", Alizarin, grouplabel, generalCallback);
ESPUI.addControl(Switcher, "", "1", Sunflower, grouplabel, generalCallback);
ESPUI.setElementStyle(grouplabel2, "font-size: x-large; font-family: serif;");
//Some controls can even support vertical orientation, currently Switchers and Sliders
ESPUI.addControl(Separator, "Vertical controls", "", None, grouptab);
auto vertgroupswitcher = ESPUI.addControl(Switcher, "Vertical Switcher Group", "0", Dark, grouptab, generalCallback);
ESPUI.setVertical(vertgroupswitcher);
//On the following lines we wrap the value returned from addControl and send it straight to setVertical
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
ESPUI.setVertical(ESPUI.addControl(Switcher, "", "0", None, vertgroupswitcher, generalCallback));
//The mechanism for labelling vertical switchers is the same as we used above for horizontal ones
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, vertgroupswitcher), clearLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, vertgroupswitcher), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, vertgroupswitcher), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, vertgroupswitcher), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, vertgroupswitcher), switcherLabelStyle);
auto vertgroupslider = ESPUI.addControl(Slider, "Vertical Slider Group", "15", Dark, grouptab, generalCallback);
ESPUI.setVertical(vertgroupslider);
ESPUI.setVertical(ESPUI.addControl(Slider, "", "25", None, vertgroupslider, generalCallback));
ESPUI.setVertical(ESPUI.addControl(Slider, "", "35", None, vertgroupslider, generalCallback));
ESPUI.setVertical(ESPUI.addControl(Slider, "", "45", None, vertgroupslider, generalCallback));
//The mechanism for labelling vertical sliders is the same as we used above for switchers
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "", None, vertgroupslider), clearLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "A", None, vertgroupslider), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "B", None, vertgroupslider), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "C", None, vertgroupslider), switcherLabelStyle);
ESPUI.setElementStyle(ESPUI.addControl(Label, "", "D", None, vertgroupslider), switcherLabelStyle);
//Note that combining vertical and horizontal sliders is going to result in very messy layout!
/*
* Tab: Example UI
* An example UI for the documentation
*-----------------------------------------------------------------------------------------------------------*/
auto exampletab = ESPUI.addControl(Tab, "Example", "Example");
ESPUI.addControl(Separator, "Control and Status", "", None, exampletab);
ESPUI.addControl(Switcher, "Power", "1", Alizarin, exampletab, generalCallback);
ESPUI.addControl(Label, "Status", "System status: OK", Wetasphalt, exampletab, generalCallback);
ESPUI.addControl(Separator, "Settings", "", None, exampletab);
ESPUI.addControl(PadWithCenter, "Attitude Control", "", Dark, exampletab, generalCallback);
auto examplegroup1 = ESPUI.addControl(Button, "Activate Features", "Feature A", Carrot, exampletab, generalCallback);
ESPUI.addControl(Button, "Activate Features", "Feature B", Carrot, examplegroup1, generalCallback);
ESPUI.addControl(Button, "Activate Features", "Feature C", Carrot, examplegroup1, generalCallback);
ESPUI.addControl(Slider, "Value control", "45", Peterriver, exampletab, generalCallback);
/*
* Tab: WiFi Credentials
* You use this tab to enter the SSID and password of a wifi network to autoconnect to.
*-----------------------------------------------------------------------------------------------------------*/
auto wifitab = ESPUI.addControl(Tab, "", "WiFi Credentials");
wifi_ssid_text = ESPUI.addControl(Text, "SSID", "", Alizarin, wifitab, textCallback);
//Note that adding a "Max" control to a text control sets the max length
ESPUI.addControl(Max, "", "32", None, wifi_ssid_text);
wifi_pass_text = ESPUI.addControl(Text, "Password", "", Alizarin, wifitab, textCallback);
ESPUI.addControl(Max, "", "64", None, wifi_pass_text);
ESPUI.addControl(Button, "Save", "Save", Peterriver, wifitab,
[](Control *sender, int type) {
if(type == B_UP) {
Serial.println("Saving credentials to EPROM...");
Serial.println(ESPUI.getControl(wifi_ssid_text)->value);
Serial.println(ESPUI.getControl(wifi_pass_text)->value);
unsigned int i;
EEPROM.begin(100);
for(i = 0; i < ESPUI.getControl(wifi_ssid_text)->value.length(); i++) {
EEPROM.write(i, ESPUI.getControl(wifi_ssid_text)->value.charAt(i));
if(i==30) break; //Even though we provided a max length, user input should never be trusted
}
EEPROM.write(i, '\0');
for(i = 0; i < ESPUI.getControl(wifi_pass_text)->value.length(); i++) {
EEPROM.write(i + 32, ESPUI.getControl(wifi_pass_text)->value.charAt(i));
if(i==94) break; //Even though we provided a max length, user input should never be trusted
}
EEPROM.write(i + 32, '\0');
EEPROM.end();
}
});
//Finally, start up the UI.
//This should only be called once we are connected to WiFi.
ESPUI.begin(HOSTNAME);
#ifdef ESP8266
} // HeapSelectIram
#endif
}
//Most elements in this test UI are assigned this generic callback which prints some
//basic information. Event types are defined in ESPUI.h
void generalCallback(Control *sender, int type) {
Serial.print("CB: id(");
Serial.print(sender->id);
Serial.print(") Type(");
Serial.print(type);
Serial.print(") '");
Serial.print(sender->label);
Serial.print("' = ");
Serial.println(sender->value);
}
// Most elements in this test UI are assigned this generic callback which prints some
// basic information. Event types are defined in ESPUI.h
// The extended param can be used to pass additional information
void paramCallback(Control* sender, int type, int param)
{
Serial.print("CB: id(");
Serial.print(sender->id);
Serial.print(") Type(");
Serial.print(type);
Serial.print(") '");
Serial.print(sender->label);
Serial.print("' = ");
Serial.println(sender->value);
Serial.print("param = ");
Serial.println(param);
}
void setup() {
randomSeed(0);
Serial.begin(115200);
while(!Serial);
if(SLOW_BOOT) delay(5000); //Delay booting to give time to connect a serial monitor
connectWifi();
#if defined(ESP32)
WiFi.setSleep(false); //For the ESP32: turn off sleeping to increase UI responsivness (at the cost of power use)
#endif
setUpUI();
}
void loop() {
static long unsigned lastTime = 0;
//Send periodic updates if switcher is turned on
if(updates && millis() > lastTime + 500) {
static uint16_t sliderVal = 10;
//Flick this switcher on and off
ESPUI.updateSwitcher(mainSwitcher, ESPUI.getControl(mainSwitcher)->value.toInt() ? false : true);
sliderVal += 10;
if(sliderVal > 400) sliderVal = 10;
//Sliders, numbers, and labels can all be updated at will
ESPUI.updateSlider(mainSlider, sliderVal);
ESPUI.updateNumber(mainNumber, random(100000));
ESPUI.updateLabel(mainLabel, String(sliderVal));
lastTime = millis();
}
//Simple debug UART interface
if(Serial.available()) {
switch(Serial.read()) {
case 'w': //Print IP details
Serial.println(WiFi.localIP());
break;
case 'W': //Reconnect wifi
connectWifi();
break;
case 'C': //Force a crash (for testing exception decoder)
#if !defined(ESP32)
((void (*)())0xf00fdead)();
#endif
break;
default:
Serial.print('#');
break;
}
}
#if !defined(ESP32)
//We don't need to call this explicitly on ESP32 but we do on 8266
MDNS.update();
#endif
}
//Utilities
//
//If you are here just to see examples of how to use ESPUI, you can ignore the following functions
//------------------------------------------------------------------------------------------------
void readStringFromEEPROM(String& buf, int baseaddress, int size) {
buf.reserve(size);
for (int i = baseaddress; i < baseaddress+size; i++) {
char c = EEPROM.read(i);
buf += c;
if(!c) break;
}
}
void connectWifi() {
int connect_timeout;
#if defined(ESP32)
WiFi.setHostname(HOSTNAME);
#else
WiFi.hostname(HOSTNAME);
#endif
Serial.println("Begin wifi...");
//Load credentials from EEPROM
if(!(FORCE_USE_HOTSPOT)) {
yield();
EEPROM.begin(100);
String stored_ssid, stored_pass;
readStringFromEEPROM(stored_ssid, 0, 32);
readStringFromEEPROM(stored_pass, 32, 96);
EEPROM.end();
//Try to connect with stored credentials, fire up an access point if they don't work.
#if defined(ESP32)
WiFi.begin(stored_ssid.c_str(), stored_pass.c_str());
#else
WiFi.begin(stored_ssid, stored_pass);
#endif
connect_timeout = 28; //7 seconds
while (WiFi.status() != WL_CONNECTED && connect_timeout > 0) {
delay(250);
Serial.print(".");
connect_timeout--;
}
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println(WiFi.localIP());
Serial.println("Wifi started");
if (!MDNS.begin(HOSTNAME)) {
Serial.println("Error setting up MDNS responder!");
}
} else {
Serial.println("\nCreating access point...");
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(IPAddress(192, 168, 1, 1), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));
WiFi.softAP(HOSTNAME);
connect_timeout = 20;
do {
delay(250);
Serial.print(",");
connect_timeout--;
} while(connect_timeout);
}
}
void textCallback(Control *sender, int type) {
//This callback is needed to handle the changed values, even though it doesn't do anything itself.
}
void randomString(char *buf, int len) {
for(auto i = 0; i < len-1; i++)
buf[i] = random(0, 26) + 'A';
buf[len-1] = '\0';
}