iobroker.laundrylens 0.4.40 → 0.4.41
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 +5 -0
- package/io-package.json +14 -14
- package/lib/washDataManager.js +34 -5
- package/package.json +1 -1
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.41 (2026-10-08)
|
|
136
|
+
- Fix: reported live - a cycle running noticeably longer than its historical average plateaued at ~99% progress / near-zero remaining time for a long stretch instead of correcting (a wash cycle showed 98% progress/2min remaining a full 34 minutes before it actually finished - confirmed from the debug log: still well inside an overrunning rinse phase, with spinning not even starting until 29 minutes later). Root cause: once the plain duration-average estimate (or, within a phase, that phase's typical duration) runs out, it has nothing more to contribute - but the live energy-based estimate (which tracks this specific run's actual pace, not a historical average) was still only partially trusted, as little as 30% weight for a consistent/low-CV profile
|
|
137
|
+
- Fixed by fully trusting the energy-based estimate once the whole-cycle average has run out (no phase data available), and leaning much more heavily on it (30/70 instead of 70/30) once the current phase has overrun its own typical duration - so an unusually long run corrects toward reality instead of sitting stuck near 0% remaining
|
|
138
|
+
- Covered by two new regression tests extending `tests/test_time_estimate.js` (one per branch)
|
|
139
|
+
|
|
135
140
|
### 0.4.40 (2026-10-07)
|
|
136
141
|
- Fix: reported live (notification history showing a predicted finish time creeping from 12:30 to 14:06 over the course of a single wash cycle, while `cycleProgress` stayed roughly accurate - over an hour off by the end) - the predicted finish time could drift later and later with every update. Root cause: whenever the recent power trace's variance exceeds a threshold (e.g. a washer motor cycling on/off during agitation), the remaining-time estimate gets "locked" to the last trusted value, to avoid jumpy/unstable predictions from noisy readings. The locked value was a frozen millisecond *duration* though, which never shrank while locked - so the countdown effectively stopped entirely for as long as the noisy condition persisted, while real wall-clock time kept passing, making `now + remaining` (the predicted finish time) creep later and later
|
|
137
142
|
- Fixed by decrementing the locked value by the real elapsed time since it was last touched, instead of freezing it as a constant - it now keeps counting down correctly even while locked, while still avoiding jumpy re-estimates from noisy readings (the original intent)
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "laundrylens",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.41",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.4.41": {
|
|
7
|
+
"en": "Fix: a cycle running noticeably longer than its historical average plateaued at ~99% progress / near-zero remaining time for a long stretch instead of correcting - reported live: a wash cycle showed 98% progress/2min remaining a full 34 minutes before it actually finished. Root cause: once the plain duration-average estimate (or, within a phase, that phase's typical duration) has run out, it has nothing more to contribute, but the live energy-based estimate (which tracks this specific run's actual pace) was still only partially trusted - as little as 30% weight for a consistent profile. Now fully (or much more heavily, in the per-phase case) trusted once the average-based estimate has nothing left to say, so the prediction corrects toward reality instead of sitting stuck near 0.",
|
|
8
|
+
"de": "Fix: Ein Zyklus, der merklich laenger lief als sein historischer Durchschnitt, blieb lange bei ~99% Fortschritt bzw. nahezu null Restzeit haengen, statt sich zu korrigieren - live gemeldet: ein Waschgang zeigte 98% Fortschritt/2min Restzeit ganze 34 Minuten vor dem tatsaechlichen Ende. Ursache: Sobald die reine Durchschnittsdauer-Schaetzung (bzw. innerhalb einer Phase deren typische Dauer) aufgebraucht ist, hat sie nichts mehr beizutragen - die live-energiebasierte Schaetzung (die das tatsaechliche Tempo dieses konkreten Laufs verfolgt) wurde aber weiterhin nur teilweise vertraut, bei einem konsistenten Profil nur mit bis zu 30% Gewicht. Wird jetzt voll (bzw. im Phasen-Fall deutlich staerker) vertraut, sobald die durchschnittsbasierte Schaetzung nichts mehr zu sagen hat, sodass sich die Vorhersage zur Realitaet hin korrigiert statt nahe 0 haengen zu bleiben.",
|
|
9
|
+
"ru": "Исправление: цикл, работавший заметно дольше своего исторического среднего, долго оставался на ~99% прогресса / почти нулевом оставшемся времени вместо коррекции - сообщено в реальном использовании: цикл стирки показывал 98% прогресса/2 мин до конца за целых 34 минуты до фактического завершения. Причина: как только простая оценка на основе средней длительности (или, внутри фазы, типичной длительности этой фазы) исчерпывается, ей больше нечего предложить, но живой оценке на основе энергопотребления (которая отслеживает реальный темп именно этого запуска) по-прежнему доверяли лишь частично - вплоть до 30% веса для стабильного профиля. Теперь ей доверяют полностью (или значительно сильнее, в случае отдельной фазы), как только оценке на основе среднего больше нечего сказать, так что прогноз корректируется в сторону реальности, а не застревает около 0.",
|
|
10
|
+
"pt": "Correcao: um ciclo que rodava visivelmente mais tempo que sua media historica estabilizava em ~99% de progresso / tempo restante quase zero por um longo periodo em vez de se corrigir - relatado ao vivo: um ciclo de lavagem mostrou 98% de progresso/2min restantes 34 minutos inteiros antes de realmente terminar. Causa raiz: assim que a estimativa pela media de duracao simples (ou, dentro de uma fase, a duracao tipica dessa fase) se esgota, ela nao tem mais nada a contribuir, mas a estimativa ao vivo baseada em energia (que acompanha o ritmo real desta execucao especifica) ainda era apenas parcialmente confiavel - ate apenas 30% de peso para um perfil consistente. Agora e totalmente (ou muito mais, no caso por fase) confiavel assim que a estimativa baseada na media nao tem mais nada a dizer, entao a previsao se corrige em direcao a realidade em vez de ficar presa perto de 0.",
|
|
11
|
+
"nl": "Fix: een cyclus die merkbaar langer liep dan zijn historische gemiddelde bleef lange tijd steken op ~99% voortgang / bijna nul resterende tijd in plaats van te corrigeren - live gemeld: een wascyclus toonde 98% voortgang/2min resterend een volle 34 minuten voordat hij daadwerkelijk klaar was. Oorzaak: zodra de simpele gemiddelde-duurschatting (of, binnen een fase, die fase se typische duur) is opgebruikt, heeft die niets meer bij te dragen, maar de live energiegebaseerde schatting (die het werkelijke tempo van deze specifieke run volgt) werd nog steeds maar gedeeltelijk vertrouwd - tot slechts 30% gewicht voor een consistent profiel. Wordt nu volledig (of veel sterker, in het geval per fase) vertrouwd zodra de gemiddelde-gebaseerde schatting niets meer te zeggen heeft, zodat de voorspelling richting de realiteit corrigeert in plaats van vast te blijven zitten bij 0.",
|
|
12
|
+
"fr": "Correction : un cycle fonctionnant nettement plus longtemps que sa moyenne historique restait bloque a ~99% de progression / temps restant quasi nul pendant une longue periode au lieu de se corriger - signale en direct : un cycle de lavage affichait 98% de progression/2min restantes 34 minutes entieres avant de reellement se terminer. Cause : des que l'estimation par simple moyenne de duree (ou, au sein d'une phase, la duree typique de cette phase) est epuisee, elle n'a plus rien a apporter, mais l'estimation en direct basee sur l'energie (qui suit le rythme reel de cette execution precise) n'etait encore que partiellement fiable - jusqu'a seulement 30% de poids pour un profil coherent. Desormais pleinement (ou bien plus fortement, dans le cas par phase) fiable des que l'estimation basee sur la moyenne n'a plus rien a dire, afin que la prediction se corrige vers la realite plutot que de rester bloquee pres de 0.",
|
|
13
|
+
"it": "Correzione: un ciclo che girava notevolmente piu a lungo della sua media storica si stabilizzava su ~99% di avanzamento / tempo residuo quasi nullo per un lungo periodo invece di correggersi - segnalato dal vivo: un ciclo di lavaggio mostrava 98% di avanzamento/2min residui ben 34 minuti prima di terminare realmente. Causa: non appena la semplice stima basata sulla durata media (o, all'interno di una fase, la durata tipica di quella fase) si esaurisce, non ha piu nulla da contribuire, ma la stima live basata sull'energia (che segue il ritmo reale di questa specifica esecuzione) era ancora solo parzialmente attendibile - fino a solo il 30% di peso per un profilo coerente. Ora e pienamente (o molto piu, nel caso per fase) attendibile non appena la stima basata sulla media non ha piu nulla da dire, cosi la previsione si corregge verso la realta invece di restare bloccata vicino a 0.",
|
|
14
|
+
"es": "Correccion: un ciclo que se ejecutaba notablemente mas tiempo que su promedio historico se estabilizaba en ~99% de progreso / tiempo restante casi cero durante un largo periodo en lugar de corregirse - informado en vivo: un ciclo de lavado mostro 98% de progreso/2min restantes 34 minutos enteros antes de terminar realmente. Causa raiz: en cuanto la simple estimacion por duracion promedio (o, dentro de una fase, la duracion tipica de esa fase) se agota, no tiene mas que aportar, pero la estimacion en vivo basada en energia (que sigue el ritmo real de esta ejecucion especifica) seguia siendo solo parcialmente confiable - hasta solo un 30% de peso para un perfil consistente. Ahora es totalmente (o mucho mas, en el caso por fase) confiable en cuanto la estimacion basada en el promedio no tiene mas que decir, de modo que la prediccion se corrige hacia la realidad en lugar de quedarse estancada cerca de 0.",
|
|
15
|
+
"pl": "Poprawka: cykl dzialajacy zauwazalnie dluzej niz jego historyczna srednia dlugo utrzymywal sie na ~99% postepu / niemal zerowym pozostalym czasie zamiast sie skorygowac - zgloszono na zywo: cykl prania pokazywal 98% postepu/2min pozostalo az 34 minuty przed faktycznym zakonczeniem. Przyczyna: gdy tylko prosta estymacja na podstawie sredniego czasu trwania (lub, w ramach fazy, typowego czasu trwania tej fazy) sie wyczerpie, nie ma juz nic do zaoferowania, ale zywej estymacji opartej na energii (ktora sledzi rzeczywiste tempo tego konkretnego przebiegu) nadal ufano tylko czesciowo - az do zaledwie 30% wagi dla spojnego profilu. Teraz jest w pelni (lub znacznie bardziej, w przypadku fazy) zaufana, gdy tylko estymacja oparta na sredniej nie ma juz nic do powiedzenia, dzieki czemu prognoza koryguje sie w strone rzeczywistosci zamiast utkwic blisko 0.",
|
|
16
|
+
"uk": "Виправлення: цикл, що працював помітно довше за свій історичний середній показник, довго залишався на ~99% прогресу / майже нульовому залишковому часі замість корекції - повідомлено наживо: цикл прання показував 98% прогресу/2хв залишилося за цілих 34 хвилини до фактичного завершення. Причина: щойно проста оцінка за середньою тривалістю (або, в межах фази, типова тривалість цієї фази) вичерпується, їй більше нічого запропонувати, але живій оцінці на основі енергоспоживання (яка відстежує реальний темп саме цього запуску) досі довіряли лише частково - аж до 30% ваги для стабільного профілю. Тепер їй довіряють повністю (або значно сильніше, у випадку окремої фази), щойно оцінці на основі середнього більше нічого сказати, тож прогноз коригується у бік реальності замість застрягання біля 0.",
|
|
17
|
+
"zh-cn": "修复:运行时间明显长于历史平均值的周期会长时间停留在约 99% 进度/接近零剩余时间,而不会自我修正——实际反馈案例:一次洗涤周期在实际完成前整整 34 分钟就显示 98% 进度/剩余 2 分钟。根本原因:一旦基于平均时长的简单估算(或在某个阶段内,该阶段的典型时长)耗尽,它就无法再提供更多信息,但基于能耗的实时估算(能追踪本次运行的实际节奏)此前仍只被部分信任——对于稳定的程序,权重最低只有 30%。现在只要基于平均值的估算已无话可说,就会完全信任(在按阶段的情况下则大幅提高信任度)能耗估算,使预测能够向现实靠拢,而不是卡在接近 0 的位置。"
|
|
18
|
+
},
|
|
6
19
|
"0.4.40": {
|
|
7
20
|
"en": "Fix: the predicted finish time ('Fertig um HH:MM') could drift later and later with every notification over the course of a single cycle - observed over an hour off by the end of a wash. Root cause: whenever the recent power trace got too noisy (e.g. a washer's motor cycling on/off during agitation), the remaining-time estimate gets 'locked' to avoid jumpy predictions - but the locked value was a frozen duration that never shrank while locked, even though real time kept passing. The countdown effectively stopped while locked, so the predicted finish time (now + frozen remaining) crept later the longer the noisy condition persisted. Now decrements by the real elapsed time while locked, so it keeps counting down correctly.",
|
|
8
21
|
"de": "Fix: Die vorhergesagte Fertigstellungszeit ('Fertig um HH:MM') konnte sich mit jeder Benachrichtigung im Laufe eines Zyklus immer weiter nach hinten verschieben - beobachtet mit ueber einer Stunde Abweichung zum Ende eines Waschgangs. Ursache: Sobald die juengste Leistungsaufnahme zu unruhig wurde (z. B. ein Motor, der bei der Waschbewegung staendig an-/abschaltet), wird die Restzeitschaetzung 'gesperrt', um sprunghafte Vorhersagen zu vermeiden - der gesperrte Wert war aber eine eingefrorene Dauer, die waehrend der Sperre nie schrumpfte, obwohl real Zeit verging. Der Countdown blieb waehrend der Sperre praktisch stehen, wodurch die vorhergesagte Fertigstellungszeit (jetzt + eingefrorene Restzeit) immer spaeter rutschte, je laenger der unruhige Zustand anhielt. Zaehlt jetzt waehrend der Sperre um die tatsaechlich vergangene Zeit weiter herunter.",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "Poprawka: phaseText mógł utknąć na wcześniejszej fazie (np. \"Aufheizen\"/nagrzewanie), podczas gdy phase poprawnie szedł dalej (np. do \"dryer_drying\") - phase był już aktualizowany przy każdym tyknięciu, ale phaseText (czytelna, zlokalizowana etykieta) był zapisywany tylko przy faktycznych przejściach stanu, a nie przy każdej zmianie fazy w obrębie jednego trwającego cyklu. Oba są teraz aktualizowane razem przy każdym tyknięciu.",
|
|
81
94
|
"uk": "Виправлення: phaseText міг застрягати на попередній фазі (наприклад, \"Aufheizen\"/нагрівання), тоді як phase коректно просувався далі (наприклад, до \"dryer_drying\") - phase вже оновлювався при кожному тіку, а phaseText (зрозуміла, локалізована мітка) записувався лише при фактичних переходах стану, а не при кожній зміні фази в межах одного робочого циклу. Тепер обидва оновлюються разом при кожному тіку.",
|
|
82
95
|
"zh-cn": "修复:phaseText 可能会卡在较早的阶段(例如「Aufheizen」/加热),而 phase 却正确地推进(例如到「dryer_drying」)——phase 早已在每次心跳时更新,但 phaseText(人类可读的本地化标签)此前只在实际状态转换时才写入,而不是在单次运行周期内每次阶段变化时都写入。现在两者会在每次心跳时一起更新。"
|
|
83
|
-
},
|
|
84
|
-
"0.4.34": {
|
|
85
|
-
"en": "Fix: availablePrograms could show [] for a device that clearly had saved programs (visible in the admin tab's own Programme list) - it was only ever written from specific admin-tab actions (create/delete/rename a program, clear all data), never at startup or after a program got auto-learned from a confirmed cycle. Fix: needsFeedback stayed false even with a cycle visibly pending confirmation in the admin tab's Lernkontrolle tab - the data point was declared but never actually written anywhere; the admin tab computed its own pending-count entirely client-side. Both are now kept in sync at adapter startup, after every finished cycle, and (for needsFeedback) after a cycle is confirmed or corrected.",
|
|
86
|
-
"de": "Fix: availablePrograms konnte [] anzeigen, obwohl ein Gerät eindeutig gespeicherte Programme hatte (sichtbar in der Admin-Tab-eigenen Programme-Liste) - der Datenpunkt wurde nur von bestimmten Admin-Tab-Aktionen geschrieben (Programm anlegen/löschen/umbenennen, alle Daten löschen), nie beim Start oder nachdem ein Programm aus einem bestätigten Zyklus automatisch gelernt wurde. Fix: needsFeedback blieb auf false, obwohl im Lernkontrolle-Tab des Admin-Tabs sichtbar ein Zyklus auf Bestätigung wartete - der Datenpunkt war deklariert, wurde aber nirgends tatsächlich beschrieben; der Admin-Tab berechnete seine eigene Anzahl offener Zyklen komplett clientseitig. Beide werden jetzt beim Adapterstart, nach jedem beendeten Zyklus und (bei needsFeedback) nach einer Bestätigung/Korrektur eines Zyklus synchron gehalten.",
|
|
87
|
-
"ru": "Исправление: availablePrograms мог показывать [], хотя у устройства явно были сохранённые программы (видимые в собственном списке «Программы» админ-вкладки) - датапоинт записывался только при определённых действиях в админ-вкладке (создание/удаление/переименование программы, очистка всех данных), но никогда при запуске или после автоматического обучения программе из подтверждённого цикла. Исправление: needsFeedback оставался false, хотя на вкладке «Контроль обучения» админ-панели был явно виден цикл, ожидающий подтверждения - датапоинт был объявлен, но нигде фактически не записывался; админ-вкладка вычисляла своё количество ожидающих циклов полностью на стороне клиента. Теперь оба синхронизируются при запуске адаптера, после каждого завершённого цикла и (для needsFeedback) после подтверждения или исправления цикла.",
|
|
88
|
-
"pt": "Correção: availablePrograms podia mostrar [] mesmo com um dispositivo claramente com programas salvos (visíveis na própria lista de Programas da aba de administração) - o data point só era escrito a partir de ações específicas da aba de administração (criar/excluir/renomear um programa, limpar todos os dados), nunca na inicialização ou após um programa ser aprendido automaticamente a partir de um ciclo confirmado. Correção: needsFeedback permanecia false mesmo com um ciclo visivelmente pendente de confirmação na aba Lernkontrolle da administração - o data point estava declarado, mas nunca era realmente escrito em lugar nenhum; a aba de administração calculava sua própria contagem pendente inteiramente no lado do cliente. Ambos agora são sincronizados na inicialização do adaptador, após cada ciclo finalizado e (para needsFeedback) após um ciclo ser confirmado ou corrigido.",
|
|
89
|
-
"nl": "Fix: availablePrograms kon [] tonen voor een apparaat dat duidelijk opgeslagen programma's had (zichtbaar in de eigen Programma's-lijst van het admin-tabblad) - het datapoint werd alleen geschreven vanuit specifieke admin-tabbladacties (programma aanmaken/verwijderen/hernoemen, alle data wissen), nooit bij opstarten of nadat een programma automatisch was geleerd uit een bevestigde cyclus. Fix: needsFeedback bleef false terwijl er zichtbaar een cyclus wachtte op bevestiging in het Lernkontrolle-tabblad van de admin - het datapoint was gedeclareerd maar werd nergens daadwerkelijk geschreven; het admin-tabblad berekende zijn eigen aantal openstaande cycli volledig client-side. Beide worden nu gesynchroniseerd bij het opstarten van de adapter, na elke afgeronde cyclus en (voor needsFeedback) na het bevestigen of corrigeren van een cyclus.",
|
|
90
|
-
"fr": "Correction : availablePrograms pouvait afficher [] pour un appareil ayant clairement des programmes enregistrés (visibles dans la propre liste Programmes de l'onglet admin) - le point de données n'était écrit que depuis des actions spécifiques de l'onglet admin (créer/supprimer/renommer un programme, effacer toutes les données), jamais au démarrage ni après qu'un programme ait été appris automatiquement à partir d'un cycle confirmé. Correction : needsFeedback restait à false alors qu'un cycle était visiblement en attente de confirmation dans l'onglet Lernkontrolle de l'admin - le point de données était déclaré mais jamais réellement écrit nulle part ; l'onglet admin calculait son propre nombre de cycles en attente entièrement côté client. Les deux sont désormais resynchronisés au démarrage de l'adaptateur, après chaque cycle terminé et (pour needsFeedback) après la confirmation ou la correction d'un cycle.",
|
|
91
|
-
"it": "Correzione: availablePrograms poteva mostrare [] per un dispositivo che aveva chiaramente programmi salvati (visibili nella lista Programmi della scheda admin stessa) - il data point veniva scritto solo da azioni specifiche della scheda admin (creare/eliminare/rinominare un programma, cancellare tutti i dati), mai all'avvio o dopo che un programma veniva appreso automaticamente da un ciclo confermato. Correzione: needsFeedback restava false anche con un ciclo visibilmente in attesa di conferma nella scheda Lernkontrolle dell'admin - il data point era dichiarato ma non veniva mai effettivamente scritto da nessuna parte; la scheda admin calcolava il proprio conteggio in sospeso interamente lato client. Entrambi vengono ora sincronizzati all'avvio dell'adattatore, dopo ogni ciclo terminato e (per needsFeedback) dopo la conferma o correzione di un ciclo.",
|
|
92
|
-
"es": "Corrección: availablePrograms podía mostrar [] para un dispositivo que claramente tenía programas guardados (visibles en la propia lista de Programas de la pestaña de administración) - el data point solo se escribía desde acciones específicas de la pestaña de administración (crear/eliminar/renombrar un programa, borrar todos los datos), nunca al iniciar ni después de que un programa se aprendiera automáticamente a partir de un ciclo confirmado. Corrección: needsFeedback permanecía en false aunque había visiblemente un ciclo pendiente de confirmación en la pestaña Lernkontrolle de administración - el data point estaba declarado pero nunca se escribía realmente en ningún sitio; la pestaña de administración calculaba su propio recuento pendiente completamente del lado del cliente. Ambos se sincronizan ahora al iniciar el adaptador, tras cada ciclo finalizado y (para needsFeedback) tras confirmar o corregir un ciclo.",
|
|
93
|
-
"pl": "Poprawka: availablePrograms mógł pokazywać [], mimo że urządzenie wyraźnie miało zapisane programy (widoczne we własnej liście Programy zakładki administratora) - datapoint był zapisywany tylko przy określonych akcjach w zakładce administratora (utworzenie/usunięcie/zmiana nazwy programu, wyczyszczenie wszystkich danych), nigdy przy starcie ani po automatycznym nauczeniu się programu z potwierdzonego cyklu. Poprawka: needsFeedback pozostawał false, mimo że w zakładce Lernkontrolle administratora widoczny był cykl oczekujący na potwierdzenie - datapoint był zadeklarowany, ale nigdzie faktycznie nie był zapisywany; zakładka administratora obliczała własną liczbę oczekujących cykli całkowicie po stronie klienta. Oba są teraz synchronizowane przy starcie adaptera, po każdym zakończonym cyklu oraz (dla needsFeedback) po potwierdzeniu lub poprawieniu cyklu.",
|
|
94
|
-
"uk": "Виправлення: availablePrograms міг показувати [], хоча пристрій явно мав збережені програми (видимі у власному списку «Програми» вкладки адміністратора) - датапоінт записувався лише при певних діях у вкладці адміністратора (створення/видалення/перейменування програми, очищення всіх даних), ніколи під час запуску або після автоматичного навчання програми з підтвердженого циклу. Виправлення: needsFeedback залишався false, хоча на вкладці «Контроль навчання» адміністратора було явно видно цикл, що очікує підтвердження - датапоінт був оголошений, але ніде фактично не записувався; вкладка адміністратора обчислювала власну кількість очікуючих циклів повністю на стороні клієнта. Обидва тепер синхронізуються під час запуску адаптера, після кожного завершеного циклу та (для needsFeedback) після підтвердження чи виправлення циклу.",
|
|
95
|
-
"zh-cn": "修复:即使设备明显已保存程序(在管理标签页自己的「程序」列表中可见),availablePrograms 仍可能显示为 []——该数据点此前只在特定的管理标签页操作中写入(创建/删除/重命名程序、清除所有数据),从不在启动时或某个程序通过已确认的周期自动学习后写入。修复:即使管理标签页的「学习检查」标签页中明显有一个周期待确认,needsFeedback 仍保持 false——该数据点已声明但从未在任何地方真正写入过;管理标签页完全在客户端自行计算待处理数量。现在两者都会在适配器启动时、每次周期结束后,以及(对于 needsFeedback)在确认或更正某个周期后保持同步。"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
package/lib/washDataManager.js
CHANGED
|
@@ -981,6 +981,7 @@ class WashDataManager {
|
|
|
981
981
|
// past cycles have data for the CURRENT phase specifically, and once
|
|
982
982
|
// we actually know when that phase started (_phaseHistory's last entry).
|
|
983
983
|
let phaseBasedRemainingMs = null;
|
|
984
|
+
let phaseOverrunning = false;
|
|
984
985
|
if (
|
|
985
986
|
profile.phaseStats &&
|
|
986
987
|
this._stablePhase &&
|
|
@@ -1004,6 +1005,10 @@ class WashDataManager {
|
|
|
1004
1005
|
0,
|
|
1005
1006
|
typicalPhaseMs - elapsedInPhaseMs,
|
|
1006
1007
|
);
|
|
1008
|
+
// Separately from the floored value above: has the current phase
|
|
1009
|
+
// already run past how long it usually takes? Used below to
|
|
1010
|
+
// decide how much to lean on the energy-based estimate instead.
|
|
1011
|
+
phaseOverrunning = elapsedInPhaseMs >= typicalPhaseMs;
|
|
1007
1012
|
let futurePhasesMs = 0;
|
|
1008
1013
|
for (let i = idx + 1; i < seq.length; i++) {
|
|
1009
1014
|
futurePhasesMs += profile.phaseStats.durationMs[seq[i]] || 0;
|
|
@@ -1041,15 +1046,39 @@ class WashDataManager {
|
|
|
1041
1046
|
// still capped from above by the phase safety net.
|
|
1042
1047
|
let blendedRemainingMs;
|
|
1043
1048
|
if (phaseBasedRemainingMs !== null) {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1049
|
+
if (energyBasedRemainingMs === null) {
|
|
1050
|
+
blendedRemainingMs = phaseBasedRemainingMs;
|
|
1051
|
+
} else if (phaseOverrunning) {
|
|
1052
|
+
// The current phase has already run past how long it usually
|
|
1053
|
+
// takes - remainingInPhaseMs (above) is floored at 0 and has
|
|
1054
|
+
// nothing further to say about *this* phase, so the light 70/30
|
|
1055
|
+
// blend below would keep reporting "almost done" (just the
|
|
1056
|
+
// typical duration of whatever phases come next) no matter how
|
|
1057
|
+
// much longer this phase actually runs. Lean on the live
|
|
1058
|
+
// energy-based signal instead - it tracks the actual pace of
|
|
1059
|
+
// *this* run rather than a historical average. Found live: a
|
|
1060
|
+
// wash cycle still well inside an overrunning rinse phase
|
|
1061
|
+
// reported 98% progress / ~2min remaining a full 34 minutes
|
|
1062
|
+
// before it actually finished.
|
|
1063
|
+
blendedRemainingMs =
|
|
1064
|
+
phaseBasedRemainingMs * 0.3 + energyBasedRemainingMs * 0.7;
|
|
1065
|
+
} else {
|
|
1066
|
+
blendedRemainingMs =
|
|
1067
|
+
phaseBasedRemainingMs * 0.7 + energyBasedRemainingMs * 0.3;
|
|
1068
|
+
}
|
|
1048
1069
|
} else {
|
|
1049
1070
|
blendedRemainingMs = timeBasedRemainingMs;
|
|
1050
1071
|
if (energyBasedRemainingMs !== null) {
|
|
1051
1072
|
const cv = profile.durationCV || 0;
|
|
1052
|
-
|
|
1073
|
+
// Same reasoning as the phase-overrun case above: once the whole
|
|
1074
|
+
// cycle has already run past its historical average
|
|
1075
|
+
// (timeBasedRemainingMs floored at 0), the clock-based estimate
|
|
1076
|
+
// has nothing more to contribute - trust the energy-based
|
|
1077
|
+
// projection fully rather than attenuating it by energyWeight.
|
|
1078
|
+
const energyWeight =
|
|
1079
|
+
timeBasedRemainingMs === 0
|
|
1080
|
+
? 1
|
|
1081
|
+
: Math.min(0.8, Math.max(0.3, 0.3 + cv * 1.25));
|
|
1053
1082
|
blendedRemainingMs =
|
|
1054
1083
|
timeBasedRemainingMs * (1 - energyWeight) +
|
|
1055
1084
|
energyBasedRemainingMs * energyWeight;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.laundrylens",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.41",
|
|
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",
|