Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// Getting started: https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-overview-quick-start/
//

#include "generated/stm32DuinoOneButton_menu.h"
#include "stm32DuinoOneButton_menu.h"
#include <SPI.h>

void setup() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@

#include <tcMenu.h>
#include "stm32DuinoOneButton_menu.h"
#include "../ThemeMonoInverseBuilder.h"
#include "ThemeMonoInverseBuilder.h"
#include <Fonts/OpenSansRegular8pt.h>

#include "TcMenuBuilder.h"

// Global variable declarations
const ConnectorLocalInfo applicationInfo = { "One Button", "4fe6e85d-2bbd-4d19-84e5-5d6746883028" };
TcMenuRemoteServer remoteServer(applicationInfo);
Expand All @@ -27,26 +29,26 @@ NoInitialisationNeeded serialInitializer;
SerialTagValueTransport serialTransport(&Serial);
TagValueRemoteServerConnection serialConnection(serialTransport, serialInitializer);

// Global Menu Item declarations
const char enumStrSettingsEnumProp_0[] = "Item1";
const char enumStrSettingsEnumProp_1[] = "Item2";
const char enumStrSettingsEnumProp_2[] = "Item3";
const char* const enumStrSettingsEnumProp[] = { enumStrSettingsEnumProp_0, enumStrSettingsEnumProp_1, enumStrSettingsEnumProp_2 };
const EnumMenuInfo minfoSettingsEnumProp = { "EnumProp", 24, 0xffff, 2, NO_CALLBACK, enumStrSettingsEnumProp };
EnumMenuItem menuSettingsEnumProp(&minfoSettingsEnumProp, 0, nullptr, INFO_LOCATION_PGM);
const AnalogMenuInfo minfoSettingsIntProp = { "IntProp", 23, 0xffff, 10, NO_CALLBACK, 0, 1, "A" };
AnalogMenuItem menuSettingsIntProp(&minfoSettingsIntProp, 0, &menuSettingsEnumProp, INFO_LOCATION_PGM);
const BooleanMenuInfo minfoSettingsOption = { "Option", 22, 0xffff, 1, NO_CALLBACK, NAMING_TRUE_FALSE };
BooleanMenuItem menuSettingsOption(&minfoSettingsOption, false, &menuSettingsIntProp, INFO_LOCATION_PGM);
const SubMenuInfo minfoSettings = { "Settings", 21, 0xffff, 0, NO_CALLBACK };
BackMenuItem menuBackSettings(&minfoSettings, &menuSettingsOption, INFO_LOCATION_PGM);
SubMenuItem menuSettings(&minfoSettings, &menuBackSettings, nullptr, INFO_LOCATION_PGM);
const AnalogMenuInfo minfoTemp = { "Temp", 20, 0xffff, 100, NO_CALLBACK, 0, 1, "%" };
AnalogMenuItem menuTemp(&minfoTemp, 0, &menuSettings, INFO_LOCATION_PGM);
const AnyMenuInfo minfoPressMe = { "Press Me", 19, 0xffff, 0, onPressMe };
ActionMenuItem menuPressMe(&minfoPressMe, &menuTemp, INFO_LOCATION_PGM);
const char* enumSettingValues[] = { "Spanner", "Hammer", "Plane" };

void buildMenu(TcMenuBuilder& builder) {
builder.usingDynamicEEPROMStorage()
.actionItem(MENU_PRESS_ME_ID, "Press Me", NoMenuFlags, onPressMe)
.analogBuilder(MENU_TEMP_ID, "Temp", DONT_SAVE, NoMenuFlags)
.maxValue(100).offset(0).divisor(1).unit("%")\
.endItem()
.subMenu(MENU_SETTINGS_ID, "Settings", NoMenuFlags)
.boolItem(MENU_SETTINGS_OPTION_ID, "Option", DONT_SAVE, NAMING_TRUE_FALSE, NoMenuFlags)
.enumItem(MENU_SETTINGS_ENUM_ID, "Tooling", DONT_SAVE, enumSettingValues, 3, NoMenuFlags)
.analogBuilder(MENU_SETTINGS_INT_ID, "IntProp", DONT_SAVE, NoMenuFlags)
.maxValue(10).offset(0).divisor(1).unit("A").endItem()
.endSub();
}

