@project-chip/matter-node.js-examples 0.7.5-alpha.0-20240222-8696097f → 0.8.0-alpha.0-20240309-64eaef67

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. package/README.md +44 -0
  2. package/dist/esm/examples/BridgedDeviceNode.js +147 -0
  3. package/dist/esm/examples/BridgedDeviceNode.js.map +7 -0
  4. package/dist/esm/examples/{BridgedDevicesNode.js → BridgedDevicesNodeLegacy.js} +2 -2
  5. package/dist/esm/examples/BridgedDevicesNodeLegacy.js.map +7 -0
  6. package/dist/esm/examples/ComposedDeviceNode.js +116 -127
  7. package/dist/esm/examples/ComposedDeviceNode.js.map +3 -3
  8. package/dist/esm/examples/ComposedDeviceNodeLegacy.js +138 -0
  9. package/dist/esm/examples/ComposedDeviceNodeLegacy.js.map +7 -0
  10. package/dist/esm/examples/ControllerNode.js +24 -20
  11. package/dist/esm/examples/ControllerNode.js.map +2 -2
  12. package/dist/esm/examples/ControllerNodeLegacy.js +227 -0
  13. package/dist/esm/examples/ControllerNodeLegacy.js.map +7 -0
  14. package/dist/esm/examples/DeviceNode.js +118 -159
  15. package/dist/esm/examples/DeviceNode.js.map +2 -2
  16. package/dist/esm/examples/DeviceNodeFull.js +253 -0
  17. package/dist/esm/examples/DeviceNodeFull.js.map +7 -0
  18. package/dist/esm/examples/DeviceNodeFullLegacy.js +171 -0
  19. package/dist/esm/examples/DeviceNodeFullLegacy.js.map +7 -0
  20. package/dist/esm/examples/IlluminatedRollerShade.js +85 -0
  21. package/dist/esm/examples/IlluminatedRollerShade.js.map +7 -0
  22. package/dist/esm/examples/LightDevice.js +34 -0
  23. package/dist/esm/examples/LightDevice.js.map +7 -0
  24. package/dist/esm/examples/MultiDeviceNode.js +133 -134
  25. package/dist/esm/examples/MultiDeviceNode.js.map +3 -3
  26. package/dist/esm/examples/MultiDeviceNodeLegacy.js +146 -0
  27. package/dist/esm/examples/MultiDeviceNodeLegacy.js.map +7 -0
  28. package/dist/esm/examples/SensorDeviceNode.js +167 -0
  29. package/dist/esm/examples/SensorDeviceNode.js.map +7 -0
  30. package/dist/esm/examples/cluster/DummyThreadNetworkCommissioningServer.js +115 -0
  31. package/dist/esm/examples/cluster/DummyThreadNetworkCommissioningServer.js.map +7 -0
  32. package/dist/esm/examples/cluster/DummyWifiNetworkCommissioningServer.js +115 -0
  33. package/dist/esm/examples/cluster/DummyWifiNetworkCommissioningServer.js.map +7 -0
  34. package/dist/esm/examples/cluster/{DummyWifiNetworkCommissioningClusterServer.js → DummyWifiNetworkCommissioningServerLegacy.js} +16 -14
  35. package/dist/esm/examples/cluster/DummyWifiNetworkCommissioningServerLegacy.js.map +7 -0
  36. package/dist/esm/examples/cluster/MyFancyOwnFunctionality.js +110 -0
  37. package/dist/esm/examples/cluster/MyFancyOwnFunctionality.js.map +7 -0
  38. package/dist/esm/tutorial/example01.js +5 -0
  39. package/dist/esm/tutorial/example01.js.map +7 -0
  40. package/dist/esm/tutorial/example02.js +7 -0
  41. package/dist/esm/tutorial/example02.js.map +7 -0
  42. package/dist/esm/tutorial/example03.js +15 -0
  43. package/dist/esm/tutorial/example03.js.map +7 -0
  44. package/dist/esm/tutorial/example04.js +10 -0
  45. package/dist/esm/tutorial/example04.js.map +7 -0
  46. package/dist/esm/tutorial/example05.js +14 -0
  47. package/dist/esm/tutorial/example05.js.map +7 -0
  48. package/package.json +9 -6
  49. package/src/examples/BridgedDeviceNode.ts +260 -0
  50. package/src/examples/{BridgedDevicesNode.ts → BridgedDevicesNodeLegacy.ts} +6 -1
  51. package/src/examples/ComposedDeviceNode.ts +173 -223
  52. package/src/examples/ComposedDeviceNodeLegacy.ts +252 -0
  53. package/src/examples/ControllerNode.ts +28 -22
  54. package/src/examples/ControllerNodeLegacy.ts +354 -0
  55. package/src/examples/DeviceNode.ts +173 -273
  56. package/src/examples/DeviceNodeFull.ts +440 -0
  57. package/src/examples/DeviceNodeFullLegacy.ts +307 -0
  58. package/src/examples/IlluminatedRollerShade.ts +130 -0
  59. package/src/examples/LightDevice.ts +60 -0
  60. package/src/examples/MultiDeviceNode.ts +184 -236
  61. package/src/examples/MultiDeviceNodeLegacy.ts +267 -0
  62. package/src/examples/SensorDeviceNode.ts +236 -0
  63. package/src/examples/cluster/DummyThreadNetworkCommissioningServer.ts +156 -0
  64. package/src/examples/cluster/DummyWifiNetworkCommissioningServer.ts +153 -0
  65. package/src/examples/cluster/{DummyWifiNetworkCommissioningClusterServer.ts → DummyWifiNetworkCommissioningServerLegacy.ts} +16 -13
  66. package/src/examples/cluster/MyFancyOwnFunctionality.ts +185 -0
  67. package/src/tsconfig.json +9 -1
  68. package/src/tutorial/example01.ts +6 -0
  69. package/src/tutorial/example02.ts +9 -0
  70. package/src/tutorial/example03.ts +19 -0
  71. package/src/tutorial/example04.ts +13 -0
  72. package/src/tutorial/example05.ts +19 -0
  73. package/dist/esm/examples/BridgedDevicesNode.js.map +0 -7
  74. package/dist/esm/examples/cluster/DummyWifiNetworkCommissioningClusterServer.js.map +0 -7
