Skip to content

Commit 485f10c

Browse files
raman325claude
andcommitted
feat: add schema 47 state properties, events, and infrastructure (1/4)
Add schema version 47 with new state properties for driver, controller, and node dumps. Add event forwarding for driver lifecycle events and controller network events. Include shared helpers, dependency updates, and documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 106d180 commit 485f10c

18 files changed

Lines changed: 646 additions & 154 deletions

API_SCHEMA.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,11 @@ Base schema.
114114

115115
- Added `allowed` property to numeric value metadata and configuration metadata
116116
- Added `purpose` property to configuration metadata
117+
118+
## Schema 47
119+
120+
- Added driver state properties: `ready`, `allNodesReady`, `configVersion`
121+
- Added node state properties: `canSleep`, `supportsWakeUpOnDemand`, `hardwareVersion`, `hasSUCReturnRoute`, `manufacturer`, `dsk`
122+
- Added controller state properties: `isSIS`, `maxPayloadSize`, `maxPayloadSizeLR`, `zwaveApiVersion`, `zwaveChipType`
123+
- Added driver events: `all nodes ready`, `error`, `bootloader ready`
124+
- Added controller events: `network found`, `network joined`, `network left`, `joining network failed`, `leaving network failed`

README.md

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1651,6 +1651,55 @@ interface {
16511651
}
16521652
```
16531653

1654+
#### `all nodes ready`
1655+
1656+
[compatible with schema version: 47+]
1657+
1658+
This event is sent when all nodes have been interviewed and are ready.
1659+
1660+
```ts
1661+
interface {
1662+
type: "event";
1663+
event: {
1664+
source: "driver";
1665+
event: "all nodes ready";
1666+
}
1667+
}
1668+
```
1669+
1670+
#### `error`
1671+
1672+
[compatible with schema version: 47+]
1673+
1674+
This event is sent when a driver error occurs.
1675+
1676+
```ts
1677+
interface {
1678+
type: "event";
1679+
event: {
1680+
source: "driver";
1681+
event: "error";
1682+
error: string;
1683+
}
1684+
}
1685+
```
1686+
1687+
#### `bootloader ready`
1688+
1689+
[compatible with schema version: 47+]
1690+
1691+
This event is sent when the controller enters bootloader mode.
1692+
1693+
```ts
1694+
interface {
1695+
type: "event";
1696+
event: {
1697+
source: "driver";
1698+
event: "bootloader ready";
1699+
}
1700+
}
1701+
```
1702+
16541703
#### `log config updated`
16551704

16561705
This event is sent whenever a client issues the `driver.update_log_config` command with the updated log config.
@@ -1769,7 +1818,7 @@ interface {
17691818

17701819
#### `nvm restore progress`
17711820

1772-
This event is sent on progress updates to the NVM restoration process when the [`controller.restore_nvm`](https://zwave-js.github.io/node-zwave-js/#/api/controller?id=nvm-backup-and-restore) command is issued by a client to the server and the NVM data is being restored to the controller.
1821+
This event is sent on progress updates to the NVM restoration process when the [`controller.restore_nvm`](https://zwave-js.github.io/node-zwave-js/#/api/controller?id=nvm-backup-and-restore) or `controller.restore_nvm_raw` command is issued by a client to the server and the NVM data is being restored to the controller.
17731822

17741823
```ts
17751824
interface {
@@ -1783,6 +1832,88 @@ interface {
17831832
}
17841833
```
17851834

1835+
#### `network found`
1836+
1837+
[compatible with schema version: 47+]
1838+
1839+
This event is sent when a new network is found during the join process (learn mode).
1840+
1841+
```ts
1842+
interface {
1843+
type: "event";
1844+
event: {
1845+
source: "controller";
1846+
event: "network found";
1847+
homeId: number;
1848+
ownNodeId: number;
1849+
}
1850+
}
1851+
```
1852+
1853+
#### `network joined`
1854+
1855+
[compatible with schema version: 47+]
1856+
1857+
This event is sent when the controller successfully joins a network.
1858+
1859+
```ts
1860+
interface {
1861+
type: "event";
1862+
event: {
1863+
source: "controller";
1864+
event: "network joined";
1865+
}
1866+
}
1867+
```
1868+
1869+
#### `network left`
1870+
1871+
[compatible with schema version: 47+]
1872+
1873+
This event is sent when the controller leaves the current network.
1874+
1875+
```ts
1876+
interface {
1877+
type: "event";
1878+
event: {
1879+
source: "controller";
1880+
event: "network left";
1881+
}
1882+
}
1883+
```
1884+
1885+
#### `joining network failed`
1886+
1887+
[compatible with schema version: 47+]
1888+
1889+
This event is sent when joining a network fails.
1890+
1891+
```ts
1892+
interface {
1893+
type: "event";
1894+
event: {
1895+
source: "controller";
1896+
event: "joining network failed";
1897+
}
1898+
}
1899+
```
1900+
1901+
#### `leaving network failed`
1902+
1903+
[compatible with schema version: 47+]
1904+
1905+
This event is sent when leaving a network fails.
1906+
1907+
```ts
1908+
interface {
1909+
type: "event";
1910+
event: {
1911+
source: "controller";
1912+
event: "leaving network failed";
1913+
}
1914+
}
1915+
```
1916+
17861917
## Schema Version
17871918

17881919
In an attempt to keep compatibility between different server and client versions, we've introduced a (basic) API Schema Version.

src/lib/broadcast_node/incoming_message.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,51 @@ import { BroadcastNodeCommand } from "./command.js";
66
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
77
export interface IncomingCommandBroadcastNodeBase extends IncomingCommandBase {}
88

9-
export interface IncomingCommandBroadcastNodeSetValue extends IncomingCommandBroadcastNodeBase {
9+
export interface IncomingCommandBroadcastNodeSetValue
10+
extends IncomingCommandBroadcastNodeBase {
1011
command: BroadcastNodeCommand.setValue;
1112
valueId: ValueID;
1213
value: unknown;
1314
options?: SetValueAPIOptions;
1415
}
1516

16-
export interface IncomingCommandBroadcastNodeGetEndpointCount extends IncomingCommandBroadcastNodeBase {
17+
export interface IncomingCommandBroadcastNodeGetEndpointCount
18+
extends IncomingCommandBroadcastNodeBase {
1719
command: BroadcastNodeCommand.getEndpointCount;
1820
}
1921

20-
export interface IncomingCommandBroadcastNodeSupportsCC extends IncomingCommandBroadcastNodeBase {
22+
export interface IncomingCommandBroadcastNodeSupportsCC
23+
extends IncomingCommandBroadcastNodeBase {
2124
command: BroadcastNodeCommand.supportsCC;
2225
index: number;
2326
commandClass: CommandClasses;
2427
}
2528

26-
export interface IncomingCommandBroadcastNodeGetCCVersion extends IncomingCommandBroadcastNodeBase {
29+
export interface IncomingCommandBroadcastNodeGetCCVersion
30+
extends IncomingCommandBroadcastNodeBase {
2731
command: BroadcastNodeCommand.getCCVersion;
2832
index: number;
2933
commandClass: CommandClasses;
3034
}
3135

32-
export interface IncomingCommandBroadcastNodeInvokeCCAPI extends IncomingCommandBroadcastNodeBase {
36+
export interface IncomingCommandBroadcastNodeInvokeCCAPI
37+
extends IncomingCommandBroadcastNodeBase {
3338
command: BroadcastNodeCommand.invokeCCAPI;
3439
index?: number;
3540
commandClass: CommandClasses;
3641
methodName: string;
3742
args: unknown[];
3843
}
3944

40-
export interface IncomingCommandBroadcastNodeSupportsCCAPI extends IncomingCommandBroadcastNodeBase {
45+
export interface IncomingCommandBroadcastNodeSupportsCCAPI
46+
extends IncomingCommandBroadcastNodeBase {
4147
command: BroadcastNodeCommand.supportsCCAPI;
4248
index?: number;
4349
commandClass: CommandClasses;
4450
}
4551

46-
export interface IncomingCommandBroadcastNodeGetDefinedValueIDs extends IncomingCommandBroadcastNodeBase {
52+
export interface IncomingCommandBroadcastNodeGetDefinedValueIDs
53+
extends IncomingCommandBroadcastNodeBase {
4754
command: BroadcastNodeCommand.getDefinedValueIDs;
4855
}
4956

src/lib/common.ts

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,17 @@ import {
77
SetValueStatus,
88
ZWaveNode,
99
} from "zwave-js";
10+
import type { GetFirmwareUpdatesOptions } from "zwave-js/Controller";
11+
import type { Client } from "./server.js";
1012
import type { ConfigurationCCAPISetOptions } from "@zwave-js/cc";
11-
import { SupervisionResult, MaybeNotKnown } from "@zwave-js/core";
13+
import {
14+
FirmwareFileFormat,
15+
guessFirmwareFileFormat,
16+
MaybeNotKnown,
17+
RFRegion,
18+
SupervisionResult,
19+
tryUnzipFirmwareFile,
20+
} from "@zwave-js/core";
1221
import {
1322
IncomingCommandNodeGetRawConfigParameterValue,
1423
IncomingCommandNodeSetRawConfigParameterValue,
@@ -109,3 +118,58 @@ export async function getRawConfigParameterValue(
109118
);
110119
return { value };
111120
}
121+
122+
export interface FirmwareFileInfo {
123+
filename: string;
124+
rawData: Uint8Array<ArrayBuffer>;
125+
format: FirmwareFileFormat;
126+
}
127+
128+
/**
129+
* Tries to determine the firmware file format, with automatic ZIP extraction fallback.
130+
* First attempts guessFirmwareFileFormat. If that fails, tries to extract from ZIP archive.
131+
*/
132+
export function parseFirmwareFile(
133+
filename: string,
134+
rawData: Uint8Array<ArrayBuffer>,
135+
explicitFormat?: FirmwareFileFormat,
136+
): FirmwareFileInfo {
137+
// If format is explicitly provided, use it directly
138+
if (explicitFormat !== undefined) {
139+
return { filename, rawData, format: explicitFormat };
140+
}
141+
142+
try {
143+
// First, try to guess the format directly
144+
const format = guessFirmwareFileFormat(filename, rawData);
145+
return { filename, rawData, format };
146+
} catch (guessError) {
147+
// If guessing failed, try to extract from ZIP
148+
const unzipped = tryUnzipFirmwareFile(rawData);
149+
if (unzipped) {
150+
return {
151+
filename: unzipped.filename,
152+
rawData: unzipped.rawData,
153+
format: unzipped.format,
154+
};
155+
}
156+
// If unzip also failed, re-throw the original error
157+
throw guessError;
158+
}
159+
}
160+
161+
export function getFirmwareUpdateOptions(
162+
message: {
163+
apiKey?: string;
164+
includePrereleases?: boolean;
165+
rfRegion?: RFRegion;
166+
},
167+
client: Client,
168+
): GetFirmwareUpdatesOptions {
169+
return {
170+
apiKey: message.apiKey,
171+
additionalUserAgentComponents: client.additionalUserAgentComponents,
172+
includePrereleases: message.includePrereleases,
173+
rfRegion: message.rfRegion,
174+
};
175+
}

src/lib/config_manager/incoming_message.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,59 @@ import { ConfigManagerCommand } from "./command.js";
44
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
55
export interface IncomingCommandConfigManagerBase extends IncomingCommandBase {}
66

7-
export interface IncomingCommandConfigManagerLookupDevice extends IncomingCommandConfigManagerBase {
7+
export interface IncomingCommandConfigManagerLookupDevice
8+
extends IncomingCommandConfigManagerBase {
89
command: ConfigManagerCommand.lookupDevice;
910
manufacturerId: number;
1011
productType: number;
1112
productId: number;
1213
firmwareVersion?: string;
1314
}
1415

15-
export interface IncomingCommandConfigManagerLoadManufacturers extends IncomingCommandConfigManagerBase {
16+
export interface IncomingCommandConfigManagerLoadManufacturers
17+
extends IncomingCommandConfigManagerBase {
1618
command: ConfigManagerCommand.loadManufacturers;
1719
}
1820

19-
export interface IncomingCommandConfigManagerLookupManufacturer extends IncomingCommandConfigManagerBase {
21+
export interface IncomingCommandConfigManagerLookupManufacturer
22+
extends IncomingCommandConfigManagerBase {
2023
command: ConfigManagerCommand.lookupManufacturer;
2124
manufacturerId: number;
2225
}
23-
export interface IncomingCommandConfigManagerLoadDeviceIndex extends IncomingCommandConfigManagerBase {
26+
export interface IncomingCommandConfigManagerLoadDeviceIndex
27+
extends IncomingCommandConfigManagerBase {
2428
command: ConfigManagerCommand.loadDeviceIndex;
2529
}
26-
export interface IncomingCommandConfigManagerGetIndex extends IncomingCommandConfigManagerBase {
30+
export interface IncomingCommandConfigManagerGetIndex
31+
extends IncomingCommandConfigManagerBase {
2732
command: ConfigManagerCommand.getIndex;
2833
}
29-
export interface IncomingCommandConfigManagerLoadFulltextDeviceIndex extends IncomingCommandConfigManagerBase {
34+
export interface IncomingCommandConfigManagerLoadFulltextDeviceIndex
35+
extends IncomingCommandConfigManagerBase {
3036
command: ConfigManagerCommand.loadFulltextDeviceIndex;
3137
}
32-
export interface IncomingCommandConfigManagerGetFulltextIndex extends IncomingCommandConfigManagerBase {
38+
export interface IncomingCommandConfigManagerGetFulltextIndex
39+
extends IncomingCommandConfigManagerBase {
3340
command: ConfigManagerCommand.getFulltextIndex;
3441
}
35-
export interface IncomingCommandConfigManagerLookupDevicePreserveConditions extends IncomingCommandConfigManagerBase {
42+
export interface IncomingCommandConfigManagerLookupDevicePreserveConditions
43+
extends IncomingCommandConfigManagerBase {
3644
command: ConfigManagerCommand.lookupDevicePreserveConditions;
3745
manufacturerId: number;
3846
productType: number;
3947
productId: number;
4048
firmwareVersion?: string;
4149
}
42-
export interface IncomingCommandConfigManagerManufacturers extends IncomingCommandConfigManagerBase {
50+
export interface IncomingCommandConfigManagerManufacturers
51+
extends IncomingCommandConfigManagerBase {
4352
command: ConfigManagerCommand.manufacturers;
4453
}
45-
export interface IncomingCommandConfigManagerLoadAll extends IncomingCommandConfigManagerBase {
54+
export interface IncomingCommandConfigManagerLoadAll
55+
extends IncomingCommandConfigManagerBase {
4656
command: ConfigManagerCommand.loadAll;
4757
}
48-
export interface IncomingCommandConfigManagerConfigVersion extends IncomingCommandConfigManagerBase {
58+
export interface IncomingCommandConfigManagerConfigVersion
59+
extends IncomingCommandConfigManagerBase {
4960
command: ConfigManagerCommand.configVersion;
5061
}
5162
export type IncomingMessageConfigManager =

src/lib/const.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export const version = require("../../package.json").version;
66
export const minSchemaVersion = 0;
77

88
// maximal/current schema version the server supports
9-
export const maxSchemaVersion = 46;
9+
export const maxSchemaVersion = 47;
1010

1111
export const applicationName = "zwave-js-server";
1212
export const dnssdServiceType = applicationName;

0 commit comments

Comments
 (0)