iobroker.zeptrion 0.8.3 → 0.8.5

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 CHANGED
@@ -7,62 +7,62 @@
7
7
  [![Tests](https://github.com/bueste/ioBroker.zeptrion/workflows/Test%20and%20Release/badge.svg)](https://github.com/bueste/ioBroker.zeptrion/actions)
8
8
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
9
 
10
- Adapter für Feller **zeptrion / zApp** WLAN-Aktoren (WLAN-Nebenstelle 4K = zApp-Gateway,
11
- WLAN-Zwischenmodul 2K = zApp-Booster) für Licht- und Storensteuerung, basierend auf der
12
- zrap Webservice API (Feller-Dokument 10.ZEPAPI-E.1612 / Version 1.0, Firmware ab 01.08.18).
13
-
14
-
15
-
16
- ## Funktionsumfang
17
-
18
- - **Kanalsteuerung** (`zrap/chctrl`): on/off/stop/toggle, open/close, move_open/move_close,
19
- dim_up/dim_down inkl. zeitgesteuerter Varianten (`_t` in ms), sowie Szenen
20
- recall_s1-4 / store_s1-4 / delete_s1-4 - als einzelne Buttons UND als freies
21
- `command`-Textfeld.
22
- - **Kanalzustand** (`zrap/chscan` als periodischer Resync + `zrap/chnotify` als
23
- Long-Poll-Push für nahezu Echtzeit-Updates) und **Kanalbeschreibung** (`zrap/chdes`,
24
- read/write: Name, Gruppe, Icon, Typ, Kategorie).
25
- - **Geräteinformationen** (`zrap/id`): Hardware-/Software-/Bootloader-Version, Seriennummer,
26
- Systemname, Gerätetyp.
27
- - **Signalstärke** (`zrap/rssi`, gepollt).
28
- - **Netzwerkstatus** (`zrap/net`, read-only): SSID, IP, MAC, Modus, Verschlüsselung,
29
- Maske, Gateway.
30
- - **Systembefehle** (`zrap/sys`): Neustart, Werksreset, Zurücksetzen in Access-Point-Modus.
31
- - **Standort** (`zrap/loc`), **NTP-Konfiguration** (`zrap/ntp`) und **Datum/Zeit**
32
- (`zrap/date`) inkl. Ein-Klick-Synchronisation der Geräte-Uhrzeit mit dem ioBroker-Host.
33
- - **mDNS-Discovery** (Kapitel 4 der API-Doku): durchsucht das lokale Netz nach
34
- zeptrion-Geräten und übernimmt Funde deaktiviert in die Konfigurationstabelle
35
- (Discovery kombiniert mit manueller Kontrolle/Aktivierung).
36
- - **Sammelbefehle für Hagelalarm**: `control.closeAllShutters` / `openAllShutters` /
37
- `stopAllShutters` steuern alle konfigurierten Kanäle über alle aktiven Geräte gleichzeitig
38
- - dank Multicast-Bündelung (siehe unten) als je EIN Request pro Gerät, nicht pro Kanal.
39
- - **Multicast-Befehlsbündelung**: Kanalbefehle desselben Geräts, die innerhalb von 50ms
40
- eintreffen, werden automatisch zu einem einzigen `zrap/chctrl`-Multicast-POST gebündelt
41
- (Kapitel 3.6.5 der API-Doku) statt mehrerer sequentieller Einzelrequests.
42
- - **Storen-Positionsschätzung** (optional, `posEstimate`): da die Hardware laut Doku für
43
- Storenkanäle praktisch immer `-1` (unbekannt) liefert, kann pro Gerät eine
44
- Motor-Laufzeit hinterlegt werden; der Adapter schätzt daraus die Position anhand
45
- Bewegungsrichtung und verstrichener Zeit (Best Effort, kein Hardware-Feedback,
46
- manuell kalibrierbar).
47
- - **Smartfront-Unterstützung** (optional, `zapi/smartfront/*`): Temperatur/Helligkeit/
48
- Luftfeuchtigkeit auslesen, LED-Hintergrundfarbe setzen (nur für Geräte mit
49
- angeschlossenem Feller-Smartfront-Taster, Checkbox in der Konfiguration).
50
- - Robustes Error-Handling: unterscheidet ECONNREFUSED/Timeout/DNS-Fehler, Backoff bei
51
- wiederholten Fehlern, pro Gerät und global sichtbarer Verbindungsstatus. mDNS-Discovery
52
- ist zusätzlich gegen Exceptions durch fremde/kaputte Netzwerkpakete abgesichert.
53
-
54
- Nicht implementiert (siehe "Bekannte Einschränkungen"): Schreibzugriff auf `zrap/net`
55
- (WLAN-Zugangsdaten ändern), `zrap/scheduler`, Smartbutton-Webhook-Programmierung
10
+ Adapter for Feller **zeptrion / zApp** WLAN actuators (WLAN Nebenstelle 4K = zApp gateway,
11
+ WLAN Zwischenmodul 2K = zApp booster) for light and shutter/blind control, based on the
12
+ zrap web service API (Feller document 10.ZEPAPI-E.1612 / version 1.0, firmware from 01.08.18).
13
+
14
+ _(Eine deutsche Version dieser README ist verfügbar unter [README_de.md](README_de.md).)_
15
+
16
+ ## Feature overview
17
+
18
+ - **Channel control** (`zrap/chctrl`): on/off/stop/toggle, open/close, move_open/move_close,
19
+ dim_up/dim_down including timed variants (`_t` in ms), as well as scenes
20
+ recall_s1-4 / store_s1-4 / delete_s1-4 - both as individual buttons AND as a free-text
21
+ `command` field.
22
+ - **Channel state** (`zrap/chscan` as a periodic resync + `zrap/chnotify` as a long-poll
23
+ push for near real-time updates) and **channel description** (`zrap/chdes`,
24
+ read/write: name, group, icon, type, category).
25
+ - **Device information** (`zrap/id`): hardware/software/bootloader version, serial number,
26
+ system name, device type.
27
+ - **Signal strength** (`zrap/rssi`, polled).
28
+ - **Network status** (`zrap/net`, read-only): SSID, IP, MAC, mode, encryption,
29
+ mask, gateway.
30
+ - **System commands** (`zrap/sys`): reboot, factory reset, reset to access-point mode.
31
+ - **Location** (`zrap/loc`), **NTP configuration** (`zrap/ntp`) and **date/time**
32
+ (`zrap/date`) including one-click synchronization of the device clock with the ioBroker host.
33
+ - **mDNS discovery** (chapter 4 of the API documentation): scans the local network for
34
+ zeptrion devices and adds finds to the configuration table in a disabled state
35
+ (discovery combined with manual review/activation).
36
+ - **Bulk commands for hail alerts**: `control.closeAllShutters` / `openAllShutters` /
37
+ `stopAllShutters` control all configured channels across all active devices at once
38
+ - thanks to multicast bundling (see below), as a single request per device, not per channel.
39
+ - **Multicast command bundling**: channel commands for the same device that arrive within
40
+ 50ms of each other are automatically bundled into a single `zrap/chctrl` multicast POST
41
+ (chapter 3.6.5 of the API documentation) instead of several sequential individual requests.
42
+ - **Shutter position estimation** (optional, `posEstimate`): since the hardware, per the
43
+ documentation, practically always reports `-1` (unknown) for shutter channels, a motor
44
+ travel time can be configured per device; the adapter estimates the position from this
45
+ based on direction of movement and elapsed time (best effort, no hardware feedback,
46
+ manually calibratable).
47
+ - **Smartfront support** (optional, `zapi/smartfront/*`): read temperature/brightness/
48
+ humidity, set LED background color (only for devices with a connected Feller Smartfront
49
+ switch, checkbox in the configuration).
50
+ - Robust error handling: distinguishes ECONNREFUSED/timeout/DNS errors, backoff on
51
+ repeated failures, per-device and global connection status. mDNS discovery is
52
+ additionally hardened against exceptions caused by malformed/unrelated network packets.
53
+
54
+ Not implemented (see "Known limitations"): write access to `zrap/net`
55
+ (changing WLAN credentials), `zrap/scheduler`, Smartbutton webhook programming
56
56
  (`zapi/smartbt/*`).
57
57
 
58
58
  ## Installation
59
59
 
60
- ### a) Lokal/manuell (vor Store-Veröffentlichung)
60
+ ### a) Local/manual (before store publication)
61
61
 
62
62
  ```bash
63
63
  cd /opt/iobroker/node_modules
64
64
  mkdir iobroker.zeptrion
65
- # Dateien dieses Pakets hierhin kopieren
65
+ ## copy the files of this package here
66
66
  cd iobroker.zeptrion
67
67
  npm install --production
68
68
 
@@ -71,193 +71,215 @@ iobroker upload zeptrion
71
71
  iobroker add zeptrion
72
72
  ```
73
73
 
74
- ### b) Über den ioBroker Adapter-Store (nach erfolgter Veröffentlichung)
75
-
76
- Admin-Oberfläche -> Adapter -> "zeptrion" suchen -> Installieren.
77
-
78
- ## Konfiguration
79
-
80
- - **HTTP Timeout**: Timeout pro Request an ein Gerät (Default 4000 ms).
81
- - **Discovery-Button**: durchsucht das lokale Netz per mDNS (Service-Type `_zapp._tcp`,
82
- Fallback `_http._tcp` für Firmware < 01.08.xx anhand des Hostname-Musters
83
- `zapp-YYWWNNNN`). Neu gefundene Geräte werden **deaktiviert** in die Tabelle
84
- übernommen - Zeile danach prüfen, ID/Name vergeben, Kanalzahl kontrollieren
85
- (3340-4-x = 4 Kanäle, 3340-2-x = 2 Kanäle) und aktivieren. mDNS funktioniert nur
86
- innerhalb des gleichen Netzsegments/VLANs.
87
- - **Geräte-Tabelle** (auch komplett manuell befüllbar, ohne Discovery):
88
- - `Aktiv`, `ID` (a-z 0-9 _ -), `Bezeichnung`, `IP-Adresse/Hostname`,
89
- `Kanäle` (1-4), `Art` (Storen/Licht/unbekannt - steuert die ioBroker-Objektrollen,
90
- siehe unten), `Laufzeit Storenmotor` (Sekunden, 0=deaktiviert - schaltet
91
- `posEstimate` frei, siehe unten, gilt als Standard für alle Kanäle),
92
- `Laufzeit/Kanal` (optional, kommagetrennt, z.B. `22,28` - überschreibt die
93
- Standard-Laufzeit einzeln je Kanal; nützlich bei 2K-Geräten, deren beide
94
- Kanäle unterschiedliche Motor-Laufzeiten haben; leere Einträge fallen auf
95
- die Standard-Laufzeit zurück), `Smartfront` (Checkbox, nur bei angeschlossenem
96
- Feller-Smartfront-Taster aktivieren), `Poll (s)` (Default 30, für RSSI +
97
- periodischen chscan-Resync; die eigentlichen Kanalupdates laufen über den
98
- chnotify-Long-Poll unabhängig davon).
99
-
100
- ## Objektbaum pro Gerät (`zeptrion.0.<id>`)
74
+ ### b) Via the ioBroker Adapter Store (once published)
75
+
76
+ Admin UI -> Adapters -> search for "zeptrion" -> Install.
77
+
78
+ ## Configuration
79
+
80
+ - **HTTP Timeout**: timeout per request to a device (default 4000 ms).
81
+ - **Discovery button**: scans the local network via mDNS (service type `_zapp._tcp`,
82
+ fallback `_http._tcp` for firmware < 01.08.xx based on the hostname pattern
83
+ `zapp-YYWWNNNN`). Newly found devices are added to the table in a **disabled** state
84
+ - review the row afterwards, assign an ID/name, verify the channel count
85
+ (3340-4-x = 4 channels, 3340-2-x = 2 channels) and enable it. mDNS only works
86
+ within the same network segment/VLAN.
87
+ - **Device table** (can also be filled in entirely manually, without discovery):
88
+ - `Active`, `ID` (a-z 0-9 _ -), `Name`, `IP address/hostname`,
89
+ `Channels` (1-4), `Kind` (Shutter/Light/unknown - controls the ioBroker object roles,
90
+ see below), `Shutter motor travel time` (seconds, 0=disabled - enables
91
+ `posEstimate`, see below, acts as the default for all channels),
92
+ `Travel time/channel` (optional, comma-separated, e.g. `22,28` - overrides the
93
+ default travel time individually per channel; useful for 2K devices where the two
94
+ channels have different motor travel times; empty entries fall back to
95
+ the default travel time), `Smartfront` (checkbox, only enable if a
96
+ Feller Smartfront switch is connected), `Poll (s)` (default 30, for RSSI +
97
+ periodic chscan resync; the actual channel updates run independently
98
+ via the chnotify long-poll).
99
+
100
+ ## Object tree per device (`zeptrion.0.<id>`)
101
101
 
102
102
  ```
103
103
  <id>.info.connection / lastError / hw / sw / boot / sn / sys / type / oen / rssi / refresh
104
104
  <id>.network.ssid / ip / mac / mode / enc / mask / gw / bssid (read-only)
105
- <id>.system.reboot / unlock / factoryDefault / networkDefault (Buttons; factoryDefault erfordert unlock binnen 30s)
105
+ <id>.system.reboot / unlock / factoryDefault / networkDefault (buttons; factoryDefault requires unlock within 30s)
106
106
  <id>.location.name (read/write)
107
107
  <id>.ntp.url / per (read/write)
108
- <id>.date.rfc1123 / tz / dst / syncNow (read/write + Button)
108
+ <id>.date.rfc1123 / tz / dst / syncNow (read/write + button)
109
109
 
110
- <id>.channels.chN.val Kanalzustand 0-100 / -1 (roher Hardwarewert)
111
- <id>.channels.chN.posEstimate nur bei Art=Storen: Software-Positionsschätzung
112
- 0=zu/100=offen, auch manuell schreibbar (Kalibrierung)
113
- <id>.channels.chN.name / group / icon / type / cat Kanalbeschreibung (read/write)
114
- <id>.channels.chN.command freies Kommando (String)
110
+ <id>.channels.chN.val channel state 0-100 / -1 (raw hardware value)
111
+ <id>.channels.chN.posEstimate only for kind=Shutter: software position estimate
112
+ 0=closed/100=open, also manually writable (calibration)
113
+ <id>.channels.chN.name / group / icon / type / cat channel description (read/write)
114
+ <id>.channels.chN.command free-text command (string)
115
115
  <id>.channels.chN.stop / on / off / toggle / open / close /
116
- move_open / move_close / dim_up / dim_down (Buttons)
117
- <id>.channels.chN.recall_s1..4 / store_s1..4 / delete_s1..4 (Buttons)
116
+ move_open / move_close / dim_up / dim_down (buttons)
117
+ <id>.channels.chN.recall_s1..4 / store_s1..4 / delete_s1..4 (buttons)
118
118
 
119
- <id>.smartfront.temp / lux / hum nur wenn "Smartfront" aktiviert (read)
120
- <id>.smartfront.ledState aktueller LED-Status als JSON (read)
121
- <id>.smartfront.ledSet LED(s) setzen, JSON-Array (write)
119
+ <id>.smartfront.temp / lux / hum only if "Smartfront" is enabled (read)
120
+ <id>.smartfront.ledState current LED status as JSON (read)
121
+ <id>.smartfront.ledSet set LED(s), JSON array (write)
122
122
  ```
123
123
 
124
124
  Global:
125
125
 
126
126
  ```
127
- info.connection mind. ein Gerät erreichbar
128
- control.closeAllShutters Button: ALLE konfigurierten Kanäle -> "close"
129
- control.openAllShutters Button: ALLE konfigurierten Kanäle -> "open"
130
- control.stopAllShutters Button: ALLE konfigurierten Kanäle -> "stop"
127
+ info.connection at least one device reachable
128
+ control.closeAllShutters button: ALL configured channels -> "close"
129
+ control.openAllShutters button: ALL configured channels -> "open"
130
+ control.stopAllShutters button: ALL configured channels -> "stop"
131
131
  ```
132
132
 
133
- ## Objekt-Rollen und "Art" (kind)
133
+ ## Object roles and "kind"
134
134
 
135
- Die zrap-API selbst unterscheidet nicht zwischen Licht- und Storenkanal - das steckt
136
- allein in der Verkabelung/im Aktor. Damit Visualisierungen (VIS, evtl. spätere
137
- ioBroker.iot/Alexa-Anbindung) Kanäle trotzdem sinnvoll klassifizieren können, kann pro
138
- Gerät die "Art" gesetzt werden:
135
+ The zrap API itself does not distinguish between a light and a shutter channel - that
136
+ is purely a matter of wiring/the actuator. So that visualizations (VIS, possibly a
137
+ future ioBroker.iot/Alexa integration) can still classify channels meaningfully, the
138
+ "kind" can be set per device:
139
139
 
140
- | Art | `<ch>.val` Rolle | `stop`/`open`/`close` Rolle |
140
+ | Kind | `<ch>.val` role | `stop`/`open`/`close` role |
141
141
  |---|---|---|
142
- | Storen/Rolladen | `level.blind` | `button.stop` / `button.open.blind` / `button.close.blind` |
143
- | Licht | `level.dimmer` | generisch `button` |
144
- | unbekannt (Default) | `value` | generisch `button` |
142
+ | Shutter/blind | `level.blind` | `button.stop` / `button.open.blind` / `button.close.blind` |
143
+ | Light | `level.dimmer` | generic `button` |
144
+ | unknown (default) | `value` | generic `button` |
145
145
 
146
- Wichtig: `level.blind` täuscht **keine** echte Positionsrückmeldung vor - laut Feller-Doku
147
- liefert `chscan`/`chnotify` für einen Storenkanal so gut wie immer `-1` (unbekannt), da die
148
- Hardware selbst keine Lamellenposition zurückmeldet. Die Rolle verbessert nur die
149
- Erkennung durch VIS-Widgets, der Zahlenwert bleibt i.d.R. uninformativ.
146
+ Important: `level.blind` does **not** fake genuine position feedback - per the Feller
147
+ documentation, `chscan`/`chnotify` for a shutter channel almost always returns `-1`
148
+ (unknown), since the hardware itself does not report a blind position. The role only
149
+ improves recognition by VIS widgets; the numeric value generally remains uninformative.
150
150
 
151
- ## Hagelalarm-Nutzung
151
+ ## Hail alert usage
152
152
 
153
153
  ```javascript
154
- // JavaScript-Adapter Beispiel
155
- on({id: 'wetter.0.warnungen.hagel', val: true}, function () {
154
+ // JavaScript adapter example
155
+ on({id: 'weather.0.warnings.hail', val: true}, function () {
156
156
  setState('zeptrion.0.control.closeAllShutters', true);
157
157
  });
158
158
  ```
159
159
 
160
- Fehler bei einzelnen Geräten (offline etc.) unterbrechen die übrigen Kanäle nicht -
161
- jeder fehlgeschlagene Kanal wird einzeln geloggt und in `<id>.info.lastError` vermerkt.
162
-
163
- ## Bekannte Einschränkungen / bewusste Entscheidungen
164
-
165
- - **Smartbutton-Webhook-Programmierung** (`zapi/smartbt/prgm`/`prgn`/`prgs`) ist nicht
166
- implementiert: dabei ruft der Taster bei Tastendruck direkt eine URL auf ioBroker auf
167
- (echtes Push, ganz ohne Polling). Das würde einen eingehenden HTTP-Server im Adapter
168
- voraussetzen, den es aktuell nicht gibt - eine grössere Architekturerweiterung, kein
169
- kleiner Zusatz. Bleibt als möglicher zukünftiger Ausbauschritt dokumentiert.
170
- - **Schreibzugriff auf `zrap/net`** ist nicht implementiert - WLAN-Zugangsdaten eines
171
- Aktors per Skript zu ändern ist riskant (Verbindungsverlust, Reboot nötig). Kann bei
172
- Bedarf ergänzt werden.
173
- - **Scheduler (`zrap/scheduler`)** und die **zeptrionAir-Smartfront-Services**
174
- (`zapi/smartfront/*`, `zapi/smartbt/*`) sind nicht implementiert, da für den
175
- Storen-/Hagel-Use-Case nicht relevant. Die vorhandene `zrapGet`/`zrapPost`-Struktur
176
- in `main.js` lässt sich leicht erweitern.
177
- - `chctrl` liefert laut Doku HTTP 302 ohne Body - Redirects werden bewusst nicht verfolgt
178
- (`maxRedirects: 0`), um unnötige Zusatzrequests zu vermeiden.
179
- - Bei wiederholten Fehlern eines Geräts wird das Poll-Intervall bis maximal das
180
- 5-fache verlängert (einfacher Backoff).
181
-
182
- ## Entwicklung / Tests
160
+ Failures on individual devices (offline, etc.) do not interrupt the remaining channels -
161
+ each failed channel is logged individually and recorded in `<id>.info.lastError`.
162
+
163
+ ## Known limitations / deliberate decisions
164
+
165
+ - **Smartbutton webhook programming** (`zapi/smartbt/prgm`/`prgn`/`prgs`) is not
166
+ implemented: this would have the switch call a URL on ioBroker directly on a button
167
+ press (true push, no polling at all). That would require an incoming HTTP server in
168
+ the adapter, which does not currently exist - a larger architectural extension, not a
169
+ small addition. Documented as a possible future enhancement.
170
+ - **Write access to `zrap/net`** is not implemented - changing an actuator's WLAN
171
+ credentials via script is risky (loss of connection, reboot required). Can be added
172
+ if needed.
173
+ - **Scheduler (`zrap/scheduler`)** and the **zeptrionAir Smartfront services**
174
+ (`zapi/smartfront/*`, `zapi/smartbt/*`) are not implemented, as they are not relevant
175
+ to the shutter/hail use case. The existing `zrapGet`/`zrapPost` structure
176
+ in `main.js` can easily be extended.
177
+ - Per the documentation, `chctrl` returns HTTP 302 without a body - redirects are
178
+ deliberately not followed (`maxRedirects: 0`) to avoid unnecessary extra requests.
179
+ - On repeated failures for a device, the poll interval is extended up to a maximum of
180
+ 5x (simple backoff).
181
+
182
+ ## Development / Tests
183
183
 
184
184
  ```bash
185
185
  npm install
186
186
  npm run lint
187
- npm test # Package-Konsistenz + Unit-Tests
188
- npm run test:integration # startet echten js-controller (dauert länger)
187
+ npm test # package consistency + unit tests
188
+ npm run test:integration # starts a real js-controller (takes longer)
189
189
  ```
190
+
190
191
  ## Changelog
191
192
 
193
+ ### 0.8.5 (2026-07-16)
194
+ - Enabled automated npm releases via GitHub Actions using npm Trusted Publishing (OIDC) - no more manual publishing, and this and all future tagged releases are automatically signed with npm provenance. No functional/API changes.
195
+
196
+ ### 0.8.4 (2026-07-16)
197
+ - Cleanup release addressing the ioBroker adapter store checker findings, no functional/behavioral changes
198
+ - Updated fast-xml-parser 4.5.7 -> 5.9.3, eslint, mocha, chai and the testing-action-check GitHub Action (verified identical XML parsing output for the zrap API response shapes used by this adapter)
199
+ - Removed devDependencies already bundled by @iobroker/testing
200
+ - Fixed jsonConfig.json i18n declaration (was "true" without an admin/i18n directory) and added missing translations for the work area "kind" dropdown options
201
+ - Added package-lock.json and aligned dependabot.yml/auto-merge workflow with the current ioBroker-Bot templates
202
+
203
+ ### 0.8.3 (2026-07-14)
204
+ - CI workflow activated (lint + tests on every push/PR via GitHub Actions), removed redundant duplicate icon file at repo root (only admin/zeptrion.png is used), cleaned up outdated publish instructions in README
205
+
206
+ ### 0.8.2
207
+ - Per-channel motor travel time override (new "Travel/ch (s)" column and CSV column): 2K/4K devices where individual channels have different shutter travel times can now be configured correctly - previously only one travel time applied to all channels of a device
208
+
209
+ ### 0.8.1
210
+ - Channel commands (open/close/stop/dim/...) are now logged at info level on send (single and multicast), including failures on warn level - previously only system commands were logged
211
+
212
+ ### 0.8.0
213
+ - Fixed orphaned states remaining after a device is removed/replaced (objects are now cleaned up on start), official Feller zeptrion logo as icon (used with permission)
214
+
192
215
  ### 0.7.0 (2026-07-10)
193
- - Skalierung für 20+ Geräte: paralleles Setup, Poll-Jitter, Duplikat-Erkennung
194
- - Strikte Startup-Validierung jeder konfigurierten Geräte-Zeile
195
- - CSV-Massenimport (eigener Konfig-Tab) mit Zeilen-Validierung und Auto-ID
196
- - FIX: Positionsschätzung nach Stopp während Endlagenfahrt korrekt
197
- - FIX: Adapter-Timer-Cleanup (this.clearTimeout), führende Nullen in chdes-Codes bleiben erhalten
216
+ - Scaling for 20+ devices: parallel setup, poll jitter, duplicate detection
217
+ - Strict startup validation for every configured device row
218
+ - CSV bulk import (dedicated config tab) with row validation and auto-ID
219
+ - FIX: position estimate correctly handled after a stop during an end-position run
220
+ - FIX: adapter timer cleanup (this.clearTimeout), leading zeros in chdes codes are preserved
198
221
 
199
222
  ### 0.6.0 (2026-07-10)
200
- - Auto-ID aus Host, Geräte-Test-Button (Erreichbarkeit + zeptrion-Verifikation + Kanalzahl-Prüfung)
201
- - Kanal-Objektnamen aus dem Gerät (chdes), neues Icon, Geräte-Icons
223
+ - Auto-ID from host, device test button (reachability + zeptrion verification + channel count check)
224
+ - Channel object names taken from the device (chdes), new icon, device icons
202
225
 
203
226
  ### 0.5.1 (2026-07-10)
204
- - KRITISCHER FIX: XML-Parser übersprang die Nutzdaten wegen des XML-Deklarations-Keys - alle GET-Werte blieben in 0.5.0 null
227
+ - CRITICAL FIX: the XML parser skipped the payload because of the XML declaration key - all GET values remained null in 0.5.0
205
228
 
206
229
  ### 0.5.0 (2026-07-07)
207
- - setPosition: zeitbasierte %-Anfahrt für Storen (Chunking wegen 32s-API-Limit, Referenzfahrt bei unbekannter Position)
208
- - tiltOpen/tiltClose: Lamellen-Kipp-Impulse (konfigurierbare Impulsdauer)
209
- - calibrate: Positionsschätzung ohne Fahrt setzen
210
-
211
- ### 0.4.0 (2026-07-07) - Security- & Qualitäts-Härtung
212
- - **Verriegelter Werksreset**: `system.factoryDefault` funktioniert nur noch innerhalb
213
- von 30s nach Setzen von `system.unlock` - ein einzelner versehentlicher setState aus
214
- Script/VIS kann das Gerät nicht mehr plätten.
215
- - **Crashsicheres onStateChange**: der komplette Handler (inkl. der Sammelbefehle) läuft
216
- jetzt in einer zentralen Fehlerbehandlung - keine Unhandled Promise Rejections mehr
217
- möglich.
218
- - **Eingabevalidierung**: Kanalbeschreibung (32/32/24/4/4 Bytes UTF-8), Standort (32),
219
- NTP-URL (32) und NTP-Intervall (0-255) werden vor dem Senden geprüft; klare
220
- Fehlermeldung statt HTTP-400 vom Gerät. Umlaute zählen korrekt als 2 Bytes.
221
- - **Adapter-verwaltete Timer** (`this.setTimeout`) überall - automatische Aufräumung
222
- beim Unload gemäss ioBroker-Guidelines.
223
- - **Verbindungs-Ökonomie**: solange der chnotify-Long-Poll gesund läuft, wird der
224
- redundante chscan-Resync nur noch bei jedem 5. Poll ausgeführt (schont die
225
- schwachen Embedded-Webserver der Unterputzaktoren).
226
- - **chnotify abschaltbar** (Experten-Tab) für Umgebungen mit Verbindungsproblemen.
227
- - **Admin-UI neu**: Tabs (Geräte/Experten), durchgängig EN+DE, Eingabe-Validatoren
228
- (ID-Muster, Host-Muster), Tooltips an jeder Spalte, Sicherheitshinweis.
229
- - ESLint auf Flat Config (v9) migriert, Lint läuft sauber durch; Smoke-Tests für
230
- Kommando-Validierung, Byte-Limits, Positionsmathematik und Multicast-Body.
230
+ - setPosition: time-based %-approach for shutters (chunked due to the 32s API limit, reference run when position is unknown)
231
+ - tiltOpen/tiltClose: slat tilt pulses (configurable pulse duration)
232
+ - calibrate: set the position estimate without moving
233
+
234
+ ### 0.4.0 (2026-07-07) - Security & quality hardening
235
+ - **Locked factory reset**: `system.factoryDefault` now only works within
236
+ 30s of setting `system.unlock` - a single accidental setState from a
237
+ script/VIS can no longer wipe the device.
238
+ - **Crash-safe onStateChange**: the entire handler (including the bulk commands) now
239
+ runs inside centralized error handling - unhandled promise rejections are
240
+ no longer possible.
241
+ - **Input validation**: channel description (32/32/24/4/4 bytes UTF-8), location (32),
242
+ NTP URL (32) and NTP interval (0-255) are validated before sending; a clear
243
+ error message instead of an HTTP 400 from the device. Umlauts are correctly counted as 2 bytes.
244
+ - **Adapter-managed timers** (`this.setTimeout`) used everywhere - automatic cleanup
245
+ on unload per the ioBroker guidelines.
246
+ - **Connection economy**: as long as the chnotify long-poll is running healthily, the
247
+ redundant chscan resync now only runs on every 5th poll (goes easier on the
248
+ weak embedded web servers of the flush-mounted actuators).
249
+ - **chnotify can be disabled** (Expert tab) for environments with connection issues.
250
+ - **New admin UI**: tabs (Devices/Expert), fully EN+DE, input validators
251
+ (ID pattern, host pattern), tooltips on every column, security notice.
252
+ - Migrated ESLint to flat config (v9), lint runs cleanly; smoke tests for
253
+ command validation, byte limits, position math and multicast body.
231
254
 
232
255
  ### 0.3.0 (2026-07-07)
233
- - Kanalbefehle desselben Geräts werden innerhalb eines 50ms-Fensters automatisch zu
234
- einem einzigen Multicast-POST an `/zrap/chctrl` gebündelt statt sequentiell einzeln
235
- gesendet - insbesondere `control.closeAllShutters` (Hagelalarm) profitiert davon
236
- massiv (ein Request pro Gerät statt einer pro Kanal).
237
- - Optionale zeitbasierte Storen-Positionsschätzung (`posEstimate`) anhand konfigurierbarer
238
- Motor-Laufzeit, da die Hardware selbst keine Position zurückmeldet.
239
- - Optionale Smartfront-Unterstützung (`zapi/smartfront/*`): Temperatur/Helligkeit/
240
- Feuchtigkeit auslesen, LED-Hintergrundfarbe setzen.
241
- - Rollen-Korrektur: `level.blind` sitzt jetzt auf der Positionsschätzung statt auf dem
242
- rohen (meist -1) Hardwarewert.
256
+ - Channel commands for the same device are automatically bundled within a 50ms window
257
+ into a single multicast POST to `/zrap/chctrl` instead of being sent sequentially
258
+ one by one - `control.closeAllShutters` (hail alert) in particular
259
+ benefits massively from this (one request per device instead of one per channel).
260
+ - Optional time-based shutter position estimate (`posEstimate`) based on a configurable
261
+ motor travel time, since the hardware itself does not report a position.
262
+ - Optional Smartfront support (`zapi/smartfront/*`): read temperature/brightness/
263
+ humidity, set LED background color.
264
+ - Role fix: `level.blind` is now applied to the position estimate instead of the
265
+ raw (usually -1) hardware value.
243
266
 
244
267
  ### 0.2.0 (2026-07-07)
245
- - Kanalzustände werden jetzt primär über `zrap/chnotify` (Long-Poll) nahezu in
246
- Echtzeit aktualisiert statt nur per Intervall-Polling; `chscan`-Poll bleibt als
247
- periodischer Resync/Fallback erhalten.
248
- - Zusätzliches Sicherheitsnetz (Busy-Window, 5s) verhindert, dass ein zeitgleicher
249
- chscan-Resync einen gerade gesendeten Bewegungsbefehl mit einem veralteten Wert
250
- überschreibt.
251
- - mDNS-Discovery-Handler gegen Exceptions durch fremde/kaputte Netzwerkpakete
252
- abgesichert (try/catch je Service-Event statt nur um die Subscription herum).
253
- - Neues Geräte-Feld "Art" (Storen/Licht/unbekannt) steuert Standard-Objektrollen
254
- (`level.blind`, `button.stop`, `button.open.blind`, `button.close.blind` bzw.
255
- `level.dimmer`) für bessere VIS-/Smart-Home-Integration.
256
- - Strukturierte `native`-Metadaten (Host, Kanalnummer, Art) an Geräte-/Kanal-Objekten.
268
+ - Channel states are now primarily updated near real-time via `zrap/chnotify`
269
+ (long-poll) instead of only via interval polling; `chscan` polling remains as a
270
+ periodic resync/fallback.
271
+ - An additional safety net (busy window, 5s) prevents a concurrent
272
+ chscan resync from overwriting a just-sent movement command with a stale value.
273
+ - mDNS discovery handler hardened against exceptions caused by malformed/unrelated
274
+ network packets (try/catch per service event instead of only around the subscription).
275
+ - New device field "kind" (Shutter/Light/unknown) controls the default object roles
276
+ (`level.blind`, `button.stop`, `button.open.blind`, `button.close.blind` resp.
277
+ `level.dimmer`) for better VIS/smart-home integration.
278
+ - Structured `native` metadata (host, channel number, kind) on device/channel objects.
257
279
 
258
280
  ### 0.1.0 (2026-07-07)
259
- - Erste Version: Kanalsteuerung, Kanalzustand/-beschreibung, Geräte-/Netzwerkinfo,
260
- Systembefehle, Standort/NTP/Datum, Sammelbefehle für Hagelalarm, mDNS-Discovery.
281
+ - First version: channel control, channel state/description, device/network info,
282
+ system commands, location/NTP/date, bulk commands for hail alerts, mDNS discovery.
261
283
 
262
284
  ## License
263
285