iobroker.laundrylens 0.4.31 → 0.4.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -132,6 +132,11 @@ This also works inside the conditional `[...]` blocks: `[🌡️ Outside: {state
132
132
 
133
133
  ### **WORK IN PROGRESS**
134
134
 
135
+ ### 0.4.32 (2026-09-27)
136
+ - Fix: follow-up to 0.4.31 - a restart alone did not clear an *already*-stale `state` data point (e.g. stuck on "Running"), even with 0.4.31 installed. `onReady()` only re-wrote the `state`/`stateText`/`running`/`program`/`phase` data points when a restore branch fired (sensor currently drawing power, or a saved cycle needs resuming/finishing) - with neither true (the common case: an idle device whose last cycle already finished cleanly), nothing touched them at all, so a stale leftover value would survive any number of restarts
137
+ - Fixed by unconditionally re-syncing these data points with the manager's actual resolved state (`manager.currentState`/`manager.getStatus()`) at the end of every device's startup, regardless of which restore branch fired or didn't. Covered by a new source-inspection regression test (`tests/test_startup_state_sync.js`); also re-ran the full js-controller integration test since this touches `onReady()`
138
+ - If you're still seeing a stuck status after installing 0.4.31: this release should finally clear it on the next restart
139
+
135
140
  ### 0.4.31 (2026-09-27)
136
141
  - Fix: reported live - the admin tab showed the dryer as off while the `state` data point still read "Running". Root cause: the dryer's anti-crease "power drop" quick-finish path (`WashDataManager.processPowerReading()` - force-ends a cycle 45s after a sudden power drop, to react faster than waiting for the full off-delay) set the in-memory state to `off` directly and called the internal `_onCycleFinished()`, but - unlike the normal `_onDetectorState()` OFF transition - never invoked the `onStateChange` callback afterwards. That callback is what `main.js`'s `_onManagerState()` uses to write the `state`/`stateText`/`running`/`program`/`programText`/`phase`/`phaseText` data points, so they stayed frozen on their last value from before the drop even though the live status the admin tab reads (`WashDataManager._buildStatus()` via `getStatus`) was already correct. `lastCycle`/`lastCycleProgram`/etc. were unaffected (a separate callback), which is why cycle history looked fine while only the live status data points were stuck
137
142
  - Fixed by firing `onStateChange` after the quick-finish, exactly as the normal end-of-cycle transition already does. Covered by a new regression test (`tests/test_dryer_drop_finish_state_callback.js`)
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "laundrylens",
4
- "version": "0.4.31",
4
+ "version": "0.4.32",
5
5
  "news": {
6
+ "0.4.32": {
7
+ "en": "Follow-up fix to 0.4.31: a restart alone did not clear an already-stale state data point (e.g. stuck on \"Running\"), even with 0.4.31 installed. onReady() only re-writes the state/stateText/running/program/phase data points when a restore branch fires (sensor currently active, or a saved cycle needs resuming/finishing) - with neither true, the common case, nothing touched them at all. Now every device's startup unconditionally re-syncs these data points with the manager's actual resolved state, so a restart always clears any stale value immediately, regardless of cause.",
8
+ "de": "Folgefix zu 0.4.31: ein reiner Neustart raeumte einen bereits haengengebliebenen Status-Datenpunkt (z.B. festgefahren auf \"Running\") nicht auf, selbst mit installiertem 0.4.31. onReady() schrieb die Datenpunkte state/stateText/running/program/phase bisher nur neu, wenn ein Restore-Zweig griff (Sensor aktuell aktiv, oder ein gespeicherter Zyklus muss fortgesetzt/beendet werden) - traf keins von beidem zu, der Normalfall, wurde nichts angefasst. Jetzt synchronisiert jeder Geraete-Start diese Datenpunkte bedingungslos mit dem tatsaechlichen, aufgeloesten Zustand des Managers, sodass ein Neustart jeden haengengebliebenen Wert sofort beseitigt, unabhaengig von der Ursache.",
9
+ "ru": "Дополнительное исправление к 0.4.31: одна лишь перезагрузка не устраняла уже зависший датапоинт состояния (например, застрявший на \"Running\"), даже при установленном 0.4.31. onReady() перезаписывал датапоинты state/stateText/running/program/phase только при срабатывании ветки восстановления (датчик сейчас активен либо сохранённый цикл нужно возобновить/завершить) - если ни то, ни другое не верно (обычный случай), ничего не менялось. Теперь при каждом запуске устройства эти датапоинты безусловно синхронизируются с фактическим состоянием менеджера, поэтому перезапуск всегда немедленно устраняет любое зависшее значение, независимо от причины.",
10
+ "pt": "Correcao de acompanhamento a 0.4.29: reiniciar sozinho nao limpava um data point de estado ja obsoleto (por exemplo, preso em \"Running\"), mesmo com a 0.4.31 instalada. O onReady() so reescrevia os data points state/stateText/running/program/phase quando um ramo de restauracao era acionado (sensor atualmente ativo, ou um ciclo salvo precisa ser retomado/finalizado) - sem nenhum dos dois, o caso comum, nada era alterado. Agora a inicializacao de cada dispositivo sincroniza incondicionalmente esses data points com o estado real resolvido do gerenciador, entao reiniciar sempre limpa qualquer valor obsoleto imediatamente, independente da causa.",
11
+ "nl": "Vervolgfix op 0.4.31: een herstart alleen wiste een reeds verouderd state-datapoint (bijv. vastgelopen op \"Running\") niet, zelfs met 0.4.31 geinstalleerd. onReady() herschreef de datapoints state/stateText/running/program/phase alleen wanneer een herstel-tak werd geactiveerd (sensor momenteel actief, of een opgeslagen cyclus moet worden hervat/afgerond) - was geen van beide waar, het normale geval, dan werd er niets aangepast. Nu synchroniseert elke apparaatstart deze datapoints onvoorwaardelijk met de daadwerkelijk vastgestelde status van de manager, zodat een herstart elke verouderde waarde altijd meteen opheldert, ongeacht de oorzaak.",
12
+ "fr": "Correction complementaire a 0.4.31 : un simple redemarrage ne nettoyait pas un data point d'etat deja obsolete (par ex. bloque sur \"Running\"), meme avec la 0.4.31 installee. onReady() ne reecrivait les data points state/stateText/running/program/phase que lorsqu'une branche de restauration se declenchait (capteur actuellement actif, ou un cycle enregistre doit etre repris/termine) - si aucun des deux n'etait vrai, le cas courant, rien n'etait modifie. Desormais, chaque demarrage d'appareil resynchronise inconditionnellement ces data points avec l'etat reel resolu du gestionnaire, de sorte qu'un redemarrage efface toujours immediatement toute valeur obsolete, quelle qu'en soit la cause.",
13
+ "it": "Correzione di follow-up alla 0.4.31: un semplice riavvio non ripuliva un data point di stato gia bloccato (ad es. fermo su \"Running\"), anche con la 0.4.31 installata. onReady() riscriveva i data point state/stateText/running/program/phase solo quando si attivava un ramo di ripristino (sensore attualmente attivo, oppure un ciclo salvato deve essere ripreso/terminato) - se nessuno dei due era vero, il caso comune, non veniva modificato nulla. Ora l'avvio di ogni dispositivo risincronizza incondizionatamente questi data point con lo stato effettivo risolto del manager, cosi un riavvio ripulisce sempre immediatamente qualsiasi valore bloccato, indipendentemente dalla causa.",
14
+ "es": "Correccion de seguimiento a 0.4.31: reiniciar por si solo no limpiaba un data point de estado ya obsoleto (por ejemplo, atascado en \"Running\"), incluso con 0.4.31 instalado. onReady() solo reescribia los data points state/stateText/running/program/phase cuando se activaba una rama de restauracion (sensor actualmente activo, o un ciclo guardado necesita reanudarse/finalizarse) - si ninguno de los dos era cierto, el caso comun, no se tocaba nada. Ahora el arranque de cada dispositivo resincroniza incondicionalmente estos data points con el estado real resuelto del gestor, por lo que reiniciar siempre limpia de inmediato cualquier valor atascado, sin importar la causa.",
15
+ "pl": "Poprawka uzupelniajaca do 0.4.31: samo ponowne uruchomienie nie czyscilo juz nieaktualnego datapointu stanu (np. utknietego na \"Running\"), nawet po zainstalowaniu 0.4.31. onReady() ponownie zapisywal datapointy state/stateText/running/program/phase tylko wtedy, gdy uruchamiala sie galaz przywracania (czujnik aktualnie aktywny lub zapisany cykl wymaga wznowienia/zakonczenia) - jesli zadne z tych warunkow nie bylo spelnione, czyli w typowym przypadku, nic nie bylo zmieniane. Teraz uruchomienie kazdego urzadzenia bezwarunkowo synchronizuje te datapointy z faktycznym, rozwiazanym stanem menedzera, dzieki czemu ponowne uruchomienie zawsze natychmiast czysci kazda utkniete wartosc, niezaleznie od przyczyny.",
16
+ "uk": "Додаткове виправлення до 0.4.31: сама лише перезагрузка не очищала вже застарілий датапоінт стану (наприклад, застряглий на \"Running\"), навіть із встановленим 0.4.31. onReady() перезаписував датапоінти state/stateText/running/program/phase лише коли спрацьовувала гілка відновлення (датчик наразі активний, або збережений цикл потрібно відновити/завершити) - якщо жодне з цього не було правдою, звичайний випадок, нічого не змінювалося. Тепер запуск кожного пристрою безумовно синхронізує ці датапоінти з фактичним, визначеним станом менеджера, тому перезапуск завжди негайно очищує будь-яке застарile значення, незалежно від причини.",
17
+ "zh-cn": "0.4.31 的后续修复:即使安装了 0.4.31,仅重启也无法清除已经过期的状态数据点(例如卡在「Running」)。此前 onReady() 只有在触发恢复分支时(传感器当前处于活动状态,或需要恢复/结束已保存的周期)才会重写 state/stateText/running/program/phase 数据点——如果两者都不成立(这是常见情况),则完全不做任何更改。现在每台设备启动时都会无条件将这些数据点与管理器实际解析出的状态同步,因此重启总能立即清除任何过期的值,无论原因是什么。"
18
+ },
6
19
  "0.4.31": {
7
20
  "en": "Fix: a real bug report - the admin tab showed the dryer as off while the state data point still read \"Running\". Root cause: the dryer's anti-crease \"power drop\" quick-finish path (which force-ends a cycle 45s after a sudden power drop, to react faster than waiting for the full off-delay) set the in-memory state to off directly but never notified the rest of the adapter about it - so the state/stateText/running/program/phase data points stayed frozen on their last value from before the drop, even though the live status the admin tab reads was already correct. Fixed by firing the same notification the normal end-of-cycle transition already fires. If you're seeing this right now, restarting the adapter clears the stuck values immediately without waiting for the next cycle.",
8
21
  "de": "Fix: ein realer Fehlerbericht - der Admin-Tab zeigte den Trockner als aus an, waehrend der Status-Datenpunkt noch \"Running\" anzeigte. Ursache: der Anti-Knitter-Schnellabschluss des Trockners (der einen Zyklus 45 Sekunden nach einem ploetzlichen Leistungsabfall zwangsbeendet, um schneller zu reagieren als die volle Ausschaltverzoegerung abzuwarten) setzte den internen Status direkt auf aus, benachrichtigte aber nie den Rest des Adapters darueber - daher blieben die Datenpunkte state/stateText/running/program/phase auf ihrem letzten Wert vor dem Abfall eingefroren, obwohl der Live-Status, den der Admin-Tab liest, bereits korrekt war. Behoben, indem dieselbe Benachrichtigung ausgeloest wird, die der normale Zyklusende-Uebergang ohnehin schon ausloest. Wer das gerade sieht: ein Neustart des Adapters raeumt die haengengebliebenen Werte sofort auf, ohne auf den naechsten Zyklus warten zu muessen.",
@@ -80,19 +93,6 @@
80
93
  "pl": "Nowość: pełny model uczenia się czasu trwania faz do szacowania pozostałego czasu. Każdy program uczy się teraz nie tylko całkowitego czasu trwania, ale także tego, jak długo zazwyczaj trwa każda pojedyncza faza i w jakiej kolejności. Gdy dostępnych jest wystarczająco dużo danych, pozostały czas jest szacowany jako \"czas pozostały w bieżącej fazie plus typowy czas trwania każdej fazy, która historycznie następuje po niej\" - znacznie dokładniejsze pod koniec cyklu niż pojedyncza średnia dla całego cyklu.",
81
94
  "uk": "Новинка: повна модель навчання тривалості фаз для оцінки залишкового часу. Тепер кожна програма вивчає не лише загальну тривалість, а й те, скільки зазвичай триває кожна окрема фаза та в якому порядку. Щойно накопичиться достатньо даних, залишковий час оцінюється як «час, що залишився в поточній фазі, плюс типова тривалість кожної фази, яка історично йде після неї» - значно точніше наприкінці циклу, ніж єдине загальне середнє значення.",
82
95
  "zh-cn": "新功能:用于剩余时间估算的完整分阶段时长学习模型。现在每个程序不仅学习总时长,还学习每个单独阶段(加热、洗涤、脱水、烘干、冷却等)通常需要多长时间,以及它们的先后顺序。一旦积累了足够的数据,剩余时间将被估算为\"当前阶段剩余时间,加上历史上在此之后各阶段的典型时长之和\"——这在周期接近结束时比单一的整体周期平均值准确得多,尤其适用于像烘干机主烘干阶段这种相对总时长位置波动很大的阶段。"
83
- },
84
- "0.4.24": {
85
- "en": "Improved remaining-time/progress accuracy, especially for the dryer: each program now also learns how much its real duration actually varies cycle to cycle (e.g. a dryer's drying time depends heavily on load size/dampness, so it naturally varies much more than a fixed-temperature wash). The remaining-time estimate now leans more on the live energy-consumption pace for programs known to vary a lot, and more on the historical time average for consistent ones. The reported progress percentage is now derived from that same estimate, so it can no longer disagree with the predicted finish time. Added a remaining-time cap for the dryer's short \"cooling\" phase, matching the washer's existing \"spinning\" cap.",
86
- "de": "Genauigkeit von Restzeit/Fortschritt verbessert, besonders beim Trockner: Jedes Programm lernt jetzt zusätzlich, wie stark seine tatsächliche Dauer von Zyklus zu Zyklus wirklich schwankt (z.B. hängt die Trockenzeit stark von Beladungsgröße/Feuchte ab und schwankt daher naturgemäß viel stärker als ein Waschgang mit fester Temperatur). Die Restzeit-Schätzung stützt sich jetzt bei Programmen mit bekannt hoher Schwankung stärker auf das aktuelle Verbrauchstempo, bei gleichbleibenden Programmen stärker auf den historischen Zeitdurchschnitt. Die angezeigte Fortschrittsprozentzahl wird jetzt aus derselben Schätzung abgeleitet, sodass sie nicht mehr im Widerspruch zur vorhergesagten Endzeit stehen kann. Eine Restzeit-Obergrenze für die kurze „Abkühlen\"-Phase des Trockners ergänzt, passend zur bereits bestehenden „Schleudern\"-Obergrenze der Waschmaschine.",
87
- "ru": "Улучшена точность оставшегося времени/прогресса, особенно для сушильной машины: теперь каждая программа также учится тому, насколько сильно её реальная длительность варьируется от цикла к циклу. Оценка оставшегося времени теперь больше опирается на текущий темп потребления энергии для программ с известной высокой изменчивостью и больше на исторический средний показатель для стабильных программ. Отображаемый процент прогресса теперь рассчитывается на основе той же оценки. Добавлено ограничение оставшегося времени для короткой фазы охлаждения сушилки, аналогично существующему ограничению для фазы отжима стиральной машины.",
88
- "pt": "Precisão do tempo restante/progresso melhorada, especialmente para a secadora: cada programa agora também aprende o quanto sua duração real varia de ciclo para ciclo. A estimativa de tempo restante agora se apoia mais no ritmo de consumo de energia ao vivo para programas conhecidos por variar muito, e mais na média histórica de tempo para os consistentes. A porcentagem de progresso exibida agora é derivada dessa mesma estimativa. Adicionado um limite de tempo restante para a fase curta de \"resfriamento\" da secadora, semelhante ao limite já existente de \"centrifugação\" da lavadora.",
89
- "nl": "Nauwkeurigheid van resterende tijd/voortgang verbeterd, vooral voor de droger: elk programma leert nu ook hoezeer de werkelijke duur echt varieert per cyclus. De schatting van de resterende tijd leunt nu meer op het actuele energieverbruikstempo bij programma's met bekende grote variatie, en meer op het historische tijdgemiddelde bij consistente programma's. Het weergegeven voortgangspercentage wordt nu afgeleid van dezelfde schatting. Een limiet voor de resterende tijd toegevoegd voor de korte \"afkoel\"-fase van de droger, vergelijkbaar met de bestaande \"centrifugeren\"-limiet van de wasmachine.",
90
- "fr": "Précision du temps restant/de la progression améliorée, en particulier pour le sèche-linge : chaque programme apprend désormais aussi à quel point sa durée réelle varie d'un cycle à l'autre. L'estimation du temps restant s'appuie désormais davantage sur le rythme de consommation d'énergie en direct pour les programmes connus pour beaucoup varier, et davantage sur la moyenne historique pour les programmes constants. Le pourcentage de progression affiché est désormais dérivé de cette même estimation. Ajout d'une limite de temps restant pour la courte phase de \"refroidissement\" du sèche-linge, à l'image de la limite \"essorage\" déjà existante du lave-linge.",
91
- "it": "Precisione di tempo rimanente/progresso migliorata, specialmente per l'asciugatrice: ogni programma ora impara anche quanto la sua durata reale varia effettivamente da ciclo a ciclo. La stima del tempo rimanente ora si basa maggiormente sul ritmo di consumo energetico in tempo reale per i programmi noti per variare molto, e maggiormente sulla media storica per quelli costanti. La percentuale di progresso mostrata è ora derivata dalla stessa stima. Aggiunto un limite al tempo rimanente per la breve fase di \"raffreddamento\" dell'asciugatrice, come già avviene per la fase di \"centrifuga\" della lavatrice.",
92
- "es": "Precisión del tiempo restante/progreso mejorada, especialmente para la secadora: cada programa ahora también aprende cuánto varía realmente su duración de un ciclo a otro. La estimación del tiempo restante ahora se apoya más en el ritmo de consumo de energía en vivo para programas con alta variabilidad conocida, y más en el promedio histórico de tiempo para los consistentes. El porcentaje de progreso mostrado ahora se deriva de esa misma estimación. Se añadió un límite de tiempo restante para la breve fase de \"enfriamiento\" de la secadora, similar al límite de \"centrifugado\" ya existente de la lavadora.",
93
- "pl": "Poprawiono dokładność pozostałego czasu/postępu, zwłaszcza dla suszarki: każdy program uczy się teraz również, jak bardzo jego rzeczywisty czas trwania różni się między cyklami. Szacowanie pozostałego czasu opiera się teraz bardziej na bieżącym tempie zużycia energii dla programów o znanej dużej zmienności, a bardziej na historycznej średniej czasowej dla stabilnych programów. Wyświetlany procent postępu jest teraz wyprowadzany z tego samego oszacowania. Dodano limit pozostałego czasu dla krótkiej fazy \"chłodzenia\" suszarki, podobnie jak istniejący już limit dla fazy \"wirowania\" pralki.",
94
- "uk": "Покращено точність залишкового часу/прогресу, особливо для сушарки: кожна програма тепер також вивчає, наскільки сильно її реальна тривалість насправді відрізняється від циклу до циклу. Оцінка залишкового часу тепер більше спирається на поточний темп споживання енергії для програм із відомою високою мінливістю та більше на історичне середнє значення для стабільних програм. Відображений відсоток прогресу тепер визначається на основі тієї самої оцінки. Додано обмеження залишкового часу для короткої фази \"охолодження\" сушарки, за аналогією з наявним обмеженням \"віджиму\" пральної машини.",
95
- "zh-cn": "改进了剩余时间/进度的准确性,尤其是烘干机:现在每个程序还会学习其实际时长在各周期之间的真实波动程度(例如烘干时间在很大程度上取决于负载大小/湿度,因此天然比恒温洗涤波动更大)。对于已知波动较大的程序,剩余时间估算现在更多依赖实时能耗节奏;对于稳定的程序,则更多依赖历史平均时长。显示的进度百分比现在基于同一估算得出,因此不会再与预计完成时间相矛盾。新增了烘干机简短\"冷却\"阶段的剩余时间上限,与洗衣机现有的\"脱水\"阶段上限保持一致。"
96
96
  }
97
97
  },
98
98
  "titleLang": {
package/main.js CHANGED
@@ -583,6 +583,24 @@ class WashdataAdapter extends utils.Adapter {
583
583
  this.log.info(
584
584
  `${deviceCfg.name}: started – sensor: ${deviceCfg.powerId}`,
585
585
  );
586
+
587
+ // Always re-sync the persisted state/stateText/running/program/
588
+ // phase data points with the manager's actual resolved state at
589
+ // this point, regardless of which restore branch above fired (or
590
+ // none at all). Without this, a clean startup with no active
591
+ // cycle to restore never touches these data points at all - so
592
+ // any stale value left over from before the restart (the exact
593
+ // symptom fixed in 0.4.31: the state data point stuck on
594
+ // "Running" after a dryer anti-crease quick-finish that forgot
595
+ // to fire onStateChange) would stay stuck forever, surviving
596
+ // even a full adapter restart, until a brand new cycle happened
597
+ // to start. This call is idempotent - if the data points already
598
+ // match, it's a harmless no-op.
599
+ this._onManagerState(
600
+ deviceCfg.deviceId,
601
+ manager.currentState,
602
+ manager.getStatus(),
603
+ );
586
604
  }
587
605
 
588
606
  this.setState("info.connection", true, true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.laundrylens",
3
- "version": "0.4.31",
3
+ "version": "0.4.32",
4
4
  "description": "ioBroker adapter that detects washing machine and dryer cycles via smart plug power measurement, matches them against learned programs and estimates remaining time",
5
5
  "author": {
6
6
  "name": "backfisch88",