Watch the feed by the declared keepalive and HA by the API link (0.2.26)
Since 0.2.20 the manager repeats a layout every 120 s, while the firmware
treated anything older than 95 s (sized for the original 25 s keepalive) as
stale: on a quiet screen every card read "Niet beschikbaar" and the header
"HA niet verbonden" for 25-45 s of each two-minute round, on both boards.
"HA niet verbonden" now follows ESPHome's own api_is_connected(); the feed
watchdog uses the cadence the layout message declares ("keepalive", seconds,
120 s when absent) and tolerates one missed round plus loop slack before
showing "ESP Screens niet actief". The tick redraws once when either flips.
Firmware 0.2.22 for CYD and Guition.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "esphome/components/json/json_util.h"
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/util.h"
|
||||
#include "esphome/core/time.h"
|
||||
#include "lvgl.h"
|
||||
#include <functional>
|
||||
@@ -42,6 +43,9 @@ inline std::string timer_text(const Tile &t);
|
||||
inline std::string last_run_text(uint32_t epoch);
|
||||
inline int active_index = -1;
|
||||
inline uint32_t last_received = 0;
|
||||
// Seconds between the manager's full repeats; every layout message declares it (app
|
||||
// 0.2.26+). Older managers get the 120 s that app 0.2.20 introduced.
|
||||
inline uint32_t keepalive_seconds = 120;
|
||||
inline std::function<void()> layout_changed, refresh, dismiss, settings_changed;
|
||||
inline esphome::ESPPreferenceObject settings_preference;
|
||||
inline void load_settings() {
|
||||
@@ -98,7 +102,13 @@ inline bool has_icon_glyph(uint32_t codepoint) {
|
||||
for (auto &w : widgets) if (w.icon_font) { lv_font_glyph_dsc_t dsc; return lv_font_get_glyph_dsc(w.icon_font, &dsc, codepoint, 0); }
|
||||
return false;
|
||||
}
|
||||
inline bool fresh() { return model.ready() && esphome::millis() - last_received < 95000; }
|
||||
// Home Assistant's API link as ESPHome itself tracks it: gone the moment the socket drops,
|
||||
// back the moment HA reconnects, no guessing from message age.
|
||||
inline bool ha_connected() { return esphome::api_is_connected(); }
|
||||
// The manager repeats the whole layout every keepalive; one missed round plus its 20 s
|
||||
// loop slack and the sending itself are tolerated before the feed counts as gone.
|
||||
inline bool feed_alive() { return esphome::millis() - last_received < keepalive_seconds * 2000 + 60000; }
|
||||
inline bool fresh() { return model.ready() && ha_connected() && feed_alive(); }
|
||||
inline float number(JsonVariant value, float fallback = NAN) {
|
||||
if (!value.is<float>() && !value.is<int>()) return fallback;
|
||||
float n = value.as<float>();
|
||||
@@ -141,6 +151,8 @@ inline std::string receive(const std::string &payload) {
|
||||
if(!root["swipe_pages"].isNull() && !root["swipe_pages"].is<bool>())return false;
|
||||
if(!root["rotation"].isNull() && (!root["rotation"].is<unsigned>() ||
|
||||
root["rotation"].as<unsigned>()>270 || root["rotation"].as<unsigned>()%90!=0))return false;
|
||||
if(!root["keepalive"].isNull() && (!root["keepalive"].is<unsigned>() ||
|
||||
root["keepalive"].as<unsigned>()<5 || root["keepalive"].as<unsigned>()>3600))return false;
|
||||
inbox = string(root["inbox"], 160);
|
||||
bool changed = false;
|
||||
if (!model.set_layout(entities, string(root["title"], 96), changed)) return false;
|
||||
@@ -158,6 +170,7 @@ inline std::string receive(const std::string &payload) {
|
||||
}
|
||||
if(rotation_changed && settings_changed)settings_changed();
|
||||
if (changed) { active_index = -1; for (auto &w : widgets) w.cached_active = -1; if (dismiss) dismiss(); }
|
||||
if (root["keepalive"].is<unsigned>()) keepalive_seconds = root["keepalive"].as<unsigned>();
|
||||
last_received = esphome::millis();
|
||||
if (layout_changed) layout_changed();
|
||||
if (refresh) refresh();
|
||||
@@ -1255,7 +1268,7 @@ inline void set_busy(Widgets &w,bool busy,bool large){
|
||||
inline void render(lv_obj_t *room) {
|
||||
if (!enabled) return;
|
||||
room_label=room;
|
||||
label(room, !model.configured ? "Kies tegels in HA" : !model.ready() ? "Tegels laden..." : !fresh() ? "HA niet verbonden" : model.title);
|
||||
label(room, !model.configured ? "Kies tegels in HA" : !model.ready() ? "Tegels laden..." : !ha_connected() ? "HA niet verbonden" : !feed_alive() ? "ESP Screens niet actief" : model.title);
|
||||
for (size_t slot = 0; slot < 6; ++slot) {
|
||||
auto &w=widgets[slot];
|
||||
if(!w.tile || w.index>=model.count)continue;
|
||||
@@ -1549,6 +1562,7 @@ inline void show_page(int &page, lv_obj_t *previous, lv_obj_t *next, lv_obj_t *n
|
||||
}
|
||||
|
||||
inline uint32_t last_live_second=0;
|
||||
inline bool was_fresh=false;
|
||||
inline void tick() {
|
||||
if(detail_root && !lv_obj_has_flag(detail_root,LV_OBJ_FLAG_HIDDEN) && detail_index<model.count){
|
||||
auto &t=model.tiles[detail_index];bool waiting=t.awaiting_action(esphome::millis());
|
||||
@@ -1563,6 +1577,9 @@ inline void tick() {
|
||||
}
|
||||
if(!enabled)return;
|
||||
bool redraw=false;
|
||||
// HA dropping or returning and the feed timing out change every card at once.
|
||||
bool now_fresh=fresh();
|
||||
if(now_fresh!=was_fresh){was_fresh=now_fresh;redraw=true;}
|
||||
for(auto &t:model.tiles)if(t.pending && !t.loading(esphome::millis())){t.pending=false;redraw=true;}
|
||||
// A -/+ edit goes out as one call once the finger rests; a value HA never reports is dropped after a while.
|
||||
for(size_t i=0;i<model.count;++i){
|
||||
|
||||
+4
-2
@@ -137,8 +137,10 @@ alleen hun waarde; detailmenu’s en standby wisselen niet van pagina.
|
||||
|
||||
Er staan zes tegels op een pagina. Bij maximaal zes verdwijnen Vorige/Volgende.
|
||||
De standby-tijd is standaard tien minuten. Bij offline apparaten blokkeert het
|
||||
scherm acties. Als de app/HA langer dan circa 95 seconden geen updates geeft,
|
||||
wordt de bediening geblokkeerd totdat de gegevens opnieuw ontvangen zijn.
|
||||
scherm acties. Valt de verbinding met Home Assistant weg, dan meldt het scherm
|
||||
direct "HA niet verbonden"; stuurt de app twee rondes (circa vijf minuten) niets,
|
||||
dan "ESP Screens niet actief". In beide gevallen is de bediening geblokkeerd
|
||||
totdat de gegevens opnieuw ontvangen zijn.
|
||||
|
||||
Je mag indelingen opslaan terwijl een scherm offline is. De app verstuurt ze
|
||||
zodra het scherm terugkomt. De app moet blijven draaien voor actuele tegeldata.
|
||||
|
||||
@@ -177,6 +177,20 @@ staan iconen in de browser uit het midden); draai daarna `generate_packages.py`.
|
||||
De substituties `MDI_GLYPH_*` zijn vervallen: `TILEn_ICON` in handmatige
|
||||
profielen moet uit de set komen. Geen gewijzigde preferences of sleutels.
|
||||
|
||||
### Compatibiliteit 0.2.26 / firmware 0.2.22
|
||||
|
||||
Opslagversie en tegelprotocol blijven 1. Het layoutbericht krijgt het additieve veld
|
||||
`keepalive` (seconden, 5–3600): het interval waarin de app de hele indeling herhaalt
|
||||
(`KEEPALIVE_SECONDS` in `server.py`, 120 s sinds 0.2.20). De firmware leidt daar zijn
|
||||
bewaking van de gegevensstroom uit af (twee rondes plus 60 s) en meldt daarna
|
||||
"ESP Screens niet actief"; "HA niet verbonden" komt nu van ESPHome's eigen
|
||||
API-verbindingsstatus (`api_is_connected()`), niet meer uit de leeftijd van het laatste
|
||||
bericht. Zonder het veld rekent firmware 0.2.22 met 120 s; firmware tot 0.2.21 negeert
|
||||
het veld en houdt zijn vaste 95 s, wat met een keepalive van 120 s de bekende
|
||||
"HA niet verbonden"-flikkering geeft. Verander `KEEPALIVE_SECONDS` daarom alleen samen
|
||||
met een firmwareflash van bestaande schermen, of houd hem onder 40 s. Geen gewijzigde
|
||||
preferences of sleutels.
|
||||
|
||||
### Compatibiliteit 0.2.24 / firmware 0.2.20
|
||||
|
||||
Alleen intern: `Tile::forecast` en `Tile::hours` zijn vectoren (voorheen vaste arrays in
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Guition ESP32-S3-4848S040 / 4-inch EU wallbox, 480x480 IPS + GT911.
|
||||
# Use guition-device.yaml; see docs/GUITION.md. CYD hardware is a separate profile.
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.21"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.22"
|
||||
DYNAMIC_TILES: "false"
|
||||
DASHBOARD_INBOX_INTERNAL: "true"
|
||||
DEVICE_NAME: "guition-wallbox"
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
############################################################
|
||||
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.21"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.22"
|
||||
DYNAMIC_TILES: "false"
|
||||
DASHBOARD_INBOX_INTERNAL: "true"
|
||||
DEVICE_NAME: "cyd-new"
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@
|
||||
############################################################
|
||||
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.21"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.22"
|
||||
DYNAMIC_TILES: "true"
|
||||
DASHBOARD_INBOX_INTERNAL: "false"
|
||||
DEVICE_NAME: "cyd-new"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Guition ESP32-S3-4848S040 / 4-inch EU wallbox, 480x480 IPS + GT911.
|
||||
# Use guition-device.yaml; see docs/GUITION.md. CYD hardware is a separate profile.
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.21"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.22"
|
||||
DYNAMIC_TILES: "true"
|
||||
DASHBOARD_INBOX_INTERNAL: "false"
|
||||
DEVICE_NAME: "guition-new"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.2.26 (firmware 0.2.22)
|
||||
|
||||
- **"HA niet verbonden" om de twee minuten opgelost**: sinds 0.2.20 herhaalt de app de indeling elke 120 s, maar de firmware verwachtte binnen 95 s een bericht (gemaakt voor de oude 25 s). Op een rustig scherm stonden alle tegels daardoor 25 tot 45 s per ronde op "Niet beschikbaar". De firmware gebruikt nu ESPHome's eigen API-verbindingsstatus voor "HA niet verbonden" (direct bij wegvallen en terugkeren van Home Assistant) en bewaakt de gegevensstroom apart met het interval dat de app zelf declareert: het layoutbericht bevat `keepalive` (seconden). Pas na twee gemiste rondes plus marge meldt het scherm "ESP Screens niet actief". Zonder het veld (oudere app) rekent de firmware met 120 s. Firmware 0.2.22 voor beide borden; firmware tot 0.2.21 negeert het veld en houdt zijn 95 s.
|
||||
|
||||
## 0.2.25 (firmware 0.2.21)
|
||||
|
||||
- **− / + in één beweging**: snel drie keer tikken telt drie stappen (van 20 naar 17); de touch-guard hield een tweede tik op dezelfde knop binnen 600 ms tegen. De − / + knoppen gebruiken nu een eigen korte guard (150 ms, alleen tegen stuiteren) en stappen ook door zolang je ze vasthoudt (drie per seconde). Na 700 ms rust gaat nog steeds één opdracht naar Home Assistant.
|
||||
|
||||
@@ -16,7 +16,7 @@ WEEKDAYS = ['ma', 'di', 'wo', 'do', 'vr', 'za', 'zo']
|
||||
REPO = 'https://github.com/MaxGramser/homeassistant_espscreen'
|
||||
REFS = {'cyd': 'main', 'guition': 'main'}
|
||||
# Firmware shipped with this app release; screens below it get an update offer.
|
||||
FIRMWARE_VERSION = '0.2.21'
|
||||
FIRMWARE_VERSION = '0.2.22'
|
||||
ATTRS = frozenset('brightness percentage current_position current_temperature temperature current_humidity min_temp max_temp target_temp_step supported_color_modes hvac_modes hvac_action hs_color color_temp_kelvin min_color_temp_kelvin max_color_temp_kelvin fan_speed_list unit_of_measurement battery_level fan_speed volume_level is_volume_muted media_title options min max step temperature_unit supported_features device_class next_rising next_setting finishes_at duration remaining humidity wind_speed wind_speed_unit apparent_temperature fan_modes swing_modes fan_mode swing_mode'.split())
|
||||
# Attributes whose boolean value the screen needs; every other bool stays behind.
|
||||
BOOL_ATTRS = frozenset(['is_volume_muted'])
|
||||
|
||||
@@ -21,6 +21,8 @@ LOG = logging.getLogger('screen_manager')
|
||||
|
||||
REGISTRY_EVENTS = ('entity_registry_updated', 'device_registry_updated', 'area_registry_updated')
|
||||
SCREEN_ENTITY_NAMES = {'Tegelinstellingen', 'Schermfirmware', 'Guition schermtype', 'Apparaatnaam', 'IP-adres'}
|
||||
# Full repeat of a screen's layout and states. Every layout message declares it, so the
|
||||
# firmware sizes its feed watchdog from this one constant (firmware 0.2.22+).
|
||||
KEEPALIVE_SECONDS = 120
|
||||
|
||||
class HomeAssistant:
|
||||
@@ -312,7 +314,8 @@ class Manager:
|
||||
if needed:
|
||||
self.status[inbox]=f"Indeling bewaard; firmware {needed}+ nodig voor deze tegels"
|
||||
return
|
||||
messages = [{'v': 1, 'op': 'layout', 'inbox': inbox, 'title': layout['title'], 'entities': [t['entity'] for t in layout['tiles']]}]
|
||||
messages = [{'v': 1, 'op': 'layout', 'inbox': inbox, 'title': layout['title'], 'entities': [t['entity'] for t in layout['tiles']],
|
||||
'keepalive': KEEPALIVE_SECONDS}]
|
||||
if 'settings' in layout:
|
||||
messages[0]['settings'] = {k:v for k,v in layout['settings'].items() if k not in ('swipe_pages','rotation')}
|
||||
messages[0]['swipe_pages'] = layout['settings'].get('swipe_pages',False)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: ESP Screen Manager
|
||||
version: "0.2.25"
|
||||
version: "0.2.26"
|
||||
slug: esp_screen_manager
|
||||
description: Kies tegels voor je CYD en Guition touchscreen, zonder opnieuw flashen.
|
||||
url: https://github.com/MaxGramser/homeassistant_espscreen
|
||||
|
||||
@@ -5,6 +5,7 @@ import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'screen_manager/app'))
|
||||
from server import KEEPALIVE_SECONDS
|
||||
from core import validate_layout, state_message, packets
|
||||
from firmware import Firmware
|
||||
from test_portal import ManagerTests
|
||||
@@ -101,6 +102,7 @@ class SpecialTileSync(unittest.IsolatedAsyncioTestCase):
|
||||
await m.sync_one('text.screen',m.layouts['text.screen'])
|
||||
sent=[message for _,message in m.ha.messages]
|
||||
self.assertEqual(sent[0]['entities'],['screen.clock','sun.sun'])
|
||||
self.assertEqual(sent[0]['keepalive'],KEEPALIVE_SECONDS,'the screen sizes its feed watchdog from the declared cadence')
|
||||
self.assertEqual((sent[1]['state'],sent[1]['name']),('ok','Klok'))
|
||||
self.assertEqual(sent[2]['x'],{'rise':'05:15','set':'17:50'},'fake HA has no time zone: UTC')
|
||||
m.ha.states['sensor.screen_firmware']={'state':'0.2.13'};m.ha.messages.clear()
|
||||
|
||||
Reference in New Issue
Block a user