Skip to content

Commit 8bbeeb1

Browse files
committed
feat: display device status on oled
1 parent 54e647e commit 8bbeeb1

6 files changed

Lines changed: 222 additions & 34 deletions

File tree

include/version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
#ifndef VERSION
3-
#define VERSION "dev.1770586580 - 2026-02-08 13:36:20.742165"
3+
#define VERSION "dev.1770607793 - 2026-02-08 19:29:53.255795"
44
#endif
55
#ifndef VERSION_SHORT
6-
#define VERSION_SHORT "dev.1770586580"
6+
#define VERSION_SHORT "dev.1770607793"
77
#endif

src/Device.cpp

Lines changed: 188 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ CDevice::CDevice() {
5454

5555
virtualCanvas->setTextSize(1);
5656
virtualCanvas->setCursor(0, 10);
57-
virtualCanvas->print("Init...");
57+
virtualCanvas->print("Starting up");
5858

5959
// Initialize scrolling
6060
scrollOffset = 0;
@@ -68,13 +68,21 @@ CDevice::CDevice() {
6868
showingTempMessage = false;
6969
tempMessageEndTime = 0;
7070

71+
// Boot progress
72+
bootProgress = 0;
73+
74+
// WiFi connected banner
75+
wifiConnectedShownAt = 0;
76+
wifiConnectedBannerDone = false;
77+
7178
// Calculate content bounds
7279
updateContentBounds();
7380

7481
tMillisDisplayToggle = millis();
7582
displayToggleState = false;
7683
wifiConnected = false;
7784
strcpy(wifiSSID, "");
85+
strcpy(wifiPass, "");
7886
strcpy(wifiIP, "");
7987
#endif
8088

@@ -86,9 +94,41 @@ void CDevice::setState(DeviceState state) {
8694
if (_state != state) {
8795
Log.infoln("Device state: %s -> %s", deviceStateToString(_state), deviceStateToString(state));
8896
_state = state;
97+
#ifdef OLED
98+
if (state == DeviceState::WIFI_CONNECTED) {
99+
wifiConnectedShownAt = millis();
100+
wifiConnectedBannerDone = false;
101+
lastTimeUpdate = 0; // Force time update after banner
102+
}
103+
#endif
89104
}
90105
}
91106

107+
void CDevice::setBootProgress(uint8_t percent) {
108+
#ifdef OLED
109+
if (percent > 100) percent = 100;
110+
bootProgress = percent;
111+
#endif
112+
}
113+
114+
void CDevice::setWifiAPInfo(const char* ssid, const char* password, const char* ip) {
115+
#ifdef OLED
116+
strncpy(wifiSSID, ssid, sizeof(wifiSSID) - 1);
117+
wifiSSID[sizeof(wifiSSID) - 1] = '\0';
118+
strncpy(wifiPass, password, sizeof(wifiPass) - 1);
119+
wifiPass[sizeof(wifiPass) - 1] = '\0';
120+
strncpy(wifiIP, ip, sizeof(wifiIP) - 1);
121+
wifiIP[sizeof(wifiIP) - 1] = '\0';
122+
#endif
123+
}
124+
125+
void CDevice::setWifiConnectedInfo(const char* ip) {
126+
#ifdef OLED
127+
strncpy(wifiIP, ip, sizeof(wifiIP) - 1);
128+
wifiIP[sizeof(wifiIP) - 1] = '\0';
129+
#endif
130+
}
131+
92132
CDevice::~CDevice() {
93133
#ifdef OLED
94134
if (virtualCanvas) {
@@ -108,36 +148,24 @@ void CDevice::loop() {
108148
// Check if temporary message has expired
109149
if (showingTempMessage && millis() >= tempMessageEndTime) {
110150
showingTempMessage = false;
111-
lastTimeUpdate = 0; // Force time update
151+
lastTimeUpdate = 0; // Force time update after temp message
112152
}
113153

114-
// Update time display once per minute (60000 ms) if not showing temp message
115-
if (_state == DeviceState::WIFI_CONNECTED && !showingTempMessage && millis() - lastTimeUpdate >= 60000) {
116-
struct tm timeinfo;
117-
lastTimeUpdate = millis();
118-
virtualCanvas->fillScreen(0);
119-
120-
if (getLocalTime(&timeinfo, 100)) { // Short timeout to avoid blocking when NTP is unavailable
121-
virtualCanvas->setTextColor(1); // White text
122-
virtualCanvas->setTextSize(2);
123-
124-
// Format time as HH:MM AM/PM
125-
int hour12 = timeinfo.tm_hour % 12;
126-
if (hour12 == 0) hour12 = 12; // Convert 0 to 12 for 12-hour format
127-
128-
char timeStr[16];
129-
snprintf(timeStr, sizeof(timeStr), "%02d:%02d", hour12, timeinfo.tm_min);
130-
int16_t textWidth = strlen(timeStr) * 12;
131-
132-
virtualCanvas->setCursor((72 - textWidth) / 2, 0);
133-
virtualCanvas->print(timeStr);
134-
virtualCanvas->setCursor(72 / 2 - 16, 16);
135-
virtualCanvas->print((timeinfo.tm_hour >= 12) ? "PM" : "AM");
136-
} else {
137-
Log.warningln("Failed to get local time for display update");
154+
// State-based rendering (only when not showing a temporary message)
155+
if (!showingTempMessage) {
156+
switch (_state) {
157+
case DeviceState::INITIALIZING:
158+
drawInitializing();
159+
break;
160+
case DeviceState::WIFI_AP_CREATED:
161+
drawWifiAP();
162+
break;
163+
case DeviceState::WIFI_CONNECTED:
164+
drawWifiConnected();
165+
break;
166+
default:
167+
break;
138168
}
139-
// Update content bounds after drawing
140-
updateContentBounds();
141169
}
142170

143171
// Update scroll position every 50ms
@@ -257,4 +285,136 @@ void CDevice::displayTemporaryMessage(const char* message, unsigned long duratio
257285
tempMessageEndTime = millis() + durationMs;
258286
#endif
259287
}
288+
289+
void CDevice::drawInitializing() {
290+
#ifdef CONFIG_IDF_TARGET_ESP32C3
291+
if (!virtualCanvas) return;
292+
293+
virtualCanvas->fillScreen(0);
294+
virtualCanvas->setTextColor(1);
295+
virtualCanvas->setTextSize(1); // 6x8 font
296+
297+
// "Starting up" centered
298+
const char* msg = "Starting up";
299+
int16_t textWidth = strlen(msg) * 6;
300+
virtualCanvas->setCursor((OLED_SCREEN_WIDTH - textWidth) / 2, 4);
301+
virtualCanvas->print(msg);
302+
303+
// Progress bar: 4px padding each side, 2px below text
304+
int16_t barX = 4;
305+
int16_t barY = 18;
306+
int16_t barW = OLED_SCREEN_WIDTH - 8;
307+
int16_t barH = 10;
308+
309+
// Outline
310+
virtualCanvas->drawRect(barX, barY, barW, barH, 1);
311+
312+
// Filled portion
313+
int16_t fillW = (int16_t)((barW - 2) * bootProgress / 100);
314+
if (fillW > 0) {
315+
virtualCanvas->fillRect(barX + 1, barY + 1, fillW, barH - 2, 1);
316+
}
317+
318+
updateContentBounds();
319+
#endif
320+
}
321+
322+
void CDevice::drawWifiAP() {
323+
#ifdef CONFIG_IDF_TARGET_ESP32C3
324+
if (!virtualCanvas) return;
325+
326+
virtualCanvas->fillScreen(0);
327+
virtualCanvas->setTextColor(1);
328+
virtualCanvas->setTextSize(1); // Smallest font (6x8)
329+
330+
// Line 1: "WiFi Created"
331+
332+
333+
// Line 2: SSID
334+
virtualCanvas->setCursor(0, 9);
335+
virtualCanvas->print(wifiSSID);
336+
337+
// Line 3: Password
338+
virtualCanvas->setCursor(0, 18);
339+
virtualCanvas->print(wifiPass);
340+
341+
// Line 4: IP address
342+
virtualCanvas->setCursor(0, 27);
343+
virtualCanvas->print(wifiIP);
344+
345+
updateContentBounds();
346+
#endif
347+
}
348+
349+
void CDevice::drawWifiConnected() {
350+
#ifdef CONFIG_IDF_TARGET_ESP32C3
351+
if (!virtualCanvas) return;
352+
353+
// Show "WiFi connected" + IP for 10 seconds, then switch to time
354+
if (!wifiConnectedBannerDone && millis() - wifiConnectedShownAt < 10000) {
355+
virtualCanvas->fillScreen(0);
356+
virtualCanvas->setTextColor(1);
357+
virtualCanvas->setTextSize(1);
358+
359+
const char* msg = "WiFi connected";
360+
virtualCanvas->setCursor(0, 0);
361+
virtualCanvas->print(msg);
362+
363+
virtualCanvas->setCursor(0, 9);
364+
virtualCanvas->print(wifiIP);
365+
366+
virtualCanvas->setCursor(0, 18);
367+
virtualCanvas->print("Web server ready");
368+
369+
updateContentBounds();
370+
} else {
371+
if (!wifiConnectedBannerDone) {
372+
wifiConnectedBannerDone = true;
373+
lastTimeUpdate = 0; // Force immediate time draw
374+
}
375+
drawTime();
376+
}
377+
#endif
378+
}
379+
380+
void CDevice::drawTime() {
381+
#ifdef CONFIG_IDF_TARGET_ESP32C3
382+
if (!virtualCanvas) return;
383+
384+
// Update once per minute
385+
if (millis() - lastTimeUpdate < 60000) return;
386+
lastTimeUpdate = millis();
387+
388+
virtualCanvas->fillScreen(0);
389+
390+
struct tm timeinfo;
391+
if (getLocalTime(&timeinfo, 100)) {
392+
virtualCanvas->setTextColor(1);
393+
virtualCanvas->setTextSize(2); // Large font for time
394+
395+
int hour12 = timeinfo.tm_hour % 12;
396+
if (hour12 == 0) hour12 = 12;
397+
398+
char timeStr[16];
399+
snprintf(timeStr, sizeof(timeStr), "%02d:%02d", hour12, timeinfo.tm_min);
400+
int16_t textWidth = strlen(timeStr) * 12; // textSize 2 = 12px per char
401+
402+
virtualCanvas->setCursor((OLED_SCREEN_WIDTH - textWidth) / 2, 0);
403+
virtualCanvas->print(timeStr);
404+
405+
// AM/PM below
406+
const char* ampm = (timeinfo.tm_hour >= 12) ? "PM" : "AM";
407+
int16_t ampmWidth = strlen(ampm) * 12;
408+
virtualCanvas->setCursor((OLED_SCREEN_WIDTH - ampmWidth) / 2, 20);
409+
virtualCanvas->print(ampm);
410+
} else {
411+
virtualCanvas->setTextColor(1);
412+
virtualCanvas->setTextSize(1);
413+
virtualCanvas->setCursor(0, 10);
414+
virtualCanvas->print("Time N/A");
415+
}
416+
417+
updateContentBounds();
418+
#endif
419+
}
260420
#endif

src/Device.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ class CDevice {
2828

2929
DeviceState getState() const { return _state; }
3030
void setState(DeviceState state);
31+
void setBootProgress(uint8_t percent); // 0-100
32+
33+
// Set WiFi info for OLED display (call before setState)
34+
void setWifiAPInfo(const char* ssid, const char* password, const char* ip);
35+
void setWifiConnectedInfo(const char* ip);
3136

3237
#ifdef OLED
3338
Adafruit_SSD1306 *_display;
@@ -45,10 +50,18 @@ class CDevice {
4550
#ifdef OLED
4651
unsigned long tMillisDisplayToggle;
4752
bool displayToggleState;
48-
char wifiSSID[32];
53+
char wifiSSID[64];
54+
char wifiPass[64];
4955
char wifiIP[32];
5056
bool wifiConnected;
5157

58+
// Boot progress bar
59+
uint8_t bootProgress; // 0-100
60+
61+
// WiFi connected display timing
62+
unsigned long wifiConnectedShownAt;
63+
bool wifiConnectedBannerDone;
64+
5265
// Virtual screen scrolling
5366
int16_t scrollOffset;
5467
int8_t scrollDirection;
@@ -65,5 +78,10 @@ class CDevice {
6578
static const int16_t HARDWARE_X_OFFSET = 28;
6679
static const int16_t HARDWARE_Y_OFFSET = 24;
6780
static const unsigned long SCROLL_PAUSE_MS = 500;
81+
82+
void drawInitializing();
83+
void drawWifiAP();
84+
void drawWifiConnected();
85+
void drawTime();
6886
#endif
6987
};

src/main.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@ void setup() {
5252
intLEDOn();
5353

5454
device = new CDevice();
55+
device->setBootProgress(20);
56+
5557
wifiManager = new CWifiManager();
5658
wifiManager->setDevice(device);
59+
device->setBootProgress(50);
5760

5861
ledManager = new CLEDManager();
5962
ledManager->setModeChangeCallback([]() {
@@ -69,10 +72,12 @@ void setup() {
6972
#endif
7073
});
7174
ledManager->setup();
75+
device->setBootProgress(80);
7276

7377
wifiManager->setModes(ledManager->getModes());
7478
wifiManager->updateModeChangeTime();
7579

80+
device->setBootProgress(100);
7681
Log.noticeln("Setup completed!");
7782
}
7883

src/wifi/HTMLAssets.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const char htmlBottom[] PROGMEM = R"=====(
6767
</main>
6868
<footer class="container">
6969
<small>Version %s</small>
70-
<small><a href="https://github.com/jaisor/ESP_LED_Controller">https://github.com/jaisor/ESP_LED_Controller</a>
70+
<small><a href="https://github.com/jaisor/ESP_LED_Controller/tree/led_headphone_stand">https://github.com/jaisor/ESP_LED_Controller/tree/led_headphone_stand</a>
7171
<small hidden="true">%s</small>
7272
</footer>
7373
</body>

src/wifi/WifiManager.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,9 @@ void CWifiManager::listen() {
260260
#ifdef OLED
261261
if (device) {
262262
if (isApMode()) {
263-
//device->displayApInfo(softAP_SSID, WIFI_FALLBACK_PASS, WiFi.softAPIP().toString().c_str());
263+
device->setWifiAPInfo(softAP_SSID, WIFI_FALLBACK_PASS, WiFi.softAPIP().toString().c_str());
264264
} else {
265-
//device->displayWifiInfo(SSID, WiFi.localIP().toString().c_str());
265+
device->setWifiConnectedInfo(WiFi.localIP().toString().c_str());
266266
}
267267
}
268268
#endif
@@ -301,6 +301,11 @@ void CWifiManager::loop() {
301301
if (status != WF_LISTENING) {
302302
// Start listening for requests
303303
if (device) {
304+
if (isApMode()) {
305+
device->setWifiAPInfo(softAP_SSID, WIFI_FALLBACK_PASS, WiFi.softAPIP().toString().c_str());
306+
} else {
307+
device->setWifiConnectedInfo(WiFi.localIP().toString().c_str());
308+
}
304309
device->setState(isApMode() ? DeviceState::WIFI_AP_CREATED : DeviceState::WIFI_CONNECTED);
305310
}
306311
listen();

0 commit comments

Comments
 (0)