Skip to content

Commit f760a27

Browse files
committed
#68 ensure that nothing tries to do a full recursive EEPROM load before setupMenu() initialisation. Provide a new function to just load one item selectively.
1 parent 35422bf commit f760a27

File tree

5 files changed

+117
-81
lines changed

5 files changed

+117
-81
lines changed

examples/esp8266WifiOled/esp8266WifiOled.ino

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <RemoteMenuItem.h>
2121
#include <MockIoAbstraction.h>
2222
#include <ESP8266WiFi.h>
23+
#include <EepromItemStorage.h>
2324

2425
// contains the graphical widget title components.
2526
#include "stockIcons/wifiAndConnectionIcons16x12.h"
@@ -80,12 +81,12 @@ void onCommsChange(CommunicationInfo info) {
8081
//
8182
void setup() {
8283
Serial.begin(115200);
84+
Serial.println("Starting NodeMCU example");
8385

8486
// set up the inbuilt ESP rom to use for load and store.
8587
EEPROM.begin(512);
8688
eeprom = new ArduinoEEPROMAbstraction(&EEPROM);
8789

88-
8990
// now we enable authentication using EEPROM authentication. Where the EEPROM is
9091
// queried for authentication requests, and any additional pairs are stored there too.
9192
// first we initialise the authManager, then pass it to the class.
@@ -100,13 +101,10 @@ void setup() {
100101
menuRemoteMonitor.registerCommsNotification(onCommsChange);
101102
menuAuthKeyMgr.setLocalOnly(true);
102103

103-
serdebugF("start load");
104-
105-
// because we are initialising wifi from the menu entries, we need to load the eeprom
106-
// values very early, in this case, set the root item first, before calling load.
107-
menuMgr.setRootMenu(&menuTomatoTemp);
108-
menuMgr.load(*eeprom);
109-
serdebugF("end load");
104+
// because we are initialising wifi from the menu entries, we need to load the WiFi
105+
// specific eeprom values very early, so we just load the two items we need.
106+
loadMenuItem(eeprom, &menuSSID);
107+
loadMenuItem(eeprom, &menuPwd);
110108

111109
// this sketch assumes you've successfully connected to the Wifi before, does not
112110
// call begin.. You can initialise the wifi whichever way you wish here.
@@ -122,6 +120,14 @@ void setup() {
122120
serdebugF("Connecting to Wifi using settings from connectivity menu");
123121
}
124122

123+
renderer.setFirstWidget(&wifiWidget);
124+
125+
// initialise the menu.
126+
setupMenu();
127+
128+
// load back the core menu items
129+
menuMgr.load(*eeprom);
130+
125131
// now monitor the wifi level every second and report it in a widget.
126132
taskManager.scheduleFixedRate(1000, [] {
127133
if(WiFi.status() == WL_CONNECTED) {
@@ -140,11 +146,6 @@ void setup() {
140146
}
141147
});
142148

143-
renderer.setFirstWidget(&wifiWidget);
144-
145-
// initialise the menu.
146-
setupMenu();
147-
148149
//
149150
// here we simulate the temperature changing.
150151
// temperature doesn't change that often, even 5 seconds is probably too short.

examples/nokia5110/nokia5110.ino

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,9 @@ void setup() {
6767
menuRemoteMonitor.registerCommsNotification(onCommsChange);
6868
menuAuthKeyMgr.setLocalOnly(true);
6969

70-
// we can load the menu back from eeprom, the second parameter is an
71-
// optional override of the magic key. This key is saved out with the
72-
// menu, and the values are only loaded when the key matches.
73-
menuMgr.setRootMenu(&menuHall);
74-
menuMgr.load(eeprom, 0xd00d);
70+
// here we load an item very early because we need to initialise it before the menu starts.
71+
// be very careful not to use any menu infrastructure during the callback.
72+
loadMenuItem(&eeprom, menuIP, 0xd00d);
7573

7674
// spin up the Ethernet library, get the IP address from the menu
7775
byte* rawIp = menuIP.getIpAddress();
@@ -81,6 +79,11 @@ void setup() {
8179
// initialise the menu
8280
setupMenu();
8381

82+
// we can load the menu back from eeprom, the second parameter is an
83+
// optional override of the magic key. This key is saved out with the
84+
// menu, and the values are only loaded when the key matches.
85+
menuMgr.load(eeprom, 0xd00d);
86+
8487
// because we are using the simple adafruit configuration option, tcMenu will set up the display for us.
8588
// it's less configurable but supports most of the popular choices. You can tweak the settings after setupMenu().
8689
gfx.setContrast(60);

examples/takeOverDisplay/takeOverDisplay.ino

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,11 @@ void setup() {
9393
menuRemoteMonitor.registerCommsNotification(onCommsChange);
9494
menuAuthKeyMgr.setLocalOnly(true);
9595

96-
// here we use the EEPROM to load back the last set of values.
97-
menuMgr.setRootMenu(&menuTime);
98-
menuMgr.load(eeprom);
96+
// here we need to access the ip address before the menu is fully initialised, so we just load the item
97+
// be careful not to use any infrastructure of the menu in its callback
98+
if(!loadMenuItem(&eeprom, &menuConnectivityIPAddress)) {
99+
menuConnectivityIPAddress.setIpAddress(192, 168, 0, 200);
100+
}
99101

100102
// spin up the Ethernet library, get the IP address from the menu
101103
byte* rawIp = menuConnectivityIPAddress.getIpAddress();
@@ -108,6 +110,8 @@ void setup() {
108110
// this is put in by the menu designer and must be called (always ensure devices are setup first).
109111
setupMenu();
110112

113+
menuMgr.load(eeprom);
114+
111115
// and print out the IP address
112116
char sz[20];
113117
menuConnectivityIPAddress.copyValue(sz, sizeof(sz));

src/EepromItemStorage.cpp

Lines changed: 76 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -72,71 +72,77 @@ void saveMenuStructure(EepromAbstraction* eeprom, uint16_t magicKey) {
7272
saveRecursively(eeprom, menuMgr.getRoot());
7373
}
7474

75+
void loadSingleItem(EepromAbstraction* eeprom, MenuItem* nextMenuItem) {
76+
if (nextMenuItem->getEepromPosition() == 0xffff) {
77+
// ignore this one, not got an eeprom entry..
78+
}
79+
else if (nextMenuItem->getMenuType() == MENUTYPE_TEXT_VALUE) {
80+
auto textItem = reinterpret_cast<TextMenuItem*>(nextMenuItem);
81+
eeprom->readIntoMemArray((uint8_t*)textItem->getTextValue(), textItem->getEepromPosition(), textItem->textLength());
82+
textItem->cleanUpArray();
83+
textItem->setSendRemoteNeededAll();
84+
textItem->setChanged(true);
85+
textItem->triggerCallback();
86+
}
87+
else if (nextMenuItem->getMenuType() == MENUTYPE_TIME) {
88+
auto timeItem = reinterpret_cast<TimeFormattedMenuItem*>(nextMenuItem);
89+
eeprom->readIntoMemArray((uint8_t*)timeItem->getUnderlyingData(), timeItem->getEepromPosition(), 4);
90+
timeItem->setSendRemoteNeededAll();
91+
timeItem->setChanged(true);
92+
timeItem->triggerCallback();
93+
}
94+
else if (nextMenuItem->getMenuType() == MENUTYPE_DATE) {
95+
auto dateItem = reinterpret_cast<DateFormattedMenuItem*>(nextMenuItem);
96+
eeprom->readIntoMemArray((uint8_t*)dateItem->getUnderlyingData(), dateItem->getEepromPosition(), 4);
97+
dateItem->setSendRemoteNeededAll();
98+
dateItem->setChanged(true);
99+
dateItem->triggerCallback();
100+
}
101+
else if (nextMenuItem->getMenuType() == MENUTYPE_IPADDRESS) {
102+
auto ipItem = reinterpret_cast<IpAddressMenuItem*>(nextMenuItem);
103+
eeprom->readIntoMemArray(ipItem->getIpAddress(), ipItem->getEepromPosition(), 4);
104+
ipItem->setSendRemoteNeededAll();
105+
ipItem->setChanged(true);
106+
ipItem->triggerCallback();
107+
}
108+
else if (nextMenuItem->getMenuType() == MENUTYPE_SCROLLER_VALUE) {
109+
auto scroller = reinterpret_cast<ScrollChoiceMenuItem*>(nextMenuItem);
110+
scroller->setCurrentValue(eeprom->read16(scroller->getEepromPosition()));
111+
}
112+
else if (nextMenuItem->getMenuType() == MENUTYPE_COLOR_VALUE) {
113+
auto rgb = reinterpret_cast<Rgb32MenuItem*>(nextMenuItem);
114+
auto data = rgb->getUnderlying();
115+
data->red = eeprom->read8(rgb->getEepromPosition());
116+
data->green = eeprom->read8(rgb->getEepromPosition() + 1);
117+
data->blue = eeprom->read8(rgb->getEepromPosition() + 2);
118+
data->alpha = eeprom->read8(rgb->getEepromPosition() + 3);
119+
}
120+
else if (nextMenuItem->getMenuType() == MENUTYPE_LARGENUM_VALUE) {
121+
auto numItem = reinterpret_cast<EditableLargeNumberMenuItem*>(nextMenuItem);
122+
numItem->getLargeNumber()->setNegative(eeprom->read8(numItem->getEepromPosition()));
123+
eeprom->readIntoMemArray(numItem->getLargeNumber()->getNumberBuffer(), numItem->getEepromPosition() + 1, 6);
124+
}
125+
else if (nextMenuItem->getMenuType() == MENUTYPE_INT_VALUE) {
126+
auto intItem = (AnalogMenuItem*)nextMenuItem;
127+
intItem->setCurrentValue(eeprom->read16(intItem->getEepromPosition()));
128+
}
129+
else if (nextMenuItem->getMenuType() == MENUTYPE_ENUM_VALUE) {
130+
auto valItem = (EnumMenuItem*)nextMenuItem;
131+
valItem->setCurrentValue(eeprom->read16(valItem->getEepromPosition()));
132+
}
133+
else if (nextMenuItem->getMenuType() == MENUTYPE_BOOLEAN_VALUE) {
134+
auto valItem = (BooleanMenuItem*)nextMenuItem;
135+
valItem->setCurrentValue(eeprom->read8(valItem->getEepromPosition()));
136+
}
137+
}
138+
75139
void loadRecursively(EepromAbstraction* eeprom, MenuItem* nextMenuItem) {
76140
while (nextMenuItem) {
77141
if (nextMenuItem->getMenuType() == MENUTYPE_SUB_VALUE) {
78142
loadRecursively(eeprom, ((SubMenuItem*)nextMenuItem)->getChild());
79143
}
80-
else if (nextMenuItem->getEepromPosition() == 0xffff) {
81-
// ignore this one, not got an eeprom entry..
82-
}
83-
else if (nextMenuItem->getMenuType() == MENUTYPE_TEXT_VALUE) {
84-
auto textItem = reinterpret_cast<TextMenuItem*>(nextMenuItem);
85-
eeprom->readIntoMemArray((uint8_t*)textItem->getTextValue(), textItem->getEepromPosition(), textItem->textLength());
86-
textItem->cleanUpArray();
87-
textItem->setSendRemoteNeededAll();
88-
textItem->setChanged(true);
89-
textItem->triggerCallback();
90-
}
91-
else if (nextMenuItem->getMenuType() == MENUTYPE_TIME) {
92-
auto timeItem = reinterpret_cast<TimeFormattedMenuItem*>(nextMenuItem);
93-
eeprom->readIntoMemArray((uint8_t*)timeItem->getUnderlyingData(), timeItem->getEepromPosition(), 4);
94-
timeItem->setSendRemoteNeededAll();
95-
timeItem->setChanged(true);
96-
timeItem->triggerCallback();
97-
}
98-
else if (nextMenuItem->getMenuType() == MENUTYPE_DATE) {
99-
auto dateItem = reinterpret_cast<DateFormattedMenuItem*>(nextMenuItem);
100-
eeprom->readIntoMemArray((uint8_t*)dateItem->getUnderlyingData(), dateItem->getEepromPosition(), 4);
101-
dateItem->setSendRemoteNeededAll();
102-
dateItem->setChanged(true);
103-
dateItem->triggerCallback();
104-
}
105-
else if (nextMenuItem->getMenuType() == MENUTYPE_IPADDRESS) {
106-
auto ipItem = reinterpret_cast<IpAddressMenuItem*>(nextMenuItem);
107-
eeprom->readIntoMemArray(ipItem->getIpAddress(), ipItem->getEepromPosition(), 4);
108-
ipItem->setSendRemoteNeededAll();
109-
ipItem->setChanged(true);
110-
ipItem->triggerCallback();
111-
}
112-
else if (nextMenuItem->getMenuType() == MENUTYPE_SCROLLER_VALUE) {
113-
auto scroller = reinterpret_cast<ScrollChoiceMenuItem*>(nextMenuItem);
114-
scroller->setCurrentValue(eeprom->read16(scroller->getEepromPosition()));
115-
}
116-
else if (nextMenuItem->getMenuType() == MENUTYPE_COLOR_VALUE) {
117-
auto rgb = reinterpret_cast<Rgb32MenuItem*>(nextMenuItem);
118-
auto data = rgb->getUnderlying();
119-
data->red = eeprom->read8(rgb->getEepromPosition());
120-
data->green = eeprom->read8(rgb->getEepromPosition() + 1);
121-
data->blue = eeprom->read8(rgb->getEepromPosition() + 2);
122-
data->alpha = eeprom->read8(rgb->getEepromPosition() + 3);
123-
}
124-
else if (nextMenuItem->getMenuType() == MENUTYPE_LARGENUM_VALUE) {
125-
auto numItem = reinterpret_cast<EditableLargeNumberMenuItem*>(nextMenuItem);
126-
numItem->getLargeNumber()->setNegative(eeprom->read8(numItem->getEepromPosition()));
127-
eeprom->readIntoMemArray(numItem->getLargeNumber()->getNumberBuffer(), numItem->getEepromPosition() + 1, 6);
128-
}
129-
else if (nextMenuItem->getMenuType() == MENUTYPE_INT_VALUE) {
130-
auto intItem = (AnalogMenuItem*)nextMenuItem;
131-
intItem->setCurrentValue(eeprom->read16(intItem->getEepromPosition()));
132-
}
133-
else if (nextMenuItem->getMenuType() == MENUTYPE_ENUM_VALUE) {
134-
auto valItem = (EnumMenuItem*)nextMenuItem;
135-
valItem->setCurrentValue(eeprom->read16(valItem->getEepromPosition()));
136-
}
137-
else if (nextMenuItem->getMenuType() == MENUTYPE_BOOLEAN_VALUE) {
138-
auto valItem = (BooleanMenuItem*)nextMenuItem;
139-
valItem->setCurrentValue(eeprom->read8(valItem->getEepromPosition()));
144+
else {
145+
loadSingleItem(eeprom, nextMenuItem);
140146
}
141147
nextMenuItem = nextMenuItem->getNext();
142148
}
@@ -154,3 +160,13 @@ bool loadMenuStructure(EepromAbstraction* eeprom, uint16_t magicKey) {
154160
return false;
155161
}
156162
}
163+
164+
bool loadMenuItem(EepromAbstraction* eeprom, MenuItem* theItem, uint16_t magicKey) {
165+
if (eeprom->read16(0) == magicKey) {
166+
loadSingleItem(eeprom, theItem);
167+
return true;
168+
}
169+
else {
170+
return false;
171+
}
172+
}

src/EepromItemStorage.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#include "EepromAbstraction.h"
1515

16+
class MenuItem;
17+
1618
/**
1719
* Save a menu structure to the EEPROM storage device passed in, such that all editable menu items with valid EEPROM
1820
* address (IE not -1). The eeprom structure will be saved after the first two bytes which are the magic key. This key
@@ -30,4 +32,14 @@ void saveMenuStructure(EepromAbstraction* eeprom, uint16_t magicKey = 0xfade);
3032
*/
3133
bool loadMenuStructure(EepromAbstraction* eeprom, uint16_t magicKey = 0xfade);
3234

35+
/**
36+
* Loads a single menu item back from storage, this can be used to selectively load critical menu items before
37+
* the setupMenu() call is made, but care must be taken to ensure that the callbacks for these items do not rely
38+
* on any menu infrastructure whatsoever.
39+
* @param eeprom the EEPROM storage to load from
40+
* @param theItem the menu item to try and load if the magic key matches
41+
* @param magicKey the key to check against, only loaded if the key matches.
42+
*/
43+
bool loadMenuItem(EepromAbstraction* eeprom, MenuItem* theItem, uint16_t magicKey = 0xfade);
44+
3345
#endif //_EEPROM_ITEM_STORAGE_H_

0 commit comments

Comments
 (0)