@@ -1,302 +1,202 @@
1
- #!/usr/bin/env node
2
1
  /**
3
2
  * @license
4
- * Copyright 2022 The node-matter Authors
3
+ * Copyright 2022-2024 Matter.js Authors
5
4
  * SPDX-License-Identifier: Apache-2.0
6
5
  */
7
6
 
8
7
  /**
9
- * This example shows how to create a simple on-off Matter device.
8
+ * This example shows how to create a simple on-off Matter device as a light or as a socket.
10
9
  * It can be used as CLI script and starting point for your own device node implementation.
10
+ * This example is CJS conform and do not use top level await's.
11
11
  */
12
12
 
13
13
  /**
14
14
  * Import needed modules from @project-chip/matter-node.js
15
15
  */
16
16
  // Include this first to auto-register Crypto, Network and Time Node.js implementations
17
- import { CommissioningServer, MatterServer } from "@project-chip/matter-node.js";
17
+ import "@project-chip/matter-node.js";
18
18
 
19
- import { BleNode } from "@project-chip/matter-node-ble.js/ble";
20
- import { Ble } from "@project-chip/matter-node.js/ble";
21
- import { OnOffLightDevice, OnOffPluginUnitDevice, logEndpoint } from "@project-chip/matter-node.js/device";
22
- import { Format, Level, Logger } from "@project-chip/matter-node.js/log";
23
- import { QrCode } from "@project-chip/matter-node.js/schema";
24
- import { StorageBackendDisk, StorageManager } from "@project-chip/matter-node.js/storage";
25
- import { Time } from "@project-chip/matter-node.js/time";
26
- import {
27
- commandExecutor,
28
- getIntParameter,
29
- getParameter,
30
- hasParameter,
31
- requireMinNodeVersion,
32
- singleton,
33
- } from "@project-chip/matter-node.js/util";
19
+ import { requireMinNodeVersion } from "@project-chip/matter-node.js/util";
34
20
  import { DeviceTypeId, VendorId } from "@project-chip/matter.js/datatype";
