implement a battery bar

This commit is contained in:
dj2ls
2026-06-08 10:20:58 +02:00
parent d6054b317a
commit e10bf85fc3
6 changed files with 75 additions and 11 deletions
+7
View File
@@ -85,6 +85,9 @@ bool UserConfig::parseJson(const String& json) {
_settings.touchSensitivity = doc["touch_sens"] | 3;
_settings.bleEnabled = false;
// battery settings
_settings.batteryDisplay = doc["batt_display"] | 0;
_settings.gpsTimeEnabled = doc["gps_time"] | true;
_settings.gpsLocationEnabled = doc["gps_location"] | false;
_settings.timezoneIdx = doc["tz_idx"] | 6;
@@ -157,6 +160,10 @@ String UserConfig::serializeToJson() const {
doc["touch_sens"] = _settings.touchSensitivity;
doc["ble_enabled"] = false;
// battery settings
doc["batt_display"] = _settings.batteryDisplay;
doc["gps_time"] = _settings.gpsTimeEnabled;
doc["gps_location"] = _settings.gpsLocationEnabled;
doc["tz_idx"] = _settings.timezoneIdx;
+3
View File
@@ -57,6 +57,9 @@ struct UserSettings {
uint8_t brightness = 100; // Percentage 1-100
bool denseFontMode = false; // T-Deck Plus: adaptive font toggle
// Battery
uint8_t batteryDisplay = 0; // 0 = percent, 1 = bar
// Keyboard
uint8_t keyboardBrightness = 100; // Percentage 0-100 (0 = off)
bool keyboardAutoOn = false; // Backlight ON when switching to ACTIVE power state
+6
View File
@@ -1244,6 +1244,11 @@ void setup() {
audio.setVolume(userConfig.settings().audioVolume);
audio.begin();
// Step 26: Battery init
ui.lvStatusBar().setBatteryDisplay(userConfig.settings().batteryDisplay);
// Boot complete — transition to Home screen
// Yield to LVGL instead of blocking delay
lvBootScreen.setProgress(0.98f, "Ready");
@@ -1907,6 +1912,7 @@ void loop() {
lastStatusUpdate = millis();
if (powerMgr.isScreenOn()) {
ui.lvStatusBar().setBatteryPercent(powerMgr.batteryPercent());
ui.lvStatusBar().setBatteryDisplay(userConfig.settings().batteryDisplay); // Switch between bar and percent
// Update TCP connection indicator
bool anyTcpUp = false;
for (auto* tcp : tcpClients) {
+42 -11
View File
@@ -54,6 +54,17 @@ void LvStatusBar::create(lv_obj_t* parent) {
lv_label_set_long_mode(_lblBatt, LV_LABEL_LONG_CLIP);
lv_obj_align(_lblBatt, LV_ALIGN_RIGHT_MID, -4, 0);
// Right: battery bar
_barBatt = lv_bar_create(_bar);
lv_obj_set_size(_barBatt, 20, 8);
lv_bar_set_range(_barBatt, 0, 100);
lv_bar_set_value(_barBatt, 0, LV_ANIM_OFF);
lv_obj_align(_barBatt, LV_ALIGN_RIGHT_MID, -4, 0);
lv_obj_set_style_bg_color(_barBatt, lv_color_hex(0x444444), LV_PART_MAIN);
lv_obj_set_style_bg_opa(_barBatt, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_bg_color(_barBatt, lv_color_hex(0xFFFFFF), LV_PART_INDICATOR);
lv_obj_set_style_bg_opa(_barBatt, LV_OPA_COVER, LV_PART_INDICATOR);
// Toast overlay (hidden by default). It is a child of the bar so boot mode
// and other shell visibility changes affect it with the status bar.
_toast = lv_obj_create(_bar);
@@ -185,6 +196,12 @@ void LvStatusBar::setBatteryPercent(int pct) {
refreshBattery();
}
void LvStatusBar::setBatteryDisplay(uint8_t mode) {
if (_battDisplay == mode) return;
_battDisplay = mode;
refreshBattery();
}
void LvStatusBar::flashAnnounce() {
_announceFlashEnd = millis() + 1000;
refreshIndicators();
@@ -224,21 +241,35 @@ void LvStatusBar::refreshIndicators() {
}
void LvStatusBar::refreshBattery() {
if (!_lblBatt) return;
if (!_lblBatt || !_barBatt) return;
if(_battDisplay == 1){
// Bar mode
lv_obj_clear_flag(_barBatt, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(_lblBatt, LV_OBJ_FLAG_HIDDEN);
lv_bar_set_value(_barBatt, _battPct < 0 ? 0 : _battPct, LV_ANIM_OFF);
char buf[8];
uint32_t col = Theme::TEXT_MUTED;
if (_battPct < 0) {
snprintf(buf, sizeof(buf), "--%%");
} else {
snprintf(buf, sizeof(buf), "%d%%", _battPct);
col = Theme::TEXT_PRIMARY;
if (_battPct <= 15) col = Theme::ERROR_CLR;
else if (_battPct <= 30) col = Theme::WARNING_CLR;
// Percent mode
lv_obj_clear_flag(_lblBatt, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(_barBatt, LV_OBJ_FLAG_HIDDEN);
char buf[8];
uint32_t col = Theme::TEXT_MUTED;
if (_battPct < 0) {
snprintf(buf, sizeof(buf), "--%%");
} else {
snprintf(buf, sizeof(buf), "%d%%", _battPct);
col = Theme::TEXT_PRIMARY;
if (_battPct <= 15) col = Theme::ERROR_CLR;
else if (_battPct <= 30) col = Theme::WARNING_CLR;
}
lv_label_set_text(_lblBatt, buf);
lv_obj_set_style_text_color(_lblBatt, lv_color_hex(col), 0);
}
lv_label_set_text(_lblBatt, buf);
lv_obj_set_style_text_color(_lblBatt, lv_color_hex(col), 0);
}
void LvStatusBar::refreshTimeColor() {
+4
View File
@@ -19,6 +19,7 @@ public:
void setAutoIfacePeers(int n);
void setGPSFix(bool hasFix);
void setBatteryPercent(int pct);
void setBatteryDisplay(uint8_t mode); // 0 = percent, 1 = bar
void flashAnnounce();
void showToast(const char* msg, uint32_t durationMs = 1500);
@@ -37,6 +38,7 @@ private:
lv_obj_t* _lblTime = nullptr; // Left: current time
lv_obj_t* _lblLinks = nullptr; // Center: brand/status text
lv_obj_t* _lblBatt = nullptr; // Right: battery %
lv_obj_t* _barBatt = nullptr; // Right: Battery bar
lv_obj_t* _toast = nullptr;
lv_obj_t* _lblToast = nullptr;
@@ -51,6 +53,8 @@ private:
bool _gpsFix = false;
bool _use24h = false;
int _battPct = -1;
uint8_t _battDisplay = 0;
int _lastHour = -1;
int _lastMinute = -1;
unsigned long _announceFlashEnd = 0;
+13
View File
@@ -514,6 +514,19 @@ void LvSettingsScreen::buildItems() {
return summary;
}});
// Battery
int battStart = idx;
_items.push_back({"Battery Display", SettingType::ENUM_CHOICE,
[&s]() { return (int)s.batteryDisplay; },
[&s](int v) { s.batteryDisplay = (uint8_t)v; },
nullptr, 0, 1, 1, {"Percent", "Bar"}});
idx++;
_categories.push_back({"Battery", battStart, idx - battStart,
[&s]() -> String {
return s.batteryDisplay == 0 ? String("Percent") : String("Bar");
}});
// LoRa link
int radioStart = idx;
_items.push_back({"LoRa Radio", SettingType::TOGGLE,