homebridge-plugin-klares4 2.0.1-beta1 → 2.0.1
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/CHANGELOG.md +35 -0
- package/LICENSE +2 -2
- package/README.md +30 -1
- package/config.schema.json +108 -1
- package/dist/ksa/cache-service.d.ts +11 -0
- package/dist/ksa/cache-service.d.ts.map +1 -0
- package/dist/ksa/cache-service.js +73 -0
- package/dist/ksa/cache-service.js.map +1 -0
- package/dist/ksa/derive.d.ts +3 -0
- package/dist/ksa/derive.d.ts.map +1 -0
- package/dist/ksa/derive.js +191 -0
- package/dist/ksa/derive.js.map +1 -0
- package/dist/ksa/parser.d.ts +4 -0
- package/dist/ksa/parser.d.ts.map +1 -0
- package/dist/ksa/parser.js +112 -0
- package/dist/ksa/parser.js.map +1 -0
- package/dist/ksa/types.d.ts +85 -0
- package/dist/ksa/types.d.ts.map +1 -0
- package/dist/ksa/types.js +3 -0
- package/dist/ksa/types.js.map +1 -0
- package/dist/platform/config-file-service.d.ts +1 -0
- package/dist/platform/config-file-service.d.ts.map +1 -1
- package/dist/platform/config-file-service.js +12 -4
- package/dist/platform/config-file-service.js.map +1 -1
- package/dist/platform/index.d.ts +1 -0
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js +4 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/ksa-import-service.d.ts +15 -0
- package/dist/platform/ksa-import-service.d.ts.map +1 -0
- package/dist/platform/ksa-import-service.js +149 -0
- package/dist/platform/ksa-import-service.js.map +1 -0
- package/dist/platform/types.d.ts +2 -1
- package/dist/platform/types.d.ts.map +1 -1
- package/dist/types/websocket.types.d.ts +35 -0
- package/dist/types/websocket.types.d.ts.map +1 -1
- package/dist/websocket-client/command-service.d.ts.map +1 -1
- package/dist/websocket-client/command-service.js +1 -0
- package/dist/websocket-client/command-service.js.map +1 -1
- package/dist/websocket-client/index.js +1 -1
- package/dist/websocket-client/index.js.map +1 -1
- package/dist/websocket-client/state.d.ts +2 -2
- package/dist/websocket-client/state.d.ts.map +1 -1
- package/dist/websocket-client/state.js +25 -4
- package/dist/websocket-client/state.js.map +1 -1
- package/dist/websocket-client/thermostat-command-id-resolver.d.ts +2 -1
- package/dist/websocket-client/thermostat-command-id-resolver.d.ts.map +1 -1
- package/dist/websocket-client/thermostat-command-id-resolver.js +2 -2
- package/dist/websocket-client/thermostat-command-id-resolver.js.map +1 -1
- package/dist/websocket-client/thermostat-config-sync.js +4 -0
- package/dist/websocket-client/thermostat-config-sync.js.map +1 -1
- package/dist/websocket-client/thermostat-status-updater.d.ts +1 -0
- package/dist/websocket-client/thermostat-status-updater.d.ts.map +1 -1
- package/dist/websocket-client/thermostat-status-updater.js +18 -0
- package/dist/websocket-client/thermostat-status-updater.js.map +1 -1
- package/dist/websocket-client/types.d.ts +6 -0
- package/dist/websocket-client/types.d.ts.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.1] - 2026-03-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- KSA import pipeline (`ksaImport`) with deterministic derivation for thermostat command routing, Domus sensor mapping, room mapping, and optional custom names.
|
|
15
|
+
- Sanitized KSA runtime cache (`klares4-ksa-cache.json`) with whitelist-only structural metadata (no raw backup persistence).
|
|
16
|
+
- Bilingual technical documentation under `docs/en` and `docs/it` covering architecture, websocket behavior, Domus routing, config, and troubleshooting.
|
|
17
|
+
- CI/CD upgrade:
|
|
18
|
+
- Node 20/22 CI validation matrix with strict type-check + tests + build artifact
|
|
19
|
+
- npm publish workflow via GitHub Actions (tag/manual release path, provenance, and publish guards).
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Thermostat authoritative state alignment on Domus installations using `STATUS_TEMPERATURES` for realtime mode/setpoint/current state.
|
|
24
|
+
- Thermostat routing mismatch on systems where output IDs, Domus sensor IDs, and `CFG_THERMOSTATS.ID` are not numerically aligned.
|
|
25
|
+
- Startup synchronization robustness by preloading thermostat structural mapping from sanitized KSA cache when `PRG_THERMOSTATS` is not exposed by firmware.
|
|
26
|
+
- Degraded routing behavior now evaluates mapped Domus sensor candidates before raw output fallback in non-PRG environments.
|
|
27
|
+
|
|
28
|
+
## [2.0.1-beta2] - 2026-03-13
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- New KSA import workflow in plugin config (`ksaImport`) to parse central backup metadata and derive deterministic routing data.
|
|
33
|
+
- Sanitized KSA cache persisted in Homebridge storage (`klares4-ksa-cache.json`) with thermostat/output/sensor/room mappings only (no raw backup persistence).
|
|
34
|
+
- Automatic derivation from KSA for:
|
|
35
|
+
- `domusThermostat.manualCommandPairs` (`output -> CFG/STATUS thermostat ID`)
|
|
36
|
+
- `domusThermostat.manualPairs` (`output -> Domus sensor`)
|
|
37
|
+
- optional `roomMapping` and optional `customNames`.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- Runtime thermostat routing now preloads program mappings from KSA cache when realtime `PRG_THERMOSTATS` is unavailable on panel firmware.
|
|
42
|
+
- Degraded command resolver now evaluates mapped Domus sensor IDs before raw output fallback, improving compatibility in non-PRG environments.
|
|
43
|
+
- Initial websocket state can bootstrap thermostat program maps from cached KSA data to avoid startup desynchronization.
|
|
44
|
+
|
|
10
45
|
## [2.0.1-beta1] - 2026-03-13
|
|
11
46
|
|
|
12
47
|
### Fixed
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 Paolo
|
|
3
|
+
Copyright (c) 2025-26 Paolo Trivisonno
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -8,6 +8,13 @@ Complete plugin for Ksenia Lares4 systems integrating security zones, lights, co
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
## Full Documentation
|
|
12
|
+
|
|
13
|
+
- English docs: `docs/en/`
|
|
14
|
+
- Documentazione italiana: `docs/it/`
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
11
18
|
## English Documentation
|
|
12
19
|
|
|
13
20
|
### Features
|
|
@@ -109,6 +116,7 @@ The plugin can be fully configured via the Homebridge UI graphical interface. Re
|
|
|
109
116
|
| `allowInsecureTls` | boolean | false | Disable TLS certificate validation (trusted LAN only) |
|
|
110
117
|
| `logLevel` | number | 1 | 0=minimal, 1=normal, 2=debug |
|
|
111
118
|
| `domusThermostat` | object | enabled/freshness defaults | DOMUS thermostat mapping, manual overrides, freshness fallback |
|
|
119
|
+
| `ksaImport` | object | disabled | Import KSA backup metadata for thermostat routing, room mapping and optional config apply |
|
|
112
120
|
| `debug` | boolean | false | Detailed logging |
|
|
113
121
|
| `excludeZones` | string[] | [] | Zones to exclude |
|
|
114
122
|
| `excludeOutputs` | string[] | [] | Outputs to exclude |
|
|
@@ -251,11 +259,31 @@ npm run verify
|
|
|
251
259
|
|
|
252
260
|
This runs:
|
|
253
261
|
|
|
254
|
-
- max file size gate (`src/**/*.ts` <=
|
|
262
|
+
- max file size gate (`src/**/*.ts` <= 350 lines),
|
|
255
263
|
- strict TypeScript checks (`--noUnusedLocals --noUnusedParameters`),
|
|
256
264
|
- full test suite,
|
|
257
265
|
- build compatibility gate.
|
|
258
266
|
|
|
267
|
+
### CI/CD
|
|
268
|
+
|
|
269
|
+
GitHub Actions workflows:
|
|
270
|
+
|
|
271
|
+
- `CI` (`.github/workflows/ci.yml`): Node 20/22 validation, strict type-checks, tests, build artifact.
|
|
272
|
+
- `Release Publish` (`.github/workflows/release-publish.yml`): npm publish with provenance from tags (`v*`) or manual dispatch.
|
|
273
|
+
|
|
274
|
+
Trusted publishing:
|
|
275
|
+
|
|
276
|
+
- `Release Publish` uses GitHub OIDC trusted publishing (`id-token: write`).
|
|
277
|
+
- No `NPM_TOKEN` secret is required.
|
|
278
|
+
|
|
279
|
+
Release policy:
|
|
280
|
+
|
|
281
|
+
- tag push `v<package.json version>` triggers publish;
|
|
282
|
+
- npm dist-tag auto-derived from version:
|
|
283
|
+
- `*-beta*` -> `beta`
|
|
284
|
+
- `*-rc*` -> `rc`
|
|
285
|
+
- stable -> `latest`
|
|
286
|
+
|
|
259
287
|
### Roadmap
|
|
260
288
|
|
|
261
289
|
#### Planned for v1.2.0
|
|
@@ -401,6 +429,7 @@ Il plugin puo essere configurato completamente tramite l'interfaccia grafica di
|
|
|
401
429
|
| `heartbeatInterval` | number | 30000 | Intervallo heartbeat (ms) |
|
|
402
430
|
| `logLevel` | number | 1 | 0=minimal, 1=normal, 2=debug |
|
|
403
431
|
| `domusThermostat` | object | default attivi | Mapping termostati DOMUS, override manuali e fallback freshness |
|
|
432
|
+
| `ksaImport` | object | disabilitato | Import metadata da backup KSA per routing termostati, room mapping e apply opzionale |
|
|
404
433
|
| `debug` | boolean | false | Logging dettagliato |
|
|
405
434
|
| `excludeZones` | string[] | [] | Zone da escludere |
|
|
406
435
|
| `excludeOutputs` | string[] | [] | Output da escludere |
|
package/config.schema.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"singular": true,
|
|
5
5
|
"customUi": false,
|
|
6
6
|
"headerDisplay": "<div style='margin-bottom:12px;'><h3 style='margin:0 0 6px 0;'>Klares4 - Ksenia Lares4 per Homebridge</h3><p style='margin:0 0 12px 0;'>Plugin Homebridge per controllo locale della centrale Ksenia Lares4.</p><div style='padding:10px 12px;border:1px solid currentColor;border-radius:8px;'><strong>Prerequisiti:</strong><ul style='margin:8px 0 0 18px;padding:0;'><li>Centrale raggiungibile in rete locale</li><li>Interfaccia WebSocket abilitata</li><li>PIN utente valido (4-8 cifre)</li></ul></div></div>",
|
|
7
|
-
"footerDisplay": "<div style='margin-top:16px;padding-top:12px;border-top:1px solid currentColor;'><p style='margin:0 0 8px 0;'>Versione 2.0.1
|
|
7
|
+
"footerDisplay": "<div style='margin-top:16px;padding-top:12px;border-top:1px solid currentColor;'><p style='margin:0 0 8px 0;'>Versione 2.0.1 • Sviluppato da Paolo Trivisonno</p><p style='margin:0;'><a href='https://github.com/paolo-trivi/homebridge-plugin-klares4' target='_blank' rel='noopener noreferrer'>Documentazione</a> | <a href='https://github.com/paolo-trivi/homebridge-plugin-klares4/issues' target='_blank' rel='noopener noreferrer'>Segnala Bug</a> | <a href='https://github.com/sponsors/paolo-trivi' target='_blank' rel='noopener noreferrer'>Supporta</a></p></div>",
|
|
8
8
|
"schema": {
|
|
9
9
|
"type": "object",
|
|
10
10
|
"properties": {
|
|
@@ -300,6 +300,58 @@
|
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
},
|
|
303
|
+
"ksaImport": {
|
|
304
|
+
"type": "object",
|
|
305
|
+
"default": {
|
|
306
|
+
"enabled": false,
|
|
307
|
+
"applyAtStartup": false,
|
|
308
|
+
"applyDomusMappings": true,
|
|
309
|
+
"applyRoomMapping": true,
|
|
310
|
+
"applyCustomNames": false,
|
|
311
|
+
"applyExclusionSuggestions": false
|
|
312
|
+
},
|
|
313
|
+
"properties": {
|
|
314
|
+
"enabled": {
|
|
315
|
+
"title": "Abilita Import KSA",
|
|
316
|
+
"type": "boolean",
|
|
317
|
+
"default": false,
|
|
318
|
+
"description": "Carica il file backup .ksa per generare mapping e metadata strutturali"
|
|
319
|
+
},
|
|
320
|
+
"filePath": {
|
|
321
|
+
"title": "Percorso File .ksa",
|
|
322
|
+
"type": "string",
|
|
323
|
+
"placeholder": "/var/lib/homebridge/prg-xxxx.ksa",
|
|
324
|
+
"description": "Percorso assoluto del file backup .ksa esportato dalla centrale"
|
|
325
|
+
},
|
|
326
|
+
"applyAtStartup": {
|
|
327
|
+
"title": "Applica su config al riavvio",
|
|
328
|
+
"type": "boolean",
|
|
329
|
+
"default": false,
|
|
330
|
+
"description": "Preview + apply: se attivo, applica su config.json e poi si resetta a false"
|
|
331
|
+
},
|
|
332
|
+
"applyDomusMappings": {
|
|
333
|
+
"title": "Applica mapping Domus termostati",
|
|
334
|
+
"type": "boolean",
|
|
335
|
+
"default": true
|
|
336
|
+
},
|
|
337
|
+
"applyRoomMapping": {
|
|
338
|
+
"title": "Applica room mapping",
|
|
339
|
+
"type": "boolean",
|
|
340
|
+
"default": true
|
|
341
|
+
},
|
|
342
|
+
"applyCustomNames": {
|
|
343
|
+
"title": "Applica nomi personalizzati",
|
|
344
|
+
"type": "boolean",
|
|
345
|
+
"default": false
|
|
346
|
+
},
|
|
347
|
+
"applyExclusionSuggestions": {
|
|
348
|
+
"title": "Applica suggerimenti esclusioni",
|
|
349
|
+
"type": "boolean",
|
|
350
|
+
"default": false,
|
|
351
|
+
"description": "Non consigliato di default: applica liste esclusione suggerite dal parser"
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
},
|
|
303
355
|
"mqtt": {
|
|
304
356
|
"type": "object",
|
|
305
357
|
"properties": {
|
|
@@ -619,6 +671,61 @@
|
|
|
619
671
|
}
|
|
620
672
|
]
|
|
621
673
|
},
|
|
674
|
+
{
|
|
675
|
+
"type": "fieldset",
|
|
676
|
+
"title": "Import KSA",
|
|
677
|
+
"expandable": false,
|
|
678
|
+
"items": [
|
|
679
|
+
{
|
|
680
|
+
"key": "ksaImport.enabled",
|
|
681
|
+
"title": "Import KSA Attivo"
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
"key": "ksaImport.filePath",
|
|
685
|
+
"title": "Percorso File .ksa",
|
|
686
|
+
"condition": {
|
|
687
|
+
"functionBody": "return model.ksaImport && model.ksaImport.enabled === true;"
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
"key": "ksaImport.applyAtStartup",
|
|
692
|
+
"title": "Apply alla Config al Prossimo Avvio",
|
|
693
|
+
"description": "Esegue preview nei log e applica i blocchi selezionati, poi torna automaticamente OFF",
|
|
694
|
+
"condition": {
|
|
695
|
+
"functionBody": "return model.ksaImport && model.ksaImport.enabled === true;"
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
"type": "flex",
|
|
700
|
+
"flex-flow": "row wrap",
|
|
701
|
+
"condition": {
|
|
702
|
+
"functionBody": "return model.ksaImport && model.ksaImport.enabled === true;"
|
|
703
|
+
},
|
|
704
|
+
"items": [
|
|
705
|
+
{
|
|
706
|
+
"key": "ksaImport.applyDomusMappings",
|
|
707
|
+
"title": "Domus Mapping",
|
|
708
|
+
"flex": "1 1 200px"
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
"key": "ksaImport.applyRoomMapping",
|
|
712
|
+
"title": "Room Mapping",
|
|
713
|
+
"flex": "1 1 200px"
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
"key": "ksaImport.applyCustomNames",
|
|
717
|
+
"title": "Custom Names",
|
|
718
|
+
"flex": "1 1 200px"
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
"key": "ksaImport.applyExclusionSuggestions",
|
|
722
|
+
"title": "Exclusions",
|
|
723
|
+
"flex": "1 1 200px"
|
|
724
|
+
}
|
|
725
|
+
]
|
|
726
|
+
}
|
|
727
|
+
]
|
|
728
|
+
},
|
|
622
729
|
{
|
|
623
730
|
"type": "fieldset",
|
|
624
731
|
"title": "Scenari",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Logger } from 'homebridge';
|
|
2
|
+
import type { KsaSanitizedCache } from '../types';
|
|
3
|
+
export declare class KsaCacheService {
|
|
4
|
+
private readonly log;
|
|
5
|
+
private readonly cachePath;
|
|
6
|
+
constructor(storagePath: string, log: Logger);
|
|
7
|
+
get path(): string;
|
|
8
|
+
save(cache: KsaSanitizedCache): Promise<void>;
|
|
9
|
+
load(): Promise<KsaSanitizedCache | undefined>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=cache-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-service.d.ts","sourceRoot":"","sources":["../../src/ksa/cache-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAIlD,qBAAa,eAAe;IAGS,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,WAAW,EAAE,MAAM,EAAmB,GAAG,EAAE,MAAM;IAI7D,IAAW,IAAI,IAAI,MAAM,CAExB;IAEY,IAAI,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,IAAI,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;CAmB9D"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.KsaCacheService = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const CACHE_FILE_NAME = 'klares4-ksa-cache.json';
|
|
40
|
+
class KsaCacheService {
|
|
41
|
+
constructor(storagePath, log) {
|
|
42
|
+
this.log = log;
|
|
43
|
+
this.cachePath = path.join(storagePath, CACHE_FILE_NAME);
|
|
44
|
+
}
|
|
45
|
+
get path() {
|
|
46
|
+
return this.cachePath;
|
|
47
|
+
}
|
|
48
|
+
async save(cache) {
|
|
49
|
+
await fs.promises.writeFile(this.cachePath, JSON.stringify(cache, null, 2), 'utf8');
|
|
50
|
+
}
|
|
51
|
+
async load() {
|
|
52
|
+
try {
|
|
53
|
+
const raw = await fs.promises.readFile(this.cachePath, 'utf8');
|
|
54
|
+
const parsed = JSON.parse(raw);
|
|
55
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
if (!Array.isArray(parsed.thermostatPrograms)) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
return parsed;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
65
|
+
if (!message.includes('ENOENT')) {
|
|
66
|
+
this.log.warn(`Unable to load KSA cache: ${message}`);
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.KsaCacheService = KsaCacheService;
|
|
73
|
+
//# sourceMappingURL=cache-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-service.js","sourceRoot":"","sources":["../../src/ksa/cache-service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAI7B,MAAM,eAAe,GAAG,wBAAwB,CAAC;AAEjD,MAAa,eAAe;IAGxB,YAAY,WAAmB,EAAmB,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;QACzD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC7D,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,KAAwB;QACtC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACxF,CAAC;IAEM,KAAK,CAAC,IAAI;QACb,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAC;YACpD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxC,OAAO,SAAS,CAAC;YACrB,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC5C,OAAO,SAAS,CAAC;YACrB,CAAC;YACD,OAAO,MAAM,CAAC;QAClB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,OAAO,SAAS,CAAC;QACrB,CAAC;IACL,CAAC;CACJ;AAlCD,0CAkCC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../src/ksa/derive.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoB,eAAe,EAAgB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEjG,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,gBAAgB,EACzB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,QAAQ,EAAE,MAAM,GACjB,eAAe,CAgBjB"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deriveKsaImportResult = deriveKsaImportResult;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const device_state_projector_1 = require("../websocket/device-state-projector");
|
|
6
|
+
function deriveKsaImportResult(program, sourceFilePath, rawBytes) {
|
|
7
|
+
const cache = buildSanitizedCache(program, sourceFilePath, rawBytes);
|
|
8
|
+
const derivedConfig = buildDerivedConfig(program, cache);
|
|
9
|
+
return {
|
|
10
|
+
summary: {
|
|
11
|
+
outputs: program.outputs.length,
|
|
12
|
+
zones: program.zones.length,
|
|
13
|
+
scenarios: program.scenarios.length,
|
|
14
|
+
sensors: program.busHas.length,
|
|
15
|
+
thermostats: program.thermostats.length,
|
|
16
|
+
rooms: program.rooms.length,
|
|
17
|
+
maps: program.maps.length,
|
|
18
|
+
},
|
|
19
|
+
cache,
|
|
20
|
+
derivedConfig,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function buildSanitizedCache(program, sourceFilePath, rawBytes) {
|
|
24
|
+
const thermostatProgramIdByOutputId = {};
|
|
25
|
+
const domusSensorIdByThermostatProgramId = {};
|
|
26
|
+
const thermostatPrograms = program.thermostats
|
|
27
|
+
.map((thermostat) => {
|
|
28
|
+
const thermostatProgramId = asId(thermostat.ID);
|
|
29
|
+
if (!thermostatProgramId) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const heatingOutputId = normalizeNullableId(thermostat.HEATING_OUT);
|
|
33
|
+
const coolingOutputId = normalizeNullableId(thermostat.COOLING_OUT);
|
|
34
|
+
const domusSensorId = normalizeNullableId(thermostat.PERIPH?.PID);
|
|
35
|
+
if (heatingOutputId) {
|
|
36
|
+
thermostatProgramIdByOutputId[heatingOutputId] = thermostatProgramId;
|
|
37
|
+
}
|
|
38
|
+
if (coolingOutputId) {
|
|
39
|
+
thermostatProgramIdByOutputId[coolingOutputId] = thermostatProgramId;
|
|
40
|
+
}
|
|
41
|
+
if (domusSensorId) {
|
|
42
|
+
domusSensorIdByThermostatProgramId[thermostatProgramId] = domusSensorId;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
id: thermostatProgramId,
|
|
46
|
+
description: normalizeLabel(thermostat.DES) ?? undefined,
|
|
47
|
+
heatingOutputId: heatingOutputId ?? undefined,
|
|
48
|
+
coolingOutputId: coolingOutputId ?? undefined,
|
|
49
|
+
domusSensorId: domusSensorId ?? undefined,
|
|
50
|
+
};
|
|
51
|
+
})
|
|
52
|
+
.filter((entry) => entry !== null);
|
|
53
|
+
return {
|
|
54
|
+
sourceFilePath,
|
|
55
|
+
sourceFileHash: (0, crypto_1.createHash)('sha256').update(rawBytes).digest('hex'),
|
|
56
|
+
parsedAt: new Date().toISOString(),
|
|
57
|
+
thermostatPrograms,
|
|
58
|
+
thermostatProgramIdByOutputId,
|
|
59
|
+
domusSensorIdByThermostatProgramId,
|
|
60
|
+
outputNamesById: toNameRecord(program.outputs),
|
|
61
|
+
zoneNamesById: toNameRecord(program.zones),
|
|
62
|
+
scenarioNamesById: toNameRecord(program.scenarios),
|
|
63
|
+
domusSensorNamesById: toNameRecord(program.busHas.map((sensor) => ({
|
|
64
|
+
ID: sensor.ID,
|
|
65
|
+
DES: sensor.DOMUS?.DES ?? `Sensor ${sensor.ID}`,
|
|
66
|
+
}))),
|
|
67
|
+
roomNameById: toNameRecord(program.rooms),
|
|
68
|
+
roomDeviceRefs: toRoomDeviceRefs(program.maps),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function buildDerivedConfig(program, cache) {
|
|
72
|
+
const outputById = new Map(program.outputs.map((output) => [String(output.ID), output]));
|
|
73
|
+
const roomNameById = cache.roomNameById;
|
|
74
|
+
const roomDevices = new Map();
|
|
75
|
+
for (const map of cache.roomDeviceRefs) {
|
|
76
|
+
const roomName = roomNameById[map.roomId];
|
|
77
|
+
if (!roomName) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const resolvedDeviceIds = resolveRoomMapToDeviceIds(map, outputById);
|
|
81
|
+
if (resolvedDeviceIds.length === 0) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const bucket = roomDevices.get(roomName) ?? new Set();
|
|
85
|
+
for (const deviceId of resolvedDeviceIds) {
|
|
86
|
+
bucket.add(deviceId);
|
|
87
|
+
}
|
|
88
|
+
roomDevices.set(roomName, bucket);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
domusThermostat: {
|
|
92
|
+
manualPairs: Object.entries(cache.thermostatProgramIdByOutputId)
|
|
93
|
+
.map(([outputId, thermostatProgramId]) => ({
|
|
94
|
+
thermostatOutputId: outputId,
|
|
95
|
+
domusSensorId: cache.domusSensorIdByThermostatProgramId[thermostatProgramId],
|
|
96
|
+
}))
|
|
97
|
+
.filter((pair) => Boolean(pair.domusSensorId)),
|
|
98
|
+
manualCommandPairs: Object.entries(cache.thermostatProgramIdByOutputId)
|
|
99
|
+
.map(([outputId, thermostatProgramId]) => ({
|
|
100
|
+
thermostatOutputId: outputId,
|
|
101
|
+
commandThermostatId: thermostatProgramId,
|
|
102
|
+
})),
|
|
103
|
+
},
|
|
104
|
+
roomMapping: {
|
|
105
|
+
enabled: true,
|
|
106
|
+
rooms: [...roomDevices.entries()].map(([roomName, devices]) => ({
|
|
107
|
+
roomName,
|
|
108
|
+
devices: [...devices].map((deviceId) => ({ deviceId })),
|
|
109
|
+
})),
|
|
110
|
+
},
|
|
111
|
+
customNames: {
|
|
112
|
+
outputs: cache.outputNamesById,
|
|
113
|
+
zones: cache.zoneNamesById,
|
|
114
|
+
sensors: cache.domusSensorNamesById,
|
|
115
|
+
scenarios: cache.scenarioNamesById,
|
|
116
|
+
},
|
|
117
|
+
suggestedExclusions: {
|
|
118
|
+
outputs: [],
|
|
119
|
+
zones: [],
|
|
120
|
+
sensors: [],
|
|
121
|
+
scenarios: [],
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function resolveRoomMapToDeviceIds(map, outputById) {
|
|
126
|
+
if (map.objectType === 'prgOutputs') {
|
|
127
|
+
const output = outputById.get(map.objectId);
|
|
128
|
+
if (!output) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
const outputType = (0, device_state_projector_1.determineOutputType)(output.CAT ?? '', output.MOD);
|
|
132
|
+
return [`${outputType}_${map.objectId}`];
|
|
133
|
+
}
|
|
134
|
+
if (map.objectType === 'prgZones') {
|
|
135
|
+
return [`zone_${map.objectId}`];
|
|
136
|
+
}
|
|
137
|
+
if (map.objectType === 'prgScenarios') {
|
|
138
|
+
return [`scenario_${map.objectId}`];
|
|
139
|
+
}
|
|
140
|
+
if (map.objectType === 'prgBusHas') {
|
|
141
|
+
return [`sensor_temp_${map.objectId}`, `sensor_hum_${map.objectId}`, `sensor_light_${map.objectId}`];
|
|
142
|
+
}
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
function toNameRecord(items) {
|
|
146
|
+
const record = {};
|
|
147
|
+
for (const item of items) {
|
|
148
|
+
const id = asId(item.ID);
|
|
149
|
+
if (!id) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const name = normalizeLabel(item.DES);
|
|
153
|
+
if (name) {
|
|
154
|
+
record[id] = name;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return record;
|
|
158
|
+
}
|
|
159
|
+
function toRoomDeviceRefs(maps) {
|
|
160
|
+
return maps
|
|
161
|
+
.map((map) => ({
|
|
162
|
+
roomId: asId(map.ROOM),
|
|
163
|
+
objectType: normalizeLabel(map.OT) ?? '',
|
|
164
|
+
objectId: asId(map.OID),
|
|
165
|
+
}))
|
|
166
|
+
.filter((map) => Boolean(map.roomId) && Boolean(map.objectType) && Boolean(map.objectId));
|
|
167
|
+
}
|
|
168
|
+
function asId(value) {
|
|
169
|
+
if (typeof value === 'string') {
|
|
170
|
+
return value.trim();
|
|
171
|
+
}
|
|
172
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
173
|
+
return Math.trunc(value).toString();
|
|
174
|
+
}
|
|
175
|
+
return '';
|
|
176
|
+
}
|
|
177
|
+
function normalizeNullableId(value) {
|
|
178
|
+
const normalized = asId(value);
|
|
179
|
+
if (!normalized || normalized.toUpperCase() === 'NU' || normalized.toUpperCase() === 'NA') {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
return normalized;
|
|
183
|
+
}
|
|
184
|
+
function normalizeLabel(value) {
|
|
185
|
+
if (typeof value !== 'string') {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const normalized = value.trim();
|
|
189
|
+
return normalized ? normalized : null;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=derive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive.js","sourceRoot":"","sources":["../../src/ksa/derive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/ksa/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAMhD,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAGxF;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAYvE"}
|