35
- import DummyWifiNetworkCommissioningClusterServer from "./cluster/DummyWifiNetworkCommissioningClusterServer.js";
36
-
37
- const logger = Logger.get("Device");
21
+ import { logEndpoint } from "@project-chip/matter.js/device";
22
+ import { OnOffLightDevice } from "@project-chip/matter.js/devices/OnOffLightDevice";
23
+ import { OnOffPlugInUnitDevice } from "@project-chip/matter.js/devices/OnOffPlugInUnitDevice";
24
+ import { Endpoint, EndpointServer } from "@project-chip/matter.js/endpoint";
25
+ import { Environment, StorageService } from "@project-chip/matter.js/environment";
26
+ import { ServerNode } from "@project-chip/matter.js/node";
27
+ import { Time } from "@project-chip/matter.js/time";
28
+ import { execSync } from "child_process";
38
29
 
39
30
  requireMinNodeVersion(16);
40
31
 
41
- /** Configure logging */
42
- switch (getParameter("loglevel")) {
43
- case "fatal":
44
- Logger.defaultLogLevel = Level.FATAL;
45
- break;
46
- case "error":
47
- Logger.defaultLogLevel = Level.ERROR;
48
- break;
49
- case "warn":
50
- Logger.defaultLogLevel = Level.WARN;
51
- break;
52
- case "info":
53
- Logger.defaultLogLevel = Level.INFO;
54
- break;
55
- }
56
-
57
- switch (getParameter("logformat")) {
58
- case "plain":
59
- Logger.format = Format.PLAIN;
60
- break;
61
- case "html":
62
- Logger.format = Format.HTML;
63
- break;
64
- default:
65
- if (process.stdin?.isTTY) Logger.format = Format.ANSI;
66
- }
67
-
68
- if (hasParameter("ble")) {
69
- // Initialize Ble
70
- Ble.get = singleton(
71
- () =>
72
- new BleNode({
73
- hciId: getIntParameter("ble-hci-id"),
74
- }),
75
- );
76
- }
77
-
78
- const storageLocation = getParameter("store") ?? ".device-node";
79
- const storage = new StorageBackendDisk(storageLocation, hasParameter("clearstorage"));
80
- logger.info(`Storage location: ${storageLocation} (Directory)`);
81
- logger.info(
82
- 'Use the parameter "-store NAME" to specify a different storage location, use -clearstorage to start with an empty storage.',
83
- );
84
-
85
- class Device {
86
- private matterServer: MatterServer | undefined;
87
-
88
- async start() {
89
- logger.info(`node-matter`);
90
-
91
- /**
92
- * Initialize the storage system.
93
- *
94
- * The storage manager is then also used by the Matter server, so this code block in general is required,
95
- * but you can choose a different storage backend as long as it implements the required API.
96
- */
97
-
98
- const storageManager = new StorageManager(storage);
99
- await storageManager.initialize();
100
-
101
- /**
102
- * Collect all needed data
103
- *
104
- * This block makes sure to collect all needed data from cli or storage. Replace this with where ever your data
105
- * come from.
106
- *
107
- * Note: This example also uses the initialized storage system to store the device parameter data for convenience
108
- * and easy reuse. When you also do that be careful to not overlap with Matter-Server own contexts
109
- * (so maybe better not ;-)).
110
- */
111
-
112
- const deviceStorage = storageManager.createContext("Device");
113
-
114
- if (deviceStorage.has("isSocket")) {
115
- logger.info("Device type found in storage. -type parameter is ignored.");
116
- }
117
- const isSocket = deviceStorage.get("isSocket", getParameter("type") === "socket");
118
- const deviceName = "Matter test device";
119
- const vendorName = "matter-node.js";
120
- const passcode = getIntParameter("passcode") ?? deviceStorage.get("passcode", 20202021);
121
- const discriminator = getIntParameter("discriminator") ?? deviceStorage.get("discriminator", 3840);
122
- // product name / id and vendor id should match what is in the device certificate
123
- const vendorId = getIntParameter("vendorid") ?? deviceStorage.get("vendorid", 0xfff1);
124
- const productName = `node-matter OnOff ${isSocket ? "Socket" : "Light"}`;
125
- const productId = getIntParameter("productid") ?? deviceStorage.get("productid", 0x8000);
126
-
127
- const netInterface = getParameter("netinterface");
128
- const port = getIntParameter("port") ?? 5540;
129
-
130
- const uniqueId = getIntParameter("uniqueid") ?? deviceStorage.get("uniqueid", Time.nowMs());
131
-
132
- deviceStorage.set("passcode", passcode);
133
- deviceStorage.set("discriminator", discriminator);
134
- deviceStorage.set("vendorid", vendorId);
135
- deviceStorage.set("productid", productId);
136
- deviceStorage.set("isSocket", isSocket);
137
- deviceStorage.set("uniqueid", uniqueId);
138
-
139
- /**
140
- * Create Device instance and add needed Listener
141
- *
142
- * Create an instance of the matter device class you want to use.
143
- * This example uses the OnOffLightDevice or OnOffPluginUnitDevice depending on the value of the type parameter.
144
- * To execute the on/off scripts defined as parameters a listener for the onOff attribute is registered via the
145
- * device specific API.
146
- *
147
- * The below logic also adds command handlers for commands of clusters that normally are handled device internally
148
- * like identify that can be implemented with the logic when these commands are called.
149
- */
150
-
151
- const onOffDevice = isSocket ? new OnOffPluginUnitDevice() : new OnOffLightDevice();
152
- onOffDevice.addOnOffListener(on => commandExecutor(on ? "on" : "off")?.());
153
-
154
- onOffDevice.addCommandHandler("identify", async ({ request: { identifyTime } }) =>
155
- logger.info(`Identify called for OnOffDevice: ${identifyTime}`),
156
- );
157
-
158
- /**
159
- * Create Matter Server and CommissioningServer Node
160
- *
161
- * To allow the device to be announced, found, paired and operated we need a MatterServer instance and add a
162
- * commissioningServer to it and add the just created device instance to it.
163
- * The CommissioningServer node defines the port where the server listens for the UDP packages of the Matter protocol
164
- * and initializes deice specific certificates and such.
165
- *
166
- * The below logic also adds command handlers for commands of clusters that normally are handled internally
167
- * like testEventTrigger (General Diagnostic Cluster) that can be implemented with the logic when these commands
168
- * are called.
169
- */
170
-
171
- this.matterServer = new MatterServer(storageManager, { mdnsInterface: netInterface });
172
-
173
- const commissioningServer = new CommissioningServer({
32
+ async function main() {
33
+ /** Initialize configuration values */
34
+ const {
35
+ isSocket,
36
+ deviceName,
37
+ vendorName,
38
+ passcode,
39
+ discriminator,
40
+ vendorId,
41
+ productName,
42
+ productId,
43
+ port,
44
+ uniqueId,
45
+ } = await getConfiguration();
46
+
47
+ /**
48
+ * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration
49
+ */
50
+ const server = await ServerNode.create({
51
+ // Required: Give the Node a unique ID which is used to store the state of this node
52
+ id: uniqueId,
53
+
54
+ // Provide Network relevant configuration like the port
55
+ // Optional when operating only one device on a host, Default port is 5540
56
+ network: {
174
57
  port,
175
- deviceName,
176
- deviceType: DeviceTypeId(onOffDevice.deviceType),
58
+ },
59
+
60
+ // Provide Commissioning relevant settings
61
+ // Optional for development/testing purposes
62
+ commissioning: {
177
63
  passcode,
178
64
  discriminator,
179
- basicInformation: {
180
- vendorName,
181
- vendorId: VendorId(vendorId),
182
- nodeLabel: productName,
183
- productName,
184
- productLabel: productName,
185
- productId,
186
- serialNumber: `node-matter-${uniqueId}`,
187
- },
188
- delayedAnnouncement: hasParameter("ble"), // Delay announcement when BLE is used to show how limited advertisement works
189
- activeSessionsChangedCallback: fabricIndex => {
190
- console.log(
191
- `activeSessionsChangedCallback: Active sessions changed on Fabric ${fabricIndex}`,
192
- commissioningServer.getActiveSessionInformation(fabricIndex),
193
- );
194
- },
195
- commissioningChangedCallback: fabricIndex => {
196
- console.log(
197
- `commissioningChangedCallback: Commissioning changed on Fabric ${fabricIndex}`,
198
- commissioningServer.getCommissionedFabricInformation(fabricIndex)[0],
199
- );
200
- },
201
- });
202
-
203
- // optionally add a listener for the testEventTrigger command from the GeneralDiagnostics cluster
204
- commissioningServer.addCommandHandler("testEventTrigger", async ({ request: { enableKey, eventTrigger } }) =>
205
- logger.info(`testEventTrigger called on GeneralDiagnostic cluster: ${enableKey} ${eventTrigger}`),
206
- );
207
-
208
- /**
209
- * Modify automatically added clusters of the Root endpoint if needed
210
- * In this example we change the networkCommissioning cluster into one for "Wifi only" devices when BLE is used
211
- * for commissioning, to demonstrate how to do this.
212
- * If you want to implement Ethernet only devices that get connected to the network via LAN/Ethernet cable,
213
- * then all this is not needed.
214
- * The same as shown here for Wi-Fi is also possible theoretical for Thread only or combined devices.
215
- */
216
-
217
- if (hasParameter("ble")) {
218
- // matter.js will create a Ethernet-only device by default when ut comes to Network Commissioning Features.
219
- // To offer e.g. a "Wi-Fi only device" (or any other combination) we need to override the Network Commissioning
220
- // cluster and implement all the need handling here. This is a "static implementation" for pure demonstration
221
- // purposes and just "simulates" the actions to be done. In a real world implementation this would be done by
222
- // the device implementor based on the relevant networking stack.
223
- // The NetworkCommissioningCluster and all logics are described in Matter Core Specifications section 11.8
224
- commissioningServer.addRootClusterServer(DummyWifiNetworkCommissioningClusterServer);
225
- }
226
-
227
- commissioningServer.addDevice(onOffDevice);
228
-
229
- await this.matterServer.addCommissioningServer(commissioningServer);
230
-
231
- /**
232
- * Start the Matter Server
233
- *
234
- * After everything was plugged together we can start the server. When not delayed announcement is set for the
235
- * CommissioningServer node then this command also starts the announcement of the device into the network.
236
- */
237
-
238
- await this.matterServer.start();
239
-
240
- logEndpoint(commissioningServer.getRootEndpoint());
241
-
242
- // When we want to limit the initial announcement to one medium (e.g. BLE) then we need to delay the
243
- // announcement and provide the limiting information.
244
- // Without delaying the announcement is directly triggered with the above "start()" call.
245
- if (hasParameter("ble")) {
246
- // Announce operational in BLE network only if we have ble enabled, else everywhere
247
- await commissioningServer.advertise({ ble: true });
65
+ },
66
+
67
+ // Provide Node announcement settings
68
+ // Optional: If Ommitted some development defaults are used
69
+ productDescription: {
70
+ name: deviceName,
71
+ deviceType: DeviceTypeId(isSocket ? OnOffPlugInUnitDevice.deviceType : OnOffLightDevice.deviceType),
72
+ },
73
+
74
+ // Provide defaults for the BasicInformation cluster on the Root endpoint
75
+ // Optional: If Omitted some development defaults are used
76
+ basicInformation: {
77
+ vendorName,
78
+ vendorId: VendorId(vendorId),
79
+ nodeLabel: productName,
80
+ productName,
81
+ productLabel: productName,
82
+ productId,
83
+ serialNumber: `matterjs-${uniqueId}`,
84
+ uniqueId,
85
+ },
86
+ });
87
+
88
+ /**
89
+ * Matter Nodes are a composition of endpoints. Create and add a single endpoint to the node. This example uses the
90
+ * OnOffLightDevice or OnOffPlugInUnitDevice depending on the value of the type parameter. It also assigns this Part a
91
+ * unique ID to store the endpoint number for it in the storage to restore the device on restart.
92
+ * In this case we directly use the default command implementation from matter.js. Check out the DeviceNodeFull example
93
+ * to see how to customize the command handlers.
94
+ */
95
+ const endpoint = new Endpoint(isSocket ? OnOffPlugInUnitDevice : OnOffLightDevice, { id: "onoff" });
96
+ await server.add(endpoint);
97
+
98
+ /**
99
+ * Register state change handlers of the node for identify and onoff states to react to the commands.
100
+ * If the code in these change handlers fail then the change is also rolled back and not executed and an error is
101
+ * reported back to the controller.
102
+ */
103
+ let isIdentifying = false;
104
+ endpoint.events.identify.identifyTime$Change.on(value => {
105
+ // identifyTime is set when an identify command is called and then decreased every second while indentify logic runs.
106
+ if (value > 0 && !isIdentifying) {
107
+ isIdentifying = true;
108
+ console.log(`Run identify logic, ideally blink a light every 0.5s ...`);
109
+ } else if (value === 0) {
110
+ isIdentifying = false;
111
+ console.log(`Stop identify logic ...`);
248
112
  }
113
+ });
114
+
115
+ endpoint.events.onOff.onOff$Change.on(value => {
116
+ executeCommand(value ? "on" : "off");
117
+ console.log(`OnOff is now ${value ? "ON" : "OFF"}`);
118
+ });
119
+
120
+ /**
121
+ * Log the endpoint structure for debugging reasons and to allow to verify anything is correct
122
+ */
123
+ logEndpoint(EndpointServer.forEndpoint(server));
124
+
125
+ /**
126
+ * In order to start the node and announce it into the network we use the run method which resolves when the node goes
127
+ * offline again because we do not need anything more here. See the Full example for other starting options.
128
+ * The QR Code is printed automatically.
129
+ */
130
+ await server.run();
131
+ }
249
132
 
250
- /**
251
- * Print Pairing Information
252
- *
253
- * If the device is not already commissioned (this info is stored in the storage system) then get and print the
254
- * pairing details. This includes the QR code that can be scanned by the Matter app to pair the device.
255
- */
133
+ main().catch(error => console.error(error));
256
134
 
257
- logger.info("Listening");
258
- if (!commissioningServer.isCommissioned()) {
259
- const pairingData = commissioningServer.getPairingCode({
260
- ble: hasParameter("ble"),
261
- softAccessPoint: false,
262
- onIpNetwork: false,
263
- });
135
+ /*********************************************************************************************************
136
+ * Convenience Methods
137
+ *********************************************************************************************************/
264
138
 
265
- const { qrPairingCode, manualPairingCode } = pairingData;
139
+ /** Defined a shell command from an environment variable and execute it and log the response. */
140
+ function executeCommand(scriptParamName: string) {
141
+ const script = Environment.default.vars.string(scriptParamName);
142
+ if (script === undefined) return undefined;
143
+ console.log(`${scriptParamName}: ${execSync(script).toString().slice(0, -1)}`);
144
+ }
266
145
 
267
- console.log(QrCode.get(qrPairingCode));
268
- logger.info(
269
- `QR Code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`,
270
- );
271
- logger.info(`Manual pairing code: ${manualPairingCode}`);
272
- } else {
273
- logger.info("Device is already commissioned. Waiting for controllers to connect ...");
274
- }
275
- }
146
+ async function getConfiguration() {
147
+ /**
148
+ * Collect all needed data
149
+ *
150
+ * This block collects all needed data from cli, environment or storage. Replace this with where ever your data come from.
151
+ *
152
+ * Note: This example uses the matter.js process storage system to store the device parameter data for convenience
153
+ * and easy reuse. When you also do that be careful to not overlap with Matter-Server own storage contexts
154
+ * (so maybe better not do it ;-)).
155
+ */
156
+ const environment = Environment.default;
157
+
158
+ const storageService = environment.get(StorageService);
159
+ console.log(`Storage location: ${storageService.location} (Directory)`);
160
+ console.log(
161
+ 'Use the parameter "--storage-path=NAME-OR-PATH" to specify a different storage location in this directory, use --storage-clear to start with an empty storage.',
162
+ );
163
+ const deviceStorage = (await storageService.open("device")).createContext("data");
276
164
 
277
- async stop() {
278
- await this.matterServer?.close();
165
+ const isSocket = deviceStorage.get("isSocket", environment.vars.get("type") === "socket");
166
+ if (deviceStorage.has("isSocket")) {
167
+ console.log(`Device type ${isSocket ? "socket" : "light"} found in storage. --type parameter is ignored.`);
279
168
  }
169
+ const deviceName = "Matter test device";
170
+ const vendorName = "matter-node.js";
171
+ const passcode = environment.vars.number("passcode") ?? deviceStorage.get("passcode", 20202021);
172
+ const discriminator = environment.vars.number("discriminator") ?? deviceStorage.get("discriminator", 3840);
173
+ // product name / id and vendor id should match what is in the device certificate
174
+ const vendorId = environment.vars.number("vendorid") ?? deviceStorage.get("vendorid", 0xfff1);
175
+ const productName = `node-matter OnOff ${isSocket ? "Socket" : "Light"}`;
176
+ const productId = environment.vars.number("productid") ?? deviceStorage.get("productid", 0x8000);
177
+
178
+ const port = environment.vars.number("port") ?? 5540;
179
+
180
+ const uniqueId = environment.vars.string("uniqueid") ?? deviceStorage.get("uniqueid", Time.nowMs().toString());
181
+
182
+ // Persist basic data to keep them also on restart
183
+ deviceStorage.set("passcode", passcode);
184
+ deviceStorage.set("discriminator", discriminator);
185
+ deviceStorage.set("vendorid", vendorId);
186
+ deviceStorage.set("productid", productId);
187
+ deviceStorage.set("isSocket", isSocket);
188
+ deviceStorage.set("uniqueid", uniqueId);
189
+
190
+ return {
191
+ isSocket,
192
+ deviceName,
193
+ vendorName,
194
+ passcode,
195
+ discriminator,
196
+ vendorId,
197
+ productName,
198
+ productId,
199
+ port,
200
+ uniqueId,
201
+ };
280
202
  }
281
-
282
- const device = new Device();
283
- device
284
- .start()
285
- .then(() => {
286
- /* done */
287
- })
288
- .catch(err => console.error(err));
289
-
290
- process.on("SIGINT", () => {
291
- // Clean up on CTRL-C
292
- device
293
- .stop()
294
- .then(() => {
295
- // Pragmatic way to make sure the storage is correctly closed before the process ends.
296
- storage
297
- .close()
298
- .then(() => process.exit(0))
299
- .catch(err => console.error(err));
300
- })
301
- .catch(err => console.error(err));
302
- });