data-solectrus 0.2.10
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/.github/workflows/npm-publish.yml +32 -0
- package/CHANGELOG.md +138 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/admin/custom/customComponents.js +2691 -0
- package/admin/data-solectrus.png +0 -0
- package/admin/i18n/de/translations.json +94 -0
- package/admin/i18n/en/translations.json +94 -0
- package/admin/jsonConfig.json +59 -0
- package/io-package.json +39 -0
- package/lib/formula.js +249 -0
- package/lib/jsonpath.js +202 -0
- package/lib/services/evaluator.js +266 -0
- package/lib/services/itemIds.js +56 -0
- package/lib/services/itemManager.js +217 -0
- package/lib/services/snapshot.js +48 -0
- package/lib/services/sourceDiscovery.js +67 -0
- package/lib/services/stateRegistry.js +462 -0
- package/lib/services/subscriptions.js +83 -0
- package/lib/services/tickRunner.js +282 -0
- package/main.js +253 -0
- package/package.json +36 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Publish to NPM
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: npm-publish
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout code
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Setup Node.js
|
|
20
|
+
uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: '18'
|
|
23
|
+
registry-url: 'https://registry.npmjs.org'
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: npm ci
|
|
27
|
+
|
|
28
|
+
- name: Run tests
|
|
29
|
+
run: npm run lint
|
|
30
|
+
|
|
31
|
+
- name: Publish to NPM
|
|
32
|
+
run: npm publish --provenance --access public
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.9 - 2026-01-31
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **BREAKING:** Package renamed from `iobroker.data-solectrus` to `data-solectrus` for NPM namespace compatibility
|
|
8
|
+
- Enabled GitHub Actions automated publishing via Trusted Publishing (OIDC)
|
|
9
|
+
|
|
10
|
+
## 0.2.8 - 2026-01-31
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Official NPM release with automated publishing via GitHub Actions
|
|
15
|
+
- Added NPM version and download badges to README
|
|
16
|
+
- Configured trusted publisher for secure automated releases
|
|
17
|
+
- Restructured info states: 6 core + hierarchical diagnostics (diagnostics.*, diagnostics.timing.*)
|
|
18
|
+
|
|
19
|
+
## 0.2.7 - 2026-01-30
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- New sync diagnostics under `info.*`: input timestamp gap telemetry (`info.inputTsGapMs`, `info.inputTsGapOk`, `info.inputTsGapThresholdMs`, `info.inputTsSources`, `info.inputTsMissing`).
|
|
24
|
+
- Expanded sync diagnostics: active-only gap and culprit helpers (`info.inputTsGapActiveMs`, `info.inputTsSleepingSources`, `info.inputTsOldestId`, `info.inputTsOldestAgeMs`).
|
|
25
|
+
- Runtime setting to enable/disable the input timestamp gap diagnostics (`enableInputTsGapDiagnostics`).
|
|
26
|
+
- New deterministic regression check script: `npm run check:simulate` (30s / 6 ticks) to validate PV + signed grid meter scenarios.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Admin UI: clearer wording + tooltip for “Ergebnis negativ → 0” (mode-aware hint: source vs formula).
|
|
31
|
+
- Docs: README + Wiki updated to clarify output clamp vs per-input clamp.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- Formula evaluation: item-level `noNegative` no longer clamps negative *inputs* (important for signed meters where export is negative). Only per-input `noNegative` clamps that input; item-level `noNegative` clamps the final result.
|
|
36
|
+
- Source mode: output datatype handling corrected (string/boolean/mixed items no longer force numeric parsing; primitives are mirrored correctly).
|
|
37
|
+
- Sync diagnostics robustness: initial reads now populate the timestamp cache so `info.inputTsGap*` works immediately after startup.
|
|
38
|
+
|
|
39
|
+
## 0.2.6 - 2026-01-29
|
|
40
|
+
- **Info states structure**: Reorganized `info.*` states for better readability and logical grouping (Variante D):
|
|
41
|
+
- Core states: `info.status`, `info.itemsActive`, `info.lastError`, `info.lastRun`, `info.lastRunMs`
|
|
42
|
+
- Diagnostics moved to: `info.diagnostics.*` (eval stats) and `info.diagnostics.timing.*` (timestamp skew)
|
|
43
|
+
- Old info states are automatically cleaned up on adapter restart
|
|
44
|
+
- Renamed: `evalTimeMs` → `lastRunMs`, `itemsEnabled` → `itemsActive`, `itemsConfigured` → `diagnostics.itemsTotal`
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- Admin UI: Formula Builder popup for building formulas with a palette (operators/functions/state pickers).
|
|
49
|
+
- Admin UI: Live input values inside the builder (polling while popup is open).
|
|
50
|
+
- Admin UI: Local in-browser formula preview pill (updates automatically while popup is open).
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- Admin UI: Builder crash on open (runtime error in custom UI script).
|
|
55
|
+
- Admin UI: Formula Builder live values now respect JSONPath and input clamping (neg→0) in the preview.
|
|
56
|
+
|
|
57
|
+
## 0.2.5 - 2026-01-29
|
|
58
|
+
|
|
59
|
+
### Changed
|
|
60
|
+
|
|
61
|
+
- Internal refactor: extracted formula parsing/evaluation and JSONPath helpers into separate modules under `lib/` to keep `main.js` smaller and easier to maintain.
|
|
62
|
+
- No functional changes intended.
|
|
63
|
+
|
|
64
|
+
## 0.2.4 - 2026-01-29
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- Subscription management hardening: subscriptions are now derived from enabled items and kept in sync (unsubscribe removed ids). A global cap prevents runaway subscription counts.
|
|
69
|
+
- Tick time budget to avoid long ticks piling up; new telemetry states: `info.timeBudgetMs` and `info.skippedItems`.
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- Output type consistency: formula results are no longer forced numeric for `string`/`boolean`/`mixed` outputs.
|
|
74
|
+
- Fallback after repeated errors is now type-appropriate (e.g. `''` for string outputs instead of `'0'`).
|
|
75
|
+
|
|
76
|
+
## 0.2.3 - 2026-01-29
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- Formula inputs with JSONPath can now yield strings/booleans (not only numbers). This enables conditions like `IF(opMode == 'Heating', ..., 0)` when `opMode` is an input extracted from a JSON payload.
|
|
81
|
+
- Numeric-like strings (e.g. `"12.2"`) are still treated as numbers to keep strict comparisons (`===`) working as expected.
|
|
82
|
+
|
|
83
|
+
## 0.2.2 - 2026-01-29
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- New formula helper `jp("state.id", "jsonPath")` to read primitive values (string/number/boolean) from JSON payload states via the built-in minimal JSONPath.
|
|
88
|
+
- This enables conditions like `IF(jp("...", "$['Operation Mode']") == 'Heating', ..., 0)` without requiring separate input states.
|
|
89
|
+
- Per-item diagnostics states under `data-solectrus.0.items.<outputId>.*`:
|
|
90
|
+
- `compiledOk`, `compileError`, `lastError`, `lastOkTs`, `lastEvalMs`, `consecutiveErrors`.
|
|
91
|
+
|
|
92
|
+
### Changed
|
|
93
|
+
|
|
94
|
+
- Robust tick behavior: formula/compile/snapshot failures no longer stop the adapter; errors are handled per item.
|
|
95
|
+
- Fallback behavior on errors: keep the last good value for a few retries, then set the output to `0` (config key `errorRetriesBeforeZero`, default: 3).
|
|
96
|
+
- Performance: formulas are compiled once per item (normalized expression + AST) and reused during ticks; snapshot/subscriptions use compiled source ids.
|
|
97
|
+
- Config change detection: when items change without restart, the adapter rebuilds compiled caches on the next tick.
|
|
98
|
+
|
|
99
|
+
## 0.2.1 - 2026-01-29
|
|
100
|
+
|
|
101
|
+
### Added
|
|
102
|
+
|
|
103
|
+
- Formula function `IF(condition, valueIfTrue, valueIfFalse)` (alias: `if(...)`).
|
|
104
|
+
- Helper `v("state.id")` to read raw foreign state values (string/boolean/number) from cache/snapshot.
|
|
105
|
+
- Compatibility normalization in formulas (outside strings): `AND`/`OR`/`NOT` and single `=`.
|
|
106
|
+
|
|
107
|
+
### Changed
|
|
108
|
+
|
|
109
|
+
- Expression engine: re-introduced `==` and `!=` for compatibility with existing formula styles (use `===`/`!==` when you want strict matching).
|
|
110
|
+
- `s("...")` / `v("...")` state ids are now discovered from formulas and included in snapshot/subscriptions.
|
|
111
|
+
|
|
112
|
+
## 0.2.0 - 2026-01-29
|
|
113
|
+
|
|
114
|
+
### Added
|
|
115
|
+
|
|
116
|
+
- Formula function `pow(a, b)` (use this instead of an exponent operator).
|
|
117
|
+
- One-time debug logs for blocked dangerous input keys and for skipped JSONPath when the source value is already numeric.
|
|
118
|
+
|
|
119
|
+
### Changed
|
|
120
|
+
|
|
121
|
+
- Security hardening: formula input variables use a null-prototype map and block dangerous keys (`__proto__`, `prototype`, `constructor`).
|
|
122
|
+
- Expression engine: removed support for `**` and for loose equality operators `==` / `!=` (use `===` / `!==`).
|
|
123
|
+
- Bounded internal "log once" caches to avoid unbounded growth.
|
|
124
|
+
|
|
125
|
+
## 0.1.22 - 2026-01-28
|
|
126
|
+
|
|
127
|
+
### Added
|
|
128
|
+
|
|
129
|
+
- Optional JSON extraction for `source` items and formula inputs via **JSONPath (optional)** (e.g. `$.apower`, `$.aenergy.by_minute[2]`).
|
|
130
|
+
|
|
131
|
+
### Changed
|
|
132
|
+
|
|
133
|
+
- Wiki/README updated: JSON payloads no longer require a separate alias/script when JSONPath is configured.
|
|
134
|
+
- When `Datatype` is set to `boolean` or `string`, the adapter now writes real booleans/strings to the output state (not 0/1).
|
|
135
|
+
|
|
136
|
+
### Notes
|
|
137
|
+
|
|
138
|
+
- JSONPath support is intentionally limited (dot access, bracket keys, array indexes). Unsupported expressions fall back to `0` and log a warning once.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sven Griese
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# ioBroker.Data-SOLECTRUS
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
<img src="admin/data-solectrus.png" alt="SOLECTRUS" width="120" />
|
|
8
|
+
|
|
9
|
+
Ein kleiner ioBroker-Adapter, der eigene States unter `data-solectrus.0.*` anlegt und im festen Intervall (Standard: 5s, **wall-clock aligned**) mit berechneten oder gespiegelten Werten befüllt.
|
|
10
|
+
|
|
11
|
+
Kurz gesagt: 🧮 **Formeln** + 🔌 **beliebige ioBroker-States** → 📦 **saubere, adapter-eigene Ziel-States** (z.B. für SOLECTRUS-Dashboards).
|
|
12
|
+
|
|
13
|
+
## 📑 Inhaltsverzeichnis
|
|
14
|
+
|
|
15
|
+
- [✨ Highlights](#-highlights)
|
|
16
|
+
- [📦 Installation](#-installation)
|
|
17
|
+
- [🚀 Quickstart](#-quickstart)
|
|
18
|
+
- [⚡ Wichtige Semantik (Vorzeichen & Clamps)](#-wichtige-semantik-vorzeichen--clamps)
|
|
19
|
+
- [📚 Wiki & Anwendungsbeispiele](#-wiki--anwendungsbeispiele)
|
|
20
|
+
- [📊 Diagnose-States](#-diagnose-states)
|
|
21
|
+
- [🔧 Entwicklung & Tests](#-entwicklung--tests)
|
|
22
|
+
- [⚙️ Konfiguration](#-konfiguration)
|
|
23
|
+
- [🧮 Formeln](#-formeln)
|
|
24
|
+
|
|
25
|
+
## ✨ Highlights
|
|
26
|
+
|
|
27
|
+
- 🔗 **Quell-Items**: 1:1 spiegeln (optional mit JSONPath)
|
|
28
|
+
- 🧮 **Formel-Items**: Werte aus vielen Quellen zusammenrechnen
|
|
29
|
+
- 📸 **Snapshot-Modus**: Reduziert Timing-Effekte bei zeitversetzten Quell-Updates
|
|
30
|
+
- 🎚️ **Ergebnis-Regeln**: Clamps am Ergebnis (z.B. negativ → 0, Min/Max)
|
|
31
|
+
- 📊 **Diagnose-States**: Laufzeit, Fehler und Sync-Statistiken
|
|
32
|
+
|
|
33
|
+
## 📦 Installation
|
|
34
|
+
|
|
35
|
+
Der Adapter kann lokal als `.tgz` gebaut und in ioBroker installiert werden (oder via GitHub-Release, falls vorhanden).
|
|
36
|
+
|
|
37
|
+
- Paket bauen: `npm pack`
|
|
38
|
+
- Installation in ioBroker: Admin → Adapter → „Benutzerdefiniert" / URL/Datei → `data-solectrus-<version>.tgz` (z.B. `data-solectrus-0.2.9.tgz`)
|
|
39
|
+
- Oder direkt von NPM: `npm install data-solectrus`
|
|
40
|
+
|
|
41
|
+
Hinweis: Adaptername in ioBroker ist `data-solectrus` (Instanz: `data-solectrus.0`).
|
|
42
|
+
|
|
43
|
+
## 🚀 Quickstart
|
|
44
|
+
|
|
45
|
+
Der Adapter ist absichtlich „leer" – du legst nur die Werte an, die du brauchst.
|
|
46
|
+
|
|
47
|
+
### 1️⃣ Werte anlegen
|
|
48
|
+
**Admin → Adapter → data-solectrus → Werte**
|
|
49
|
+
|
|
50
|
+
- **Modus „Quelle"**: Genau einen State 1:1 spiegeln
|
|
51
|
+
- **Modus „Formel"**: Mehrere Inputs zusammenrechnen
|
|
52
|
+
|
|
53
|
+
### 2️⃣ Snapshot aktivieren (optional)
|
|
54
|
+
**Globale Einstellungen**
|
|
55
|
+
|
|
56
|
+
Wenn deine Quellen zeitversetzt updaten und du kurzzeitig unplausible Kombinationen siehst, aktiviere den Snapshot-Modus.
|
|
57
|
+
|
|
58
|
+
## ⚡ Wichtige Semantik (Vorzeichen & Clamps)
|
|
59
|
+
|
|
60
|
+
### Ergebnis negativ → 0
|
|
61
|
+
|
|
62
|
+
Die Option **„Ergebnis negativ → 0“** wirkt nur auf das **Ergebnis** des Items (Output).
|
|
63
|
+
|
|
64
|
+
- Wenn du nur einzelne Inputs bereinigen willst (z.B. PV darf nie negativ sein, aber Netzleistung ist signed), nutze dafür pro Input **„neg→0“** oder `max(0, …)` in der Formel.
|
|
65
|
+
|
|
66
|
+
### Beispiel: Hausverbrauch aus PV + signed Netzleistung
|
|
67
|
+
|
|
68
|
+
- `gridSigned`: Import positiv, Export negativ
|
|
69
|
+
- Hausverbrauch: `pvTotal + gridSigned`
|
|
70
|
+
|
|
71
|
+
Wenn PV=4639W und Export=-2514W, ergibt sich Hausverbrauch ≈ 2125W.
|
|
72
|
+
|
|
73
|
+
## 📚 Wiki & Anwendungsbeispiele
|
|
74
|
+
|
|
75
|
+
Ausführliche Beispiele und Erklärungen findest du im Wiki:
|
|
76
|
+
👉 https://github.com/Felliglanz/data-solectrus/wiki
|
|
77
|
+
|
|
78
|
+
**Direktlinks:**
|
|
79
|
+
|
|
80
|
+
- 🏠 [Hausverbrauch berechnen](https://github.com/Felliglanz/data-solectrus/wiki/Hausverbrauch)
|
|
81
|
+
- 🎚️ [Werte begrenzen](https://github.com/Felliglanz/data-solectrus/wiki/Werte-begrenzen)
|
|
82
|
+
- 🔧 [Formel-Builder nutzen](https://github.com/Felliglanz/data-solectrus/wiki/Formel-Builder)
|
|
83
|
+
- 📖 [Alle Anwendungsfälle](https://github.com/Felliglanz/data-solectrus/wiki/Use-Cases)
|
|
84
|
+
|
|
85
|
+
## 📊 Diagnose-States
|
|
86
|
+
|
|
87
|
+
Der Adapter legt strukturierte States unter `data-solectrus.0.info.*` an:
|
|
88
|
+
|
|
89
|
+
### 🎯 Kern-Infos (immer sichtbar)
|
|
90
|
+
|
|
91
|
+
- `info.connection` – Standard ioBroker Verbindungsstatus
|
|
92
|
+
- `info.itemsActive` – Anzahl aktivierter Werte
|
|
93
|
+
- `info.lastError` – Letzter Fehler (leer wenn alles OK)
|
|
94
|
+
- `info.lastRun` – Zeitstempel letzter Durchlauf (ISO 8601)
|
|
95
|
+
- `info.lastRunMs` – Dauer letzter Durchlauf (ms)
|
|
96
|
+
- `info.status` – Adapter-Status (`starting`, `ok`, `no_items_enabled`)
|
|
97
|
+
|
|
98
|
+
### 🔍 Diagnose (eingeklappt im Objektbaum)
|
|
99
|
+
|
|
100
|
+
**`info.diagnostics.*`**
|
|
101
|
+
|
|
102
|
+
- `evalBudgetMs` – Verfügbare Zeit pro Durchlauf (ms)
|
|
103
|
+
- `evalSkipped` – Übersprungene Werte im letzten Durchlauf
|
|
104
|
+
- `itemsTotal` – Gesamtzahl konfigurierter Werte (aktiv + inaktiv)
|
|
105
|
+
|
|
106
|
+
**`info.diagnostics.timing.*`** *(Timestamp-Analyse für zeitversetzte Quellen)*
|
|
107
|
+
|
|
108
|
+
- `gapMs` – Differenz zwischen ältestem und neuestem Eingabe-Zeitstempel (ms)
|
|
109
|
+
- `gapOk` – ✅ wenn Differenz unter Schwellwert
|
|
110
|
+
- `gapActiveMs` – Differenz nur für aktive Quellen (ms)
|
|
111
|
+
- `gapActiveOk` – ✅ wenn aktive Differenz unter Schwellwert
|
|
112
|
+
- `sources` – Anzahl Eingaben mit Zeitstempel
|
|
113
|
+
- `sourcesActive` – Anzahl aktiver Eingaben (kürzlich aktualisiert)
|
|
114
|
+
- `sourcesSleeping` – Anzahl schlafender Eingaben (alte Zeitstempel)
|
|
115
|
+
- `oldestId` – State-ID mit ältestem Zeitstempel
|
|
116
|
+
- `oldestAgeMs` – Alter der ältesten Eingabe (ms)
|
|
117
|
+
- `newestId` – State-ID mit neuestem Zeitstempel
|
|
118
|
+
- `newestAgeMs` – Alter der neuesten Eingabe (ms)
|
|
119
|
+
|
|
120
|
+
### 📈 Pro-Wert Diagnose
|
|
121
|
+
|
|
122
|
+
Unter `data-solectrus.0.items.<outputId>.*`:
|
|
123
|
+
|
|
124
|
+
- `compiledOk` – ✅ Kompilierung erfolgreich
|
|
125
|
+
- `compileError` – Kompilierungs-Fehler (leer bei OK)
|
|
126
|
+
- `lastError` – Letzter Laufzeit-Fehler
|
|
127
|
+
- `lastOkTs` – Zeitstempel letzte erfolgreiche Berechnung
|
|
128
|
+
- `lastEvalMs` – Dauer letzte Berechnung (ms)
|
|
129
|
+
- `consecutiveErrors` – Anzahl aufeinanderfolgender Fehler
|
|
130
|
+
|
|
131
|
+
## 🔧 Entwicklung & Tests
|
|
132
|
+
|
|
133
|
+
Für schnelle Checks (z.B. nach Refactorings) gibt es einen Runtime-Smoke-Test, der **ohne** ioBroker-Controller läuft.
|
|
134
|
+
Er mockt die minimal benötigte Adapter-API und führt einmalig diese Phasen aus:
|
|
135
|
+
|
|
136
|
+
- `cleanupOldInfoStates()` (räumt alte Struktur auf)
|
|
137
|
+
- `createInfoStates()` (legt neue Struktur an)
|
|
138
|
+
- `prepareItems()` (inkl. Formel-Compile, Source-Discovery, Subscriptions)
|
|
139
|
+
- `runTick()` (ein Tick mit Snapshot + Berechnung + Output-States)
|
|
140
|
+
|
|
141
|
+
Ausführen:
|
|
142
|
+
|
|
143
|
+
- `npm run smoke`
|
|
144
|
+
|
|
145
|
+
## ⚙️ Konfiguration
|
|
146
|
+
|
|
147
|
+
Die Konfiguration ist absichtlich **leer** – du fügst nur die Werte hinzu, die du brauchst.
|
|
148
|
+
|
|
149
|
+
### 🌍 Globale Einstellungen
|
|
150
|
+
|
|
151
|
+
**⏱️ Aktualisierungs-Intervall**
|
|
152
|
+
- Intervall in Sekunden (min. 1 Sekunde)
|
|
153
|
+
- Läuft synchron zur Uhr: Bei 5s → `...:00, ...:05, ...:10, ...`
|
|
154
|
+
|
|
155
|
+
**📸 Snapshot-Modus (optional)**
|
|
156
|
+
- **Eingaben synchron einlesen**: Liest alle benötigten States einmal pro Durchlauf aktiv ein
|
|
157
|
+
- Reduziert Abweichungen, wenn Quellen zeitversetzt aktualisieren
|
|
158
|
+
- **Snapshot-Verzögerung**: Optionaler Delay in ms (z.B. 100–300ms) nach dem Durchlauf-Start
|
|
159
|
+
|
|
160
|
+
**🛡️ Fehlerbehandlung**
|
|
161
|
+
- `errorRetriesBeforeZero` – Anzahl Fehlversuche, bevor Output auf `0` gesetzt wird (Standard: 3)
|
|
162
|
+
|
|
163
|
+
### 📝 Werte konfigurieren
|
|
164
|
+
|
|
165
|
+
Jeder Eintrag erzeugt genau **einen Output-State**.
|
|
166
|
+
|
|
167
|
+
Felder:
|
|
168
|
+
|
|
169
|
+
- **Enabled**: aktiviert/deaktiviert.
|
|
170
|
+
- **Name**: Anzeigename (optional).
|
|
171
|
+
- **Folder/Group**: optionaler Ordner/Channel-Prefix.
|
|
172
|
+
- Beispiel: `pv` + Target ID `leistung` → Output wird `data-solectrus.0.pv.leistung`.
|
|
173
|
+
- **Target ID**: Ziel-State innerhalb des Adapters (relativ). Beispiel: `leistung`, `pv.gesamt`.
|
|
174
|
+
- Erlaubt sind nur Segmente mit `A-Z`, `a-z`, `0-9`, `_`, `-` und `.` (keine absoluten IDs, kein `..`).
|
|
175
|
+
- **Mode**:
|
|
176
|
+
- `source`: 1:1 Spiegelung eines ioBroker-States (mit optionaler Nachbearbeitung).
|
|
177
|
+
- `formula`: Berechnung aus mehreren Inputs.
|
|
178
|
+
- **ioBroker Source State**:
|
|
179
|
+
- bei `mode=source`: der Quell-State (vollqualifiziert, z.B. `some.adapter.0.channel.state`).
|
|
180
|
+
- bei `mode=formula`: pro Input ein Source-State.
|
|
181
|
+
- **JSONPath (optional)**:
|
|
182
|
+
- Wenn der Source-State (oder ein Input) statt einer Zahl ein JSON als Text enthält, kann hier ein JSONPath angegeben werden, um daraus einen numerischen Wert zu extrahieren.
|
|
183
|
+
- Beispiele: `$.apower`, `$.aenergy.by_minute[2]`
|
|
184
|
+
- **Inputs** (nur `mode=formula`): Liste aus (Key, Source State).
|
|
185
|
+
- Optional pro Input: **Input negativ auf 0** (klemmt nur diesen Input vor der Rechnung).
|
|
186
|
+
- Optional pro Input: **JSONPath**
|
|
187
|
+
- Wenn JSONPath auf einen String/Boolean zeigt, wird dieser Wert als Variable bereitgestellt (z.B. für `IF(opMode == 'Heating', ...)`).
|
|
188
|
+
- Wenn JSONPath auf eine Zahl zeigt (oder einen numerischen String wie `"12.2"`), wird der Wert als Zahl bereitgestellt.
|
|
189
|
+
- **Wichtig zu Keys**: In Formeln sind `-` und Leerzeichen Operatoren/Trenner.
|
|
190
|
+
- Verwende daher am besten nur `a-z`, `0-9`, `_` (z.B. `bkw_garage`, `enpal`, `zendure`).
|
|
191
|
+
- Intern werden ungültige Zeichen im Key zu `_` umgewandelt.
|
|
192
|
+
- **Formula expression**: Formel-String.
|
|
193
|
+
- **Datatype**: optional (Standard: number).
|
|
194
|
+
- **Role**, **Unit**: optional (für Metadaten).
|
|
195
|
+
|
|
196
|
+
Nachbearbeitung:
|
|
197
|
+
|
|
198
|
+
- **Clamp negative to 0**: negative Werte werden auf `0` gesetzt.
|
|
199
|
+
- wirkt auf das **Ergebnis** des Items (Output).
|
|
200
|
+
- wenn du nur einzelne Quellen/Inputs „bereinigen“ willst (z.B. PV darf nie negativ sein, aber Netzleistung ist signed), nutze dafür **Input negativ auf 0** direkt am jeweiligen Input oder `max(0, …)` in der Formel.
|
|
201
|
+
- **Clamp result**: Ergebnis begrenzen (Min/Max). Leere Felder bedeuten „nicht begrenzen“.
|
|
202
|
+
|
|
203
|
+
## 🧮 Formeln
|
|
204
|
+
|
|
205
|
+
### Variablen
|
|
206
|
+
|
|
207
|
+
Variablen kommen aus den **Eingaben** (Schlüssel → Quell-State).
|
|
208
|
+
|
|
209
|
+
**Beispiel:**
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
// Eingaben definiert:
|
|
213
|
+
pv1 = 1000
|
|
214
|
+
pv2 = 1500
|
|
215
|
+
pv3 = 800
|
|
216
|
+
|
|
217
|
+
// Formel:
|
|
218
|
+
pv1 + pv2 + pv3 // = 3300
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**🔧 Verfügbare Funktionen:**
|
|
222
|
+
|
|
223
|
+
Siehe [Formel-Builder Wiki](https://github.com/Felliglanz/data-solectrus/wiki/Formel-Builder) für alle mathematischen Funktionen, Operatoren und Beispiele.
|
|
224
|
+
|
|
225
|
+
**✅ Tests ausführen:**
|
|
226
|
+
|
|
227
|
+
- `npm run lint` – Syntax-Prüfung
|
|
228
|
+
- `npm run smoke` – Runtime-Test (mockt ioBroker)
|
|
229
|
+
- `npm run check:simulate` – 30s Regressions-Test (PV + signed Meter)
|