mirror of
https://github.com/agessaman/MeshCore.git
synced 2026-08-28 09:44:26 +00:00
A merge conflict resolution collapsed the `// node name` comment and its `_display->setCursor(0, 0)` call onto a single line, which commented out the cursor reset. The node name then rendered at whatever cursor position was left over from the previous frame (the end of the IP: line), so it trailed the IP address and wrapped onto the next line instead of appearing at the top of the home screen. Split the comment and setCursor back onto separate lines so the name is drawn at (0, 0) again.
216 lines
7.4 KiB
C++
216 lines
7.4 KiB
C++
#include "UITask.h"
|
|
#include "target.h"
|
|
#include <Arduino.h>
|
|
#include <helpers/CommonCLI.h>
|
|
|
|
#ifndef USER_BTN_PRESSED
|
|
#define USER_BTN_PRESSED LOW
|
|
#endif
|
|
|
|
#ifdef WITH_MQTT_BRIDGE
|
|
#include <WiFi.h>
|
|
#include <helpers/esp32/WebConfigServer.h> // defines WITH_WEBCONFIG on ESP32
|
|
#endif
|
|
|
|
#define AUTO_OFF_MILLIS 20000 // 20 seconds
|
|
#define BOOT_SCREEN_MILLIS 4000 // 4 seconds
|
|
|
|
#define POWEROFF_DELAY 3000
|
|
|
|
// 'meshcore', 128x13px
|
|
static const uint8_t meshcore_logo [] PROGMEM = {
|
|
0x3c, 0x01, 0xe3, 0xff, 0xc7, 0xff, 0x8f, 0x03, 0x87, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe,
|
|
0x3c, 0x03, 0xe3, 0xff, 0xc7, 0xff, 0x8e, 0x03, 0x8f, 0xfe, 0x3f, 0xfe, 0x1f, 0xff, 0x1f, 0xfe,
|
|
0x3e, 0x03, 0xc3, 0xff, 0x8f, 0xff, 0x0e, 0x07, 0x8f, 0xfe, 0x7f, 0xfe, 0x1f, 0xff, 0x1f, 0xfc,
|
|
0x3e, 0x07, 0xc7, 0x80, 0x0e, 0x00, 0x0e, 0x07, 0x9e, 0x00, 0x78, 0x0e, 0x3c, 0x0f, 0x1c, 0x00,
|
|
0x3e, 0x0f, 0xc7, 0x80, 0x1e, 0x00, 0x0e, 0x07, 0x1e, 0x00, 0x70, 0x0e, 0x38, 0x0f, 0x3c, 0x00,
|
|
0x7f, 0x0f, 0xc7, 0xfe, 0x1f, 0xfc, 0x1f, 0xff, 0x1c, 0x00, 0x70, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
|
|
0x7f, 0x1f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x0e, 0x38, 0x0e, 0x3f, 0xf8,
|
|
0x7f, 0x3f, 0xc7, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1c, 0x00, 0xf0, 0x1e, 0x3f, 0xfe, 0x3f, 0xf0,
|
|
0x77, 0x3b, 0x87, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xfc, 0x38, 0x00,
|
|
0x77, 0xfb, 0x8f, 0x00, 0x00, 0x07, 0x1c, 0x0f, 0x3c, 0x00, 0xe0, 0x1c, 0x7f, 0xf8, 0x38, 0x00,
|
|
0x73, 0xf3, 0x8f, 0xff, 0x0f, 0xff, 0x1c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x78, 0x7f, 0xf8,
|
|
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfe, 0x3c, 0x0e, 0x3f, 0xf8, 0xff, 0xfc, 0x70, 0x3c, 0x7f, 0xf8,
|
|
0xe3, 0xe3, 0x8f, 0xff, 0x1f, 0xfc, 0x3c, 0x0e, 0x1f, 0xf8, 0xff, 0xf8, 0x70, 0x3c, 0x7f, 0xf8,
|
|
};
|
|
|
|
void UITask::begin(NodePrefs* node_prefs, const char* build_date, const char* firmware_version) {
|
|
_prevBtnState = HIGH;
|
|
_auto_off = millis() + AUTO_OFF_MILLIS;
|
|
_started_at = millis();
|
|
_node_prefs = node_prefs;
|
|
_display->turnOn();
|
|
|
|
#if defined(PIN_USER_BTN) && defined(DISPLAY_CLASS)
|
|
user_btn.begin();
|
|
#endif
|
|
|
|
// strip off dash and commit hash by changing dash to null terminator
|
|
// e.g: v1.2.3-abcdef -> v1.2.3
|
|
char *version = strdup(firmware_version);
|
|
char *dash = strchr(version, '-');
|
|
if(dash){
|
|
*dash = 0;
|
|
}
|
|
|
|
// v1.2.3 (1 Jan 2025)
|
|
snprintf(_version_info, sizeof(_version_info), "%s (%s)", version, build_date);
|
|
free(version);
|
|
}
|
|
|
|
void UITask::renderCurrScreen() {
|
|
char tmp[80];
|
|
if (millis() < _started_at + BOOT_SCREEN_MILLIS) { // boot screen
|
|
// meshcore logo
|
|
_display->setColor(DisplayDriver::BLUE);
|
|
int logoWidth = 128;
|
|
_display->drawXbm((_display->width() - logoWidth) / 2, 3, meshcore_logo, logoWidth, 13);
|
|
|
|
// meshcore website
|
|
const char* website = "https://meshcore.io";
|
|
_display->setColor(DisplayDriver::LIGHT);
|
|
_display->setTextSize(1);
|
|
_display->drawTextCentered(_display->width() / 2, 22, website);
|
|
|
|
// version info
|
|
_display->setColor(DisplayDriver::LIGHT);
|
|
_display->setTextSize(1);
|
|
_display->drawTextCentered(_display->width() / 2, 35, _version_info);
|
|
|
|
// node type
|
|
const char* node_type = "< Repeater >";
|
|
_display->drawTextCentered(_display->width() / 2, 48, node_type);
|
|
} else if (_powering_off_at > 0) {
|
|
// meshcore logo
|
|
_display->setColor(DisplayDriver::BLUE);
|
|
int logoWidth = 128;
|
|
_display->drawXbm((_display->width() - logoWidth) / 2, 3, meshcore_logo, logoWidth, 13);
|
|
|
|
// meshcore website
|
|
const char* website = "https://meshcore.io";
|
|
_display->setColor(DisplayDriver::LIGHT);
|
|
_display->setTextSize(1);
|
|
_display->drawTextCentered(_display->width()/ 2, 22, website);
|
|
|
|
// Powering off
|
|
const char* poweroff_string = "Turning OFF";
|
|
uint16_t poffWidth = _display->getTextWidth(poweroff_string);
|
|
_display->setCursor((_display->width() - poffWidth) / 2, 48);
|
|
_display->drawTextCentered(_display->width()/2, 48, poweroff_string);
|
|
} else { // home screen
|
|
#ifdef WITH_WEBCONFIG
|
|
if (WebConfigServer::isRebootPending()) {
|
|
// save confirmed on-device: show ground truth even if the browser
|
|
// lost its connection before the confirmation reached it
|
|
_display->setTextSize(1);
|
|
_display->setColor(DisplayDriver::GREEN);
|
|
_display->setCursor(0, 14);
|
|
_display->print("Config saved!");
|
|
_display->setColor(DisplayDriver::LIGHT);
|
|
_display->setCursor(0, 30);
|
|
_display->print("Rebooting...");
|
|
return;
|
|
}
|
|
char wc_ssid[33], wc_ip[16];
|
|
if (WebConfigServer::getSetupInfo(wc_ssid, sizeof(wc_ssid), wc_ip, sizeof(wc_ip))) {
|
|
// setup portal active: show join instructions instead of the home screen
|
|
_display->setTextSize(1);
|
|
_display->setColor(DisplayDriver::GREEN);
|
|
_display->setCursor(0, 0);
|
|
_display->print("Observer WiFi Setup");
|
|
|
|
_display->setColor(DisplayDriver::LIGHT);
|
|
_display->setCursor(0, 14);
|
|
_display->print("Join WiFi:");
|
|
_display->setColor(DisplayDriver::YELLOW);
|
|
_display->setCursor(6, 24);
|
|
_display->print(wc_ssid);
|
|
|
|
_display->setColor(DisplayDriver::LIGHT);
|
|
_display->setCursor(0, 40);
|
|
_display->print("Then browse to:");
|
|
_display->setColor(DisplayDriver::YELLOW);
|
|
_display->setCursor(6, 50);
|
|
_display->print(wc_ip);
|
|
return;
|
|
}
|
|
#endif
|
|
// node name
|
|
_display->setCursor(0, 0);
|
|
_display->setTextSize(1);
|
|
_display->setColor(DisplayDriver::GREEN);
|
|
_display->print(_node_prefs->node_name);
|
|
|
|
// freq / sf
|
|
_display->setCursor(0, 20);
|
|
_display->setColor(DisplayDriver::YELLOW);
|
|
sprintf(tmp, "FREQ: %06.3f SF%d", _node_prefs->freq, _node_prefs->sf);
|
|
_display->print(tmp);
|
|
|
|
// bw / cr
|
|
_display->setCursor(0, 30);
|
|
sprintf(tmp, "BW: %03.2f CR: %d", _node_prefs->bw, _node_prefs->cr);
|
|
_display->print(tmp);
|
|
|
|
#ifdef WITH_MQTT_BRIDGE
|
|
// Display IP address for MQTT bridge devices
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
IPAddress ip = WiFi.localIP();
|
|
_display->setCursor(0, 40);
|
|
_display->setColor(DisplayDriver::LIGHT);
|
|
snprintf(tmp, sizeof(tmp), "IP: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
|
_display->print(tmp);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void UITask::loop() {
|
|
#if defined(PIN_USER_BTN) && defined(DISPLAY_CLASS)
|
|
int ev = user_btn.check();
|
|
if (ev == BUTTON_EVENT_CLICK) {
|
|
if (_display->isOn()) {
|
|
// TODO: any action ?
|
|
} else {
|
|
_display->turnOn();
|
|
}
|
|
_auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer
|
|
} else if (ev == BUTTON_EVENT_LONG_PRESS) {
|
|
_display->turnOn();
|
|
Serial.println("Powering Off");
|
|
_powering_off_at = millis() + POWEROFF_DELAY;
|
|
}
|
|
#endif
|
|
|
|
#ifdef WITH_WEBCONFIG
|
|
// While the setup portal is up there's no user button to wake the screen
|
|
// reliably - keep it on so the join instructions stay visible.
|
|
if (WebConfigServer::getSetupInfo(NULL, 0, NULL, 0)) {
|
|
if (!_display->isOn()) _display->turnOn();
|
|
_auto_off = millis() + AUTO_OFF_MILLIS;
|
|
}
|
|
#endif
|
|
|
|
if (_display->isOn()) {
|
|
if (millis() >= _next_refresh) {
|
|
_display->startFrame();
|
|
renderCurrScreen();
|
|
_display->endFrame();
|
|
|
|
_next_refresh = millis() + 1000; // refresh every second
|
|
}
|
|
if (millis() > _auto_off) {
|
|
_display->turnOff();
|
|
}
|
|
}
|
|
|
|
if (_powering_off_at > 0) { // power off timer armed
|
|
#ifdef LED_PIN
|
|
digitalWrite(LED_PIN, LED_STATE_ON); // switch on the led until poweroff
|
|
#endif
|
|
if (millis() > _powering_off_at) {
|
|
_board->powerOff(); // should not return
|
|
}
|
|
}
|
|
}
|