From ea7bf3387bdcbcdfa89b251d070a52cef3d8afb5 Mon Sep 17 00:00:00 2001 From: Max Gramser Date: Sun, 13 Sep 2026 15:20:38 +0200 Subject: [PATCH] Rapid -/+ taps and hold-to-repeat on the setpoint pill (0.2.25) App 0.2.25 / firmware 0.2.21. The 600 ms touch-guard lockout dropped a second tap on the same -/+ key; stepper keys now use a 150 ms bounce guard, repeat while held (3 per second), and still send one call after 700 ms of rest. Co-Authored-By: Claude Fable 5.1 --- components/smart_display/cyd_ui.h | 11 +++++++++++ components/smart_display/runtime_tiles.h | 14 ++++++++++---- docs/TEST_RESULTS_0224.md | 8 ++++++++ guition-4848s040.yaml | 2 +- home-like-2432s028.yaml | 2 +- packages/cyd.yaml | 2 +- packages/guition.yaml | 2 +- screen_manager/CHANGELOG.md | 4 ++++ screen_manager/app/core.py | 2 +- screen_manager/config.yaml | 2 +- tests/test_cyd_ui.cpp | 7 +++++++ 11 files changed, 46 insertions(+), 10 deletions(-) diff --git a/components/smart_display/cyd_ui.h b/components/smart_display/cyd_ui.h index aa64efd..cd705b1 100644 --- a/components/smart_display/cyd_ui.h +++ b/components/smart_display/cyd_ui.h @@ -42,6 +42,17 @@ class TouchGuard { bool accept(uint32_t now, int tile) { return !moved_ && accept_slider(now, tile); } + // For -/+ keys: every clean tap counts, even the third within a second, so a + // setpoint moves several steps in one go. Only bounce (same key within `gap`) is dropped. + bool accept_repeat(uint32_t now, int tile, uint32_t gap = 150) { + if (moved_ || accepted_ || now - started_ < 40) return false; + if (has_previous_ && tile == previous_tile_ && now - previous_ < gap) return false; + accepted_ = true; + has_previous_ = true; + previous_tile_ = tile; + previous_ = now; + return true; + } // Only for a slider which captured this contact and did not lose the press. // Consume the gesture so its parent can never also turn it into a tile tap. bool accept_slider(uint32_t now, int tile) { diff --git a/components/smart_display/runtime_tiles.h b/components/smart_display/runtime_tiles.h index e19b931..f266055 100644 --- a/components/smart_display/runtime_tiles.h +++ b/components/smart_display/runtime_tiles.h @@ -1086,6 +1086,8 @@ inline int layout_panel(Widgets &w,const Tile &t,bool large,int content_w,int co lv_obj_set_style_radius(w.pill,LV_RADIUS_CIRCLE,0);lv_obj_set_style_bg_opa(w.pill,LV_OPA_COVER,0); panel_key(w,0,w.pill,m,m.pill_key,m.key_h+2,true);panel_icon(w,0,icon_font);lv_label_set_text(w.key_icons[0],tile_controls::glyph::MINUS); panel_key(w,1,w.pill,m,m.pill_key,m.key_h+2,true);panel_icon(w,1,icon_font);lv_label_set_text(w.key_icons[1],tile_controls::glyph::PLUS); + // Holding -/+ keeps stepping (LVGL repeats while pressed); one call goes out after the finger rests. + for(unsigned n=0;n<2;++n)lv_obj_add_event_cb(w.keys[n],control_event,LV_EVENT_LONG_PRESSED_REPEAT,(void*)(uintptr_t)((&w-widgets.data())*16+n)); lv_obj_set_pos(w.keys[0],0,0);lv_obj_set_pos(w.keys[1],m.pill_w-m.pill_key,0); w.pill_value=lv_label_create(w.pill);lv_obj_remove_flag(w.pill_value,LV_OBJ_FLAG_CLICKABLE); lv_obj_set_style_text_font(w.pill_value,text_font,0);lv_obj_set_style_text_align(w.pill_value,LV_TEXT_ALIGN_CENTER,0); @@ -1207,12 +1209,16 @@ inline void control_event(lv_event_t *e) { if(!enabled || !fresh() || w.index>=model.count || !w.keys[n])return; if(lv_obj_has_state(w.keys[n],LV_STATE_DISABLED))return; uint32_t now=esphome::millis(); - if(!cyd::touch_guard.accept(now,400+slot*16+n))return; auto &t=model.tiles[w.index]; - if(!t.available())return; int command=w.key_commands[n]; - if(command==tile_controls::STEP_DOWN || command==tile_controls::STEP_UP){ - // Local at once; tick() sends the last value after a short pause. + bool step=command==tile_controls::STEP_DOWN || command==tile_controls::STEP_UP; + bool held=lv_event_get_code(e)==LV_EVENT_LONG_PRESSED_REPEAT; + if(held){ if(!step || now-t.edit_since<300)return; } // three steps a second while holding + else if(step){ if(!cyd::touch_guard.accept_repeat(now,400+slot*16+n))return; } + else if(!cyd::touch_guard.accept(now,400+slot*16+n))return; + if(!t.available())return; + if(step){ + // Local at once, tap after tap; tick() sends the last value after a short pause. float current=std::isfinite(t.edit_value)?t.edit_value:tile_controls::edit_target(t); t.edit_value=tile_controls::step_value(current,tile_controls::edit_step(t),t.minimum,t.maximum,command==tile_controls::STEP_UP?1:-1); t.edit_since=now;t.edit_sent=false; diff --git a/docs/TEST_RESULTS_0224.md b/docs/TEST_RESULTS_0224.md index feda47a..73fa285 100644 --- a/docs/TEST_RESULTS_0224.md +++ b/docs/TEST_RESULTS_0224.md @@ -27,3 +27,11 @@ greep op de mini-slider, CYD-kaarten in het lichte palet, wifi zonder modem-slaa - Guition en CYD `ui_self_test` met `send_layout.py --controls` (18 tegels): 10/10 PASS, geen geometrie-, paneel- of paletfouten. - Nog fysiek te bekijken door Max: greep op de mini-slider, CYD-lichtkaart in het lichte palet. + +## Aanvulling 0.2.25 / firmware 0.2.21 + +- − / + accepteert snelle opeenvolgende tikken (eigen guard van 150 ms) en stapt door bij + vasthouden; `tests/test_cyd_ui.cpp` dekt `accept_repeat`. Python 82 OK, C++ 11 PASS. +- Beide borden via OTA op 0.2.21; `ui_self_test` met de 18-tegels demo 10/10 PASS + (Guition heap 6,35 MB, CYD 37–38 KB vrij). Fysiek: drie keer tikken van 20 naar 17 en + vasthouden te controleren door Max. diff --git a/guition-4848s040.yaml b/guition-4848s040.yaml index 3b3e1ab..f807b80 100644 --- a/guition-4848s040.yaml +++ b/guition-4848s040.yaml @@ -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.20" + SCREEN_FIRMWARE_VERSION: "0.2.21" DYNAMIC_TILES: "false" DASHBOARD_INBOX_INTERNAL: "true" DEVICE_NAME: "guition-wallbox" diff --git a/home-like-2432s028.yaml b/home-like-2432s028.yaml index 9765829..4c771e3 100644 --- a/home-like-2432s028.yaml +++ b/home-like-2432s028.yaml @@ -58,7 +58,7 @@ ############################################################ substitutions: - SCREEN_FIRMWARE_VERSION: "0.2.20" + SCREEN_FIRMWARE_VERSION: "0.2.21" DYNAMIC_TILES: "false" DASHBOARD_INBOX_INTERNAL: "true" DEVICE_NAME: "cyd-new" diff --git a/packages/cyd.yaml b/packages/cyd.yaml index 28b5734..3ba7924 100644 --- a/packages/cyd.yaml +++ b/packages/cyd.yaml @@ -59,7 +59,7 @@ ############################################################ substitutions: - SCREEN_FIRMWARE_VERSION: "0.2.20" + SCREEN_FIRMWARE_VERSION: "0.2.21" DYNAMIC_TILES: "true" DASHBOARD_INBOX_INTERNAL: "false" DEVICE_NAME: "cyd-new" diff --git a/packages/guition.yaml b/packages/guition.yaml index 68c4daa..c6d8b84 100644 --- a/packages/guition.yaml +++ b/packages/guition.yaml @@ -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.20" + SCREEN_FIRMWARE_VERSION: "0.2.21" DYNAMIC_TILES: "true" DASHBOARD_INBOX_INTERNAL: "false" DEVICE_NAME: "guition-new" diff --git a/screen_manager/CHANGELOG.md b/screen_manager/CHANGELOG.md index b2924cc..094b393 100644 --- a/screen_manager/CHANGELOG.md +++ b/screen_manager/CHANGELOG.md @@ -1,3 +1,7 @@ +## 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. + ## 0.2.24 (firmware 0.2.20) - **Lichter en zuiniger**: de dag- en uurvoorspelling zitten alleen nog in het geheugen van weertegels (was 832 bytes in elk van de twintig tegels, ruim 16 KB op de CYD zonder PSRAM). De mini-slider onderin een tegel (**Kleine slider**) heeft nu dezelfde zichtbare witte greep als de nieuwe schuiven. De licht-, ventilator- en zonweringkaart op de CYD gebruiken het lichte palet van de Guition (de laatste rest van het donkere thema). diff --git a/screen_manager/app/core.py b/screen_manager/app/core.py index 5a052ba..5b5c94c 100644 --- a/screen_manager/app/core.py +++ b/screen_manager/app/core.py @@ -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.20' +FIRMWARE_VERSION = '0.2.21' 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']) diff --git a/screen_manager/config.yaml b/screen_manager/config.yaml index 1d147ed..7e8b920 100644 --- a/screen_manager/config.yaml +++ b/screen_manager/config.yaml @@ -1,5 +1,5 @@ name: ESP Screen Manager -version: "0.2.24" +version: "0.2.25" slug: esp_screen_manager description: Kies tegels voor je CYD en Guition touchscreen, zonder opnieuw flashen. url: https://github.com/MaxGramser/homeassistant_espscreen diff --git a/tests/test_cyd_ui.cpp b/tests/test_cyd_ui.cpp index 1d23c64..2c3c785 100644 --- a/tests/test_cyd_ui.cpp +++ b/tests/test_cyd_ui.cpp @@ -14,6 +14,13 @@ int main() { assert(quantize_temperature(-1, 160, 300, 5) == 160); assert(quantize_temperature(999, 160, 299, 5) == 299); assert(quantize_temperature(201, 160, 300, 0) == 201); + // -/+ keys: quick successive taps on the same key all count; bounce within 150 ms does not. + cyd::TouchGuard r; + r.begin(1000); assert(r.accept_repeat(1060, 7)); assert(!r.accept_repeat(1070, 7)); // one contact, one step + r.begin(1200); assert(r.accept_repeat(1260, 7)); // 200 ms later: accepted + r.begin(1300); assert(!r.accept_repeat(1340, 7)); // 80 ms after the last: bounce + r.begin(1300); r.update(40, 0); assert(!r.accept_repeat(1500, 7)); // a swipe is never a step + r.begin(1600); assert(r.accept_repeat(1660, 8)); // the other key right away cyd::TouchGuard g; g.begin(100); assert(!g.accept(120, 1)); // resistive noise pulse