hm-simulator 1.3.0 → 1.3.2
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 +29 -0
- package/README.md +50 -15
- package/lib/faults.d.ts +1 -0
- package/lib/faults.js +8 -1
- package/lib/sim.js +78 -15
- package/package.json +1 -1
- package/sim.d.ts +41 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,35 @@
|
|
|
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.3.2
|
|
7
|
+
|
|
8
|
+
- `getParamsetDescription` of an address the interface does not know answers the `unknownInstance`
|
|
9
|
+
fault - `-2 Invalid device` under hmipserver's default table, `-2 Unknown instance` under rfd's -
|
|
10
|
+
as both interface processes do on 3.89.11; it answered `''`. A paramset the channel does not list
|
|
11
|
+
answers the new table entry `unknownParamsetDescription` (`-3 Unknown Paramset` / `-3 Unknown
|
|
12
|
+
paramset`, measured); a paramset the channel has but the description set lacks still answers `''`
|
|
13
|
+
(B-5, found through node-red-contrib-ccu's handling of the fault on a real CCU).
|
|
14
|
+
- `getLinkPeers` of a device address faults on `rfd` with the `notSupported` entry (`-1 Failure`
|
|
15
|
+
under rfd's table, as rfd 3.89.11 answers; `-1 Generic error` under the default one), where it
|
|
16
|
+
answered the peers of all channels; on hmipserver and the other interfaces it answers the channels'
|
|
17
|
+
lists one after the other, a peer linked with two of the channels twice, as hmipserver 3.89.11 does
|
|
18
|
+
(B-4).
|
|
19
|
+
|
|
20
|
+
## 1.3.1
|
|
21
|
+
|
|
22
|
+
- `getLinks` without an address reports `FLAGS: 1` (`SENDER_BROKEN`) on every device-internal link of
|
|
23
|
+
`rfd` - a relay's own button on the relay, a dimmer's channel on its virtual channels - as rfd
|
|
24
|
+
3.89.11 does although such a link works; filtered by an address the link carries its stored flags,
|
|
25
|
+
0, as rfd answers there too. A test that shows a client how it handles rfd's flag can now make the
|
|
26
|
+
link with `addLink` instead of seeding it (B-3, found through Homematic Manager's links list).
|
|
27
|
+
- `replaceDevice` answers `true`, as the specification's `bool` says, where it answered `''` (a
|
|
28
|
+
client that takes the answer as the success saw a replacement that did happen as failed).
|
|
29
|
+
- rfd's `listReplaceableDevices` names only the devices of the same type that are unreachable
|
|
30
|
+
(`setReachable(iface, address, false)`); a device that still answers is not replaced.
|
|
31
|
+
- The declarations gain `clients` (the registered logic layers per interface, read-only, `Client`),
|
|
32
|
+
`dispatch` with its `DispatchContext` (the servers' entry, which a test may wrap to record calls),
|
|
33
|
+
and `replaceDevice`'s `true` (B-2, found through Homematic Manager's tests on 1.3.0).
|
|
34
|
+
|
|
6
35
|
## 1.3.0
|
|
7
36
|
|
|
8
37
|
- The calls Homematic Manager makes, measured on rfd and hmipserver of firmware 3.89.11:
|
package/README.md
CHANGED
|
@@ -487,6 +487,23 @@ Where the simulator imitates an interface process, this says whether the shape w
|
|
|
487
487
|
CCU or is the simulator's model. The measurements were made for Homematic Manager (tasks 6 and 58)
|
|
488
488
|
on CCUs with firmware 3.89.8 and 3.89.x.
|
|
489
489
|
|
|
490
|
+
### Direct links
|
|
491
|
+
|
|
492
|
+
rfd (firmware 3.89.11, 2026-09-30) answers `getLinks("", flags)` - the list of all links - with
|
|
493
|
+
`FLAGS: 1` (`SENDER_BROKEN`) on every **device-internal** link: a relay's own button on the relay
|
|
494
|
+
(`:1` → `:1`), a dimmer's channel on its virtual channels. The link works; the bit carries no
|
|
495
|
+
information there. Asked for one address, `getLinks("ABC0000001:1", 0)` and `getLinks("ABC0000001",
|
|
496
|
+
0)` answer the same link with `FLAGS: 0`, and `getLinkPeers` names the own channel once. The simulator
|
|
497
|
+
does the same on `rfd`: `addLink` stores `FLAGS: 0`, the unfiltered list adds bit 1 to internal links
|
|
498
|
+
(seeded flags are kept and or-ed), the filtered one reports what is stored. hmipserver is not
|
|
499
|
+
measured and reports the stored flags.
|
|
500
|
+
|
|
501
|
+
`getLinkPeers` of a **device** address (measured 2026-10-02, 3.89.11): rfd refuses it with `-1
|
|
502
|
+
Failure`; hmipserver answers the channels' peer lists one after the other, so a peer linked with two
|
|
503
|
+
of the channels is named twice. The simulator does the same: on `rfd` the `notSupported` entry of the
|
|
504
|
+
fault table in force (`-1 Generic error` under hmipserver's default table, `-1 Failure` under
|
|
505
|
+
`FAULT_TABLES.bidcos`), on every other interface the channels' lists in channel order.
|
|
506
|
+
|
|
490
507
|
### CONFIG_PENDING
|
|
491
508
|
|
|
492
509
|
What a `putParamset MASTER` does, per interface (`interfaces.<iface>.configPendingMode`):
|
|
@@ -523,20 +540,21 @@ The two models are the explanations that competed before the measurement (Homema
|
|
|
523
540
|
The default table is **hmipserver's**, because that is the one an application has to survive
|
|
524
541
|
(measured):
|
|
525
542
|
|
|
526
|
-
| key
|
|
527
|
-
|
|
|
528
|
-
| `unknownMethod`
|
|
529
|
-
| `unknownInstance`
|
|
530
|
-
| `unknownParamset`
|
|
531
|
-
| `
|
|
532
|
-
| `
|
|
533
|
-
| `
|
|
534
|
-
| `
|
|
535
|
-
| `
|
|
536
|
-
| `
|
|
537
|
-
| `
|
|
538
|
-
| `
|
|
539
|
-
| `
|
|
543
|
+
| key | code | string | when |
|
|
544
|
+
| ---------------------------- | ---- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
545
|
+
| `unknownMethod` | -1 | Invalid XML-RPC message | no handler for the method name (hmipserver answers this without a faultCode) |
|
|
546
|
+
| `unknownInstance` | -2 | Invalid device | address not known to this interface |
|
|
547
|
+
| `unknownParamset` | -2 | Invalid device | `getParamset`/`putParamset` of a paramset the device does not have |
|
|
548
|
+
| `unknownParamsetDescription` | -3 | Unknown Paramset | `getParamsetDescription` of a paramset the channel does not list (3.89.11 appends the name: `Unknown Paramset: NOSUCH`) |
|
|
549
|
+
| `unknownLink` | -2 | Invalid device | the two channels are not linked |
|
|
550
|
+
| `unknownParameter` | -5 | Unknown Parameter for value key | the paramset has no such parameter |
|
|
551
|
+
| `readOnly` | -5 | Invalid parameter or value | `OPERATIONS & 2` is not set |
|
|
552
|
+
| `typeError` | -5 | Invalid parameter or value | value does not fit the parameter's `TYPE` |
|
|
553
|
+
| `outOfRange` | -5 | Invalid parameter or value | ENUM value not in `VALUE_LIST` |
|
|
554
|
+
| `invalidValue` | -5 | Invalid parameter or value | the stored channel configuration cannot be transferred |
|
|
555
|
+
| `notSupported` | -1 | Generic error | a method this interface does not implement |
|
|
556
|
+
| `notReachable` | -1 | Generic error (UNREACH) | a sleeping battery device |
|
|
557
|
+
| `invalidArguments` | -321 | Invalid arguments | wrong number of arguments; hmipserver really answers a Java exception message here |
|
|
540
558
|
|
|
541
559
|
Over XML-RPC a fault is an XML-RPC fault, over BIN-RPC a message of type `0xff` with a
|
|
542
560
|
`faultCode`/`faultString` struct. rfd's table is exported as `BIDCOS_FAULTS` and differs in more
|
|
@@ -549,6 +567,22 @@ new HmSim({faults: FAULT_TABLES.bidcos});
|
|
|
549
567
|
new HmSim({faults: {unknownParameter: {faultCode: -4, faultString: 'Unknown parameter'}}}); // one entry
|
|
550
568
|
```
|
|
551
569
|
|
|
570
|
+
### Unknown addresses and paramsets
|
|
571
|
+
|
|
572
|
+
Measured 2026-10-02 on rfd and hmipserver of firmware 3.89.11, with a device address and a channel
|
|
573
|
+
address alike: an address the interface does not know is a fault from every method that takes one -
|
|
574
|
+
`getDeviceDescription`, `getParamsetDescription`, `getParamset`, `getLinks`, `getLinkPeers` - rfd's
|
|
575
|
+
`-2 Unknown instance`, hmipserver's `-2 Invalid device`. The simulator answers `unknownInstance` of
|
|
576
|
+
the table in force everywhere (until 1.3.1 `getParamsetDescription` answered `''` there).
|
|
577
|
+
|
|
578
|
+
`getParamsetDescription` of a paramset the channel does not have: hmipserver answers `-3 Unknown
|
|
579
|
+
Paramset: <name>`; rfd answers `-3 Unknown paramset` on a channel without a `LINK` paramset and the
|
|
580
|
+
`LINK` description on a channel that has one (the name is taken as a peer address, as `getParamset`
|
|
581
|
+
does). The simulator answers `unknownParamsetDescription` whenever the channel's `PARAMSETS` lacks
|
|
582
|
+
the name. A paramset the channel lists but the description set has no entry for still answers `''`:
|
|
583
|
+
that is a gap in the fixture (logged once, see
|
|
584
|
+
[Device data and fixtures](#device-data-and-fixtures)), not something an interface process does.
|
|
585
|
+
|
|
552
586
|
### Service messages
|
|
553
587
|
|
|
554
588
|
`getServiceMessages` answers `[[address, datapoint, value]]`: every datapoint whose description
|
|
@@ -609,7 +643,8 @@ lifted again):
|
|
|
609
643
|
|
|
610
644
|
The simulator answers so, with the fault table in force (`-1 Generic error` under hmipserver's
|
|
611
645
|
default table where rfd says `-1 Failure`) and `''` for hmipserver's empty body. Its models:
|
|
612
|
-
`listReplaceableDevices` on rfd lists the other devices of the same `TYPE
|
|
646
|
+
`listReplaceableDevices` on rfd lists the other devices of the same `TYPE` that are unreachable
|
|
647
|
+
(`setReachable(iface, address, false)`; a device that still answers is not replaced); `setMetadata` on rfd
|
|
613
648
|
knows only its own addresses; `setInterfaceClock` is recorded, not measured (it sets the clock the
|
|
614
649
|
devices get). `addDevice(serial)` pairs only the device of `scriptKeyMismatch`, with the right
|
|
615
650
|
temporary key; any other serial is `unknownInstance`, the mismatch a `notSupported` fault.
|
package/lib/faults.d.ts
CHANGED
package/lib/faults.js
CHANGED
|
@@ -35,8 +35,11 @@ const DEFAULT_FAULTS = {
|
|
|
35
35
|
unknownMethod: {faultCode: -1, faultString: 'Invalid XML-RPC message'},
|
|
36
36
|
// device or channel address not known to this interface process
|
|
37
37
|
unknownInstance: {faultCode: -2, faultString: 'Invalid device'},
|
|
38
|
-
// the device/channel exists but does not have the requested paramset
|
|
38
|
+
// the device/channel exists but does not have the requested paramset (getParamset, putParamset)
|
|
39
39
|
unknownParamset: {faultCode: -2, faultString: 'Invalid device'},
|
|
40
|
+
// getParamsetDescription of a paramset the channel does not have. hmipserver 3.89.11 appends the
|
|
41
|
+
// name it was asked for (`Unknown Paramset: NOSUCH`); measured 2026-10-02
|
|
42
|
+
unknownParamsetDescription: {faultCode: -3, faultString: 'Unknown Paramset'},
|
|
40
43
|
// the paramset exists but does not contain the requested parameter (getValue/setValue)
|
|
41
44
|
unknownParameter: {faultCode: -5, faultString: 'Unknown Parameter for value key'},
|
|
42
45
|
// the two channels are not linked with each other
|
|
@@ -68,6 +71,10 @@ const BIDCOS_FAULTS = {
|
|
|
68
71
|
// rfd does not fault here at all: an unknown paramset name is taken as a peer channel address
|
|
69
72
|
// and the link defaults come back. The entry covers what the simulator cannot model.
|
|
70
73
|
unknownParamset: {faultCode: -2, faultString: 'Unknown instance'},
|
|
74
|
+
// getParamsetDescription of a paramset the channel does not have, on a channel without a LINK
|
|
75
|
+
// paramset; a channel that has one answers the LINK description for any unknown name (rfd
|
|
76
|
+
// 3.89.11, measured 2026-10-02)
|
|
77
|
+
unknownParamsetDescription: {faultCode: -3, faultString: 'Unknown paramset'},
|
|
71
78
|
unknownParameter: {faultCode: -5, faultString: 'Unknown parameter'},
|
|
72
79
|
unknownLink: {faultCode: -1, faultString: 'Failure'},
|
|
73
80
|
// rfd accepts a setValue on a read-only datapoint, so this is never raised against it
|
package/lib/sim.js
CHANGED
|
@@ -45,6 +45,15 @@ const CALLBACK_LOG_SIZE = 10000;
|
|
|
45
45
|
/** the interfaces that speak the BidCos protocol, and therefore have setTempKey */
|
|
46
46
|
const BIDCOS_INTERFACES = new Set(['rfd', 'wired']);
|
|
47
47
|
|
|
48
|
+
/** FLAGS bit of a link whose sender rfd counts as broken (bit 2 is the receiver) */
|
|
49
|
+
const LINK_SENDER_BROKEN = 1;
|
|
50
|
+
|
|
51
|
+
/** The device part of a channel address: `ABC0000001:1` -> `ABC0000001`. */
|
|
52
|
+
function deviceOf(address) {
|
|
53
|
+
const colon = String(address).indexOf(':');
|
|
54
|
+
return colon === -1 ? String(address) : String(address).slice(0, colon);
|
|
55
|
+
}
|
|
56
|
+
|
|
48
57
|
/** device types of the HmIP radio modules, which carry DUTY_CYCLE_LEVEL and CARRIER_SENSE_LEVEL */
|
|
49
58
|
const RADIO_MODULE_TYPES = new Set(['RPI-RF-MOD', 'HmIP-RFUSB', 'HmIP-RFUSB-TK', 'HMIP-CCU3', 'HmIP-CCU3']);
|
|
50
59
|
|
|
@@ -562,6 +571,28 @@ class HmSim {
|
|
|
562
571
|
return this.requireDevice(iface, address);
|
|
563
572
|
}
|
|
564
573
|
|
|
574
|
+
/**
|
|
575
|
+
* The RPC `getParamsetDescription`: unlike {@link getParamsetDescription}, which the simulator
|
|
576
|
+
* calls for itself, an address the interface does not know is a fault (rfd `-2 Unknown instance`,
|
|
577
|
+
* hmipserver `-2 Invalid device`, measured on 3.89.11), and so is a paramset the channel does not
|
|
578
|
+
* list in `PARAMSETS` (`-3` on both). A paramset the channel has but the description set lacks
|
|
579
|
+
* still answers `''`, logged once by {@link resolveParamsetKey} - that is a gap in the fixture,
|
|
580
|
+
* not something an interface process does.
|
|
581
|
+
* @param {string} iface
|
|
582
|
+
* @param {string} address device or channel address
|
|
583
|
+
* @param {string} paramset MASTER, VALUES, LINK or SERVICE
|
|
584
|
+
*/
|
|
585
|
+
describeParamset(iface, address, paramset) {
|
|
586
|
+
const device = this.requireDevice(iface, address);
|
|
587
|
+
if (typeof paramset !== 'string' || paramset === '') {
|
|
588
|
+
throw this.fault('invalidArguments', 'paramset type');
|
|
589
|
+
}
|
|
590
|
+
if (Array.isArray(device.PARAMSETS) && !device.PARAMSETS.includes(paramset)) {
|
|
591
|
+
throw this.fault('unknownParamsetDescription', `${address}/${paramset}`);
|
|
592
|
+
}
|
|
593
|
+
return this.getParamsetDescription(iface, device, paramset);
|
|
594
|
+
}
|
|
595
|
+
|
|
565
596
|
getValue(iface, address, datapoint) {
|
|
566
597
|
const {description, values} = this.storedParamset(iface, address, 'VALUES');
|
|
567
598
|
if (!description[datapoint]) {
|
|
@@ -897,14 +928,24 @@ class HmSim {
|
|
|
897
928
|
links = links.filter((link) => addresses.has(link.SENDER) || addresses.has(link.RECEIVER));
|
|
898
929
|
}
|
|
899
930
|
|
|
900
|
-
|
|
931
|
+
// rfd (measured, firmware 3.89.11): the list of *all* links carries FLAGS bit 1 (SENDER_BROKEN)
|
|
932
|
+
// on every device-internal link - a relay's own button on the relay, a dimmer's channel on its
|
|
933
|
+
// virtual channels - although the link works; asked for one address, the same link comes with
|
|
934
|
+
// its stored flags, 0. The simulator does the same on rfd, whatever `flags` asks for.
|
|
935
|
+
const internalBroken = iface === 'rfd' && !address;
|
|
936
|
+
return links.map((link) => this.linkStruct(iface, link, flags, internalBroken));
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/** Sender and receiver on one device: `ABC0000001:1` and `ABC0000001:2`, or the same channel. */
|
|
940
|
+
isInternalLink(link) {
|
|
941
|
+
return deviceOf(link.SENDER) === deviceOf(link.RECEIVER);
|
|
901
942
|
}
|
|
902
943
|
|
|
903
|
-
linkStruct(iface, link, flags) {
|
|
944
|
+
linkStruct(iface, link, flags, internalBroken = false) {
|
|
904
945
|
const result = {
|
|
905
946
|
SENDER: link.SENDER,
|
|
906
947
|
RECEIVER: link.RECEIVER,
|
|
907
|
-
FLAGS: link.FLAGS || 0,
|
|
948
|
+
FLAGS: (link.FLAGS || 0) | (internalBroken && this.isInternalLink(link) ? LINK_SENDER_BROKEN : 0),
|
|
908
949
|
NAME: link.NAME || '',
|
|
909
950
|
DESCRIPTION: link.DESCRIPTION || '',
|
|
910
951
|
};
|
|
@@ -930,14 +971,31 @@ class HmSim {
|
|
|
930
971
|
}
|
|
931
972
|
}
|
|
932
973
|
|
|
974
|
+
/**
|
|
975
|
+
* The peers of a channel: the other end of every link it is on, the own channel once for a link
|
|
976
|
+
* with itself. For a device address rfd answers `-1 Failure` (measured, 3.89.11); hmipserver
|
|
977
|
+
* answers the channels' lists one after the other, a peer linked with two of the channels twice
|
|
978
|
+
* (measured, 3.89.11) - the simulator does the same on every interface but `rfd`.
|
|
979
|
+
* @param {string} iface
|
|
980
|
+
* @param {Array} params [address]
|
|
981
|
+
* @returns {string[]} channel addresses
|
|
982
|
+
*/
|
|
933
983
|
getLinkPeers(iface, params) {
|
|
934
|
-
const
|
|
984
|
+
const [address] = params || [];
|
|
985
|
+
const device = this.requireDevice(iface, address);
|
|
986
|
+
if (iface === 'rfd' && !device.PARENT) {
|
|
987
|
+
// rfd's -1 Failure; -1 Generic error under hmipserver's default table
|
|
988
|
+
throw this.fault('notSupported', `getLinkPeers of a device address: ${address}`);
|
|
989
|
+
}
|
|
990
|
+
|
|
935
991
|
const peers = [];
|
|
936
|
-
for (const
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
992
|
+
for (const channel of this.channelsOf(iface, address)) {
|
|
993
|
+
for (const link of this.links[iface] || []) {
|
|
994
|
+
if (link.SENDER === channel) {
|
|
995
|
+
peers.push(link.RECEIVER);
|
|
996
|
+
} else if (link.RECEIVER === channel) {
|
|
997
|
+
peers.push(link.SENDER);
|
|
998
|
+
}
|
|
941
999
|
}
|
|
942
1000
|
}
|
|
943
1001
|
return peers;
|
|
@@ -1373,9 +1431,11 @@ class HmSim {
|
|
|
1373
1431
|
|
|
1374
1432
|
/**
|
|
1375
1433
|
* `listReplaceableDevices(address)` - the devices a device can take the place of. rfd: the other
|
|
1376
|
-
* devices of the same `TYPE`
|
|
1377
|
-
*
|
|
1378
|
-
*
|
|
1434
|
+
* devices of the same `TYPE` that are unreachable (`setReachable(iface, address, false)`) - a
|
|
1435
|
+
* device that still answers is not replaced (the simulator's model, after what the CCU's WebUI
|
|
1436
|
+
* offers; measured: `[]` for rfd's own `BidCoS-RF`, `-2 Unknown instance` for an address it does
|
|
1437
|
+
* not know). hmipserver answers with an empty HTTP body whatever it is asked (measured, firmware
|
|
1438
|
+
* 3.89.11), which the simulator answers as `''`.
|
|
1379
1439
|
*/
|
|
1380
1440
|
listReplaceableDevices(iface, params) {
|
|
1381
1441
|
const [address] = params || [];
|
|
@@ -1389,7 +1449,10 @@ class HmSim {
|
|
|
1389
1449
|
if (device.PARENT) {
|
|
1390
1450
|
return [];
|
|
1391
1451
|
}
|
|
1392
|
-
|
|
1452
|
+
const unreachable = this.unreachable[iface] || new Set();
|
|
1453
|
+
return this.deviceList(iface).filter(
|
|
1454
|
+
(entry) => entry.TYPE === device.TYPE && entry.ADDRESS !== address && unreachable.has(entry.ADDRESS),
|
|
1455
|
+
);
|
|
1393
1456
|
}
|
|
1394
1457
|
|
|
1395
1458
|
/**
|
|
@@ -1736,7 +1799,7 @@ class HmSim {
|
|
|
1736
1799
|
}
|
|
1737
1800
|
|
|
1738
1801
|
this.deleteDevice(iface, oldAddress);
|
|
1739
|
-
return
|
|
1802
|
+
return true;
|
|
1740
1803
|
}
|
|
1741
1804
|
|
|
1742
1805
|
reportValueUsage(iface, params) {
|
|
@@ -2392,7 +2455,7 @@ class HmSim {
|
|
|
2392
2455
|
'system.multicall': (iface, params) => this.multicall(iface, params),
|
|
2393
2456
|
init: (iface, params) => this.init(iface, params),
|
|
2394
2457
|
listDevices: (iface) => this.devices[iface].devices,
|
|
2395
|
-
getParamsetDescription: (iface, params) => this.
|
|
2458
|
+
getParamsetDescription: (iface, params) => this.describeParamset(iface, params[0], params[1]),
|
|
2396
2459
|
getDeviceDescription: (iface, params) => this.getDeviceDescription(iface, params[0]),
|
|
2397
2460
|
ping: (iface, params) => this.ping(iface, params),
|
|
2398
2461
|
setValue: (iface, params) => {
|
package/package.json
CHANGED
package/sim.d.ts
CHANGED
|
@@ -257,6 +257,31 @@ declare namespace HmSim {
|
|
|
257
257
|
/** `method -> handler(iface, params)`, as the servers dispatch it. */
|
|
258
258
|
type RpcMethodTable = Record<string, (iface: string, params: unknown[]) => unknown>;
|
|
259
259
|
|
|
260
|
+
/** A logic layer registered with `init`: what the simulator calls back. */
|
|
261
|
+
interface Client {
|
|
262
|
+
/** the interface id the client gave `init` */
|
|
263
|
+
id: string;
|
|
264
|
+
/** its callback url, as given */
|
|
265
|
+
url: string;
|
|
266
|
+
/** the key in `clients[iface]` (the url, exactly) */
|
|
267
|
+
key: string;
|
|
268
|
+
/** the underlying binrpc or xmlrpc client */
|
|
269
|
+
client: unknown;
|
|
270
|
+
/** one callback to the client; logged in `getCallbackLog()` */
|
|
271
|
+
methodCall(
|
|
272
|
+
method: string,
|
|
273
|
+
params: unknown[],
|
|
274
|
+
callback: (error: Error | null | undefined, result?: unknown) => void,
|
|
275
|
+
options?: {timeout?: number},
|
|
276
|
+
): void;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** What the servers hand `dispatch` besides the call. */
|
|
280
|
+
interface DispatchContext {
|
|
281
|
+
/** the connection the call came in on, for an injected `closeSocket` */
|
|
282
|
+
socket?: {destroy(): void};
|
|
283
|
+
}
|
|
284
|
+
|
|
260
285
|
/** The ports once `whenReady()` resolved. */
|
|
261
286
|
type Ports = Partial<Record<InterfaceName, number>>;
|
|
262
287
|
|
|
@@ -305,6 +330,8 @@ declare class HmSim {
|
|
|
305
330
|
/** stored state per interface and address: `{VALUES, MASTER, LINKS, ...}` */
|
|
306
331
|
values: Record<string, Record<string, Record<string, Record<string, unknown>>>>;
|
|
307
332
|
links: Record<string, HmSim.Link[]>;
|
|
333
|
+
/** the registered logic layers per interface, by callback url: the subscriptions `init(url, '')` removes */
|
|
334
|
+
readonly clients: Record<string, Record<string, HmSim.Client>>;
|
|
308
335
|
serviceMessages: Record<string, HmSim.ServiceMessage[]>;
|
|
309
336
|
/** every reportValueUsage */
|
|
310
337
|
valueUsage: Array<{iface: string; address: string; valueId: string; refCounter: number; ts: number}>;
|
|
@@ -378,6 +405,8 @@ declare class HmSim {
|
|
|
378
405
|
paramset: string,
|
|
379
406
|
): HmSim.ParamsetDescription | undefined;
|
|
380
407
|
getDeviceDescription(iface: string, address: string): HmSim.DeviceDescription;
|
|
408
|
+
/** the RPC `getParamsetDescription`: faults for an unknown address or a paramset the channel lacks */
|
|
409
|
+
describeParamset(iface: string, address: string, paramset: string): HmSim.ParamsetDescription | undefined;
|
|
381
410
|
|
|
382
411
|
/* ---------------------------------------------------------------- scenario api: service messages and health */
|
|
383
412
|
|
|
@@ -421,10 +450,21 @@ declare class HmSim {
|
|
|
421
450
|
|
|
422
451
|
/** One RPC method as a client call would run it; throws the fault. */
|
|
423
452
|
callMethod(iface: string, method: string, params?: unknown[]): unknown;
|
|
453
|
+
/**
|
|
454
|
+
* The servers' entry for every incoming call: injected faults and the lifecycle gates apply, then
|
|
455
|
+
* `callMethod`, and `callback(fault)` or `callback(null, result)`. A test wraps it to record calls.
|
|
456
|
+
*/
|
|
457
|
+
dispatch(
|
|
458
|
+
iface: string,
|
|
459
|
+
method: string,
|
|
460
|
+
params: unknown[],
|
|
461
|
+
callback: (fault: HmSim.RpcFault | null | undefined, result?: unknown) => void,
|
|
462
|
+
context?: HmSim.DispatchContext,
|
|
463
|
+
): void;
|
|
424
464
|
getLinks(iface: string, params?: unknown[]): Array<HmSim.Link & Record<string, unknown>>;
|
|
425
465
|
getLinkPeers(iface: string, params: unknown[]): string[];
|
|
426
466
|
deleteDevice(iface: string, address: string, flags?: number): '';
|
|
427
|
-
replaceDevice(iface: string, oldAddress: string, newAddress: string):
|
|
467
|
+
replaceDevice(iface: string, oldAddress: string, newAddress: string): true;
|
|
428
468
|
getKeyMismatchDevice(iface: string, params?: [reset?: boolean]): string;
|
|
429
469
|
suppressServiceMessages(
|
|
430
470
|
iface: string,
|