iobroker.metermaster 0.9.2 → 0.9.3
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 +9 -1
- package/io-package.json +14 -1
- package/main.js +69 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/MPunktBPunkt/ioBroker.metermaster)
|
|
4
4
|
|
|
5
|
-
[](https://github.com/MPunktBPunkt/ioBroker.metermaster)
|
|
6
6
|
[](https://github.com/MPunktBPunkt/ioBroker.metermaster/blob/main/LICENSE)
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
|
|
@@ -247,6 +247,14 @@ iobroker restart metermaster.0
|
|
|
247
247
|
|
|
248
248
|
## Changelog
|
|
249
249
|
|
|
250
|
+
### 0.9.3
|
|
251
|
+
- Fix state roles for ioBroker object structure check (repochecker E1008/E1009/E1011)
|
|
252
|
+
- Migration of existing objects on adapter start
|
|
253
|
+
|
|
254
|
+
### 0.9.2
|
|
255
|
+
- Adapter checker compliance: npm news cleanup, devDependencies, trusted publishing
|
|
256
|
+
- npm publish via GitHub Actions with provenance
|
|
257
|
+
|
|
250
258
|
### 0.9.1
|
|
251
259
|
- Lowered admin dependency to >=7.6.20 (fixes startup when admin 7.7.x is installed)
|
|
252
260
|
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "metermaster",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.3",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.9.3": {
|
|
7
|
+
"en": "Fix state roles for ioBroker object structure check (date, text, json, info.firmware)",
|
|
8
|
+
"de": "State-Rollen für ioBroker-Objektstruktur-Prüfung korrigiert (date, text, json, info.firmware)",
|
|
9
|
+
"ru": "Исправлены роли states для проверки структуры объектов ioBroker",
|
|
10
|
+
"pt": "Corrigidas roles de states para verificação da estrutura de objetos ioBroker",
|
|
11
|
+
"nl": "State-rollen gecorrigeerd voor ioBroker objectstructuurcontrole",
|
|
12
|
+
"fr": "Rôles des states corrigés pour la vérification de structure d'objets ioBroker",
|
|
13
|
+
"it": "Corrette le role degli state per il controllo struttura oggetti ioBroker",
|
|
14
|
+
"es": "Corregidos roles de states para verificación de estructura de objetos ioBroker",
|
|
15
|
+
"pl": "Poprawiono role states dla kontroli struktury obiektów ioBroker",
|
|
16
|
+
"uk": "Виправлено ролі states для перевірки структури об'єктів ioBroker",
|
|
17
|
+
"zh-cn": "修复 state 角色以通过 ioBroker 对象结构检查"
|
|
18
|
+
},
|
|
6
19
|
"0.9.2": {
|
|
7
20
|
"en": "Adapter checker compliance: npm news cleanup, devDependencies, trusted publishing",
|
|
8
21
|
"de": "Adapter-Checker-Konformität: npm-News bereinigt, devDependencies, Trusted Publishing",
|
package/main.js
CHANGED
|
@@ -6,7 +6,7 @@ const crypto = require('node:crypto');
|
|
|
6
6
|
const https = require('node:https');
|
|
7
7
|
const { exec } = require('node:child_process');
|
|
8
8
|
|
|
9
|
-
const CURRENT_VERSION = '0.9.
|
|
9
|
+
const CURRENT_VERSION = '0.9.3';
|
|
10
10
|
const GITHUB_REPO = 'MPunktBPunkt/ioBroker.metermaster';
|
|
11
11
|
const GITHUB_URL = 'https://github.com/MPunktBPunkt/ioBroker.metermaster';
|
|
12
12
|
|
|
@@ -81,6 +81,7 @@ adapter.on('ready', async () => {
|
|
|
81
81
|
// In-Memory-Cache aus gespeicherten ioBroker-States wiederherstellen
|
|
82
82
|
await restoreCacheFromStates();
|
|
83
83
|
await restoreNodesFromStates();
|
|
84
|
+
await migrateStateRoles();
|
|
84
85
|
|
|
85
86
|
// ESP32-Node-States beobachten (Heartbeat-Erkennung via simple-api)
|
|
86
87
|
adapter.subscribeStates('nodes.*');
|
|
@@ -215,11 +216,11 @@ async function ensureNodeStates(mac) {
|
|
|
215
216
|
await ensureChannel(base, `ESP32 Node ${mac}`);
|
|
216
217
|
await ensureState(`${base}.ip`, { name: 'IP-Adresse', type: 'string', role: 'info.ip', read: true, write: false });
|
|
217
218
|
await ensureState(`${base}.name`, { name: 'Gerätename', type: 'string', role: 'info.name', read: true, write: false });
|
|
218
|
-
await ensureState(`${base}.version`, { name: 'Firmware-Version', type: 'string', role: 'info.
|
|
219
|
-
await ensureState(`${base}.lastSeen`, { name: 'Zuletzt gesehen (ms)', type: 'number', role: 'value.time',
|
|
220
|
-
await ensureState(`${base}.config`, { name: 'Konfiguration (JSON)', type: 'string', role: '
|
|
221
|
-
await ensureState(`${base}.configAck`, { name: 'Config-Quittierung', type: 'string', role: '
|
|
222
|
-
await ensureState(`${base}.cmd`, { name: 'Befehl (JSON)', type: 'string', role: '
|
|
219
|
+
await ensureState(`${base}.version`, { name: 'Firmware-Version', type: 'string', role: 'info.firmware', read: true, write: false });
|
|
220
|
+
await ensureState(`${base}.lastSeen`, { name: 'Zuletzt gesehen (ms)', type: 'number', role: 'value.time', read: true, write: false });
|
|
221
|
+
await ensureState(`${base}.config`, { name: 'Konfiguration (JSON)', type: 'string', role: 'json', read: true, write: true });
|
|
222
|
+
await ensureState(`${base}.configAck`, { name: 'Config-Quittierung', type: 'string', role: 'json', read: true, write: false });
|
|
223
|
+
await ensureState(`${base}.cmd`, { name: 'Befehl (JSON)', type: 'string', role: 'json', read: true, write: true });
|
|
223
224
|
}
|
|
224
225
|
|
|
225
226
|
// ─── HTTP-Server ──────────────────────────────────────────────────────────────
|
|
@@ -478,10 +479,10 @@ async function storeReading(data) {
|
|
|
478
479
|
if (isNew) log(LVL.INFO, CAT.DATAPOINT, `Neuer Zähler`, `metermaster.0.${base}`);
|
|
479
480
|
|
|
480
481
|
const dpNew = await ensureState(`${base}.readings.latest`, { name: `${data.meter} – Letzter Wert`, type: 'number', role: 'value', unit: data.unit||'', read: true, write: false });
|
|
481
|
-
await ensureState(`${base}.readings.latestDate`, { name: 'Ablesedatum', type: 'string', role: '
|
|
482
|
-
await ensureState(`${base}.name`, { name: 'Zählername', type: 'string', role: 'info.name',
|
|
483
|
-
await ensureState(`${base}.unit`, { name: 'Einheit', type: 'string', role: '
|
|
484
|
-
await ensureState(`${base}.typeName`, { name: 'Zählertyp', type: 'string', role: '
|
|
482
|
+
await ensureState(`${base}.readings.latestDate`, { name: 'Ablesedatum', type: 'string', role: 'date', read: true, write: false });
|
|
483
|
+
await ensureState(`${base}.name`, { name: 'Zählername', type: 'string', role: 'info.name', read: true, write: false });
|
|
484
|
+
await ensureState(`${base}.unit`, { name: 'Einheit', type: 'string', role: 'text', read: true, write: false });
|
|
485
|
+
await ensureState(`${base}.typeName`, { name: 'Zählertyp', type: 'string', role: 'text', read: true, write: false });
|
|
485
486
|
await ensureState(`${base}.readings.history`, { name: 'Historische Ablesungen', type: 'array', role: 'list', read: true, write: false });
|
|
486
487
|
|
|
487
488
|
if (dpNew) log(LVL.INFO, CAT.DATAPOINT, `Datenpunkte angelegt`, `${base}.readings.{latest,latestDate,history} + name/unit/typeName`);
|
|
@@ -532,20 +533,72 @@ async function ensureChannel(id, name) {
|
|
|
532
533
|
return true;
|
|
533
534
|
}
|
|
534
535
|
async function ensureState(id, common) {
|
|
536
|
+
const fullCommon = {
|
|
537
|
+
...common,
|
|
538
|
+
read: common.read !== undefined ? common.read : true,
|
|
539
|
+
write: common.write !== undefined ? common.write : false,
|
|
540
|
+
def: common.type === 'number' ? 0 : (common.type === 'array' ? '[]' : '')
|
|
541
|
+
};
|
|
535
542
|
const ex = await adapter.getObjectAsync(id).catch(() => null);
|
|
536
|
-
if (ex)
|
|
543
|
+
if (ex) {
|
|
544
|
+
const patch = {};
|
|
545
|
+
for (const key of ['role', 'type', 'read', 'write', 'unit']) {
|
|
546
|
+
if (fullCommon[key] !== undefined && ex.common[key] !== fullCommon[key]) {
|
|
547
|
+
patch[key] = fullCommon[key];
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if (Object.keys(patch).length) {
|
|
551
|
+
await adapter.extendObjectAsync(id, { common: patch });
|
|
552
|
+
}
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
537
555
|
await adapter.setObjectNotExistsAsync(id, {
|
|
538
556
|
type: 'state',
|
|
539
|
-
common:
|
|
540
|
-
read: common.read !== undefined ? common.read : true,
|
|
541
|
-
write: common.write !== undefined ? common.write : false,
|
|
542
|
-
def: common.type === 'number' ? 0 : (common.type === 'array' ? '[]' : '')
|
|
543
|
-
},
|
|
557
|
+
common: fullCommon,
|
|
544
558
|
native: {}
|
|
545
559
|
});
|
|
546
560
|
return true;
|
|
547
561
|
}
|
|
548
562
|
|
|
563
|
+
// ─── State-Rollen-Migration (deprecated → ioBroker-Rollenkatalog) ───────────────
|
|
564
|
+
const DEPRECATED_ROLE_MAP = {
|
|
565
|
+
'value.datetime': 'date',
|
|
566
|
+
'value.unit': 'text',
|
|
567
|
+
'info.type': 'text',
|
|
568
|
+
'info.version': 'info.firmware',
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
function resolveMigratedRole(id, common) {
|
|
572
|
+
if (DEPRECATED_ROLE_MAP[common.role]) {
|
|
573
|
+
return DEPRECATED_ROLE_MAP[common.role];
|
|
574
|
+
}
|
|
575
|
+
if (common.role === 'value' && common.type === 'string') {
|
|
576
|
+
const field = id.split('.').pop();
|
|
577
|
+
if (field === 'config' || field === 'configAck' || field === 'cmd') {
|
|
578
|
+
return 'json';
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return null;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
async function migrateStateRoles() {
|
|
585
|
+
try {
|
|
586
|
+
const objects = await adapter.getForeignObjectsAsync('*', { type: 'state' });
|
|
587
|
+
if (!objects) return;
|
|
588
|
+
let fixed = 0;
|
|
589
|
+
for (const [id, obj] of Object.entries(objects)) {
|
|
590
|
+
const newRole = resolveMigratedRole(id, obj.common || {});
|
|
591
|
+
if (newRole && obj.common.role !== newRole) {
|
|
592
|
+
await adapter.extendObjectAsync(id, { common: { role: newRole } });
|
|
593
|
+
fixed++;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (fixed) log(LVL.INFO, CAT.SYSTEM, 'State-Rollen migriert', `${fixed} Objekte`);
|
|
597
|
+
} catch (e) {
|
|
598
|
+
log(LVL.WARN, CAT.SYSTEM, 'State-Rollen-Migration fehlgeschlagen', e.message);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
549
602
|
// ─── API Endpunkte ────────────────────────────────────────────────────────────
|
|
550
603
|
function serveDataJson(res) {
|
|
551
604
|
sendJson(res, 200, { data: receivedData, receivedTotal: readingsReceived });
|
package/package.json
CHANGED