void setupMenu() {
auto builder = TcMenuBuilder(&MenuManager::ROOT);
buildMenu(builder);

// First we set up eeprom and authentication (if needed).
setSizeBasedEEPROMStorageEnabled(false);
glBspRom.initialise(0);
Expand All @@ -55,7 +57,7 @@ void setupMenu() {
gfx.begin();
renderer.setUpdatesPerSecond(5);
switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, false);
menuMgr.initWithoutInput(&renderer, &menuPressMe);
menuMgr.initWithoutInput(&renderer, getMenuItemById(MENU_PRESS_ME_ID));
oneButtonHandler.start();
remoteServer.addConnection(&serialConnection);
installMonoInverseTitleTheme(renderer, MenuFontDef(&OpenSansRegular8pt, 0), MenuFontDef(&OpenSansRegular8pt, 0), true, BaseGraphicalRenderer::NO_TITLE, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,16 @@ extern const UnicodeFont OpenSansRegular8pt[];
// Any externals needed by IO expanders, EEPROMs etc


// Global Menu Item exports
extern EnumMenuItem menuSettingsEnumProp;
extern AnalogMenuItem menuSettingsIntProp;
extern BooleanMenuItem menuSettingsOption;
extern BackMenuItem menuBackSettings;
extern SubMenuItem menuSettings;
extern AnalogMenuItem menuTemp;
extern ActionMenuItem menuPressMe;
// Global Menu Item IDs
#define MENU_PRESS_ME_ID 1
#define MENU_TEMP_ID 2
#define MENU_SETTINGS_ID 3
#define MENU_SETTINGS_OPTION_ID 4
#define MENU_SETTINGS_INT_ID 5
#define MENU_SETTINGS_ENUM_ID 6

// Provide a wrapper to get hold of the root menu item and export setupMenu
inline MenuItem& rootMenuItem() { return menuPressMe; }
inline MenuItem& rootMenuItem() { return *getMenuItemById(MENU_PRESS_ME_ID); }
void setupMenu();

// Callback functions must always include CALLBACK_FUNCTION after the return type
Expand Down
44 changes: 44 additions & 0 deletions examples/esp/esp32s2Saola/esp32s2Saola.emf
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,50 @@
"visible": true,
"staticDataInRAM": false
}
},
{
"parentId": 0,
"type": "subMenu",
"item": {
"secured": false,
"name": "IoT Setup",
"id": 22,
"eepromAddress": -1,
"readOnly": false,
"localOnly": false,
"visible": true,
"staticDataInRAM": false
}
},
{
"parentId": 22,
"type": "textItem",
"defaultValue": "",
"item": {
"textLength": 5,
"itemType": "IP_ADDRESS",
"name": "IP Addr",
"id": 23,
"eepromAddress": -1,
"readOnly": false,
"localOnly": false,
"visible": true,
"staticDataInRAM": false
}
},
{
"parentId": 22,
"type": "customBuildItem",
"item": {
"menuType": "REMOTE_IOT_MONITOR",
"name": "IoT Monitor1",
"id": 24,
"eepromAddress": -1,
"readOnly": false,
"localOnly": true,
"visible": true,
"staticDataInRAM": false
}
}
],
"codeOptions": {
Expand Down
58 changes: 45 additions & 13 deletions examples/esp/esp32s2Saola/esp32s2Saola.ino
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,53 @@
bool connectedToWiFi = false;
void startWiFiAndListener();

// we add two widgets that show both the connection status and wifi signal strength
// these are added to the renderer and rendered upon any change.
// we add two widgets, one generated by tcMenu Designer Bitmap and Widget Creator, and the inbuilt Wi-Fi widget
// START widgets

// https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/rendering-with-tcmenu-lcd-tft-oled
TitleWidget wifiWidget(iconsWifi, 5, 16, 12);

using namespace tcgfx;

// XBM_LSB_FIRST width=12, height=12, size=24
// auto size = Coord(12, 12);
const uint8_t myWidgetWidIcon0[] PROGMEM = {
0x00,0x00,0x8e,0x03,0x51,0x04,0x51,0x04,0x51,0x04,0x51,0x04,0x51,0x04,0x51,0x04,0x59,0x06,0x5d,0x07,
0x5d,0x07,0x8e,0x03
};
// XBM_LSB_FIRST width=12, height=12, size=24
// auto size = Coord(12, 12);
const uint8_t myWidgetWidIcon1[] PROGMEM = {
0x00,0x00,0x8e,0x03,0xd7,0x05,0xd7,0x05,0xd3,0x04,0x51,0x04,0x51,0x04,0x51,0x04,0x51,0x04,0x51,0x04,
0x51,0x04,0x8e,0x03
};
const uint8_t* const myWidgetWidIcons[] PROGMEM = { myWidgetWidIcon0, myWidgetWidIcon1 };

// See https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/creating-and-using-bitmaps-menu/
TitleWidget myWidgetWidget(myWidgetWidIcons, 2, 12, 12, nullptr);

// END widgets

void setup() {
// before proceeding, we must start wire and serial, then call setup menu.
Serial.begin(115200);
serdebugF("Starting ESP32-S2 example");
SPI.begin(36, 37, 35, -1);

EEPROM.begin(512);

setupMenu();

// always call load after setupMenu, as the EEPROM you chose in initialised only after this setupMenu()
menuMgr.load();

// set the number of rows in the list.
menuExtrasMyList.setNumberOfRows(42);
getListItemById(EXTRAS_LIST_ID).setNumberOfRows(42);

// next start WiFi and register our wifi widget
startWiFiAndListener();

auto themeBuilder = TcThemeBuilder(renderer);
themeBuilder.addingTitleWidget(wifiWidget);
themeBuilder.addingTitleWidget(myWidgetWidget);

// lastly we capture when the root title is pressed present a standard version dialog.
setTitlePressedCallback([](int titleCb) {
Expand All @@ -61,11 +82,13 @@ void loop() {
}

void startWiFiAndListener() {
TextMenuItem& ssidMenuItem = getTextItemById(CONNECTIVITY_SSID_ID);
TextMenuItem& passphraseMenuItem = getTextItemById(CONNECTIVITY_PASSCODE_ID);
// You can choose between station and access point mode by setting the connectivity/Wifi Mode option to your
// own choice
if(menuConnectivityWiFiMode.getCurrentValue() == MENU_WIFIMODE_STATION) {
if(asEnumItem(getMenuItemById(CONNECTIVITY_WIFI_MODE_ID)).getCurrentValue() == MENU_WIFIMODE_STATION) {
// we are in station mode
WiFi.begin(menuConnectivitySSID.getTextValue(), menuConnectivityPasscode.getTextValue());
WiFi.begin(ssidMenuItem.getTextValue(), passphraseMenuItem.getTextValue());
WiFi.mode(WIFI_STA);
serdebugF("Connecting to Wifi using settings from connectivity menu");
}
Expand All @@ -74,25 +97,34 @@ void startWiFiAndListener() {
WiFi.mode(WIFI_AP);
char ssid[25];
char pwd[25];
copyMenuItemValueDefault(&menuConnectivitySSID, ssid, sizeof ssid, "tcmenu");
copyMenuItemValueDefault(&menuConnectivityPasscode, pwd, sizeof pwd, "secret");
copyMenuItemValueDefault(&ssidMenuItem, ssid, sizeof ssid, "tcmenu");
copyMenuItemValueDefault(&passphraseMenuItem, pwd, sizeof pwd, "secret");
WiFi.softAP(ssid, pwd);
serdebugF3("Started up in AP mode, connect with ", ssid, pwd);
}

// now monitor the wifi level every second and report it in a widget.
taskManager.scheduleFixedRate(1000, [] {
//
// Here we use the inbuilt task manager to schedule something to run every second. To use
// it you simply provide either a function callback or a lambda as we do here.
//
taskManager.schedule(repeatSeconds(1), [] {
// check the wifi connection status
if(WiFi.status() == WL_CONNECTED) {
if(!connectedToWiFi) {
// we are fully connected, so we now get the address that DHCP gave us to put into
// the Ip Address item.
IPAddress localIp = WiFi.localIP();
Serial.print("Now connected to WiFi");
Serial.println(localIp);
menuConnectivityIPAddress.setIpAddress(localIp[0], localIp[1], localIp[2], localIp[3]);
getIpAddressItemById(CONNECTIVITY_IP_ADDR_ID).setIpAddress(localIp[0], localIp[1], localIp[2], localIp[3]);
connectedToWiFi = true;
}

// if the networking is up, then we always render the current signal strength in the title widget.
wifiWidget.setCurrentState(fromWiFiRSSITo4StateIndicator(WiFi.RSSI()));
}
else {
// We've not got networking, set it
connectedToWiFi = false;
wifiWidget.setCurrentState(0);
}
Expand Down Expand Up @@ -124,7 +156,7 @@ int CALLBACK_FUNCTION fnExtrasMyListRtCall(RuntimeMenuItem* item, uint8_t row, R
}

void CALLBACK_FUNCTION onListSelected(int id) {
Serial.print("List item select "); Serial.println(menuExtrasMyList.getActiveIndex());
Serial.print("List item select "); Serial.println(getListItemById(EXTRAS_LIST_ID).getActiveIndex());
}


Expand Down
86 changes: 35 additions & 51 deletions examples/esp/esp32s2Saola/esp32s2Saola_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <tcMenu.h>
#include "esp32s2Saola_menu.h"
#include "einkThemeBuilderBlock.h"
#include "TcMenuBuilder.h"

// Global variable declarations
const PROGMEM ConnectorLocalInfo applicationInfo = { "ESP32-S2 Saola board", "b447b433-fe4f-4ce7-8746-d94bfeefc707" };
Expand All @@ -27,76 +28,59 @@ EthernetInitialisation ethernetInitialisation(&server);
EthernetTagValTransport ethernetTransport;
TagValueRemoteServerConnection ethernetConnection(ethernetTransport, ethernetInitialisation);

// Global Menu Item declarations
const PROGMEM char pgmStrConnectivityAuthenticatorText[] = { "Authenticator" };
EepromAuthenticationInfoMenuItem menuConnectivityAuthenticator(pgmStrConnectivityAuthenticatorText, NO_CALLBACK, 20, nullptr);
const PROGMEM char pgmStrConnectivityIoTMonitorText[] = { "IoT Monitor" };
RemoteMenuItem menuConnectivityIoTMonitor(pgmStrConnectivityIoTMonitorText, 19, &menuConnectivityAuthenticator);
const PROGMEM AnyMenuInfo minfoConnectivityIPAddress = { "IP Address", 15, 0xffff, 0, NO_CALLBACK };
IpAddressMenuItem menuConnectivityIPAddress(&minfoConnectivityIPAddress, IpAddressStorage(127, 0, 0, 1), &menuConnectivityIoTMonitor, INFO_LOCATION_PGM);
const char enumStrConnectivityWiFiMode_0[] PROGMEM = "Station";
const char enumStrConnectivityWiFiMode_1[] PROGMEM = "Soft AP";
const char* const enumStrConnectivityWiFiMode[] PROGMEM = { enumStrConnectivityWiFiMode_0, enumStrConnectivityWiFiMode_1 };
const PROGMEM EnumMenuInfo minfoConnectivityWiFiMode = { "WiFi Mode", 18, 64, 1, NO_CALLBACK, enumStrConnectivityWiFiMode };
EnumMenuItem menuConnectivityWiFiMode(&minfoConnectivityWiFiMode, 0, &menuConnectivityIPAddress, INFO_LOCATION_PGM);
const PROGMEM AnyMenuInfo minfoConnectivityPasscode = { "Passcode", 17, 42, 0, NO_CALLBACK };
TextMenuItem menuConnectivityPasscode(&minfoConnectivityPasscode, "", 22, &menuConnectivityWiFiMode, INFO_LOCATION_PGM);
const PROGMEM AnyMenuInfo minfoConnectivitySSID = { "SSID", 16, 20, 0, NO_CALLBACK };
TextMenuItem menuConnectivitySSID(&minfoConnectivitySSID, "", 22, &menuConnectivityPasscode, INFO_LOCATION_PGM);
const PROGMEM SubMenuInfo minfoConnectivity = { "Connectivity", 14, 0xffff, 0, NO_CALLBACK };
BackMenuItem menuBackConnectivity(&minfoConnectivity, &menuConnectivitySSID, INFO_LOCATION_PGM);
SubMenuItem menuConnectivity(&minfoConnectivity, &menuBackConnectivity, nullptr, INFO_LOCATION_PGM);
const PROGMEM AnyMenuInfo minfoExtrasMyList = { "My List", 13, 0xffff, 0, onListSelected };
ListRuntimeMenuItem menuExtrasMyList(&minfoExtrasMyList, 0, fnExtrasMyListRtCall, nullptr, INFO_LOCATION_PGM);
const PROGMEM AnyMenuInfo minfoExtrasColor = { "Color", 12, 16, 0, NO_CALLBACK };
Rgb32MenuItem menuExtrasColor(&minfoExtrasColor, RgbColor32(0, 0, 0), false, &menuExtrasMyList, INFO_LOCATION_PGM);
const PROGMEM AnyMenuInfo minfoExtrasText = { "Text", 11, 11, 0, NO_CALLBACK };
TextMenuItem menuExtrasText(&minfoExtrasText, "", 5, &menuExtrasColor, INFO_LOCATION_PGM);
const PROGMEM SubMenuInfo minfoExtras = { "Extras", 10, 0xffff, 0, NO_CALLBACK };
BackMenuItem menuBackExtras(&minfoExtras, &menuExtrasText, INFO_LOCATION_PGM);
SubMenuItem menuExtras(&minfoExtras, &menuBackExtras, &menuConnectivity, INFO_LOCATION_PGM);
const PROGMEM BooleanMenuInfo minfoDoorOpen = { "Door Open", 5, 10, 1, NO_CALLBACK, NAMING_YES_NO };
BooleanMenuItem menuDoorOpen(&minfoDoorOpen, false, &menuExtras, INFO_LOCATION_PGM);
const char enumStrFoods_0[] PROGMEM = "Pizza";
const char enumStrFoods_1[] PROGMEM = "Pasta";
const char enumStrFoods_2[] PROGMEM = "Salad";
const char enumStrFoods_3[] PROGMEM = "Pie";
const char* const enumStrFoods[] PROGMEM = { enumStrFoods_0, enumStrFoods_1, enumStrFoods_2, enumStrFoods_3 };
const PROGMEM EnumMenuInfo minfoFoods = { "Foods", 4, 8, 3, NO_CALLBACK, enumStrFoods };
EnumMenuItem menuFoods(&minfoFoods, 0, &menuDoorOpen, INFO_LOCATION_PGM);
const PROGMEM AnalogMenuInfo minfoHalves = { "Halves", 3, 6, 200, NO_CALLBACK, 0, 2, "" };
AnalogMenuItem menuHalves(&minfoHalves, 0, &menuFoods, INFO_LOCATION_PGM);
const PROGMEM AnalogMenuInfo minfoDecEdit = { "Dec Edit", 2, 4, 1000, NO_CALLBACK, 0, 10, "oC" };
AnalogMenuItem menuDecEdit(&minfoDecEdit, 0, &menuHalves, INFO_LOCATION_PGM);
const PROGMEM AnalogMenuInfo minfoIntEdit = { "Int Edit", 1, 2, 100, NO_CALLBACK, 0, 1, "%" };
AnalogMenuItem menuIntEdit(&minfoIntEdit, 0, &menuDecEdit, INFO_LOCATION_PGM);
const PROGMEM AnyMenuInfo minfoHibernate = { "Hibernate", 21, 0xffff, 0, onHibernate };
ActionMenuItem menuHibernate(&minfoHibernate, &menuIntEdit, INFO_LOCATION_PGM);
const char* enumWiFiMode[] = { "Station", "Soft AP" };
const char* enumFoodsArray[] = { "Pizza", "Pasta", "Salad", "Pie" };

void buildMenu(TcMenuBuilder& builder) {
builder.usingDynamicEEPROMStorage()
.actionItem(HIBERNATE_ID, "Hibernate", NoMenuFlags, onHibernate)
.analogBuilder(INT_EDIT_ID, "Int Edit", ROM_SAVE, NoMenuFlags, 4)
.offset(0).divisor(1).maxValue(100).unit("%").endItem()
.analogBuilder(DEC_EDIT_ID, "Dec Edit", ROM_SAVE, NoMenuFlags, 0)
.offset(0).divisor(100).maxValue(1000).unit("oC").endItem()
.analogBuilder(HALVES_ID, "Halves", ROM_SAVE, MenuFlags().readOnly(), 0)
.offset(0).divisor(2).maxValue(100).unit("").endItem()
.enumItem(FOODS_ID, "Foods", ROM_SAVE, enumFoodsArray, 4, NoMenuFlags)
.boolItem(DOOR_OPEN_ID, "Door Open", ROM_SAVE, NAMING_YES_NO, NoMenuFlags)
.subMenu(EXTRAS_ID, "Extras", NoMenuFlags)
.textItem(EXTRAS_TEXT_ID, "Text", ROM_SAVE, 10, NoMenuFlags)
.rgb32Item(EXTRAS_RGB_ID, "Color", ROM_SAVE, false, NoMenuFlags)
.listItemRtCustom(EXTRAS_LIST_ID, "My List", 10, fnExtrasMyListRtCall, NoMenuFlags)
.endSub()
.subMenu(CONNECTIVITY_ID, "Connectivity", NoMenuFlags)
.textItem(CONNECTIVITY_SSID_ID, "SSID", ROM_SAVE, 20, NoMenuFlags)
.textItem(CONNECTIVITY_PASSCODE_ID, "Passcode", ROM_SAVE, 20, NoMenuFlags)
.enumItem(CONNECTIVITY_WIFI_MODE_ID, "WiFi Mode", ROM_SAVE, enumWiFiMode, 2, NoMenuFlags)
.ipAddressItem(CONNECTIVITY_IP_ADDR_ID, "IP Address", DONT_SAVE, NoMenuFlags)
.remoteConnectivityMonitor(CONNECTIVITY_MON_ID, "IoT Monitor", MenuFlags().localOnly())
.eepromAuthenticationItem(CONNECTIVITY_AUTH_ID, "Authenticator", MenuFlags().localOnly())
.endSub();
}

void setupMenu() {
auto builder = TcMenuBuilder(&MenuManager::ROOT);
buildMenu(builder);

// First we set up eeprom and authentication (if needed).
setSizeBasedEEPROMStorageEnabled(false);
glEspRom.init();
menuMgr.setEepromRef(&glEspRom);
authManager.initialise(menuMgr.getEepromAbstraction(), 200);
menuMgr.setAuthenticator(&authManager);
// Now add any readonly, non-remote and visible flags.
menuConnectivityIoTMonitor.setLocalOnly(true);
menuConnectivityAuthenticator.setLocalOnly(true);

// Code generated by plugins and new operators.
display.init(115200, true, 10, false);
display.setRotation(0);
renderer.setUpdatesPerSecond(1);
switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, true);
menuMgr.initFor4WayJoystick(&renderer, &menuHibernate, 2, 1, 3, 4, -1, 20);
menuMgr.initFor4WayJoystick(&renderer, builder.getRootItem(), 2, 1, 3, 4, -1, 20);
remoteServer.addConnection(&ethernetConnection);
applyTheme(renderer);

// We have an IoT monitor, register the server
menuConnectivityIoTMonitor.setRemoteServer(remoteServer);
getIoTRemoteMenuById(CONNECTIVITY_MON_ID).setRemoteServer(remoteServer);

// We have an EEPROM authenticator, it needs initialising
menuConnectivityAuthenticator.init();
getAuthenticationMenuById(CONNECTIVITY_AUTH_ID).init();
}

Loading
Loading