Add persistent per-screen brightness, standby and clock settings
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "runtime_model.h"
|
||||
#include "screen_settings.h"
|
||||
#include "esphome/core/preferences.h"
|
||||
#include "cyd_ui.h"
|
||||
#include "light_controls.h"
|
||||
#include "esphome/components/json/json_util.h"
|
||||
@@ -14,7 +16,30 @@ inline bool enabled = false;
|
||||
inline Model model;
|
||||
inline int active_index = -1;
|
||||
inline uint32_t last_received = 0;
|
||||
inline std::function<void()> layout_changed, refresh, dismiss;
|
||||
inline std::function<void()> layout_changed, refresh, dismiss, settings_changed;
|
||||
inline esphome::ESPPreferenceObject settings_preference;
|
||||
inline void load_settings() {
|
||||
settings_preference = esphome::global_preferences->make_preference<screen_settings::Settings>(0x53435231);
|
||||
screen_settings::Settings saved;
|
||||
if (settings_preference.load(&saved) && saved.valid()) screen_settings::current = saved;
|
||||
}
|
||||
inline bool parse_settings(JsonObject obj, screen_settings::Settings &s) {
|
||||
// Require the complete known schema; validate before touching any runtime state.
|
||||
if (obj.size() != 11) return false;
|
||||
const char *flags[] = {"standby_enabled", "night_enabled", "show_clock", "clock_24h", "home_on_standby"};
|
||||
int32_t *flag_values[] = {&s.standby_enabled, &s.night_enabled, &s.show_clock, &s.clock_24h, &s.home_on_standby};
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (!obj[flags[i]].is<bool>()) return false;
|
||||
*flag_values[i] = obj[flags[i]].as<bool>();
|
||||
}
|
||||
const char *numbers[] = {"standby_seconds", "brightness", "standby_brightness", "night_start", "night_end", "night_brightness"};
|
||||
int32_t *values[] = {&s.standby_seconds, &s.brightness, &s.standby_brightness, &s.night_start, &s.night_end, &s.night_brightness};
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
if (!obj[numbers[i]].is<int>() || obj[numbers[i]].is<bool>()) return false;
|
||||
*values[i] = obj[numbers[i]].as<int>();
|
||||
}
|
||||
return s.valid();
|
||||
}
|
||||
inline std::function<void(Tile &)> detail, detail_update;
|
||||
struct Widgets { lv_obj_t *tile{}, *title{}, *value{}, *circle{}, *icon{}; size_t index{}; int cached_active = -1; };
|
||||
inline std::array<Widgets, MAX_TILES> widgets;
|
||||
@@ -48,6 +73,11 @@ inline std::string receive(const std::string &payload) {
|
||||
auto op = string(root["op"]);
|
||||
if (op == "layout") {
|
||||
if (!root["entities"].is<JsonArray>() || !root["title"].is<const char *>()) return false;
|
||||
auto settings = screen_settings::current;
|
||||
if (!root["settings"].isNull() && (!root["settings"].is<JsonObject>() ||
|
||||
!parse_settings(root["settings"].as<JsonObject>(), settings))) {
|
||||
result = "Fout: scherminstellingen"; return false;
|
||||
}
|
||||
std::vector<std::string> entities;
|
||||
for (JsonVariant entity : root["entities"].as<JsonArray>()) {
|
||||
if (!entity.is<const char *>() || entities.size() == MAX_TILES) return false;
|
||||
@@ -55,6 +85,11 @@ inline std::string receive(const std::string &payload) {
|
||||
}
|
||||
bool changed = false;
|
||||
if (!model.set_layout(entities, string(root["title"], 96), changed)) return false;
|
||||
if (!(settings == screen_settings::current)) {
|
||||
screen_settings::current = settings;
|
||||
settings_preference.save(&settings); // ESPHome batches flash writes; no write on keepalive.
|
||||
if (settings_changed) settings_changed();
|
||||
}
|
||||
if (changed) { active_index = -1; for (auto &w : widgets) w.cached_active = -1; if (dismiss) dismiss(); }
|
||||
last_received = esphome::millis();
|
||||
if (layout_changed) layout_changed();
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace screen_settings {
|
||||
// Stable preference format. Change its version/key only with a migration.
|
||||
struct Settings {
|
||||
uint32_t version = 1;
|
||||
int32_t standby_enabled = 1, standby_seconds = 600, brightness = 100;
|
||||
int32_t standby_brightness = 20, night_enabled = 1, night_start = 1320;
|
||||
int32_t night_end = 420, night_brightness = 10, show_clock = 1;
|
||||
int32_t clock_24h = 1, home_on_standby = 0;
|
||||
bool valid() const {
|
||||
return version == 1 && (standby_enabled == 0 || standby_enabled == 1) &&
|
||||
standby_seconds >= 60 && standby_seconds <= 86400 &&
|
||||
brightness >= 5 && brightness <= 100 && standby_brightness >= 0 &&
|
||||
standby_brightness <= brightness && (night_enabled == 0 || night_enabled == 1) &&
|
||||
night_start >= 0 && night_start < 1440 && night_end >= 0 && night_end < 1440 &&
|
||||
night_brightness >= 0 && night_brightness <= brightness &&
|
||||
(show_clock == 0 || show_clock == 1) && (clock_24h == 0 || clock_24h == 1) &&
|
||||
(home_on_standby == 0 || home_on_standby == 1);
|
||||
}
|
||||
bool operator==(const Settings &b) const {
|
||||
return version == b.version && standby_enabled == b.standby_enabled &&
|
||||
standby_seconds == b.standby_seconds && brightness == b.brightness &&
|
||||
standby_brightness == b.standby_brightness && night_enabled == b.night_enabled &&
|
||||
night_start == b.night_start && night_end == b.night_end &&
|
||||
night_brightness == b.night_brightness && show_clock == b.show_clock &&
|
||||
clock_24h == b.clock_24h && home_on_standby == b.home_on_standby;
|
||||
}
|
||||
bool night(int minute) const {
|
||||
if (!night_enabled || minute < 0 || minute >= 1440 || night_start == night_end) return false;
|
||||
return night_start < night_end ? minute >= night_start && minute < night_end
|
||||
: minute >= night_start || minute < night_end;
|
||||
}
|
||||
int dim_level(int minute) const { return night(minute) ? night_brightness : standby_brightness; }
|
||||
};
|
||||
inline Settings current;
|
||||
}
|
||||
Reference in New Issue
Block a user