hm-simulator 1.4.0 → 1.5.0
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 +28 -7
- package/README.md +62 -4
- package/data/fixtures/hmip-wired.json +25645 -0
- package/data/paramset-ids.json +1 -0
- package/index.js +5 -4
- package/lib/sim.js +120 -3
- package/package.json +1 -1
- package/sim.d.ts +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
All notable changes of hm-simulator. The release workflow takes each version's section from here for the
|
|
4
4
|
GitHub release notes.
|
|
5
5
|
|
|
6
|
+
## 1.5.0 — 2026-10-30
|
|
7
|
+
|
|
8
|
+
- `getParamsetId(address, paramset)`, which answered the unknown-method fault: hmipserver's id
|
|
9
|
+
built from the device type, channel index and key (`hmipw-drbl4_2_link`), and on rfd and
|
|
10
|
+
BidCos-Wired the id the device file gives the paramset (`cc_tc_ch_wsr_link`), from the new
|
|
11
|
+
`data/paramset-ids.json` (261 BidCos device types, generated by `tools/paramset-ids.js` from
|
|
12
|
+
OpenCCU-Base's device files), with rfd's `-3 Unknown paramset` and its reading of any other key
|
|
13
|
+
as a peer address - all measured on 3.89.11. The option `paramsetIds` answers first.
|
|
14
|
+
- The fixture `data/fixtures/hmip-wired.json`: an HmIPW-DRBL4 blind actuator, HmIPW-DRI32 and
|
|
15
|
+
HmIPW-DRI16 input modules and an HmIPW-WRC6 wall button with their real descriptions (MASTER,
|
|
16
|
+
VALUES, LINK, SERVICE), and five links to the actuator whose LINK paramsets hold what the CCU's
|
|
17
|
+
WebUI writes for the shutter profile chosen (one of them as the WebUI of firmware 3.87 wrote it,
|
|
18
|
+
with the long press's `LONG_PROFILE_ACTION_TYPE` 5 the current WebUI no longer writes).
|
|
19
|
+
- The option `paramsets` (and the fixture property of that name for `--devices`): the stored
|
|
20
|
+
values MASTER, VALUES, SERVICE and link paramsets start with, on top of the defaults.
|
|
21
|
+
- The interface option `stickyWriteEvents` (default `true`, as before): with `false`, a client's
|
|
22
|
+
`setValue` or `putParamset(VALUES)` on a sticky datapoint (`FLAGS & 16`, the acknowledgement of
|
|
23
|
+
`STICKY_UNREACH`) changes the value and sends no event. A registered client on rfd 3.89.11 got
|
|
24
|
+
none when another client acknowledged the message, so a client that waits for the event shows
|
|
25
|
+
the device as "was unreachable" until its next read; a consumer's test can now ask for that
|
|
26
|
+
(found through occulited's service messages).
|
|
27
|
+
|
|
6
28
|
## 1.4.0 — 2026-10-03
|
|
7
29
|
|
|
8
30
|
- `setInstallModeWithWhitelist(on, time, [{ADDRESS, KEY_MODE, KEY}])` on hmipserver, which answered
|
|
@@ -11,7 +33,7 @@ GitHub release notes.
|
|
|
11
33
|
puts an HmIP device in reach of the next install mode: it joins, or - with a whitelist `LOCAL` key
|
|
12
34
|
that is not its own - is declined, nothing joins and the device stays in reach; `getInclusions`
|
|
13
35
|
answers every request with its result (`paired`, `declined`, `ignored`), `getInstallWhitelist` the
|
|
14
|
-
open install mode's list. The simulator's model, not a measurement
|
|
36
|
+
open install mode's list. The simulator's model, not a measurement.
|
|
15
37
|
|
|
16
38
|
## 1.3.2
|
|
17
39
|
|
|
@@ -20,12 +42,11 @@ GitHub release notes.
|
|
|
20
42
|
as both interface processes do on 3.89.11; it answered `''`. A paramset the channel does not list
|
|
21
43
|
answers the new table entry `unknownParamsetDescription` (`-3 Unknown Paramset` / `-3 Unknown
|
|
22
44
|
paramset`, measured); a paramset the channel has but the description set lacks still answers `''`
|
|
23
|
-
(
|
|
45
|
+
(found through node-red-contrib-ccu's handling of the fault on a real CCU).
|
|
24
46
|
- `getLinkPeers` of a device address faults on `rfd` with the `notSupported` entry (`-1 Failure`
|
|
25
47
|
under rfd's table, as rfd 3.89.11 answers; `-1 Generic error` under the default one), where it
|
|
26
48
|
answered the peers of all channels; on hmipserver and the other interfaces it answers the channels'
|
|
27
|
-
lists one after the other, a peer linked with two of the channels twice, as hmipserver 3.89.11 does
|
|
28
|
-
(B-4).
|
|
49
|
+
lists one after the other, a peer linked with two of the channels twice, as hmipserver 3.89.11 does.
|
|
29
50
|
|
|
30
51
|
## 1.3.1
|
|
31
52
|
|
|
@@ -33,14 +54,14 @@ paramset`, measured); a paramset the channel has but the description set lacks s
|
|
|
33
54
|
`rfd` - a relay's own button on the relay, a dimmer's channel on its virtual channels - as rfd
|
|
34
55
|
3.89.11 does although such a link works; filtered by an address the link carries its stored flags,
|
|
35
56
|
0, as rfd answers there too. A test that shows a client how it handles rfd's flag can now make the
|
|
36
|
-
link with `addLink` instead of seeding it (
|
|
57
|
+
link with `addLink` instead of seeding it (found through Homematic Manager's links list).
|
|
37
58
|
- `replaceDevice` answers `true`, as the specification's `bool` says, where it answered `''` (a
|
|
38
59
|
client that takes the answer as the success saw a replacement that did happen as failed).
|
|
39
60
|
- rfd's `listReplaceableDevices` names only the devices of the same type that are unreachable
|
|
40
61
|
(`setReachable(iface, address, false)`); a device that still answers is not replaced.
|
|
41
62
|
- The declarations gain `clients` (the registered logic layers per interface, read-only, `Client`),
|
|
42
63
|
`dispatch` with its `DispatchContext` (the servers' entry, which a test may wrap to record calls),
|
|
43
|
-
and `replaceDevice`'s `true` (
|
|
64
|
+
and `replaceDevice`'s `true` (found through Homematic Manager's tests on 1.3.0).
|
|
44
65
|
|
|
45
66
|
## 1.3.0
|
|
46
67
|
|
|
@@ -123,7 +144,7 @@ paramset`, measured); a paramset the channel has but the description set lacks s
|
|
|
123
144
|
the members in `TEAM_CHANNELS`; `setTeam(channel, team)` moves it and deletes a team nobody is
|
|
124
145
|
left in, `setTeam(channel, '')` puts it back into a team of its own, created like the one it
|
|
125
146
|
left (`newDevices`, `deleteDevices`, `updateDevice` to the logic layers). The shape is rfd's
|
|
126
|
-
as Homematic Manager
|
|
147
|
+
as Homematic Manager read it from a CCU3; when rfd deletes and creates the team devices
|
|
127
148
|
is the simulator's model, not a measurement.
|
|
128
149
|
|
|
129
150
|
## 1.0.0
|
package/README.md
CHANGED
|
@@ -126,7 +126,7 @@ that starts with the bytes `Bin` is BIN-RPC, anything else XML-RPC over HTTP.
|
|
|
126
126
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
127
127
|
| session | `init` (register and de-register a logic layer), `ping`, `system.listMethods`, `system.methodHelp`, `system.multicall` |
|
|
128
128
|
| devices | `listDevices`, `getDeviceDescription`, `deleteDevice`, `replaceDevice`, `listReplaceableDevices`, `setInstallMode`, `setInstallModeWithWhitelist` (hmipserver), `getInstallMode`, `addDevice` (BidCos only), `getKeyMismatchDevice` (rfd, hmipserver) |
|
|
129
|
-
| paramsets | `getParamsetDescription`, `getParamset`, `putParamset`, `getValue`, `setValue`, `determineParameter`, `reportValueUsage`
|
|
129
|
+
| paramsets | `getParamsetDescription`, `getParamsetId`, `getParamset`, `putParamset`, `getValue`, `setValue`, `determineParameter`, `reportValueUsage` |
|
|
130
130
|
| links | `getLinks`, `getLinkPeers`, `getLinkInfo`, `setLinkInfo`, `addLink`, `removeLink`, `activateLinkParamset` |
|
|
131
131
|
| interface | `rssiInfo`, `listBidcosInterfaces`, `setBidcosInterface`, `getServiceMessages`, `setTempKey` (BidCos only), `changeKey` (rfd, hmipserver), `logLevel`, `getVersion`, `setInterfaceClock` (rfd, hmipserver), `getLGWStatus` (only when configured) |
|
|
132
132
|
| metadata | `getMetadata`, `setMetadata` (rfd, hs485d, hmipserver), `getAllMetadata` (BidCos only) |
|
|
@@ -196,6 +196,8 @@ UTF-8. BIN-RPC strings go out as ISO-8859-1, as rfd sends them.
|
|
|
196
196
|
| `newDevices` | `{}` | devices that appear when the install mode is switched on, `{<iface>: {devices, delay}}` |
|
|
197
197
|
| `defaultRssi` | `-65` | what `rssiInfo` answers where a device has no RSSI datapoint |
|
|
198
198
|
| `metadata` | `{}` | what `getMetadata` answers before any `setMetadata`, `{<iface>: {<address>: {<key>: value}}}` |
|
|
199
|
+
| `paramsets` | `{}` | stored values to start with, `{<iface>: {<address>: {<MASTER\|VALUES\|SERVICE\|peer>: {}}}}` |
|
|
200
|
+
| `paramsetIds` | `{}` | what `getParamsetId` answers first, `{<iface>: {<address>: {<paramset>: id}}}` |
|
|
199
201
|
| `config.listenAddress` | all interfaces | `'127.0.0.1'` in tests |
|
|
200
202
|
| `config.binrpcListenPort` | – | rfd |
|
|
201
203
|
| `config.xmlrpcListenPort` | – | hmipserver |
|
|
@@ -226,6 +228,7 @@ UTF-8. BIN-RPC strings go out as ISO-8859-1, as rfd sends them.
|
|
|
226
228
|
| `pingDelay` | `0` | milliseconds between `ping` and its `PONG` |
|
|
227
229
|
| `startDelay` | `0` | milliseconds after `whenReady()` until the port accepts connections: a process that starts late (`sim.ports` knows the port from the start) |
|
|
228
230
|
| `unreachWrites` | `'accept'` | what `setValue`/`putParamset` to an unreachable device answer: `'accept'`, or `'fault'` (`notReachable`). The simulator's model, not a measurement |
|
|
231
|
+
| `stickyWriteEvents` | `true` | `false`: a client's `setValue`/`putParamset` on a sticky datapoint (`FLAGS & 16`, the acknowledgement of `STICKY_UNREACH`) sends no event, see [Device and radio health](#device-and-radio-health) |
|
|
229
232
|
| `firmwareUpdateDelay` | `0` | milliseconds per step of a firmware update |
|
|
230
233
|
| `getServiceMessagesFault` | `false` | answer `getServiceMessages` with the unknown-method fault (`Invalid XML-RPC message`), as VirtualDevices, CUxD and hmipserver were seen to on 3.89.x |
|
|
231
234
|
| `version` | `'2.6.0'` for `rfd` and `wired`, `'3.89.11.20260919'` for `hmip` | what `getVersion` answers; the rest has no `getVersion` |
|
|
@@ -319,6 +322,13 @@ sim.regaSim.scripts; // every script the ReGa mock received
|
|
|
319
322
|
with `setServiceMessage`. `STICKY_UNREACH` stays after the device is back until a client writes
|
|
320
323
|
it `false`, as rfd does. A write to an unreachable device is accepted unless `unreachWrites` is
|
|
321
324
|
`'fault'`.
|
|
325
|
+
- That acknowledgement is answered with the channel's events, like every other write. On rfd
|
|
326
|
+
3.89.11 a registered client got **no** event when another client wrote `STICKY_UNREACH` `false`
|
|
327
|
+
(observed once, from the receiving client's log; a second measurement is pending): the
|
|
328
|
+
interface option `stickyWriteEvents: false` models that - a client's write to a datapoint with
|
|
329
|
+
the sticky flag (`FLAGS & 16`) changes the value and sends nothing, so only a read finds it
|
|
330
|
+
acknowledged. Use it to test that a client does not wait for an event that never comes. The
|
|
331
|
+
default stays `true` until the measurement is repeated.
|
|
322
332
|
- The radio module is the HmIP device whose address is the last 14 characters of the interface's
|
|
323
333
|
address in `listBidcosInterfaces` (its SGTIN), or a device of a radio module's type
|
|
324
334
|
(`RPI-RF-MOD`, `HmIP-RFUSB`); without one only `listBidcosInterfaces` changes.
|
|
@@ -420,6 +430,7 @@ HMIP-PS, HMIP-SWDO, HMIP-WTH, HmIP-SMI and a radio module). Without `paramsetDes
|
|
|
420
430
|
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
421
431
|
| `data/fixtures/lab-2026-09.json` | real devices of four test systems with the descriptions of their exact firmware, links and radio modules - the recommended one |
|
|
422
432
|
| `data/fixtures/devices.json` | generated from node-red-contrib-ccu's `paramsets.json`: real descriptions, synthesised channel indexes - HmIP-PDT, HmIPW-DRS8, HmIPW-DRI16, HmIPW-DRAP, HM-LC-Sw1-Pl, HM-CC-RT-DN |
|
|
433
|
+
| `data/fixtures/hmip-wired.json` | an HmIP-Wired distribution board: HmIPW-DRBL4, HmIPW-DRI32, HmIPW-DRI16, HmIPW-WRC6, links to the DRBL4 with the LINK paramsets the WebUI writes |
|
|
423
434
|
| `data/fixtures/lab-devices.json` | a real `listDevices` of two CCUs on firmware 3.89.8 (2026-09-05), no descriptions of its own - pass the ones of `devices.json` or the bundled set alongside |
|
|
424
435
|
|
|
425
436
|
**`data/fixtures/lab-2026-09.json`**: four test systems (openccu-lite, the interface processes of
|
|
@@ -443,6 +454,30 @@ Real hardware's oddities stay: the CCU's own `HmIP-RCV-50` sends a trailing **em
|
|
|
443
454
|
`CHILDREN`, for instance. The file is also a device file for the command line (`--devices`; add
|
|
444
455
|
`--wired-port 0` or a port for BidCos-Wired).
|
|
445
456
|
|
|
457
|
+
**`data/fixtures/hmip-wired.json`**: a wired blind actuator HmIPW-DRBL4 (firmware 1.6.0, four
|
|
458
|
+
channels run as shutters), the input modules HmIPW-DRI32 (1.2.2) and HmIPW-DRI16 (1.4.6, as in
|
|
459
|
+
`lab-2026-09.json`) with their inputs in key mode, and the wall button HmIPW-WRC6 (1.0.8). The
|
|
460
|
+
descriptions of the DRBL4, DRI32 and WRC6 are hmipserver's answers as
|
|
461
|
+
[pydevccu](https://github.com/danielperna84/pydevccu) (MIT) recorded them. Five links go to the
|
|
462
|
+
DRBL4, and their `paramsets` hold what the CCU's WebUI writes for the profile chosen - the presets
|
|
463
|
+
of its easymode file (`SHUTTER_VIRTUAL_RECEIVER/MULTI_MODE_INPUT_TRANSMITTER_1.tcl` and
|
|
464
|
+
`…/KEY_TRANSCEIVER.tcl`, the first value where it lists several) on the description's defaults. The
|
|
465
|
+
WebUI is eQ-3's current source, except for one link made the way the WebUI of firmware 3.87 made it:
|
|
466
|
+
its shutter profiles still wrote `LONG_PROFILE_ACTION_TYPE` 5 for the long press, where the current
|
|
467
|
+
one writes 1 (changed in June 2026), so a CCU keeps links of both kinds.
|
|
468
|
+
|
|
469
|
+
| Sender | Receiver | Profile |
|
|
470
|
+
| ---------- | ----------- | ------------------------------------------- |
|
|
471
|
+
| DRI32 `:1` | DRBL4 `:2` | 3, "open / closed & up / down" |
|
|
472
|
+
| DRI32 `:2` | DRBL4 `:3` | 3, "open / closed & up / down" (WebUI 3.87) |
|
|
473
|
+
| DRI16 `:1` | DRBL4 `:6` | 1, "open / up" |
|
|
474
|
+
| WRC6 `:1` | DRBL4 `:10` | 3, "open / closed & up / down" |
|
|
475
|
+
| WRC6 `:2` | DRBL4 `:14` | 4, "move to position" |
|
|
476
|
+
|
|
477
|
+
Pass the four properties (`devices`, `paramsetDescriptions`, `links`, `paramsets`) to the
|
|
478
|
+
constructor, or the file to `--devices`. `tools/fixture-hmip-wired.js` builds it from a pydevccu
|
|
479
|
+
package and an OpenCCU-Base checkout.
|
|
480
|
+
|
|
446
481
|
**How descriptions are found.** A description is looked up by
|
|
447
482
|
`<interface>/<type>/<firmware>/<version>/<channel type>/<paramset>`, and a device reports the
|
|
448
483
|
firmware it runs - which a description set often does not have. Such a device uses the description
|
|
@@ -492,7 +527,7 @@ a run of the generator, or, better, by dumping a CCU that has one.
|
|
|
492
527
|
## Interface behaviour, measured
|
|
493
528
|
|
|
494
529
|
Where the simulator imitates an interface process, this says whether the shape was measured on a
|
|
495
|
-
CCU or is the simulator's model. The measurements were made for Homematic Manager
|
|
530
|
+
CCU or is the simulator's model. The measurements were made for Homematic Manager
|
|
496
531
|
on CCUs with firmware 3.89.8 and 3.89.x.
|
|
497
532
|
|
|
498
533
|
### Direct links
|
|
@@ -543,6 +578,29 @@ What a `putParamset MASTER` does, per interface (`interfaces.<iface>.configPendi
|
|
|
543
578
|
The two models are the explanations that competed before the measurement (Homematic Manager issue
|
|
544
579
|
#98); they stay for applications that want to test against them.
|
|
545
580
|
|
|
581
|
+
### Paramset ids
|
|
582
|
+
|
|
583
|
+
`getParamsetId(address, paramset)` is the CCU's own name of a paramset; its WebUI picks the form of a
|
|
584
|
+
channel or a link side by it (`easymodes/<id>.tcl`). Measured 2026-10-30 on firmware 3.89.11:
|
|
585
|
+
|
|
586
|
+
- **hmipserver builds it** from the device type, the channel index and the key, lower case and
|
|
587
|
+
joined by `_`: `hmipw-drbl4_2_link`, `hmipw-dri16_1_master`, `hmipw-dri16_master` for a device
|
|
588
|
+
address. It does that for any key - `VALUES`, `SERVICE`, a peer address
|
|
589
|
+
(`hmipw-dri16_1_00000000000102:1`), a name the channel does not have, `null` without one - and
|
|
590
|
+
for a channel without a LINK paramset as well. The simulator does the same on `hmip`, `virtual`
|
|
591
|
+
and `cuxd` (VirtualDevices and CUxD not measured).
|
|
592
|
+
- **rfd and hs485d answer the `id` of the `<paramset>` in the device file** (`firmware/rftypes`,
|
|
593
|
+
`firmware/hs485types`): `cc_tc_dev_master` for a device address (MASTER only), `maint_ch_master`,
|
|
594
|
+
`cc_tc_ch_wsr_link`, `hmw_input_ch_values` for a channel. Another key on a channel is taken as a
|
|
595
|
+
peer address and answers the LINK id; a paramset the address does not have - LINK or VALUES of a
|
|
596
|
+
device, LINK of a maintenance channel, any other key there - is `-3 Unknown paramset`. The
|
|
597
|
+
simulator answers from `data/paramset-ids.json` (261 device types, by type and the device file's
|
|
598
|
+
version, which is the description's `VERSION`; built by `tools/paramset-ids.js` from
|
|
599
|
+
OpenCCU-Base), the `unknownParamsetDescription` entry of the fault table for a paramset the
|
|
600
|
+
address does not list, and `''` for a type the files do not describe.
|
|
601
|
+
- An unknown address is `unknownInstance` on all of them. `paramsetIds` in the constructor options
|
|
602
|
+
answers before the rules above.
|
|
603
|
+
|
|
546
604
|
### Fault codes
|
|
547
605
|
|
|
548
606
|
The default table is **hmipserver's**, because that is the one an application has to survive
|
|
@@ -729,8 +787,8 @@ Usage: hm-simulator [options]
|
|
|
729
787
|
as one line to stdout with "-" (the log then goes to stderr)
|
|
730
788
|
--config <file> constructor options as a .json or .js file; the flags override it
|
|
731
789
|
--devices <file> a device file: {devices: {rfd, hmip, ...}, paramsetDescriptions, links,
|
|
732
|
-
bidcosInterfaces}, such as data/fixtures/lab-2026-09.json;
|
|
733
|
-
the bundled rfd and hmip lists
|
|
790
|
+
bidcosInterfaces, paramsets}, such as data/fixtures/lab-2026-09.json;
|
|
791
|
+
default: the bundled rfd and hmip lists
|
|
734
792
|
--tls serve the XML-RPC servers over TLS with a generated certificate
|
|
735
793
|
--tls-cert-out <file> write that certificate (PEM) to the file
|
|
736
794
|
--auth <user:password> HTTP basic auth for the XML-RPC servers and ReGa
|