iobroker.miele-local 0.3.43 → 0.3.44
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 +3 -0
- package/io-package.json +14 -14
- package/lib/objektabgleich.js +41 -0
- package/main.js +24 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -237,6 +237,9 @@ engineering work of the projects `MieleRESTServer` (akappner),
|
|
|
237
237
|
### **WORK IN PROGRESS**
|
|
238
238
|
-->
|
|
239
239
|
|
|
240
|
+
### 0.3.44
|
|
241
|
+
- (SmarthomeElektroniker) History objects are only rewritten when they actually changed - this prevents an empty (null) point in the history adapter after every adapter restart
|
|
242
|
+
|
|
240
243
|
### 0.3.43
|
|
241
244
|
|
|
242
245
|
- (SmarthomeElektroniker) All log messages are English now; diagnostic texts in states (`finding`, `check`, `progress`, `scanState`, `trendSize`), error messages and the CSV export too (review 2026-09-27)
|
package/io-package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "miele-local",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.44",
|
|
5
5
|
"titleLang": {
|
|
6
6
|
"en": "Miele@local",
|
|
7
7
|
"de": "Miele@local",
|
|
@@ -52,6 +52,19 @@
|
|
|
52
52
|
"readme": "https://github.com/SmarthomeElektroniker/ioBroker.miele-local/blob/main/README.md",
|
|
53
53
|
"loglevel": "info",
|
|
54
54
|
"news": {
|
|
55
|
+
"0.3.44": {
|
|
56
|
+
"en": "History objects are only rewritten when they actually changed - no more empty (null) points in the history adapter after every restart",
|
|
57
|
+
"de": "History-Objekte werden nur noch geschrieben, wenn sie sich wirklich geändert haben - keine leeren (null) Punkte mehr im History-Adapter nach jedem Neustart",
|
|
58
|
+
"ru": "Объекты истории перезаписываются только при реальном изменении - больше нет пустых (null) точек в адаптере history после каждого перезапуска",
|
|
59
|
+
"pt": "Os objetos de histórico só são regravados quando realmente mudam - sem mais pontos vazios (null) no adaptador history após cada reinício",
|
|
60
|
+
"nl": "Historie-objecten worden alleen herschreven als ze echt gewijzigd zijn - geen lege (null) punten meer in de history-adapter na elke herstart",
|
|
61
|
+
"fr": "Les objets d'historique ne sont réécrits que s'ils ont réellement changé - plus de points vides (null) dans l'adaptateur history après chaque redémarrage",
|
|
62
|
+
"it": "Gli oggetti della cronologia vengono riscritti solo se sono effettivamente cambiati - niente più punti vuoti (null) nell'adattatore history dopo ogni riavvio",
|
|
63
|
+
"es": "Los objetos de historial solo se reescriben cuando realmente cambian - ya no hay puntos vacíos (null) en el adaptador history tras cada reinicio",
|
|
64
|
+
"pl": "Obiekty historii są zapisywane ponownie tylko przy rzeczywistej zmianie - koniec z pustymi (null) punktami w adapterze history po każdym restarcie",
|
|
65
|
+
"uk": "Об'єкти історії перезаписуються лише за реальної зміни - більше немає порожніх (null) точок в адаптері history після кожного перезапуску",
|
|
66
|
+
"zh-cn": "历史对象仅在实际更改时才会重写 - 每次重启后 history 适配器中不再出现空 (null) 点"
|
|
67
|
+
},
|
|
55
68
|
"0.3.43": {
|
|
56
69
|
"en": "All log messages, diagnostic texts in states, error messages and the CSV export are English now; the admin UI uses English i18n keys and the diagnostics tab is translated into all 11 languages.",
|
|
57
70
|
"de": "Alle Logmeldungen, Diagnosetexte in Datenpunkten, Fehlermeldungen und der CSV-Export sind jetzt englisch; die Admin-Oberfläche nutzt englische i18n-Schlüssel, der Diagnose-Reiter ist in alle 11 Sprachen übersetzt.",
|
|
@@ -129,19 +142,6 @@
|
|
|
129
142
|
"pl": "Identyfikatory obiektów są teraz w całości angielskie: \"sammlung\" zmieniono na \"collection\", \"befund\" na \"finding\", a \"laufendSeit\" na \"runningSince\". Przy pierwszym uruchomieniu adapter przenosi istniejące wartości na nowe identyfikatory; własne skrypty trzeba dostosować, a zapisana historia pozostaje pod starym identyfikatorem w adapterze history. Ponadto od wersji 0.3.5: woda jest odczytywana ze sprawdzonego pola DOP2 i pobierana w pierwszej kolejności z EcoFeedback urządzenia, wewnętrzne wartości urządzenia można tworzyć jako stany, osobna zakładka diagnostyczna z eksportem CSV zbiera pola surowe, a konfigurowalne interwały są ograniczane w czasie działania.",
|
|
130
143
|
"uk": "Ідентифікатори об'єктів тепер повністю англійські: \"sammlung\" стало \"collection\", \"befund\" — \"finding\", \"laufendSeit\" — \"runningSince\". Під час першого запуску адаптер переносить наявні значення на нові ідентифікатори; власні скрипти потрібно оновити, а записана історія залишається зі старим ідентифікатором в адаптері history. Крім того, починаючи з 0.3.5: вода зчитується з перевіреного поля DOP2 і насамперед береться з EcoFeedback самого приладу, внутрішні величини приладу можна створювати як стани, окрема вкладка діагностики з експортом у CSV збирає сирі поля, а налаштовувані інтервали обмежуються під час роботи.",
|
|
131
144
|
"zh-cn": "对象 ID 现已全部使用英文:\"sammlung\" 改为 \"collection\",\"befund\" 改为 \"finding\",\"laufendSeit\" 改为 \"runningSince\"。首次启动时,适配器会把已有数值迁移到新的 ID;自建脚本需要相应调整,已记录的历史数据仍以旧 ID 保留在 history 适配器中。此外自 0.3.5 起:用水量取自经过验证的 DOP2 字段,并优先来自设备自身的 EcoFeedback;设备内部数值可创建为数据点;独立的诊断选项卡支持导出 CSV 以收集原始字段;可配置的轮询间隔在运行时会被限制。"
|
|
132
|
-
},
|
|
133
|
-
"0.3.5": {
|
|
134
|
-
"en": "Fix: appliance status no longer flips to \"off\" during a running program, and the remaining time is read from the correct field. Frozen EcoFeedback values are no longer booked as consumption, requests are serialised per appliance, and a cycle survives an adapter restart. EcoFeedback is only requested while an appliance is actually running. Login instructions and datapoint names translated into all supported languages.",
|
|
135
|
-
"de": "Fix: Der Geraetestatus springt waehrend eines laufenden Programms nicht mehr auf \"Aus\", und die Restzeit wird aus dem richtigen Feld gelesen. Eingefrorene EcoFeedback-Werte werden nicht mehr als Verbrauch gebucht, Anfragen laufen je Geraet nacheinander, und ein Zyklus ueberlebt einen Adapter-Neustart. EcoFeedback wird nur noch abgefragt, solange ein Geraet laeuft. Login-Anleitung und Datenpunktnamen in alle unterstuetzten Sprachen uebersetzt.",
|
|
136
|
-
"ru": "Исправлено: во время работы программы статус прибора больше не переключается на «выкл.», а оставшееся время считывается из правильного поля. Застывшие значения EcoFeedback больше не учитываются как потребление, запросы к каждому прибору выполняются последовательно, а цикл сохраняется после перезапуска адаптера. EcoFeedback запрашивается только тогда, когда прибор действительно работает. Инструкции по входу и названия точек данных переведены на все поддерживаемые языки.",
|
|
137
|
-
"pt": "Correção: o estado do aparelho já não muda para \"desligado\" durante um programa em curso, e o tempo restante é lido do campo correto. Valores EcoFeedback congelados já não são contabilizados como consumo, os pedidos são serializados por aparelho e um ciclo sobrevive a um reinício do adaptador. O EcoFeedback só é pedido enquanto o aparelho está realmente a funcionar. Instruções de início de sessão e nomes dos pontos de dados traduzidos para todos os idiomas suportados.",
|
|
138
|
-
"nl": "Opgelost: de apparaatstatus springt tijdens een lopend programma niet meer naar \"uit\", en de resterende tijd wordt uit het juiste veld gelezen. Bevroren EcoFeedback-waarden worden niet meer als verbruik geboekt, verzoeken worden per apparaat na elkaar afgehandeld en een cyclus overleeft een herstart van de adapter. EcoFeedback wordt alleen opgevraagd terwijl een apparaat echt draait. Inloginstructies en datapuntnamen vertaald in alle ondersteunde talen.",
|
|
139
|
-
"fr": "Correction : l'état de l'appareil ne passe plus à « arrêt » pendant un programme en cours, et le temps restant est lu dans le bon champ. Les valeurs EcoFeedback figées ne sont plus comptabilisées comme consommation, les requêtes sont sérialisées par appareil et un cycle survit à un redémarrage de l'adaptateur. EcoFeedback n'est interrogé que lorsqu'un appareil fonctionne réellement. Instructions de connexion et noms des points de données traduits dans toutes les langues prises en charge.",
|
|
140
|
-
"it": "Correzione: lo stato dell'apparecchio non passa più a \"spento\" durante un programma in corso e il tempo rimanente viene letto dal campo corretto. I valori EcoFeedback bloccati non vengono più contabilizzati come consumo, le richieste vengono serializzate per apparecchio e un ciclo sopravvive a un riavvio dell'adattatore. EcoFeedback viene richiesto solo mentre un apparecchio è effettivamente in funzione. Istruzioni di accesso e nomi dei punti dati tradotti in tutte le lingue supportate.",
|
|
141
|
-
"es": "Corrección: el estado del aparato ya no cambia a \"apagado\" durante un programa en curso, y el tiempo restante se lee del campo correcto. Los valores EcoFeedback congelados ya no se contabilizan como consumo, las solicitudes se serializan por aparato y un ciclo sobrevive a un reinicio del adaptador. EcoFeedback solo se solicita mientras un aparato está realmente en funcionamiento. Instrucciones de inicio de sesión y nombres de puntos de datos traducidos a todos los idiomas compatibles.",
|
|
142
|
-
"pl": "Poprawka: stan urządzenia nie przełącza się już na „wyłączone” w trakcie trwającego programu, a pozostały czas jest odczytywany z właściwego pola. Zamrożone wartości EcoFeedback nie są już księgowane jako zużycie, zapytania są szeregowane dla każdego urządzenia, a cykl przetrwa ponowne uruchomienie adaptera. EcoFeedback jest odpytywany tylko wtedy, gdy urządzenie faktycznie pracuje. Instrukcje logowania i nazwy punktów danych przetłumaczono na wszystkie obsługiwane języki.",
|
|
143
|
-
"uk": "Виправлено: під час роботи програми статус приладу більше не перемикається на «вимк.», а час, що залишився, зчитується з правильного поля. Застиглі значення EcoFeedback більше не враховуються як споживання, запити до кожного приладу виконуються послідовно, а цикл зберігається після перезапуску адаптера. EcoFeedback запитується лише тоді, коли прилад справді працює. Інструкції з входу та назви точок даних перекладено всіма підтримуваними мовами.",
|
|
144
|
-
"zh-cn": "修复:程序运行期间设备状态不再跳变为“关闭”,剩余时间从正确的字段读取。冻结的 EcoFeedback 数值不再计为能耗,每台设备的请求按顺序处理,程序周期可在适配器重启后保留。仅在设备实际运行时才请求 EcoFeedback。登录说明和数据点名称已翻译为所有支持的语言。"
|
|
145
145
|
}
|
|
146
146
|
},
|
|
147
147
|
"mode": "daemon",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { isDeepStrictEqual } = require('node:util');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Ob ein vorhandenes Objekt nachgezogen werden muss.
|
|
7
|
+
*
|
|
8
|
+
* Ein extendObject auf ein unveraendertes Objekt ist nicht harmlos: Jeder Schreibvorgang loest
|
|
9
|
+
* beim history-Adapter ein objectChange aus. Hat er den Datenpunkt nur ueber storeState in seiner
|
|
10
|
+
* Liste (ohne common.custom), sieht er darin ein Objekt ohne History-Einstellung, meldet
|
|
11
|
+
* "disabled logging" und setzt einen Leerpunkt (null) als Lueckenmarke. Am 25./27.09.2026 stand
|
|
12
|
+
* so nach jedem Adapterneustart eine Luecke im Verlauf der Waschmaschine.
|
|
13
|
+
*
|
|
14
|
+
* Verglichen werden nur die Felder, die der Adapter selbst setzt - was andere (custom, Aliase,
|
|
15
|
+
* Raumzuordnung) dazugeschrieben haben, zaehlt nicht als Abweichung.
|
|
16
|
+
*
|
|
17
|
+
* @param {object|null|undefined} vorhanden Das Objekt aus der Datenbank (oder nichts)
|
|
18
|
+
* @param {{type?: string, common?: object, native?: object}} soll Was der Adapter schreiben wuerde
|
|
19
|
+
* @returns {boolean} true, wenn das Objekt fehlt oder ein gesetztes Feld abweicht
|
|
20
|
+
*/
|
|
21
|
+
function mussNachziehen(vorhanden, soll) {
|
|
22
|
+
if (!vorhanden) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
if (soll.type && vorhanden.type !== soll.type) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
const ist = vorhanden.common || {};
|
|
29
|
+
for (const [schluessel, wert] of Object.entries(soll.common || {})) {
|
|
30
|
+
// undefined heisst "nicht setzen" - extendObject ueberginge es ebenso.
|
|
31
|
+
if (wert === undefined) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (!isDeepStrictEqual(ist[schluessel], wert)) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = { mussNachziehen };
|
package/main.js
CHANGED
|
@@ -48,6 +48,7 @@ const { MielePushListener } = require('./lib/push');
|
|
|
48
48
|
const enroll = require('./lib/enroll');
|
|
49
49
|
const dop2 = require('./lib/dop2');
|
|
50
50
|
const stats = require('./lib/stats');
|
|
51
|
+
const { mussNachziehen } = require('./lib/objektabgleich');
|
|
51
52
|
|
|
52
53
|
/*
|
|
53
54
|
* EcoFeedback: DOP2-Leaf 2/6195 (bislang nur Waschmaschinen liefern ihn).
|
|
@@ -2003,6 +2004,21 @@ class MieleLocal extends utils.Adapter {
|
|
|
2003
2004
|
this._statsCreated[deviceId] = true;
|
|
2004
2005
|
}
|
|
2005
2006
|
|
|
2007
|
+
/**
|
|
2008
|
+
* extendObject nur, wenn das Objekt fehlt oder sich etwas geaendert hat.
|
|
2009
|
+
*
|
|
2010
|
+
* Ein unnoetiger Schreibvorgang setzt beim history-Adapter einen Leerpunkt in den Verlauf
|
|
2011
|
+
* (siehe lib/objektabgleich.js) - bei jedem Adapterstart eine Luecke im Diagramm.
|
|
2012
|
+
*
|
|
2013
|
+
* @param {string} id Objekt-ID relativ zur Instanz
|
|
2014
|
+
* @param {object} soll Objekt, wie extendObject es bekaeme
|
|
2015
|
+
*/
|
|
2016
|
+
async objektNachziehen(id, soll) {
|
|
2017
|
+
if (mussNachziehen(await this.getObjectAsync(id), soll)) {
|
|
2018
|
+
await this.extendObjectAsync(id, soll);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2006
2022
|
async ensureHistoryObjects(deviceId) {
|
|
2007
2023
|
if (!this._histCreated) {
|
|
2008
2024
|
this._histCreated = {};
|
|
@@ -2019,7 +2035,7 @@ class MieleLocal extends utils.Adapter {
|
|
|
2019
2035
|
*/
|
|
2020
2036
|
await this.ensureSammlungObjects(deviceId);
|
|
2021
2037
|
const de = this.config.germanNames !== false;
|
|
2022
|
-
await this.
|
|
2038
|
+
await this.objektNachziehen(`${deviceId}.history`, {
|
|
2023
2039
|
type: 'channel',
|
|
2024
2040
|
common: { name: namen.text('Verlauf', 'History', de) },
|
|
2025
2041
|
native: {},
|
|
@@ -2111,7 +2127,7 @@ class MieleLocal extends utils.Adapter {
|
|
|
2111
2127
|
];
|
|
2112
2128
|
for (const [sub, name, typ, rolle, einheit, def] of defs) {
|
|
2113
2129
|
const hDesc = namen.beschreibung(`history.${sub}`, de); // Schluessel = tatsaechliche ID
|
|
2114
|
-
await this.
|
|
2130
|
+
await this.objektNachziehen(`${deviceId}.history.${sub}`, {
|
|
2115
2131
|
type: 'state',
|
|
2116
2132
|
common: Object.assign(
|
|
2117
2133
|
{ name, type: typ, role: rolle, unit: einheit || undefined, def, read: true, write: false },
|
|
@@ -2127,10 +2143,12 @@ class MieleLocal extends utils.Adapter {
|
|
|
2127
2143
|
* so seinen alten, nur zweisprachigen Namen, bis das Geraet wieder lief - die Objektpruefung
|
|
2128
2144
|
* des PR #6471 fand das am 11.09.2026 an der ausgeschalteten Spuelmaschine.
|
|
2129
2145
|
*/
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2146
|
+
const stunden = await this.getObjectAsync(`${deviceId}.info.operatingHours`);
|
|
2147
|
+
if (stunden) {
|
|
2148
|
+
const soll = { common: { name: namen.text('Betriebsstunden gesamt', 'Total operating hours', de) } };
|
|
2149
|
+
if (mussNachziehen(stunden, soll)) {
|
|
2150
|
+
await this.extendObjectAsync(`${deviceId}.info.operatingHours`, soll);
|
|
2151
|
+
}
|
|
2134
2152
|
}
|
|
2135
2153
|
this._histCreated[deviceId] = true;
|
|
2136
2154
|
}
|
package/package.json
CHANGED