@project-chip/matter-node.js-examples 0.7.5 → 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
@@ -0,0 +1,260 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2024 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ /**
8
+ * This example shows how to create a new device node that is composed of multiple devices.
9
+ * It creates multiple endpoints on the server. For information on how to add a composed device to a bridge please
10
+ * refer to the bridge example!
11
+ * It can be used as CLI script and starting point for your own device node implementation.
12
+ */
13
+
14
+ /**
15
+ * Import needed modules from @project-chip/matter-node.js
16
+ */
17
+ // Include this first to auto-register Crypto, Network and Time Node.js implementations
18
+ import "@project-chip/matter-node.js";
19
+
20
+ import { requireMinNodeVersion } from "@project-chip/matter-node.js/util";
21
+ import { BridgedDeviceBasicInformationServer } from "@project-chip/matter.js/behavior/definitions/bridged-device-basic-information";
22
+ import { DeviceTypeId, VendorId } from "@project-chip/matter.js/datatype";
23
+ import { logEndpoint } from "@project-chip/matter.js/device";
24
+ import { OnOffLightDevice } from "@project-chip/matter.js/devices/OnOffLightDevice";
25
+ import { OnOffPlugInUnitDevice } from "@project-chip/matter.js/devices/OnOffPlugInUnitDevice";
26
+ import { Endpoint, EndpointServer } from "@project-chip/matter.js/endpoint";
27
+ import { AggregatorEndpoint } from "@project-chip/matter.js/endpoint/definitions";
28
+ import { Environment, StorageService } from "@project-chip/matter.js/environment";
29
+ import { ServerNode } from "@project-chip/matter.js/node";
30
+ import { Time } from "@project-chip/matter.js/time";
31
+ import { execSync } from "child_process";
32
+
33
+ requireMinNodeVersion(16);
34
+
35
+ /** Initialize configuration values */
36
+ const { isSocket, deviceName, vendorName, passcode, discriminator, vendorId, productName, productId, port, uniqueId } =
37
+ await getConfiguration();
38
+
39
+ /**
40
+ * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration
41
+ */
42
+ const server = await ServerNode.create({
43
+ // Required: Give the Node a unique ID which is used to store the state of this node
44
+ id: uniqueId,
45
+
46
+ // Provide Network relevant configuration like the port
47
+ // Optional when operating only one device on a host, Default port is 5540
48
+ network: {
49
+ port,
50
+ },
51
+
52
+ // Provide Commissioning relevant settings
53
+ // Optional for development/testing purposes
54
+ commissioning: {
55
+ passcode,
56
+ discriminator,
57
+ },
58
+
59
+ // Provide Node announcement settings
60
+ // Optional: If Ommitted some development defaults are used
61
+ productDescription: {
62
+ name: deviceName,
63
+ deviceType: DeviceTypeId(isSocket[0] ? OnOffPlugInUnitDevice.deviceType : OnOffLightDevice.deviceType),
64
+ },
65
+
66
+ // Provide defaults for the BasicInformation cluster on the Root endpoint
67
+ // Optional: If Omitted some development defaults are used
68
+ basicInformation: {
69
+ vendorName,
70
+ vendorId: VendorId(vendorId),
71
+ nodeLabel: productName,
72
+ productName,
73
+ productLabel: productName,
74
+ productId,
75
+ serialNumber: `matterjs-${uniqueId}`,
76
+ uniqueId,
77
+ },
78
+ });
79
+
80
+ /**
81
+ * Matter Nodes are a composition of endpoints. Create and add a single multiple endpoint to the node to make it a
82
+ * composed device. This example uses the OnOffLightDevice or OnOffPlugInUnitDevice depending on the value of the type
83
+ * parameter. It also assigns each Endpoint a unique ID to store the endpoint number for it in the storage to restore
84
+ * the device on restart.
85
+ *
86
+ * In this case we directly use the default command implementation from matter.js. Check out the DeviceNodeFull example
87
+ * to see how to customize the command handlers.
88
+ */
89
+
90
+ const aggregator = new Endpoint(AggregatorEndpoint, { id: "aggregator" });
91
+ await server.add(aggregator);
92
+
93
+ for (let idx = 0; idx < isSocket.length; idx++) {
94
+ const i = idx + 1;
95
+ const isASocket = isSocket[idx]; // Is the Device we add a Socket or a Light?
96
+
97
+ const name = `OnOff ${isASocket ? "Socket" : "Light"} ${i}`;
98
+
99
+ const endpoint = new Endpoint(
100
+ isASocket
101
+ ? // For a Bridged Device we need to add a BridgedDeviceBasicInformation cluster as server
102
+ OnOffPlugInUnitDevice.with(BridgedDeviceBasicInformationServer)
103
+ : OnOffLightDevice.with(BridgedDeviceBasicInformationServer),
104
+ {
105
+ id: `onoff-${i}`,
106
+ bridgedDeviceBasicInformation: {
107
+ nodeLabel: name,
108
+ productName: name,
109
+ productLabel: name,
110
+ serialNumber: `node-matter-${uniqueId}-${i}`,
111
+ reachable: true,
112
+ },
113
+ },
114
+ );
115
+ await aggregator.add(endpoint);
116
+
117
+ /**
118
+ * Register state change handlers of the endpoint for identify and onoff states to react to the commands.
119
+ *
120
+ * If the code in these change handlers fail then the change is also rolled back and not executed and an error is
121
+ * reported back to the controller.
122
+ */
123
+ let isIdentifying = false;
124
+ endpoint.events.identify.identifyTime$Change.on(value => {
125
+ // identifyTime is set when an identify commandf is called and then decreased every second while indenitfy logic runs.
126
+ if (value > 0 && !isIdentifying) {
127
+ isIdentifying = true;
128
+ console.log(`${name}: Run identify logic, ideally blink a light every 0.5s ...`);
129
+ } else if (value === 0) {
130
+ isIdentifying = false;
131
+ console.log(`${name}: Stop identify logic ...`);
132
+ }
133
+ });
134
+
135
+ endpoint.events.onOff.onOff$Change.on(value => {
136
+ executeCommand(value ? `on${i}` : `off${i}`);
137
+ console.log(`${name} is now ${value ? "ON" : "OFF"}`);
138
+ });
139
+ }
140
+
141
+ /**
142
+ * In order to start the node and announce it into the network we use the run method which resolves when the node goes
143
+ * offline again because we do not need anything more here. See the Full example for other starting options.
144
+ * The QR Code is printed automatically.
145
+ */
146
+ await server.bringOnline();
147
+
148
+ /**
149
+ * Log the endpoint structure for debugging reasons and to allow to verify anything is correct
150
+ */
151
+ logEndpoint(EndpointServer.forEndpoint(server));
152
+
153
+ /*
154
+ If you want to dynamically add another device during runtime you can do so by doing the following:
155
+
156
+ const name = `OnOff Light 3`;
157
+
158
+ const endpoint = new Endpoint(OnOffLightDevice.with(BridgedDeviceBasicInformationServer), {
159
+ id: `onoff-3`,
160
+ bridgedDeviceBasicInformation: {
161
+ nodeLabel: name,
162
+ productName: name,
163
+ productLabel: name,
164
+ serialNumber: `node-matter-${uniqueId}-3`,
165
+ reachable: true,
166
+ },
167
+ });
168
+ await aggregator.add(endpoint);
169
+
170
+ endpoint.events.onOff.onOff$Change.on(value => {
171
+ executeCommand(value ? `on3` : `off3`);
172
+ console.log(`${name} is now ${value ? "ON" : "OFF"}`);
173
+ });
174
+
175
+ */
176
+
177
+ /*
178
+ To remove a device during runtime you can do so by doing the following:
179
+ console.log("Removing Light 3 now!!");
180
+
181
+ await endpoint.close();
182
+
183
+ This will automatically remove the endpoint from the bridge.
184
+ */
185
+
186
+ /*********************************************************************************************************
187
+ * Convenience Methods
188
+ *********************************************************************************************************/
189
+
190
+ /** Defined a shell command from an environment variable and execute it and log the response. */
191
+ function executeCommand(scriptParamName: string) {
192
+ const script = Environment.default.vars.string(scriptParamName);
193
+ if (script === undefined) return undefined;
194
+ console.log(`${scriptParamName}: ${execSync(script).toString().slice(0, -1)}`);
195
+ }
196
+
197
+ async function getConfiguration() {
198
+ /**
199
+ * Collect all needed data
200
+ *
201
+ * This block collects all needed data from cli, environment or storage. Replace this with where ever your data come from.
202
+ *
203
+ * Note: This example uses the matter.js process storage system to store the device parameter data for convenience
204
+ * and easy reuse. When you also do that be careful to not overlap with Matter-Server own storage contexts
205
+ * (so maybe better not do it ;-)).
206
+ */
207
+ const environment = Environment.default;
208
+
209
+ const storageService = environment.get(StorageService);
210
+ console.log(`Storage location: ${storageService.location} (Directory)`);
211
+ console.log(
212
+ '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.',
213
+ );
214
+ const deviceStorage = (await storageService.open("device")).createContext("data");
215
+
216
+ const isSocket = Array<boolean>();
217
+ const numDevices = environment.vars.number("num") || 2;
218
+ if (deviceStorage.has("isSocket")) {
219
+ console.log(`Device types found in storage. --type parameter is ignored.`);
220
+ deviceStorage.get<Array<boolean>>("isSocket").forEach(type => isSocket.push(type));
221
+ }
222
+ for (let i = 1; i <= numDevices; i++) {
223
+ if (isSocket[i - 1] !== undefined) continue;
224
+ isSocket.push(environment.vars.string(`type${i}`) === "socket");
225
+ }
226
+
227
+ const deviceName = "Matter test device";
228
+ const vendorName = "matter-node.js";
229
+ const passcode = environment.vars.number("passcode") ?? deviceStorage.get("passcode", 20202021);
230
+ const discriminator = environment.vars.number("discriminator") ?? deviceStorage.get("discriminator", 3840);
231
+ // product name / id and vendor id should match what is in the device certificate
232
+ const vendorId = environment.vars.number("vendorid") ?? deviceStorage.get("vendorid", 0xfff1);
233
+ const productName = `node-matter OnOff ${isSocket ? "Socket" : "Light"}`;
234
+ const productId = environment.vars.number("productid") ?? deviceStorage.get("productid", 0x8000);
235
+
236
+ const port = environment.vars.number("port") ?? 5540;
237
+
238
+ const uniqueId = environment.vars.string("uniqueid") ?? deviceStorage.get("uniqueid", Time.nowMs().toString());
239
+
240
+ // Persist basic data to keep them also on restart
241
+ deviceStorage.set("passcode", passcode);
242
+ deviceStorage.set("discriminator", discriminator);
243
+ deviceStorage.set("vendorid", vendorId);
244
+ deviceStorage.set("productid", productId);
245
+ deviceStorage.set("isSocket", isSocket);
246
+ deviceStorage.set("uniqueid", uniqueId);
247
+
248
+ return {
249
+ isSocket,
250
+ deviceName,
251
+ vendorName,
252
+ passcode,
253
+ discriminator,
254
+ vendorId,
255
+ productName,
256
+ productId,
257
+ port,
258
+ uniqueId,
259
+ };
260
+ }
@@ -1,10 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * @license
4
- * Copyright 2022 The node-matter Authors
4
+ * Copyright 2022-2024 Matter.js Authors
5
5
  * SPDX-License-Identifier: Apache-2.0
6
6
  */
7
7
 
8
+ /**
9
+ * IMPORTANT: This example uses a Legacy API which will be deprecated in the future.
10
+ * It is just still here to support developers in converting their code to the new API!
11
+ */
12
+
8
13
  /**
9
14
  * This example shows how to create a device bridge that exposed multiple devices.
10
15
  * It can be used as CLI script and starting point for your own device node implementation.