@project-chip/matter-node.js-examples 0.10.0-alpha.0-20240716-446c872f → 0.10.0-alpha.0-20240722-39f917c1

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/README.md CHANGED
@@ -19,19 +19,7 @@ The examples provided by this repository show different use cases demonstrating
19
19
  > With matter.js 0.8 we introduced a new API that is not compatible with the old API. The new API is more flexible and allows for more complex use cases. The old API is still supported but will be removed in a future release. The examples are provided for both APIs. The new API examples are named without "Legacy" in the filename and the npm run script is named without "-legacy". The old API examples are named with "Legacy" in the filename and the npm run script is named with "-legacy".
20
20
  > If you used the old Example scripts and want to just switch to use the new scripts you need to convert the device storage once. Please see below in the section about the ["Legacy Storage Converter"](#legacy-storage-converter).
21
21
 
22
-
23
- ### Legacy Device Examples
24
- These examples use the matter.js API up to 0.7, which is considered "Legacy" now because it will be replaced by a new API starting with 0.8. The functionality is still working, but should be considered deprecated and will be removed with a later release!
25
- The filenames of these examples were adjusted in 0.8 and a "Legacy" was added to the end of the filename and "-legacy" to the npm run script name (exception: DeviceNode is now called DeviceNodeFullLegacy). Other than that they are fully compatible with the pre-0.7 versions also regarding storage location and structure and can be directly used as before.
26
-
27
- All examples create a MatterServer instance to add Matter nodes to be announced on a definable port number (default 5540).
28
-
29
- * **BridgedDevicesNodeLegacy**: This example shows how to build a Matter-Bridge that offers multiple OnOff lights and/or sockets as a bridge. It can be configured via command line and allows for the specification of shell commands that will be executed for on and off commands on the numbered devices. For more details, see below.
30
- * **ComposedDeviceNodeLegacy**: This example shows how to build a "simple" composed device where multiple OnOff lights and sockets are combined as one composed device. The devices are all added on the root level, so no bridge is used. The composed device can be configured via command line and allows for the specification of shell commands that will be executed for on and off commands, on the numbered devices. For more details, see below.
31
- * **DeviceNodeFullLegacy**: This example shows how to build a simple Device node with just one socket or light endpoint. The shell commands to be executed by on/off commands can be configured via CLI. Additionally, this example also shows how to enable BLE for a device node and tweaks the announcement so that only BLE is announced in the beginning. This example also includes a dummy WifiNetworkCommissioning implementation that simulates Wi-Fi logic for the commissioner. Furthermore it also shows how to handle testEventTrigger calls on the GeneralDiagnostics cluster which might be needed for official device testing cases. It also implements the callbacks where implementers can get information on commissioning changes and session/connection changes to better know the status of the node.
32
- * **MultiDeviceNodeLegacy**: This example shows how to start multiple Matter nodes on one MatterServer where each node is run on its own Port, but share a single MDNS broadcaster and scanner in order to optimize resources. Each node can be configured via CLI to be an onoff socket or a light. CLI. Options also allow specification of shell commands to be executed for on and off commands.
33
-
34
- ## New API Device Examples
22
+ ## Device Examples
35
23
  Some command line parameters, for example those used to set the level of logging or the MDNS interface are now included in the new environment processing. These can be set by generic command line arguments or by using environment variables. These parameters are processed automatically so are no longer handled by the new example code directly. These are:
36
24
 
37
25
  * `--log-level=...` or environment variable `MATTER_LOG_LEVEL` or in code `environment.vars.set('log.level', Level.DEBUG)`. Allowed values are: Level.FATAL ("fatal"), Level.ERROR ("error"), Level.WARN ("warn"), Level.NOTICE ("notice"), Level.INFO ("info"), Level.DEBUG ("debug")
@@ -60,6 +48,19 @@ Additionally, these two examples are not directly configurable by CLI and mainly
60
48
  ## Controller example
61
49
  * **ControllerNode**: This example shows basically how a controller could be implemented by showing pairing and connections to a paired device. When there is an OnOff Endpoint with ID 1 then this is controlled and toggled.
62
50
 
51
+ ### Legacy Device Examples
52
+ These examples use the matter.js API up to 0.7, which is considered "Legacy" now because it will be replaced by a new API starting with 0.8. The functionality is still working, but should be considered deprecated and will be removed with a later release!
53
+ The filenames of these examples were adjusted in 0.8 and a "Legacy" was added to the end of the filename and "-legacy" to the npm run script name (exception: DeviceNode is now called DeviceNodeFullLegacy). Other than that they are fully compatible(*) with the pre-0.7 versions also regarding storage location and structure and can be directly used as before.
54
+
55
+ (*) Note: The CLI format has changed between legacy and the new device examples. In the new the parameters look like "--option=value" while in the legacy examples the parameters look like "--option value".
56
+
57
+ All examples create a MatterServer instance to add Matter nodes to be announced on a definable port number (default 5540).
58
+
59
+ * **BridgedDevicesNodeLegacy**: This example shows how to build a Matter-Bridge that offers multiple OnOff lights and/or sockets as a bridge. It can be configured via command line and allows for the specification of shell commands that will be executed for on and off commands on the numbered devices. For more details, see below.
60
+ * **ComposedDeviceNodeLegacy**: This example shows how to build a "simple" composed device where multiple OnOff lights and sockets are combined as one composed device. The devices are all added on the root level, so no bridge is used. The composed device can be configured via command line and allows for the specification of shell commands that will be executed for on and off commands, on the numbered devices. For more details, see below.
61
+ * **DeviceNodeFullLegacy**: This example shows how to build a simple Device node with just one socket or light endpoint. The shell commands to be executed by on/off commands can be configured via CLI. Additionally, this example also shows how to enable BLE for a device node and tweaks the announcement so that only BLE is announced in the beginning. This example also includes a dummy WifiNetworkCommissioning implementation that simulates Wi-Fi logic for the commissioner. Furthermore it also shows how to handle testEventTrigger calls on the GeneralDiagnostics cluster which might be needed for official device testing cases. It also implements the callbacks where implementers can get information on commissioning changes and session/connection changes to better know the status of the node.
62
+ * **MultiDeviceNodeLegacy**: This example shows how to start multiple Matter nodes on one MatterServer where each node is run on its own Port, but share a single MDNS broadcaster and scanner in order to optimize resources. Each node can be configured via CLI to be an onoff socket or a light. CLI. Options also allow specification of shell commands to be executed for on and off commands.
63
+
63
64
  ## Legacy Storage Converter
64
65
  The Legacy storage converter can convert the Device and Controller storages from the legacy examples. It will convert all relevant storage keys, but not the persisted cluster specific data (which should be acceptable because near to irrelevant for the device types we had examples for).
65
66
 
@@ -137,36 +138,36 @@ You can use -on and -off parameter to run a script to control something.
137
138
  For instance, on a Raspberry Pi, this will turn on / off the red LED:
138
139
 
139
140
  ```bash
140
- matter-device -type socket -on "echo 255 > /sys/class/leds/led1/brightness" -off "echo 0 > /sys/class/leds/led1/brightness"
141
+ matter-device --type socket --on="echo 255 > /sys/class/leds/led1/brightness" --off="echo 0 > /sys/class/leds/led1/brightness"
141
142
  ```
142
143
 
143
144
  or when starting from TS files:
144
145
 
145
146
  ```bash
146
- npm run matter-device -- -type socket -on "echo 255 > /sys/class/leds/led1/brightness" -off "echo 0 > /sys/class/leds/led1/brightness"
147
+ npm run matter-device -- --type socket --on="echo 255 > /sys/class/leds/led1/brightness" --off="echo 0 > /sys/class/leds/led1/brightness"
147
148
  ```
148
149
  (Please note the "--" to separate commandline parameters between the npm run and the executed script.
149
150
 
150
151
  **If you want to start multiple parallel processes please make sure to use different storage locations, different network port and ideally also different passcodes for each process!**
151
152
 
152
153
  The following parameters are available:
153
- * -passcode: the passcode to use for pairing (default: 20202021)
154
- * -discriminator: the discriminator to use for pairing (default: 3840, value between 0 and 4095)
155
- * -vendorid: the vendor ID as number to use for pairing (default: 65521 (0xFFF1))
156
- * -productid: the product ID as number to use for pairing (default: 32768 (0x8000))
157
- * -uniqueid: a unique ID for this device to be used in naming and to store structure information (default: ms time now)
158
- * -type: the device type to use for pairing (default: light, alternative value is "socket")
159
- * -netinterface: limit mdns announcements and scanning to the provided network interface, e.g. "en0" (default: all interfaces available)
160
- * -ble: enable BLE support (default: false) If this is enabled the device will announce itself _only_ via BLE if not commissioned and also presents a "Wifi only" device for commissioning to show this feature!
161
- * -ble-hci-id: Optionally, HCI ID to use (Linux only, default 0)
162
- * -port: the port to listen on for the device (default: 5540)
163
- * -store: the storage location (directory) to use for storing the pairing information (default: .device-node). Ideally use names starting with a ".". Delete the directory or provide an alternative name to reset the device
164
- * -on: the command to run when the device is turned on (see example above)
165
- * -off: the command to run when the device is turned off (see example above)
154
+ * --passcode: the passcode to use for pairing (default: 20202021)
155
+ * --discriminator: the discriminator to use for pairing (default: 3840, value between 0 and 4095)
156
+ * --vendorid: the vendor ID as number to use for pairing (default: 65521 (0xFFF1))
157
+ * --productid: the product ID as number to use for pairing (default: 32768 (0x8000))
158
+ * --uniqueid: a unique ID for this device to be used in naming and to store structure information (default: ms time now)
159
+ * --type: the device type to use for pairing (default: light, alternative value is "socket")
160
+ * --netinterface: limit mdns announcements and scanning to the provided network interface, e.g. "en0" (default: all interfaces available)
161
+ * --ble: enable BLE support (default: false) If this is enabled the device will announce itself _only_ via BLE if not commissioned and also presents a "Wifi only" device for commissioning to show this feature!
162
+ * --ble-hci-id: Optionally, HCI ID to use (Linux only, default 0)
163
+ * --port: the port to listen on for the device (default: 5540)
164
+ * --store: the storage location (directory) to use for storing the pairing information (default: .device-node). Ideally use names starting with a ".". Delete the directory or provide an alternative name to reset the device
165
+ * --on: the command to run when the device is turned on (see example above)
166
+ * --off: the command to run when the device is turned off (see example above)
166
167
 
167
168
  Additionally, there are some Testing parameters:
168
- * -ble-wifi-scan-ssid: The Wi-Fi SSID returned by the "ScanNetworks" call of the Wifi Network commissioning cluster used when using BLE commissioning (default: "TestSSID"). Ideally use a really existing SSID that also the commissioner (Apple, Alexa, ...) knows to make it easier to commission. Else you could get errors while commissioning.
169
- * -ble-wifi-scan-bssid: The Wi-Fi BSSID returned by the "ScanNetworks" call of the Wifi Network commissioning cluster used when using BLE commissioning (default: "00:00:00:00:00:00").
169
+ * --ble-wifi-scan-ssid: The Wi-Fi SSID returned by the "ScanNetworks" call of the Wifi Network commissioning cluster used when using BLE commissioning (default: "TestSSID"). Ideally use a really existing SSID that also the commissioner (Apple, Alexa, ...) knows to make it easier to commission. Else you could get errors while commissioning.
170
+ * --ble-wifi-scan-bssid: The Wi-Fi BSSID returned by the "ScanNetworks" call of the Wifi Network commissioning cluster used when using BLE commissioning (default: "00:00:00:00:00:00").
170
171
 
171
172
  ### Start a Matter Bridge
172
173
 
@@ -179,21 +180,21 @@ The usage and parameter are comparable to above, but the bridge adds support for
179
180
  **If you want to start multiple parallel processes please make sure to use different storage locations, different network port and ideally also different passcodes for each process!**
180
181
 
181
182
  The usage is as above but with modified parameters:
182
- * -num X: number of devices to expose (default 2)
183
- * -typeX socket: type of the devices to expose as device number X (default Light bulb)
184
- * -onX "script": script to run when the device number X is turned on
185
- * -offX "script": script to run when the device number X is turned off
183
+ * --num=X: number of devices to expose (default 2)
184
+ * --typeX=socket: type of the devices to expose as device number X (default Light bulb)
185
+ * --onX "script": script to run when the device number X is turned on
186
+ * --offX "script": script to run when the device number X is turned off
186
187
 
187
- **Please especially use the -uniqueidX parameters to assign unique own IDs to the single deices in order to remember their structure in the bridge. Such an ID should never be reused if you ever remove or add new devices! If you do not use -uniqueidX then the order you added them here is not allowed to ever change.**
188
+ **Please especially use the --uniqueidX parameters to assign unique own IDs to the single deices in order to remember their structure in the bridge. Such an ID should never be reused if you ever remove or add new devices! If you do not use --uniqueidX then the order you added them here is not allowed to ever change.**
188
189
 
189
190
  ```bash
190
- matter-bridge -num 2 -on1 "echo 255 > /sys/class/leds/led1/brightness" -off1 "echo 0 > /sys/class/leds/led1/brightness" -type2 socket -on2 "echo 255 > /sys/class/leds/led2/brightness" -off2 "echo 0 > /sys/class/leds/led2/brightness"
191
+ matter-bridge --num=2 --on1="echo 255 > /sys/class/leds/led1/brightness" --off1="echo 0 > /sys/class/leds/led1/brightness" --type2=socket --on2="echo 255 > /sys/class/leds/led2/brightness" --off2="echo 0 > /sys/class/leds/led2/brightness"
191
192
  ```
192
193
 
193
194
  or when starting from TS files:
194
195
 
195
196
  ```bash
196
- npm run matter-bridge -- -num 2 -on1 "echo 255 > /sys/class/leds/led1/brightness" -off1 "echo 0 > /sys/class/leds/led1/brightness" -type2 socket -on2 "echo 255 > /sys/class/leds/led2/brightness" -off2 "echo 0 > /sys/class/leds/led2/brightness"
197
+ npm run matter-bridge -- --num=2 --on1="echo 255 > /sys/class/leds/led1/brightness" --off1="echo 0 > /sys/class/leds/led1/brightness" --type2=socket --on2="echo 255 > /sys/class/leds/led2/brightness" --off2="echo 0 > /sys/class/leds/led2/brightness"
197
198
  ```
198
199
  (Please note the "--" to separate commandline parameters between the npm run and the executed script.
199
200
 
@@ -208,13 +209,13 @@ A composed device is one device with multiple different device types combined. T
208
209
  The parameters are like with the bridge but with an added "-type light/socket" parameter to define the type of the composed device itself.
209
210
 
210
211
  ```bash
211
- matter-composeddevice -type socket -num 2 -on1 "echo 255 > /sys/class/leds/led1/brightness" -off1 "echo 0 > /sys/class/leds/led1/brightness" -type2 socket -on2 "echo 255 > /sys/class/leds/led2/brightness" -off2 "echo 0 > /sys/class/leds/led2/brightness"
212
+ matter-composeddevice --type=socket --num=2 --on1="echo 255 > /sys/class/leds/led1/brightness" --off1="echo 0 > /sys/class/leds/led1/brightness" --type2=socket --on2="echo 255 > /sys/class/leds/led2/brightness" --off2="echo 0 > /sys/class/leds/led2/brightness"
212
213
  ```
213
214
 
214
215
  or when starting from TS files:
215
216
 
216
217
  ```bash
217
- npm run matter-composeddevice -- -type socket -num 2 -on1 "echo 255 > /sys/class/leds/led1/brightness" -off1 "echo 0 > /sys/class/leds/led1/brightness" -type2 socket -on2 "echo 255 > /sys/class/leds/led2/brightness" -off2 "echo 0 > /sys/class/leds/led2/brightness"
218
+ npm run matter-composeddevice -- --type=socket --num=2 --on1="echo 255 > /sys/class/leds/led1/brightness" --off1="echo 0 > /sys/class/leds/led1/brightness" --type2=socket --on2="echo 255 > /sys/class/leds/led2/brightness" --off2="echo 0 > /sys/class/leds/led2/brightness"
218
219
  ```
219
220
  (Please note the "--" to separate commandline parameters between the npm run and the executed script.
220
221
 
@@ -229,13 +230,13 @@ matter.js also allows it to start multiple devices in one process. With this esp
229
230
  The parameters are like with the composed device or bridge.
230
231
 
231
232
  ```bash
232
- matter-multidevice -type socket -num 2 -on1 "echo 255 > /sys/class/leds/led1/brightness" -off1 "echo 0 > /sys/class/leds/led1/brightness" -type2 socket -on2 "echo 255 > /sys/class/leds/led2/brightness" -off2 "echo 0 > /sys/class/leds/led2/brightness"
233
+ matter-multidevice --type=socket --num=2 --on1="echo 255 > /sys/class/leds/led1/brightness" --off1="echo 0 > /sys/class/leds/led1/brightness" --type2=socket --on2="echo 255 > /sys/class/leds/led2/brightness" --off2="echo 0 > /sys/class/leds/led2/brightness"
233
234
  ```
234
235
 
235
236
  or when starting from TS files:
236
237
 
237
238
  ```bash
238
- npm run matter-multidevice -- -type socket -num 2 -on1 "echo 255 > /sys/class/leds/led1/brightness" -off1 "echo 0 > /sys/class/leds/led1/brightness" -type2 socket -on2 "echo 255 > /sys/class/leds/led2/brightness" -off2 "echo 0 > /sys/class/leds/led2/brightness"
239
+ npm run matter-multidevice -- --type=socket --num=2 --on1="echo 255 > /sys/class/leds/led1/brightness" --off1="echo 0 > /sys/class/leds/led1/brightness" --type2=socket --on2="echo 255 > /sys/class/leds/led2/brightness" --off2="echo 0 > /sys/class/leds/led2/brightness"
239
240
  ```
240
241
  (Please note the "--" to separate commandline parameters between the npm run and the executed script.
241
242
 
@@ -87,7 +87,7 @@ for (let idx = 0; idx < isSocket.length; idx++) {
87
87
  console.log(`${name} is now ${value ? "ON" : "OFF"}`);
88
88
  });
89
89
  }
90
- await server.bringOnline();
90
+ await server.start();
91
91
  logEndpoint(EndpointServer.forEndpoint(server));
92
92
  function executeCommand(scriptParamName) {
93
93
  const script = Environment.default.vars.string(scriptParamName);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/examples/BridgedDevicesNode.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This example shows how to create a new device node that is composed of multiple devices.\n * It creates multiple endpoints on the server. For information on how to add a composed device to a bridge please\n * refer to the bridge example!\n * It can be used as CLI script and starting point for your own device node implementation.\n */\n\n/**\n * Import needed modules from @project-chip/matter-node.js\n */\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { requireMinNodeVersion } from \"@project-chip/matter-node.js/util\";\nimport { BridgedDeviceBasicInformationServer } from \"@project-chip/matter.js/behavior/definitions/bridged-device-basic-information\";\nimport { VendorId } from \"@project-chip/matter.js/datatype\";\nimport { logEndpoint } from \"@project-chip/matter.js/device\";\nimport { OnOffLightDevice } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { OnOffPlugInUnitDevice } from \"@project-chip/matter.js/devices/OnOffPlugInUnitDevice\";\nimport { Endpoint, EndpointServer } from \"@project-chip/matter.js/endpoint\";\nimport { AggregatorEndpoint } from \"@project-chip/matter.js/endpoints/AggregatorEndpoint\";\nimport { Environment, StorageService } from \"@project-chip/matter.js/environment\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\nimport { Time } from \"@project-chip/matter.js/time\";\nimport { execSync } from \"child_process\";\n\nrequireMinNodeVersion(16);\n\n/** Initialize configuration values */\nconst { isSocket, deviceName, vendorName, passcode, discriminator, vendorId, productName, productId, port, uniqueId } =\n await getConfiguration();\n\n/**\n * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration\n */\nconst server = await ServerNode.create({\n // Required: Give the Node a unique ID which is used to store the state of this node\n id: uniqueId,\n\n // Provide Network relevant configuration like the port\n // Optional when operating only one device on a host, Default port is 5540\n network: {\n port,\n },\n\n // Provide Commissioning relevant settings\n // Optional for development/testing purposes\n commissioning: {\n passcode,\n discriminator,\n },\n\n // Provide Node announcement settings\n // Optional: If Ommitted some development defaults are used\n productDescription: {\n name: deviceName,\n deviceType: AggregatorEndpoint.deviceType,\n },\n\n // Provide defaults for the BasicInformation cluster on the Root endpoint\n // Optional: If Omitted some development defaults are used\n basicInformation: {\n vendorName,\n vendorId: VendorId(vendorId),\n nodeLabel: productName,\n productName,\n productLabel: productName,\n productId,\n serialNumber: `matterjs-${uniqueId}`,\n uniqueId,\n },\n});\n\n/**\n * Matter Nodes are a composition of endpoints. Create and add a single multiple endpoint to the node to make it a\n * composed device. This example uses the OnOffLightDevice or OnOffPlugInUnitDevice depending on the value of the type\n * parameter. It also assigns each Endpoint a unique ID to store the endpoint number for it in the storage to restore\n * the device on restart.\n *\n * In this case we directly use the default command implementation from matter.js. Check out the DeviceNodeFull example\n * to see how to customize the command handlers.\n */\n\nconst aggregator = new Endpoint(AggregatorEndpoint, { id: \"aggregator\" });\nawait server.add(aggregator);\n\nfor (let idx = 0; idx < isSocket.length; idx++) {\n const i = idx + 1;\n const isASocket = isSocket[idx]; // Is the Device we add a Socket or a Light?\n\n const name = `OnOff ${isASocket ? \"Socket\" : \"Light\"} ${i}`;\n\n const endpoint = new Endpoint(\n isASocket\n ? // For a Bridged Device we need to add a BridgedDeviceBasicInformation cluster as server\n OnOffPlugInUnitDevice.with(BridgedDeviceBasicInformationServer)\n : OnOffLightDevice.with(BridgedDeviceBasicInformationServer),\n {\n id: `onoff-${i}`,\n bridgedDeviceBasicInformation: {\n nodeLabel: name, // Main end user name for the device\n productName: name,\n productLabel: name,\n serialNumber: `node-matter-${uniqueId}-${i}`,\n reachable: true,\n },\n },\n );\n await aggregator.add(endpoint);\n\n /**\n * Register state change handlers and events of the endpoint for identify and onoff states to react to the commands.\n *\n * If the code in these change handlers fail then the change is also rolled back and not executed and an error is\n * reported back to the controller.\n */\n endpoint.events.identify.startIdentifying.on(() => {\n console.log(`Run identify logic for ${name}, ideally blink a light every 0.5s ...`);\n });\n\n endpoint.events.identify.stopIdentifying.on(() => {\n console.log(`Stop identify logic for ${name} ...`);\n });\n\n endpoint.events.onOff.onOff$Changed.on(value => {\n executeCommand(value ? `on${i}` : `off${i}`);\n console.log(`${name} is now ${value ? \"ON\" : \"OFF\"}`);\n });\n}\n\n/**\n * In order to start the node and announce it into the network we use the run method which resolves when the node goes\n * offline again because we do not need anything more here. See the Full example for other starting options.\n * The QR Code is printed automatically.\n */\nawait server.bringOnline();\n\n/**\n * Log the endpoint structure for debugging reasons and to allow to verify anything is correct\n */\nlogEndpoint(EndpointServer.forEndpoint(server));\n\n/*\n If you want to dynamically add another device during runtime you can do so by doing the following:\n\n const name = `OnOff Light 3`;\n\n const endpoint = new Endpoint(OnOffLightDevice.with(BridgedDeviceBasicInformationServer), {\n id: `onoff-3`,\n bridgedDeviceBasicInformation: {\n nodeLabel: name,\n productName: name,\n productLabel: name,\n serialNumber: `node-matter-${uniqueId}-3`,\n reachable: true,\n },\n });\n await aggregator.add(endpoint);\n\n endpoint.events.onOff.onOff$Changed.on(value => {\n executeCommand(value ? `on3` : `off3`);\n console.log(`${name} is now ${value ? \"ON\" : \"OFF\"}`);\n });\n\n */\n\n/*\n To remove a device during runtime you can do so by doing the following:\n console.log(\"Removing Light 3 now!!\");\n\n await endpoint.close();\n\n This will automatically remove the endpoint from the bridge.\n */\n\n/*********************************************************************************************************\n * Convenience Methods\n *********************************************************************************************************/\n\n/** Defined a shell command from an environment variable and execute it and log the response. */\nfunction executeCommand(scriptParamName: string) {\n const script = Environment.default.vars.string(scriptParamName);\n if (script === undefined) return undefined;\n console.log(`${scriptParamName}: ${execSync(script).toString().slice(0, -1)}`);\n}\n\nasync function getConfiguration() {\n /**\n * Collect all needed data\n *\n * This block collects all needed data from cli, environment or storage. Replace this with where ever your data come from.\n *\n * Note: This example uses the matter.js process storage system to store the device parameter data for convenience\n * and easy reuse. When you also do that be careful to not overlap with Matter-Server own storage contexts\n * (so maybe better not do it ;-)).\n */\n const environment = Environment.default;\n\n const storageService = environment.get(StorageService);\n console.log(`Storage location: ${storageService.location} (Directory)`);\n console.log(\n '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.',\n );\n const deviceStorage = (await storageService.open(\"device\")).createContext(\"data\");\n\n const isSocket = Array<boolean>();\n const numDevices = environment.vars.number(\"num\") || 2;\n if (await deviceStorage.has(\"isSocket\")) {\n console.log(`Device types found in storage. --type parameter is ignored.`);\n (await deviceStorage.get<Array<boolean>>(\"isSocket\")).forEach(type => isSocket.push(type));\n }\n for (let i = 1; i <= numDevices; i++) {\n if (isSocket[i - 1] !== undefined) continue;\n isSocket.push(environment.vars.string(`type${i}`) === \"socket\");\n }\n\n const deviceName = \"Matter test device\";\n const vendorName = \"matter-node.js\";\n const passcode = environment.vars.number(\"passcode\") ?? (await deviceStorage.get(\"passcode\", 20202021));\n const discriminator = environment.vars.number(\"discriminator\") ?? (await deviceStorage.get(\"discriminator\", 3840));\n // product name / id and vendor id should match what is in the device certificate\n const vendorId = environment.vars.number(\"vendorid\") ?? (await deviceStorage.get(\"vendorid\", 0xfff1));\n const productName = `node-matter OnOff ${isSocket ? \"Socket\" : \"Light\"}`;\n const productId = environment.vars.number(\"productid\") ?? (await deviceStorage.get(\"productid\", 0x8000));\n\n const port = environment.vars.number(\"port\") ?? 5540;\n\n const uniqueId =\n environment.vars.string(\"uniqueid\") ?? (await deviceStorage.get(\"uniqueid\", Time.nowMs().toString()));\n\n // Persist basic data to keep them also on restart\n await deviceStorage.set({\n passcode,\n discriminator,\n vendorid: vendorId,\n productid: productId,\n isSocket,\n uniqueid: uniqueId,\n });\n\n return {\n isSocket,\n deviceName,\n vendorName,\n passcode,\n discriminator,\n vendorId,\n productName,\n productId,\n port,\n uniqueId,\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["#!/usr/bin/env node\n/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This example shows how to create a new device node that is composed of multiple devices.\n * It creates multiple endpoints on the server. For information on how to add a composed device to a bridge please\n * refer to the bridge example!\n * It can be used as CLI script and starting point for your own device node implementation.\n */\n\n/**\n * Import needed modules from @project-chip/matter-node.js\n */\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { requireMinNodeVersion } from \"@project-chip/matter-node.js/util\";\nimport { BridgedDeviceBasicInformationServer } from \"@project-chip/matter.js/behavior/definitions/bridged-device-basic-information\";\nimport { VendorId } from \"@project-chip/matter.js/datatype\";\nimport { logEndpoint } from \"@project-chip/matter.js/device\";\nimport { OnOffLightDevice } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { OnOffPlugInUnitDevice } from \"@project-chip/matter.js/devices/OnOffPlugInUnitDevice\";\nimport { Endpoint, EndpointServer } from \"@project-chip/matter.js/endpoint\";\nimport { AggregatorEndpoint } from \"@project-chip/matter.js/endpoints/AggregatorEndpoint\";\nimport { Environment, StorageService } from \"@project-chip/matter.js/environment\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\nimport { Time } from \"@project-chip/matter.js/time\";\nimport { execSync } from \"child_process\";\n\nrequireMinNodeVersion(16);\n\n/** Initialize configuration values */\nconst { isSocket, deviceName, vendorName, passcode, discriminator, vendorId, productName, productId, port, uniqueId } =\n await getConfiguration();\n\n/**\n * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration\n */\nconst server = await ServerNode.create({\n // Required: Give the Node a unique ID which is used to store the state of this node\n id: uniqueId,\n\n // Provide Network relevant configuration like the port\n // Optional when operating only one device on a host, Default port is 5540\n network: {\n port,\n },\n\n // Provide Commissioning relevant settings\n // Optional for development/testing purposes\n commissioning: {\n passcode,\n discriminator,\n },\n\n // Provide Node announcement settings\n // Optional: If Ommitted some development defaults are used\n productDescription: {\n name: deviceName,\n deviceType: AggregatorEndpoint.deviceType,\n },\n\n // Provide defaults for the BasicInformation cluster on the Root endpoint\n // Optional: If Omitted some development defaults are used\n basicInformation: {\n vendorName,\n vendorId: VendorId(vendorId),\n nodeLabel: productName,\n productName,\n productLabel: productName,\n productId,\n serialNumber: `matterjs-${uniqueId}`,\n uniqueId,\n },\n});\n\n/**\n * Matter Nodes are a composition of endpoints. Create and add a single multiple endpoint to the node to make it a\n * composed device. This example uses the OnOffLightDevice or OnOffPlugInUnitDevice depending on the value of the type\n * parameter. It also assigns each Endpoint a unique ID to store the endpoint number for it in the storage to restore\n * the device on restart.\n *\n * In this case we directly use the default command implementation from matter.js. Check out the DeviceNodeFull example\n * to see how to customize the command handlers.\n */\n\nconst aggregator = new Endpoint(AggregatorEndpoint, { id: \"aggregator\" });\nawait server.add(aggregator);\n\nfor (let idx = 0; idx < isSocket.length; idx++) {\n const i = idx + 1;\n const isASocket = isSocket[idx]; // Is the Device we add a Socket or a Light?\n\n const name = `OnOff ${isASocket ? \"Socket\" : \"Light\"} ${i}`;\n\n const endpoint = new Endpoint(\n isASocket\n ? // For a Bridged Device we need to add a BridgedDeviceBasicInformation cluster as server\n OnOffPlugInUnitDevice.with(BridgedDeviceBasicInformationServer)\n : OnOffLightDevice.with(BridgedDeviceBasicInformationServer),\n {\n id: `onoff-${i}`,\n bridgedDeviceBasicInformation: {\n nodeLabel: name, // Main end user name for the device\n productName: name,\n productLabel: name,\n serialNumber: `node-matter-${uniqueId}-${i}`,\n reachable: true,\n },\n },\n );\n await aggregator.add(endpoint);\n\n /**\n * Register state change handlers and events of the endpoint for identify and onoff states to react to the commands.\n *\n * If the code in these change handlers fail then the change is also rolled back and not executed and an error is\n * reported back to the controller.\n */\n endpoint.events.identify.startIdentifying.on(() => {\n console.log(`Run identify logic for ${name}, ideally blink a light every 0.5s ...`);\n });\n\n endpoint.events.identify.stopIdentifying.on(() => {\n console.log(`Stop identify logic for ${name} ...`);\n });\n\n endpoint.events.onOff.onOff$Changed.on(value => {\n executeCommand(value ? `on${i}` : `off${i}`);\n console.log(`${name} is now ${value ? \"ON\" : \"OFF\"}`);\n });\n}\n\n/**\n * In order to start the node and announce it into the network we use the run method which resolves when the node goes\n * offline again because we do not need anything more here. See the Full example for other starting options.\n * The QR Code is printed automatically.\n */\nawait server.start();\n\n/**\n * Log the endpoint structure for debugging reasons and to allow to verify anything is correct\n */\nlogEndpoint(EndpointServer.forEndpoint(server));\n\n/*\n If you want to dynamically add another device during runtime you can do so by doing the following:\n\n const name = `OnOff Light 3`;\n\n const endpoint = new Endpoint(OnOffLightDevice.with(BridgedDeviceBasicInformationServer), {\n id: `onoff-3`,\n bridgedDeviceBasicInformation: {\n nodeLabel: name,\n productName: name,\n productLabel: name,\n serialNumber: `node-matter-${uniqueId}-3`,\n reachable: true,\n },\n });\n await aggregator.add(endpoint);\n\n endpoint.events.onOff.onOff$Changed.on(value => {\n executeCommand(value ? `on3` : `off3`);\n console.log(`${name} is now ${value ? \"ON\" : \"OFF\"}`);\n });\n\n */\n\n/*\n To remove a device during runtime you can do so by doing the following:\n console.log(\"Removing Light 3 now!!\");\n\n await endpoint.close();\n\n This will automatically remove the endpoint from the bridge.\n */\n\n/*********************************************************************************************************\n * Convenience Methods\n *********************************************************************************************************/\n\n/** Defined a shell command from an environment variable and execute it and log the response. */\nfunction executeCommand(scriptParamName: string) {\n const script = Environment.default.vars.string(scriptParamName);\n if (script === undefined) return undefined;\n console.log(`${scriptParamName}: ${execSync(script).toString().slice(0, -1)}`);\n}\n\nasync function getConfiguration() {\n /**\n * Collect all needed data\n *\n * This block collects all needed data from cli, environment or storage. Replace this with where ever your data come from.\n *\n * Note: This example uses the matter.js process storage system to store the device parameter data for convenience\n * and easy reuse. When you also do that be careful to not overlap with Matter-Server own storage contexts\n * (so maybe better not do it ;-)).\n */\n const environment = Environment.default;\n\n const storageService = environment.get(StorageService);\n console.log(`Storage location: ${storageService.location} (Directory)`);\n console.log(\n '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.',\n );\n const deviceStorage = (await storageService.open(\"device\")).createContext(\"data\");\n\n const isSocket = Array<boolean>();\n const numDevices = environment.vars.number(\"num\") || 2;\n if (await deviceStorage.has(\"isSocket\")) {\n console.log(`Device types found in storage. --type parameter is ignored.`);\n (await deviceStorage.get<Array<boolean>>(\"isSocket\")).forEach(type => isSocket.push(type));\n }\n for (let i = 1; i <= numDevices; i++) {\n if (isSocket[i - 1] !== undefined) continue;\n isSocket.push(environment.vars.string(`type${i}`) === \"socket\");\n }\n\n const deviceName = \"Matter test device\";\n const vendorName = \"matter-node.js\";\n const passcode = environment.vars.number(\"passcode\") ?? (await deviceStorage.get(\"passcode\", 20202021));\n const discriminator = environment.vars.number(\"discriminator\") ?? (await deviceStorage.get(\"discriminator\", 3840));\n // product name / id and vendor id should match what is in the device certificate\n const vendorId = environment.vars.number(\"vendorid\") ?? (await deviceStorage.get(\"vendorid\", 0xfff1));\n const productName = `node-matter OnOff ${isSocket ? \"Socket\" : \"Light\"}`;\n const productId = environment.vars.number(\"productid\") ?? (await deviceStorage.get(\"productid\", 0x8000));\n\n const port = environment.vars.number(\"port\") ?? 5540;\n\n const uniqueId =\n environment.vars.string(\"uniqueid\") ?? (await deviceStorage.get(\"uniqueid\", Time.nowMs().toString()));\n\n // Persist basic data to keep them also on restart\n await deviceStorage.set({\n passcode,\n discriminator,\n vendorid: vendorId,\n productid: productId,\n isSocket,\n uniqueid: uniqueId,\n });\n\n return {\n isSocket,\n deviceName,\n vendorName,\n passcode,\n discriminator,\n vendorId,\n productName,\n productId,\n port,\n uniqueId,\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["isSocket", "deviceName", "vendorName", "passcode", "discriminator", "vendorId", "productName", "productId", "port", "uniqueId"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/examples/ControllerNode.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This example shows how to create a Matter controller to pair with a device and interfact with it.\n * It can be used as CLI script, but is more thought as a starting point for your own controller implementation\n * because you need to adjust the code in any way depending on your use case.\n */\n\n/**\n * Import needed modules from @project-chip/matter-node.js\n */\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { BleNode } from \"@project-chip/matter-node-ble.js/ble\";\nimport { requireMinNodeVersion } from \"@project-chip/matter-node.js/util\";\nimport { CommissioningController, NodeCommissioningOptions } from \"@project-chip/matter.js\";\nimport { Ble } from \"@project-chip/matter.js/ble\";\nimport {\n BasicInformationCluster,\n DescriptorCluster,\n GeneralCommissioning,\n OnOffCluster,\n} from \"@project-chip/matter.js/cluster\";\nimport { NodeId } from \"@project-chip/matter.js/datatype\";\nimport { NodeStateInformation } from \"@project-chip/matter.js/device\";\nimport { Environment, StorageService } from \"@project-chip/matter.js/environment\";\nimport { Logger } from \"@project-chip/matter.js/log\";\nimport { CommissioningOptions } from \"@project-chip/matter.js/protocol\";\nimport { ManualPairingCodeCodec } from \"@project-chip/matter.js/schema\";\nimport { Time } from \"@project-chip/matter.js/time\";\nimport { singleton } from \"@project-chip/matter.js/util\";\n\nconst logger = Logger.get(\"Controller\");\n\nrequireMinNodeVersion(16);\n\nconst environment = Environment.default;\n\nif (environment.vars.get(\"ble\")) {\n // Initialize Ble\n Ble.get = singleton(\n () =>\n new BleNode({\n hciId: environment.vars.number(\"ble-hci-id\"),\n }),\n );\n}\n\nconst storageService = environment.get(StorageService);\n\nconsole.log(`Storage location: ${storageService.location} (Directory)`);\nlogger.info(\n '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.',\n);\n\nclass ControllerNode {\n async start() {\n logger.info(`node-matter Controller started`);\n\n /**\n * Collect all needed data\n *\n * This block makes sure to collect all needed data from cli or storage. Replace this with where ever your data\n * come from.\n *\n * Note: This example also uses the initialized storage system to store the device parameter data for convenience\n * and easy reuse. When you also do that be careful to not overlap with Matter-Server own contexts\n * (so maybe better not ;-)).\n */\n\n const controllerStorage = (await storageService.open(\"controller\")).createContext(\"data\");\n const ip = (await controllerStorage.has(\"ip\"))\n ? controllerStorage.get<string>(\"ip\")\n : environment.vars.string(\"ip\");\n const port = (await controllerStorage.has(\"port\"))\n ? controllerStorage.get<number>(\"port\")\n : environment.vars.number(\"port\");\n const uniqueId = (await controllerStorage.has(\"uniqueid\"))\n ? await controllerStorage.get<string>(\"uniqueid\")\n : environment.vars.string(\"uniqueid\") ?? Time.nowMs().toString();\n await controllerStorage.set(\"uniqueid\", uniqueId);\n\n const pairingCode = environment.vars.string(\"pairingcode\");\n let longDiscriminator, setupPin, shortDiscriminator;\n if (pairingCode !== undefined) {\n const pairingCodeCodec = ManualPairingCodeCodec.decode(pairingCode);\n shortDiscriminator = pairingCodeCodec.shortDiscriminator;\n longDiscriminator = undefined;\n setupPin = pairingCodeCodec.passcode;\n logger.debug(`Data extracted from pairing code: ${Logger.toJSON(pairingCodeCodec)}`);\n } else {\n longDiscriminator =\n environment.vars.number(\"longDiscriminator\") ??\n (await controllerStorage.get(\"longDiscriminator\", 3840));\n if (longDiscriminator > 4095) throw new Error(\"Discriminator value must be less than 4096\");\n setupPin = environment.vars.number(\"pin\") ?? (await controllerStorage.get(\"pin\", 20202021));\n }\n if ((shortDiscriminator === undefined && longDiscriminator === undefined) || setupPin === undefined) {\n throw new Error(\n \"Please specify the longDiscriminator of the device to commission with -longDiscriminator or provide a valid passcode with -passcode\",\n );\n }\n\n // Collect commissioning options from commandline parameters\n const commissioningOptions: CommissioningOptions = {\n regulatoryLocation: GeneralCommissioning.RegulatoryLocationType.IndoorOutdoor,\n regulatoryCountryCode: \"XX\",\n };\n\n let ble = false;\n if (environment.vars.get(\"ble\")) {\n ble = true;\n const wifiSsid = environment.vars.string(\"ble-wifi-ssid\");\n const wifiCredentials = environment.vars.string(\"ble-wifi-credentials\");\n const threadNetworkName = environment.vars.string(\"ble-thread-networkname\");\n const threadOperationalDataset = environment.vars.string(\"ble-thread-operationaldataset\");\n if (wifiSsid !== undefined && wifiCredentials !== undefined) {\n logger.info(`Registering Commissioning over BLE with WiFi: ${wifiSsid}`);\n commissioningOptions.wifiNetwork = {\n wifiSsid: wifiSsid,\n wifiCredentials: wifiCredentials,\n };\n }\n if (threadNetworkName !== undefined && threadOperationalDataset !== undefined) {\n logger.info(`Registering Commissioning over BLE with Thread: ${threadNetworkName}`);\n commissioningOptions.threadNetwork = {\n networkName: threadNetworkName,\n operationalDataset: threadOperationalDataset,\n };\n }\n }\n\n /**\n * Create Matter Server and Controller Node\n *\n * To allow the device to be announced, found, paired and operated we need a MatterServer instance and add a\n * CommissioningController to it and add the just created device instance to it.\n * The Controller node defines the port where the server listens for the UDP packages of the Matter protocol\n * and initializes deice specific certificates and such.\n *\n * The below logic also adds command handlers for commands of clusters that normally are handled internally\n * like testEventTrigger (General Diagnostic Cluster) that can be implemented with the logic when these commands\n * are called.\n */\n\n const commissioningController = new CommissioningController({\n environment: {\n environment,\n id: uniqueId,\n },\n autoConnect: false,\n });\n\n /**\n * Start the Matter Server\n *\n * After everything was plugged together we can start the server. When not delayed announcement is set for the\n * CommissioningServer node then this command also starts the announcement of the device into the network.\n */\n await commissioningController.start();\n\n if (!commissioningController.isCommissioned()) {\n const options = {\n commissioning: commissioningOptions,\n discovery: {\n knownAddress: ip !== undefined && port !== undefined ? { ip, port, type: \"udp\" } : undefined,\n identifierData:\n longDiscriminator !== undefined\n ? { longDiscriminator }\n : shortDiscriminator !== undefined\n ? { shortDiscriminator }\n : {},\n discoveryCapabilities: {\n ble,\n },\n },\n passcode: setupPin,\n } as NodeCommissioningOptions;\n logger.info(`Commissioning ... ${Logger.toJSON(options)}`);\n const nodeId = await commissioningController.commissionNode(options);\n\n console.log(`Commissioning successfully done with nodeId ${nodeId}`);\n }\n\n /**\n * TBD\n */\n try {\n const nodes = commissioningController.getCommissionedNodes();\n console.log(\"Found commissioned nodes:\", Logger.toJSON(nodes));\n\n const nodeId = NodeId(environment.vars.number(\"nodeid\") ?? nodes[0]);\n if (!nodes.includes(nodeId)) {\n throw new Error(`Node ${nodeId} not found in commissioned nodes`);\n }\n\n const node = await commissioningController.connectNode(nodeId, {\n attributeChangedCallback: (\n peerNodeId,\n { path: { nodeId, clusterId, endpointId, attributeName }, value },\n ) =>\n console.log(\n `attributeChangedCallback ${peerNodeId}: Attribute ${nodeId}/${endpointId}/${clusterId}/${attributeName} changed to ${Logger.toJSON(\n value,\n )}`,\n ),\n eventTriggeredCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, eventName }, events }) =>\n console.log(\n `eventTriggeredCallback ${peerNodeId}: Event ${nodeId}/${endpointId}/${clusterId}/${eventName} triggered with ${Logger.toJSON(\n events,\n )}`,\n ),\n stateInformationCallback: (peerNodeId, info) => {\n switch (info) {\n case NodeStateInformation.Connected:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} connected`);\n break;\n case NodeStateInformation.Disconnected:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} disconnected`);\n break;\n case NodeStateInformation.Reconnecting:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} reconnecting`);\n break;\n case NodeStateInformation.WaitingForDeviceDiscovery:\n console.log(\n `stateInformationCallback ${peerNodeId}: Node ${nodeId} waiting for device discovery`,\n );\n break;\n case NodeStateInformation.StructureChanged:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} structure changed`);\n break;\n case NodeStateInformation.Decommissioned:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} decommissioned`);\n break;\n }\n },\n });\n\n // Important: This is a temporary API to proof the methods working and this will change soon and is NOT stable!\n // It is provided to proof the concept\n\n node.logStructure();\n\n // Example to initialize a ClusterClient and access concrete fields as API methods\n const descriptor = node.getRootClusterClient(DescriptorCluster);\n if (descriptor !== undefined) {\n console.log(await descriptor.attributes.deviceTypeList.get()); // you can call that way\n console.log(await descriptor.getServerListAttribute()); // or more convenient that way\n } else {\n console.log(\"No Descriptor Cluster found. This should never happen!\");\n }\n\n // Example to subscribe to a field and get the value\n const info = node.getRootClusterClient(BasicInformationCluster);\n if (info !== undefined) {\n console.log(await info.getProductNameAttribute()); // This call is executed remotely\n //console.log(await info.subscribeProductNameAttribute(value => console.log(\"productName\", value), 5, 30));\n //console.log(await info.getProductNameAttribute()); // This call is resolved locally because we have subscribed to the value!\n } else {\n console.log(\"No BasicInformation Cluster found. This should never happen!\");\n }\n\n // Example to get all Attributes of the commissioned node: */*/*\n //const attributesAll = await interactionClient.getAllAttributes();\n //console.log(\"Attributes-All:\", Logger.toJSON(attributesAll));\n\n // Example to get all Attributes of all Descriptor Clusters of the commissioned node: */DescriptorCluster/*\n //const attributesAllDescriptor = await interactionClient.getMultipleAttributes([{ clusterId: DescriptorCluster.id} ]);\n //console.log(\"Attributes-Descriptor:\", JSON.stringify(attributesAllDescriptor, null, 2));\n\n // Example to get all Attributes of the Basic Information Cluster of endpoint 0 of the commissioned node: 0/BasicInformationCluster/*\n //const attributesBasicInformation = await interactionClient.getMultipleAttributes([{ endpointId: 0, clusterId: BasicInformationCluster.id} ]);\n //console.log(\"Attributes-BasicInformation:\", JSON.stringify(attributesBasicInformation, null, 2));\n\n const devices = node.getDevices();\n if (devices[0] && devices[0].number === 1) {\n // Example to subscribe to all Attributes of endpoint 1 of the commissioned node: */*/*\n //await interactionClient.subscribeMultipleAttributes([{ endpointId: 1, /* subscribe anything from endpoint 1 */ }], 0, 180, data => {\n // console.log(\"Subscribe-All Data:\", Logger.toJSON(data));\n //});\n\n const onOff = devices[0].getClusterClient(OnOffCluster);\n if (onOff !== undefined) {\n let onOffStatus = await onOff.getOnOffAttribute();\n console.log(\"initial onOffStatus\", onOffStatus);\n\n onOff.addOnOffAttributeListener(value => {\n console.log(\"subscription onOffStatus\", value);\n onOffStatus = value;\n });\n // read data every minute to keep up the connection to show the subscription is working\n setInterval(() => {\n onOff\n .toggle()\n .then(() => {\n onOffStatus = !onOffStatus;\n console.log(\"onOffStatus\", onOffStatus);\n })\n .catch(error => logger.error(error));\n }, 60000);\n }\n }\n } finally {\n //await matterServer.close(); // Comment out when subscribes are used, else the connection will be closed\n setTimeout(() => process.exit(0), 1000000);\n }\n }\n}\n\nnew ControllerNode().start().catch(error => logger.error(error));\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["#!/usr/bin/env node\n/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This example shows how to create a Matter controller to pair with a device and interfact with it.\n * It can be used as CLI script, but is more thought as a starting point for your own controller implementation\n * because you need to adjust the code in any way depending on your use case.\n */\n\n/**\n * Import needed modules from @project-chip/matter-node.js\n */\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { BleNode } from \"@project-chip/matter-node-ble.js/ble\";\nimport { requireMinNodeVersion } from \"@project-chip/matter-node.js/util\";\nimport { CommissioningController, NodeCommissioningOptions } from \"@project-chip/matter.js\";\nimport { Ble } from \"@project-chip/matter.js/ble\";\nimport {\n BasicInformationCluster,\n DescriptorCluster,\n GeneralCommissioning,\n OnOffCluster,\n} from \"@project-chip/matter.js/cluster\";\nimport { NodeId } from \"@project-chip/matter.js/datatype\";\nimport { NodeStateInformation } from \"@project-chip/matter.js/device\";\nimport { Environment, StorageService } from \"@project-chip/matter.js/environment\";\nimport { Logger } from \"@project-chip/matter.js/log\";\nimport { CommissioningOptions } from \"@project-chip/matter.js/protocol\";\nimport { ManualPairingCodeCodec } from \"@project-chip/matter.js/schema\";\nimport { Time } from \"@project-chip/matter.js/time\";\nimport { singleton } from \"@project-chip/matter.js/util\";\n\nconst logger = Logger.get(\"Controller\");\n\nrequireMinNodeVersion(16);\n\nconst environment = Environment.default;\n\nif (environment.vars.get(\"ble\")) {\n // Initialize Ble\n Ble.get = singleton(\n () =>\n new BleNode({\n hciId: environment.vars.number(\"ble-hci-id\"),\n }),\n );\n}\n\nconst storageService = environment.get(StorageService);\n\nconsole.log(`Storage location: ${storageService.location} (Directory)`);\nlogger.info(\n '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.',\n);\n\nclass ControllerNode {\n async start() {\n logger.info(`node-matter Controller started`);\n\n /**\n * Collect all needed data\n *\n * This block makes sure to collect all needed data from cli or storage. Replace this with where ever your data\n * come from.\n *\n * Note: This example also uses the initialized storage system to store the device parameter data for convenience\n * and easy reuse. When you also do that be careful to not overlap with Matter-Server own contexts\n * (so maybe better not ;-)).\n */\n\n const controllerStorage = (await storageService.open(\"controller\")).createContext(\"data\");\n const ip = (await controllerStorage.has(\"ip\"))\n ? controllerStorage.get<string>(\"ip\")\n : environment.vars.string(\"ip\");\n const port = (await controllerStorage.has(\"port\"))\n ? controllerStorage.get<number>(\"port\")\n : environment.vars.number(\"port\");\n const uniqueId = (await controllerStorage.has(\"uniqueid\"))\n ? await controllerStorage.get<string>(\"uniqueid\")\n : (environment.vars.string(\"uniqueid\") ?? Time.nowMs().toString());\n await controllerStorage.set(\"uniqueid\", uniqueId);\n\n const pairingCode = environment.vars.string(\"pairingcode\");\n let longDiscriminator, setupPin, shortDiscriminator;\n if (pairingCode !== undefined) {\n const pairingCodeCodec = ManualPairingCodeCodec.decode(pairingCode);\n shortDiscriminator = pairingCodeCodec.shortDiscriminator;\n longDiscriminator = undefined;\n setupPin = pairingCodeCodec.passcode;\n logger.debug(`Data extracted from pairing code: ${Logger.toJSON(pairingCodeCodec)}`);\n } else {\n longDiscriminator =\n environment.vars.number(\"longDiscriminator\") ??\n (await controllerStorage.get(\"longDiscriminator\", 3840));\n if (longDiscriminator > 4095) throw new Error(\"Discriminator value must be less than 4096\");\n setupPin = environment.vars.number(\"pin\") ?? (await controllerStorage.get(\"pin\", 20202021));\n }\n if ((shortDiscriminator === undefined && longDiscriminator === undefined) || setupPin === undefined) {\n throw new Error(\n \"Please specify the longDiscriminator of the device to commission with -longDiscriminator or provide a valid passcode with -passcode\",\n );\n }\n\n // Collect commissioning options from commandline parameters\n const commissioningOptions: CommissioningOptions = {\n regulatoryLocation: GeneralCommissioning.RegulatoryLocationType.IndoorOutdoor,\n regulatoryCountryCode: \"XX\",\n };\n\n let ble = false;\n if (environment.vars.get(\"ble\")) {\n ble = true;\n const wifiSsid = environment.vars.string(\"ble-wifi-ssid\");\n const wifiCredentials = environment.vars.string(\"ble-wifi-credentials\");\n const threadNetworkName = environment.vars.string(\"ble-thread-networkname\");\n const threadOperationalDataset = environment.vars.string(\"ble-thread-operationaldataset\");\n if (wifiSsid !== undefined && wifiCredentials !== undefined) {\n logger.info(`Registering Commissioning over BLE with WiFi: ${wifiSsid}`);\n commissioningOptions.wifiNetwork = {\n wifiSsid: wifiSsid,\n wifiCredentials: wifiCredentials,\n };\n }\n if (threadNetworkName !== undefined && threadOperationalDataset !== undefined) {\n logger.info(`Registering Commissioning over BLE with Thread: ${threadNetworkName}`);\n commissioningOptions.threadNetwork = {\n networkName: threadNetworkName,\n operationalDataset: threadOperationalDataset,\n };\n }\n }\n\n /**\n * Create Matter Server and Controller Node\n *\n * To allow the device to be announced, found, paired and operated we need a MatterServer instance and add a\n * CommissioningController to it and add the just created device instance to it.\n * The Controller node defines the port where the server listens for the UDP packages of the Matter protocol\n * and initializes deice specific certificates and such.\n *\n * The below logic also adds command handlers for commands of clusters that normally are handled internally\n * like testEventTrigger (General Diagnostic Cluster) that can be implemented with the logic when these commands\n * are called.\n */\n\n const commissioningController = new CommissioningController({\n environment: {\n environment,\n id: uniqueId,\n },\n autoConnect: false,\n });\n\n /**\n * Start the Matter Server\n *\n * After everything was plugged together we can start the server. When not delayed announcement is set for the\n * CommissioningServer node then this command also starts the announcement of the device into the network.\n */\n await commissioningController.start();\n\n if (!commissioningController.isCommissioned()) {\n const options = {\n commissioning: commissioningOptions,\n discovery: {\n knownAddress: ip !== undefined && port !== undefined ? { ip, port, type: \"udp\" } : undefined,\n identifierData:\n longDiscriminator !== undefined\n ? { longDiscriminator }\n : shortDiscriminator !== undefined\n ? { shortDiscriminator }\n : {},\n discoveryCapabilities: {\n ble,\n },\n },\n passcode: setupPin,\n } as NodeCommissioningOptions;\n logger.info(`Commissioning ... ${Logger.toJSON(options)}`);\n const nodeId = await commissioningController.commissionNode(options);\n\n console.log(`Commissioning successfully done with nodeId ${nodeId}`);\n }\n\n /**\n * TBD\n */\n try {\n const nodes = commissioningController.getCommissionedNodes();\n console.log(\"Found commissioned nodes:\", Logger.toJSON(nodes));\n\n const nodeId = NodeId(environment.vars.number(\"nodeid\") ?? nodes[0]);\n if (!nodes.includes(nodeId)) {\n throw new Error(`Node ${nodeId} not found in commissioned nodes`);\n }\n\n const node = await commissioningController.connectNode(nodeId, {\n attributeChangedCallback: (\n peerNodeId,\n { path: { nodeId, clusterId, endpointId, attributeName }, value },\n ) =>\n console.log(\n `attributeChangedCallback ${peerNodeId}: Attribute ${nodeId}/${endpointId}/${clusterId}/${attributeName} changed to ${Logger.toJSON(\n value,\n )}`,\n ),\n eventTriggeredCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, eventName }, events }) =>\n console.log(\n `eventTriggeredCallback ${peerNodeId}: Event ${nodeId}/${endpointId}/${clusterId}/${eventName} triggered with ${Logger.toJSON(\n events,\n )}`,\n ),\n stateInformationCallback: (peerNodeId, info) => {\n switch (info) {\n case NodeStateInformation.Connected:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} connected`);\n break;\n case NodeStateInformation.Disconnected:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} disconnected`);\n break;\n case NodeStateInformation.Reconnecting:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} reconnecting`);\n break;\n case NodeStateInformation.WaitingForDeviceDiscovery:\n console.log(\n `stateInformationCallback ${peerNodeId}: Node ${nodeId} waiting for device discovery`,\n );\n break;\n case NodeStateInformation.StructureChanged:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} structure changed`);\n break;\n case NodeStateInformation.Decommissioned:\n console.log(`stateInformationCallback ${peerNodeId}: Node ${nodeId} decommissioned`);\n break;\n }\n },\n });\n\n // Important: This is a temporary API to proof the methods working and this will change soon and is NOT stable!\n // It is provided to proof the concept\n\n node.logStructure();\n\n // Example to initialize a ClusterClient and access concrete fields as API methods\n const descriptor = node.getRootClusterClient(DescriptorCluster);\n if (descriptor !== undefined) {\n console.log(await descriptor.attributes.deviceTypeList.get()); // you can call that way\n console.log(await descriptor.getServerListAttribute()); // or more convenient that way\n } else {\n console.log(\"No Descriptor Cluster found. This should never happen!\");\n }\n\n // Example to subscribe to a field and get the value\n const info = node.getRootClusterClient(BasicInformationCluster);\n if (info !== undefined) {\n console.log(await info.getProductNameAttribute()); // This call is executed remotely\n //console.log(await info.subscribeProductNameAttribute(value => console.log(\"productName\", value), 5, 30));\n //console.log(await info.getProductNameAttribute()); // This call is resolved locally because we have subscribed to the value!\n } else {\n console.log(\"No BasicInformation Cluster found. This should never happen!\");\n }\n\n // Example to get all Attributes of the commissioned node: */*/*\n //const attributesAll = await interactionClient.getAllAttributes();\n //console.log(\"Attributes-All:\", Logger.toJSON(attributesAll));\n\n // Example to get all Attributes of all Descriptor Clusters of the commissioned node: */DescriptorCluster/*\n //const attributesAllDescriptor = await interactionClient.getMultipleAttributes([{ clusterId: DescriptorCluster.id} ]);\n //console.log(\"Attributes-Descriptor:\", JSON.stringify(attributesAllDescriptor, null, 2));\n\n // Example to get all Attributes of the Basic Information Cluster of endpoint 0 of the commissioned node: 0/BasicInformationCluster/*\n //const attributesBasicInformation = await interactionClient.getMultipleAttributes([{ endpointId: 0, clusterId: BasicInformationCluster.id} ]);\n //console.log(\"Attributes-BasicInformation:\", JSON.stringify(attributesBasicInformation, null, 2));\n\n const devices = node.getDevices();\n if (devices[0] && devices[0].number === 1) {\n // Example to subscribe to all Attributes of endpoint 1 of the commissioned node: */*/*\n //await interactionClient.subscribeMultipleAttributes([{ endpointId: 1, /* subscribe anything from endpoint 1 */ }], 0, 180, data => {\n // console.log(\"Subscribe-All Data:\", Logger.toJSON(data));\n //});\n\n const onOff = devices[0].getClusterClient(OnOffCluster);\n if (onOff !== undefined) {\n let onOffStatus = await onOff.getOnOffAttribute();\n console.log(\"initial onOffStatus\", onOffStatus);\n\n onOff.addOnOffAttributeListener(value => {\n console.log(\"subscription onOffStatus\", value);\n onOffStatus = value;\n });\n // read data every minute to keep up the connection to show the subscription is working\n setInterval(() => {\n onOff\n .toggle()\n .then(() => {\n onOffStatus = !onOffStatus;\n console.log(\"onOffStatus\", onOffStatus);\n })\n .catch(error => logger.error(error));\n }, 60000);\n }\n }\n } finally {\n //await matterServer.close(); // Comment out when subscribes are used, else the connection will be closed\n setTimeout(() => process.exit(0), 1000000);\n }\n }\n}\n\nnew ControllerNode().start().catch(error => logger.error(error));\n"],
5
+ "mappings": "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",
6
6
  "names": ["nodeId", "info"]
7
7
  }
@@ -222,7 +222,7 @@ endpoint.events.identify.stopIdentifying.on(() => {
222
222
  console.log(`Stop identify logic ...`);
223
223
  });
224
224
  logEndpoint(EndpointServer.forEndpoint(server));
225
- await server.bringOnline();
225
+ await server.start();
226
226
  console.log("Initial Fabrics", server.state.operationalCredentials.fabrics);
227
227
  if (!server.lifecycle.isCommissioned) {
228
228
  const { qrPairingCode, manualPairingCode } = server.state.commissioning.pairingCodes;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/examples/DeviceNodeFull.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This example is not optimized for simplicity, but to show all the advanced use cases for matter.js.\n * If you want to see a simple minimalistic and more standard example please look at DeviceNode.ts or the other examples.\n *\n * This example shows how to create a simple on-off Matter device as a light or as a socket.\n * It can be used as CLI script and starting point for your own device node implementation.\n * Additional to this it shows the following:\n * * How to modify the existing clusters on Root and also Device Endpoints\n * * How to add own Cluster implementations for Standard clusters\n * * How to add a custom Cluster to an Endpoint\n * * Which events are available to get status information from the Node aon commissioning and session/subscription changes\n * * How to get cluster state values\n * * How to set one or multiple state values in a transaction.\n */\n\n/**\n * Import needed modules from @project-chip/matter-node.js\n */\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { BleNode } from \"@project-chip/matter-node-ble.js/ble\";\nimport { GeneralDiagnostics } from \"@project-chip/matter-node.js/cluster\";\nimport { createFileLogger } from \"@project-chip/matter-node.js/log\";\nimport { requireMinNodeVersion } from \"@project-chip/matter-node.js/util\";\nimport { NetworkCommissioningServer } from \"@project-chip/matter.js/behavior/definitions/network-commissioning\";\nimport { OnOffServer } from \"@project-chip/matter.js/behavior/definitions/on-off\";\nimport { Ble } from \"@project-chip/matter.js/ble\";\nimport { NetworkCommissioning } from \"@project-chip/matter.js/cluster\";\nimport { DeviceTypeId, VendorId } from \"@project-chip/matter.js/datatype\";\nimport { logEndpoint } from \"@project-chip/matter.js/device\";\nimport { OnOffLightDevice } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { OnOffPlugInUnitDevice } from \"@project-chip/matter.js/devices/OnOffPlugInUnitDevice\";\nimport { Endpoint, EndpointServer } from \"@project-chip/matter.js/endpoint\";\nimport { RootRequirements } from \"@project-chip/matter.js/endpoint/definitions\";\nimport { Environment, StorageService } from \"@project-chip/matter.js/environment\";\nimport { FabricAction } from \"@project-chip/matter.js/fabric\";\nimport { Level, Logger, levelFromString } from \"@project-chip/matter.js/log\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\nimport { QrCode } from \"@project-chip/matter.js/schema\";\nimport { Time } from \"@project-chip/matter.js/time\";\nimport { ByteArray, singleton } from \"@project-chip/matter.js/util\";\nimport { execSync } from \"child_process\";\nimport { DummyThreadNetworkCommissioningServer } from \"./cluster/DummyThreadNetworkCommissioningServer.js\";\nimport { DummyWifiNetworkCommissioningServer } from \"./cluster/DummyWifiNetworkCommissioningServer.js\";\nimport {\n MyFancyCommandRequest,\n MyFancyCommandResponse,\n MyFancyOwnFunctionalityBehavior,\n} from \"./cluster/MyFancyOwnFunctionality.js\";\n\n/**\n * The following code brings some convenience to the CLI script. It allows to set the log level and format via\n * command line parameters. It also initializes the BLE stack if the `--ble` parameter is present.\n * Some of these parameters can also be replaced by generically accepted parameters or even environment variables. See the comments in the relevant places for information.\n * When using this code as basis for your own device node implementation, you can remove this part or hard code it.\n */\n\nrequireMinNodeVersion(16);\n\n// To configure Logging use\n// * \"--log-level\" or environment variable \"MATTER_LOG_LEVEL\" or \"environment.vars.set('log.level', Level.DEBUG)\"\n// Allowed values are: Level.FATAL, Level.ERROR, Level.WARN, Level.NOTICE, Level.INFO, Level.DEBUG\n// * \"--log-format\" or environment variable \"MATTER_LOG_FORMAT\" or \"environment.vars.set('log.format', Format.PLAIN)\"\n// Allowed values are: Format.PLAIN, Format.HTML, Format.ANSI,\n\nconst environment = Environment.default;\n\n// Alternatively \"--ble-enable\" or environment variable \"BLE_ENABLED\"\n// Alternatively \"--ble-hciId\" or environment variable \"BLE_HCIID\"\nif (environment.vars.get(\"ble.enable\")) {\n // Initialize Ble\n Ble.get = singleton(\n () =>\n new BleNode({\n hciId: environment.vars.number(\"ble.hciId\"),\n }),\n );\n}\n\nfunction executeCommand(scriptParamName: string) {\n const script = environment.vars.string(scriptParamName);\n if (script === undefined) return undefined;\n console.log(`${scriptParamName}: ${execSync(script).toString().slice(0, -1)}`);\n}\n\n/**\n * Collect all needed data\n *\n * This block collects all needed data from cli or storage. Replace this with where ever your data come from.\n *\n * Note: This example uses the matter.js process storage system to store the device parameter data for convenience\n * and easy reuse. When you also do that be careful to not overlap with Matter-Server own storage contexts\n * (so maybe better not do it ;-)).\n */\n\nconst logFile = environment.vars.string(\"logfile.filename\");\nif (logFile !== undefined) {\n Logger.addLogger(\"filelogger\", await createFileLogger(logFile), {\n defaultLogLevel: levelFromString(environment.vars.string(\"logfile.loglevel\")) ?? Level.DEBUG,\n });\n}\n\nconst storageService = environment.get(StorageService);\nconsole.log(`Storage location: ${storageService.location} (Directory)`);\nconsole.log(\n '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.',\n);\n\nconst deviceStorage = (await storageService.open(\"device\")).createContext(\"data\");\n\nif (await deviceStorage.has(\"isSocket\")) {\n console.log(\"Device type found in storage. --type parameter is ignored.\");\n}\nconst isSocket = await deviceStorage.get(\"isSocket\", environment.vars.string(\"type\") === \"socket\");\nconst deviceName = \"Matter test device\";\nconst vendorName = \"matter-node.js\";\nconst passcode = environment.vars.number(\"passcode\") ?? (await deviceStorage.get(\"passcode\", 20202021));\nconst discriminator = environment.vars.number(\"discriminator\") ?? (await deviceStorage.get(\"discriminator\", 3840));\n// product name / id and vendor id should match what is in the device certificate\nconst vendorId = environment.vars.number(\"vendorid\") ?? (await deviceStorage.get(\"vendorid\", 0xfff1));\nconst productName = `node-matter OnOff ${isSocket ? \"Socket\" : \"Light\"}`;\nconst productId = environment.vars.number(\"productid\") ?? (await deviceStorage.get(\"productid\", 0x8000));\n\nconst port = environment.vars.number(\"port\") ?? 5540;\n\nconst uniqueId = environment.vars.string(\"uniqueid\") ?? (await deviceStorage.get(\"uniqueid\", Time.nowMs().toString()));\n\nawait deviceStorage.set({\n passcode,\n discriminator,\n vendorid: vendorId,\n productid: productId,\n isSocket,\n uniqueid: uniqueId,\n});\n\n// Matter exposes functionality in groups called \"clusters\". For this example device we override the matter.js \"On/Off\"\n// cluster implementation to print status to the console.\nclass OnOffShellExecServer extends OnOffServer {\n // Intercept the \"on\" command to the Matter On/Off cluster to print a log message.\n override async on() {\n executeCommand(\"on\");\n await super.on();\n }\n\n // This is the functional inverse of on() above.\n //\n // For demonstration purposes we update state ourselves rather than deferring to matter.js's default \"off\" handler\n // via super.off().\n override async off() {\n executeCommand(\"off\");\n this.state.onOff = false;\n }\n\n // Use event handlers to log on/off state reactively, after it changes.\n override initialize() {\n this.events.onOff$Changed.on(value => {\n console.log(`Light is now ${value ? \"ON\" : \"OFF\"}`);\n });\n }\n}\n\nclass TestGeneralDiagnosticsServer extends RootRequirements.GeneralDiagnosticsServer {\n override initialize() {\n this.state.testEventTriggersEnabled = true; // set to true if you support test triggers ...\n super.initialize();\n }\n\n override testEventTrigger({ enableKey, eventTrigger }: GeneralDiagnostics.TestEventTriggerRequest) {\n console.log(`testEventTrigger called on GeneralDiagnostic cluster: ${enableKey} ${eventTrigger}`);\n }\n}\n\nclass MyFancyOwnFunctionalityServer extends MyFancyOwnFunctionalityBehavior {\n /** We return the incoming value and store the length of the string in our attribute and send it out as event */\n override myFancyCommand(request: MyFancyCommandRequest): MyFancyCommandResponse {\n const { value } = request;\n this.state.myFancyValue = value.length;\n\n this.events.myFancyEvent.emit({ eventValue: value }, this.context);\n\n return { response: value };\n }\n\n override initialize() {\n this.state.myFancyValue = -1; // Always initialize with -1\n }\n}\n\n/**\n * Create Device instance and add needed Listener\n *\n * Create an instance of the matter device class you want to use.\n * This example uses the OnOffLightDevice or OnOffPluginUnitDevice depending on the value of the type parameter.\n * To execute the on/off scripts defined as parameters a listener for the onOff attribute is registered via the\n * device specific API.\n *\n * The below logic also adds command handlers for commands of clusters that normally are handled device internally\n * like identify that can be implemented with the logic when these commands are called.\n */\n\n// Devices are compositions of behaviors like OnOffServer above. To extend an existing device you use builder methods.\n//\n// In this case we are using with() to install our On/Off cluster behavior.\n// .with(\"Lighting\") not needed because we always have it in by default because we have default implementation\nconst OnOffDevice = isSocket\n ? vendorId === 0xfff4\n ? OnOffPlugInUnitDevice.with(OnOffShellExecServer, MyFancyOwnFunctionalityServer)\n : OnOffPlugInUnitDevice.with(OnOffShellExecServer)\n : vendorId === 0xfff4\n ? OnOffLightDevice.with(OnOffShellExecServer, MyFancyOwnFunctionalityServer)\n : OnOffLightDevice.with(OnOffShellExecServer);\n\n/**\n * Modify automatically added clusters of the Root endpoint if needed\n * In this example we change the networkCommissioning cluster into one for \"Wifi only\" devices when BLE is used\n * for commissioning, to demonstrate how to do this.\n * If you want to implement Ethernet only devices that get connected to the network via LAN/Ethernet cable,\n * then all this is not needed.\n * The same as shown here for Wi-Fi is also possible theoretical for Thread only or combined devices.\n */\n\n// We use the Basic Root Endpoint without a NetworkCommissioning cluster\nlet RootEndpoint = ServerNode.RootEndpoint.with(TestGeneralDiagnosticsServer);\n\nlet wifiOrThreadAdded = false;\nlet threadAdded = false;\nif (Ble.enabled) {\n // matter.js will create a Ethernet-only device by default when ut comes to Network Commissioning Features.\n // To offer e.g. a \"Wi-Fi only device\" (or any other combination) we need to override the Network Commissioning\n // cluster and implement all the need handling here. This is a \"static implementation\" for pure demonstration\n // purposes and just \"simulates\" the actions to be done. In a real world implementation this would be done by\n // the device implementor based on the relevant networking stack.\n // The NetworkCommissioningCluster and all logics are described in Matter Core Specifications section 11.8\n if (environment.vars.has(\"ble.wifi.fake\")) {\n RootEndpoint = RootEndpoint.with(DummyWifiNetworkCommissioningServer);\n wifiOrThreadAdded = true;\n } else if (environment.vars.has(\"ble.thread.fake\")) {\n RootEndpoint = RootEndpoint.with(DummyThreadNetworkCommissioningServer);\n wifiOrThreadAdded = true;\n threadAdded = true;\n }\n} else {\n RootEndpoint = RootEndpoint.with(\n NetworkCommissioningServer.with(NetworkCommissioning.Feature.EthernetNetworkInterface),\n );\n}\n\nconst networkId = new ByteArray(32);\n// Physical devices appear as \"nodes\" on a Matter network. As a device implementer you use a NodeServer to bring a\n// device online.\n//\n// Note there are a large number of options to NodeServer that we are allowing to take default values here. See\n// CompositeWindowCovering.ts for a more detailed example.\nconst server = await ServerNode.create(RootEndpoint, {\n id: uniqueId,\n network: {\n port,\n discoveryCapabilities: {\n onIpNetwork: !environment.vars.has(\"ble.enable\"),\n ble: environment.vars.has(\"ble.enable\"),\n },\n ble: environment.vars.has(\"ble.enable\"), // TODO remove when state init is fixed\n },\n commissioning: {\n passcode,\n discriminator,\n },\n productDescription: {\n name: deviceName,\n deviceType: DeviceTypeId(OnOffDevice.deviceType),\n },\n basicInformation: {\n vendorName,\n vendorId: VendorId(vendorId),\n nodeLabel: productName,\n productName,\n productLabel: productName,\n productId,\n serialNumber: `node-matter-${uniqueId}`,\n uniqueId,\n },\n\n // @ts-expect-error ... TS do not see the types because both next clusters was added conditionally\n networkCommissioning: {\n maxNetworks: 1,\n interfaceEnabled: true,\n lastConnectErrorValue: 0,\n lastNetworkId: wifiOrThreadAdded ? null : networkId,\n lastNetworkingStatus: wifiOrThreadAdded ? null : NetworkCommissioning.NetworkCommissioningStatus.Success,\n networks: [{ networkId: networkId, connected: !wifiOrThreadAdded }],\n scanMaxTimeSeconds: wifiOrThreadAdded ? 3 : undefined,\n connectMaxTimeSeconds: wifiOrThreadAdded ? 3 : undefined,\n supportedWifiBands: wifiOrThreadAdded && !threadAdded ? [NetworkCommissioning.WiFiBand[\"2G4\"]] : undefined,\n supportedThreadFeatures: wifiOrThreadAdded && threadAdded ? { isFullThreadDevice: true } : undefined,\n threadVersion: wifiOrThreadAdded && threadAdded ? 4 : undefined, // means: Thread 1.3\n },\n myFancyFunctionality: {\n myFancyValue: 0,\n },\n});\n\n// Nodes are a composition of endpoints. Add a single endpoint to the node, our example light device.\nconst endpoint = new Endpoint(OnOffDevice, { id: \"onoff\" });\nawait server.add(endpoint);\n\n/**\n * This event is triggered when the device is initially commissioned successfully.\n * This means: It is added to the first fabric.\n */\nserver.lifecycle.commissioned.on(() => console.log(\"Server was initially commissioned successfully!\"));\n\n/** This event is triggered when all fabrics are removed from the device, usually it also does a factory reset then. */\nserver.lifecycle.decommissioned.on(() => console.log(\"Server was fully decommissioned successfully!\"));\n\n/** This event is triggered when the device went online. This means that it is discoverable in the network. */\nserver.lifecycle.online.on(() => console.log(\"Server is online\"));\n\n/** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */\nserver.lifecycle.offline.on(() => console.log(\"Server is offline\"));\n\n/**\n * This event is triggered when a fabric is added, removed or updated on the device. Use this if more granular\n * information is needed.\n */\nserver.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {\n let action = \"\";\n switch (fabricAction) {\n case FabricAction.Added:\n action = \"added\";\n break;\n case FabricAction.Removed:\n action = \"removed\";\n break;\n case FabricAction.Updated:\n action = \"updated\";\n break;\n }\n console.log(`Commissioned Fabrics changed event (${action}) for ${fabricIndex} triggered`);\n console.log(server.state.commissioning.fabrics[fabricIndex]);\n});\n\n/**\n * This event is triggered when an operative new session was opened by a Controller.\n * It is not triggered for the initial commissioning process, just afterwards for real connections.\n */\nserver.events.sessions.opened.on(session => console.log(`Session opened`, session));\n\n/**\n * This event is triggered when an operative session is closed by a Controller or because the Device goes offline.\n */\nserver.events.sessions.closed.on(session => console.log(`Session closed`, session));\n\n/** This event is triggered when a subscription gets added or removed on an operative session. */\nserver.events.sessions.subscriptionsChanged.on(session => {\n console.log(`Session subscriptions changed`, session);\n console.log(`Status of all sessions`, server.state.sessions.sessions);\n});\n\n// React on a change of identificationTime to do Identify stuff for the own device\nendpoint.events.identify.startIdentifying.on(() => {\n console.log(`Run identify logic, ideally blink a light every 0.5s ...`);\n});\n\nendpoint.events.identify.stopIdentifying.on(() => {\n console.log(`Stop identify logic ...`);\n});\n\n// Our device is now built and we can bring the node online.\n//\n// Note that you may serve multiple nodes from a single process. We only have one, however, so we can use the run()\n// method of the node.\n\nlogEndpoint(EndpointServer.forEndpoint(server));\n\n/**\n * In order to start the node and announce it into the network we start the node. This method resolves when the Matter\n * node enters his online state. Alternatively, we could also use `await server.run()` which\n * resolves when the node goes offline again, but we want to execute code afterwards, so we use start() here\n */\nawait server.bringOnline();\n\nconsole.log(\"Initial Fabrics\", server.state.operationalCredentials.fabrics);\n\n/**\n * If the node is not commissioned already we display the QR code on console. The QR code is also logged\n */\nif (!server.lifecycle.isCommissioned) {\n const { qrPairingCode, manualPairingCode } = server.state.commissioning.pairingCodes;\n\n console.log(QrCode.get(qrPairingCode));\n console.log(`QR Code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`);\n console.log(`Manual pairing code: ${manualPairingCode}`);\n} else {\n console.log(\"Device is already commissioned. Waiting for controllers to connect ...\");\n\n /**\n * Sometimes reading or writing attributes is required. The following code shows how this works.\n * For read it is basically `endpoint.state.clustername.attributename`.\n * The set method allows to set one or multiple values via the structure of also clustername.attributename. When multiple values are set they are considered being one transaction which would be rolled back completely if one value fails to be set.\n */\n\n // Read onOff attribute from onOff cluster\n const onOffValue = endpoint.state.onOff.onOff;\n console.log(`current OnOff attribute: ${onOffValue}`);\n\n if (vendorId === 0xfff4) {\n // Set onOff attribute from OnOff cluster AND the myFancyValue of the MyFancyOwnFunctionality cluster together\n await endpoint.set({\n onOff: {\n onOff: !onOffValue,\n },\n // @ts-expect-error Needed because the Fancy cluster is added conditionally, so TS do not get that it's there.\n myFancyOwnFunctionality: {\n myFancyValue: 36,\n },\n });\n } else {\n // Set onOff attribute from OnOff cluster only\n await endpoint.set({\n onOff: {\n onOff: !onOffValue,\n },\n });\n }\n}\n\n/**\n * To correctly tear down the now we can use server[Symbol.asyncDispose]().\n */\nprocess.on(\"SIGINT\", () => {\n // Clean up on CTRL-C\n server\n .close()\n .then(() => process.exit(0))\n .catch(err => console.error(err));\n});\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["#!/usr/bin/env node\n/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This example is not optimized for simplicity, but to show all the advanced use cases for matter.js.\n * If you want to see a simple minimalistic and more standard example please look at DeviceNode.ts or the other examples.\n *\n * This example shows how to create a simple on-off Matter device as a light or as a socket.\n * It can be used as CLI script and starting point for your own device node implementation.\n * Additional to this it shows the following:\n * * How to modify the existing clusters on Root and also Device Endpoints\n * * How to add own Cluster implementations for Standard clusters\n * * How to add a custom Cluster to an Endpoint\n * * Which events are available to get status information from the Node aon commissioning and session/subscription changes\n * * How to get cluster state values\n * * How to set one or multiple state values in a transaction.\n */\n\n/**\n * Import needed modules from @project-chip/matter-node.js\n */\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { BleNode } from \"@project-chip/matter-node-ble.js/ble\";\nimport { GeneralDiagnostics } from \"@project-chip/matter-node.js/cluster\";\nimport { createFileLogger } from \"@project-chip/matter-node.js/log\";\nimport { requireMinNodeVersion } from \"@project-chip/matter-node.js/util\";\nimport { NetworkCommissioningServer } from \"@project-chip/matter.js/behavior/definitions/network-commissioning\";\nimport { OnOffServer } from \"@project-chip/matter.js/behavior/definitions/on-off\";\nimport { Ble } from \"@project-chip/matter.js/ble\";\nimport { NetworkCommissioning } from \"@project-chip/matter.js/cluster\";\nimport { DeviceTypeId, VendorId } from \"@project-chip/matter.js/datatype\";\nimport { logEndpoint } from \"@project-chip/matter.js/device\";\nimport { OnOffLightDevice } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { OnOffPlugInUnitDevice } from \"@project-chip/matter.js/devices/OnOffPlugInUnitDevice\";\nimport { Endpoint, EndpointServer } from \"@project-chip/matter.js/endpoint\";\nimport { RootRequirements } from \"@project-chip/matter.js/endpoint/definitions\";\nimport { Environment, StorageService } from \"@project-chip/matter.js/environment\";\nimport { FabricAction } from \"@project-chip/matter.js/fabric\";\nimport { Level, Logger, levelFromString } from \"@project-chip/matter.js/log\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\nimport { QrCode } from \"@project-chip/matter.js/schema\";\nimport { Time } from \"@project-chip/matter.js/time\";\nimport { ByteArray, singleton } from \"@project-chip/matter.js/util\";\nimport { execSync } from \"child_process\";\nimport { DummyThreadNetworkCommissioningServer } from \"./cluster/DummyThreadNetworkCommissioningServer.js\";\nimport { DummyWifiNetworkCommissioningServer } from \"./cluster/DummyWifiNetworkCommissioningServer.js\";\nimport {\n MyFancyCommandRequest,\n MyFancyCommandResponse,\n MyFancyOwnFunctionalityBehavior,\n} from \"./cluster/MyFancyOwnFunctionality.js\";\n\n/**\n * The following code brings some convenience to the CLI script. It allows to set the log level and format via\n * command line parameters. It also initializes the BLE stack if the `--ble` parameter is present.\n * Some of these parameters can also be replaced by generically accepted parameters or even environment variables. See the comments in the relevant places for information.\n * When using this code as basis for your own device node implementation, you can remove this part or hard code it.\n */\n\nrequireMinNodeVersion(16);\n\n// To configure Logging use\n// * \"--log-level\" or environment variable \"MATTER_LOG_LEVEL\" or \"environment.vars.set('log.level', Level.DEBUG)\"\n// Allowed values are: Level.FATAL, Level.ERROR, Level.WARN, Level.NOTICE, Level.INFO, Level.DEBUG\n// * \"--log-format\" or environment variable \"MATTER_LOG_FORMAT\" or \"environment.vars.set('log.format', Format.PLAIN)\"\n// Allowed values are: Format.PLAIN, Format.HTML, Format.ANSI,\n\nconst environment = Environment.default;\n\n// Alternatively \"--ble-enable\" or environment variable \"BLE_ENABLED\"\n// Alternatively \"--ble-hciId\" or environment variable \"BLE_HCIID\"\nif (environment.vars.get(\"ble.enable\")) {\n // Initialize Ble\n Ble.get = singleton(\n () =>\n new BleNode({\n hciId: environment.vars.number(\"ble.hciId\"),\n }),\n );\n}\n\nfunction executeCommand(scriptParamName: string) {\n const script = environment.vars.string(scriptParamName);\n if (script === undefined) return undefined;\n console.log(`${scriptParamName}: ${execSync(script).toString().slice(0, -1)}`);\n}\n\n/**\n * Collect all needed data\n *\n * This block collects all needed data from cli or storage. Replace this with where ever your data come from.\n *\n * Note: This example uses the matter.js process storage system to store the device parameter data for convenience\n * and easy reuse. When you also do that be careful to not overlap with Matter-Server own storage contexts\n * (so maybe better not do it ;-)).\n */\n\nconst logFile = environment.vars.string(\"logfile.filename\");\nif (logFile !== undefined) {\n Logger.addLogger(\"filelogger\", await createFileLogger(logFile), {\n defaultLogLevel: levelFromString(environment.vars.string(\"logfile.loglevel\")) ?? Level.DEBUG,\n });\n}\n\nconst storageService = environment.get(StorageService);\nconsole.log(`Storage location: ${storageService.location} (Directory)`);\nconsole.log(\n '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.',\n);\n\nconst deviceStorage = (await storageService.open(\"device\")).createContext(\"data\");\n\nif (await deviceStorage.has(\"isSocket\")) {\n console.log(\"Device type found in storage. --type parameter is ignored.\");\n}\nconst isSocket = await deviceStorage.get(\"isSocket\", environment.vars.string(\"type\") === \"socket\");\nconst deviceName = \"Matter test device\";\nconst vendorName = \"matter-node.js\";\nconst passcode = environment.vars.number(\"passcode\") ?? (await deviceStorage.get(\"passcode\", 20202021));\nconst discriminator = environment.vars.number(\"discriminator\") ?? (await deviceStorage.get(\"discriminator\", 3840));\n// product name / id and vendor id should match what is in the device certificate\nconst vendorId = environment.vars.number(\"vendorid\") ?? (await deviceStorage.get(\"vendorid\", 0xfff1));\nconst productName = `node-matter OnOff ${isSocket ? \"Socket\" : \"Light\"}`;\nconst productId = environment.vars.number(\"productid\") ?? (await deviceStorage.get(\"productid\", 0x8000));\n\nconst port = environment.vars.number(\"port\") ?? 5540;\n\nconst uniqueId = environment.vars.string(\"uniqueid\") ?? (await deviceStorage.get(\"uniqueid\", Time.nowMs().toString()));\n\nawait deviceStorage.set({\n passcode,\n discriminator,\n vendorid: vendorId,\n productid: productId,\n isSocket,\n uniqueid: uniqueId,\n});\n\n// Matter exposes functionality in groups called \"clusters\". For this example device we override the matter.js \"On/Off\"\n// cluster implementation to print status to the console.\nclass OnOffShellExecServer extends OnOffServer {\n // Intercept the \"on\" command to the Matter On/Off cluster to print a log message.\n override async on() {\n executeCommand(\"on\");\n await super.on();\n }\n\n // This is the functional inverse of on() above.\n //\n // For demonstration purposes we update state ourselves rather than deferring to matter.js's default \"off\" handler\n // via super.off().\n override async off() {\n executeCommand(\"off\");\n this.state.onOff = false;\n }\n\n // Use event handlers to log on/off state reactively, after it changes.\n override initialize() {\n this.events.onOff$Changed.on(value => {\n console.log(`Light is now ${value ? \"ON\" : \"OFF\"}`);\n });\n }\n}\n\nclass TestGeneralDiagnosticsServer extends RootRequirements.GeneralDiagnosticsServer {\n override initialize() {\n this.state.testEventTriggersEnabled = true; // set to true if you support test triggers ...\n super.initialize();\n }\n\n override testEventTrigger({ enableKey, eventTrigger }: GeneralDiagnostics.TestEventTriggerRequest) {\n console.log(`testEventTrigger called on GeneralDiagnostic cluster: ${enableKey} ${eventTrigger}`);\n }\n}\n\nclass MyFancyOwnFunctionalityServer extends MyFancyOwnFunctionalityBehavior {\n /** We return the incoming value and store the length of the string in our attribute and send it out as event */\n override myFancyCommand(request: MyFancyCommandRequest): MyFancyCommandResponse {\n const { value } = request;\n this.state.myFancyValue = value.length;\n\n this.events.myFancyEvent.emit({ eventValue: value }, this.context);\n\n return { response: value };\n }\n\n override initialize() {\n this.state.myFancyValue = -1; // Always initialize with -1\n }\n}\n\n/**\n * Create Device instance and add needed Listener\n *\n * Create an instance of the matter device class you want to use.\n * This example uses the OnOffLightDevice or OnOffPluginUnitDevice depending on the value of the type parameter.\n * To execute the on/off scripts defined as parameters a listener for the onOff attribute is registered via the\n * device specific API.\n *\n * The below logic also adds command handlers for commands of clusters that normally are handled device internally\n * like identify that can be implemented with the logic when these commands are called.\n */\n\n// Devices are compositions of behaviors like OnOffServer above. To extend an existing device you use builder methods.\n//\n// In this case we are using with() to install our On/Off cluster behavior.\n// .with(\"Lighting\") not needed because we always have it in by default because we have default implementation\nconst OnOffDevice = isSocket\n ? vendorId === 0xfff4\n ? OnOffPlugInUnitDevice.with(OnOffShellExecServer, MyFancyOwnFunctionalityServer)\n : OnOffPlugInUnitDevice.with(OnOffShellExecServer)\n : vendorId === 0xfff4\n ? OnOffLightDevice.with(OnOffShellExecServer, MyFancyOwnFunctionalityServer)\n : OnOffLightDevice.with(OnOffShellExecServer);\n\n/**\n * Modify automatically added clusters of the Root endpoint if needed\n * In this example we change the networkCommissioning cluster into one for \"Wifi only\" devices when BLE is used\n * for commissioning, to demonstrate how to do this.\n * If you want to implement Ethernet only devices that get connected to the network via LAN/Ethernet cable,\n * then all this is not needed.\n * The same as shown here for Wi-Fi is also possible theoretical for Thread only or combined devices.\n */\n\n// We use the Basic Root Endpoint without a NetworkCommissioning cluster\nlet RootEndpoint = ServerNode.RootEndpoint.with(TestGeneralDiagnosticsServer);\n\nlet wifiOrThreadAdded = false;\nlet threadAdded = false;\nif (Ble.enabled) {\n // matter.js will create a Ethernet-only device by default when ut comes to Network Commissioning Features.\n // To offer e.g. a \"Wi-Fi only device\" (or any other combination) we need to override the Network Commissioning\n // cluster and implement all the need handling here. This is a \"static implementation\" for pure demonstration\n // purposes and just \"simulates\" the actions to be done. In a real world implementation this would be done by\n // the device implementor based on the relevant networking stack.\n // The NetworkCommissioningCluster and all logics are described in Matter Core Specifications section 11.8\n if (environment.vars.has(\"ble.wifi.fake\")) {\n RootEndpoint = RootEndpoint.with(DummyWifiNetworkCommissioningServer);\n wifiOrThreadAdded = true;\n } else if (environment.vars.has(\"ble.thread.fake\")) {\n RootEndpoint = RootEndpoint.with(DummyThreadNetworkCommissioningServer);\n wifiOrThreadAdded = true;\n threadAdded = true;\n }\n} else {\n RootEndpoint = RootEndpoint.with(\n NetworkCommissioningServer.with(NetworkCommissioning.Feature.EthernetNetworkInterface),\n );\n}\n\nconst networkId = new ByteArray(32);\n// Physical devices appear as \"nodes\" on a Matter network. As a device implementer you use a NodeServer to bring a\n// device online.\n//\n// Note there are a large number of options to NodeServer that we are allowing to take default values here. See\n// CompositeWindowCovering.ts for a more detailed example.\nconst server = await ServerNode.create(RootEndpoint, {\n id: uniqueId,\n network: {\n port,\n discoveryCapabilities: {\n onIpNetwork: !environment.vars.has(\"ble.enable\"),\n ble: environment.vars.has(\"ble.enable\"),\n },\n ble: environment.vars.has(\"ble.enable\"), // TODO remove when state init is fixed\n },\n commissioning: {\n passcode,\n discriminator,\n },\n productDescription: {\n name: deviceName,\n deviceType: DeviceTypeId(OnOffDevice.deviceType),\n },\n basicInformation: {\n vendorName,\n vendorId: VendorId(vendorId),\n nodeLabel: productName,\n productName,\n productLabel: productName,\n productId,\n serialNumber: `node-matter-${uniqueId}`,\n uniqueId,\n },\n\n // @ts-expect-error ... TS do not see the types because both next clusters was added conditionally\n networkCommissioning: {\n maxNetworks: 1,\n interfaceEnabled: true,\n lastConnectErrorValue: 0,\n lastNetworkId: wifiOrThreadAdded ? null : networkId,\n lastNetworkingStatus: wifiOrThreadAdded ? null : NetworkCommissioning.NetworkCommissioningStatus.Success,\n networks: [{ networkId: networkId, connected: !wifiOrThreadAdded }],\n scanMaxTimeSeconds: wifiOrThreadAdded ? 3 : undefined,\n connectMaxTimeSeconds: wifiOrThreadAdded ? 3 : undefined,\n supportedWifiBands: wifiOrThreadAdded && !threadAdded ? [NetworkCommissioning.WiFiBand[\"2G4\"]] : undefined,\n supportedThreadFeatures: wifiOrThreadAdded && threadAdded ? { isFullThreadDevice: true } : undefined,\n threadVersion: wifiOrThreadAdded && threadAdded ? 4 : undefined, // means: Thread 1.3\n },\n myFancyFunctionality: {\n myFancyValue: 0,\n },\n});\n\n// Nodes are a composition of endpoints. Add a single endpoint to the node, our example light device.\nconst endpoint = new Endpoint(OnOffDevice, { id: \"onoff\" });\nawait server.add(endpoint);\n\n/**\n * This event is triggered when the device is initially commissioned successfully.\n * This means: It is added to the first fabric.\n */\nserver.lifecycle.commissioned.on(() => console.log(\"Server was initially commissioned successfully!\"));\n\n/** This event is triggered when all fabrics are removed from the device, usually it also does a factory reset then. */\nserver.lifecycle.decommissioned.on(() => console.log(\"Server was fully decommissioned successfully!\"));\n\n/** This event is triggered when the device went online. This means that it is discoverable in the network. */\nserver.lifecycle.online.on(() => console.log(\"Server is online\"));\n\n/** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */\nserver.lifecycle.offline.on(() => console.log(\"Server is offline\"));\n\n/**\n * This event is triggered when a fabric is added, removed or updated on the device. Use this if more granular\n * information is needed.\n */\nserver.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {\n let action = \"\";\n switch (fabricAction) {\n case FabricAction.Added:\n action = \"added\";\n break;\n case FabricAction.Removed:\n action = \"removed\";\n break;\n case FabricAction.Updated:\n action = \"updated\";\n break;\n }\n console.log(`Commissioned Fabrics changed event (${action}) for ${fabricIndex} triggered`);\n console.log(server.state.commissioning.fabrics[fabricIndex]);\n});\n\n/**\n * This event is triggered when an operative new session was opened by a Controller.\n * It is not triggered for the initial commissioning process, just afterwards for real connections.\n */\nserver.events.sessions.opened.on(session => console.log(`Session opened`, session));\n\n/**\n * This event is triggered when an operative session is closed by a Controller or because the Device goes offline.\n */\nserver.events.sessions.closed.on(session => console.log(`Session closed`, session));\n\n/** This event is triggered when a subscription gets added or removed on an operative session. */\nserver.events.sessions.subscriptionsChanged.on(session => {\n console.log(`Session subscriptions changed`, session);\n console.log(`Status of all sessions`, server.state.sessions.sessions);\n});\n\n// React on a change of identificationTime to do Identify stuff for the own device\nendpoint.events.identify.startIdentifying.on(() => {\n console.log(`Run identify logic, ideally blink a light every 0.5s ...`);\n});\n\nendpoint.events.identify.stopIdentifying.on(() => {\n console.log(`Stop identify logic ...`);\n});\n\n// Our device is now built and we can bring the node online.\n//\n// Note that you may serve multiple nodes from a single process. We only have one, however, so we can use the run()\n// method of the node.\n\nlogEndpoint(EndpointServer.forEndpoint(server));\n\n/**\n * In order to start the node and announce it into the network we start the node. This method resolves when the Matter\n * node enters his online state. Alternatively, we could also use `await server.run()` which\n * resolves when the node goes offline again, but we want to execute code afterwards, so we use start() here\n */\nawait server.start();\n\nconsole.log(\"Initial Fabrics\", server.state.operationalCredentials.fabrics);\n\n/**\n * If the node is not commissioned already we display the QR code on console. The QR code is also logged\n */\nif (!server.lifecycle.isCommissioned) {\n const { qrPairingCode, manualPairingCode } = server.state.commissioning.pairingCodes;\n\n console.log(QrCode.get(qrPairingCode));\n console.log(`QR Code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`);\n console.log(`Manual pairing code: ${manualPairingCode}`);\n} else {\n console.log(\"Device is already commissioned. Waiting for controllers to connect ...\");\n\n /**\n * Sometimes reading or writing attributes is required. The following code shows how this works.\n * For read it is basically `endpoint.state.clustername.attributename`.\n * The set method allows to set one or multiple values via the structure of also clustername.attributename. When multiple values are set they are considered being one transaction which would be rolled back completely if one value fails to be set.\n */\n\n // Read onOff attribute from onOff cluster\n const onOffValue = endpoint.state.onOff.onOff;\n console.log(`current OnOff attribute: ${onOffValue}`);\n\n if (vendorId === 0xfff4) {\n // Set onOff attribute from OnOff cluster AND the myFancyValue of the MyFancyOwnFunctionality cluster together\n await endpoint.set({\n onOff: {\n onOff: !onOffValue,\n },\n // @ts-expect-error Needed because the Fancy cluster is added conditionally, so TS do not get that it's there.\n myFancyOwnFunctionality: {\n myFancyValue: 36,\n },\n });\n } else {\n // Set onOff attribute from OnOff cluster only\n await endpoint.set({\n onOff: {\n onOff: !onOffValue,\n },\n });\n }\n}\n\n/**\n * To correctly tear down the now we can use server[Symbol.asyncDispose]().\n */\nprocess.on(\"SIGINT\", () => {\n // Clean up on CTRL-C\n server\n .close()\n .then(() => process.exit(0))\n .catch(err => console.error(err));\n});\n"],
5
+ "mappings": ";AACA;AAAA;AAAA;AAAA;AAAA;AAyBA,OAAO;AAEP,SAAS,eAAe;AAExB,SAAS,wBAAwB;AACjC,SAAS,6BAA6B;AACtC,SAAS,kCAAkC;AAC3C,SAAS,mBAAmB;AAC5B,SAAS,WAAW;AACpB,SAAS,4BAA4B;AACrC,SAAS,cAAc,gBAAgB;AACvC,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AACjC,SAAS,6BAA6B;AACtC,SAAS,UAAU,sBAAsB;AACzC,SAAS,wBAAwB;AACjC,SAAS,aAAa,sBAAsB;AAC5C,SAAS,oBAAoB;AAC7B,SAAS,OAAO,QAAQ,uBAAuB;AAC/C,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,WAAW,iBAAiB;AACrC,SAAS,gBAAgB;AACzB,SAAS,6CAA6C;AACtD,SAAS,2CAA2C;AACpD;AAAA,EAGI;AAAA,OACG;AASP,sBAAsB,EAAE;AAQxB,MAAM,cAAc,YAAY;AAIhC,IAAI,YAAY,KAAK,IAAI,YAAY,GAAG;AAEpC,MAAI,MAAM;AAAA,IACN,MACI,IAAI,QAAQ;AAAA,MACR,OAAO,YAAY,KAAK,OAAO,WAAW;AAAA,IAC9C,CAAC;AAAA,EACT;AACJ;AAEA,SAAS,eAAe,iBAAyB;AAC7C,QAAM,SAAS,YAAY,KAAK,OAAO,eAAe;AACtD,MAAI,WAAW,OAAW,QAAO;AACjC,UAAQ,IAAI,GAAG,eAAe,KAAK,SAAS,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE;AACjF;AAYA,MAAM,UAAU,YAAY,KAAK,OAAO,kBAAkB;AAC1D,IAAI,YAAY,QAAW;AACvB,SAAO,UAAU,cAAc,MAAM,iBAAiB,OAAO,GAAG;AAAA,IAC5D,iBAAiB,gBAAgB,YAAY,KAAK,OAAO,kBAAkB,CAAC,KAAK,MAAM;AAAA,EAC3F,CAAC;AACL;AAEA,MAAM,iBAAiB,YAAY,IAAI,cAAc;AACrD,QAAQ,IAAI,qBAAqB,eAAe,QAAQ,cAAc;AACtE,QAAQ;AAAA,EACJ;AACJ;AAEA,MAAM,iBAAiB,MAAM,eAAe,KAAK,QAAQ,GAAG,cAAc,MAAM;AAEhF,IAAI,MAAM,cAAc,IAAI,UAAU,GAAG;AACrC,UAAQ,IAAI,4DAA4D;AAC5E;AACA,MAAM,WAAW,MAAM,cAAc,IAAI,YAAY,YAAY,KAAK,OAAO,MAAM,MAAM,QAAQ;AACjG,MAAM,aAAa;AACnB,MAAM,aAAa;AACnB,MAAM,WAAW,YAAY,KAAK,OAAO,UAAU,KAAM,MAAM,cAAc,IAAI,YAAY,QAAQ;AACrG,MAAM,gBAAgB,YAAY,KAAK,OAAO,eAAe,KAAM,MAAM,cAAc,IAAI,iBAAiB,IAAI;AAEhH,MAAM,WAAW,YAAY,KAAK,OAAO,UAAU,KAAM,MAAM,cAAc,IAAI,YAAY,KAAM;AACnG,MAAM,cAAc,qBAAqB,WAAW,WAAW,OAAO;AACtE,MAAM,YAAY,YAAY,KAAK,OAAO,WAAW,KAAM,MAAM,cAAc,IAAI,aAAa,KAAM;AAEtG,MAAM,OAAO,YAAY,KAAK,OAAO,MAAM,KAAK;AAEhD,MAAM,WAAW,YAAY,KAAK,OAAO,UAAU,KAAM,MAAM,cAAc,IAAI,YAAY,KAAK,MAAM,EAAE,SAAS,CAAC;AAEpH,MAAM,cAAc,IAAI;AAAA,EACpB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA,UAAU;AACd,CAAC;AAID,MAAM,6BAA6B,YAAY;AAAA;AAAA,EAE3C,MAAe,KAAK;AAChB,mBAAe,IAAI;AACnB,UAAM,MAAM,GAAG;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAe,MAAM;AACjB,mBAAe,KAAK;AACpB,SAAK,MAAM,QAAQ;AAAA,EACvB;AAAA;AAAA,EAGS,aAAa;AAClB,SAAK,OAAO,cAAc,GAAG,WAAS;AAClC,cAAQ,IAAI,gBAAgB,QAAQ,OAAO,KAAK,EAAE;AAAA,IACtD,CAAC;AAAA,EACL;AACJ;AAEA,MAAM,qCAAqC,iBAAiB,yBAAyB;AAAA,EACxE,aAAa;AAClB,SAAK,MAAM,2BAA2B;AACtC,UAAM,WAAW;AAAA,EACrB;AAAA,EAES,iBAAiB,EAAE,WAAW,aAAa,GAA+C;AAC/F,YAAQ,IAAI,yDAAyD,SAAS,IAAI,YAAY,EAAE;AAAA,EACpG;AACJ;AAEA,MAAM,sCAAsC,gCAAgC;AAAA;AAAA,EAE/D,eAAe,SAAwD;AAC5E,UAAM,EAAE,MAAM,IAAI;AAClB,SAAK,MAAM,eAAe,MAAM;AAEhC,SAAK,OAAO,aAAa,KAAK,EAAE,YAAY,MAAM,GAAG,KAAK,OAAO;AAEjE,WAAO,EAAE,UAAU,MAAM;AAAA,EAC7B;AAAA,EAES,aAAa;AAClB,SAAK,MAAM,eAAe;AAAA,EAC9B;AACJ;AAkBA,MAAM,cAAc,WACd,aAAa,QACT,sBAAsB,KAAK,sBAAsB,6BAA6B,IAC9E,sBAAsB,KAAK,oBAAoB,IACnD,aAAa,QACX,iBAAiB,KAAK,sBAAsB,6BAA6B,IACzE,iBAAiB,KAAK,oBAAoB;AAYlD,IAAI,eAAe,WAAW,aAAa,KAAK,4BAA4B;AAE5E,IAAI,oBAAoB;AACxB,IAAI,cAAc;AAClB,IAAI,IAAI,SAAS;AAOb,MAAI,YAAY,KAAK,IAAI,eAAe,GAAG;AACvC,mBAAe,aAAa,KAAK,mCAAmC;AACpE,wBAAoB;AAAA,EACxB,WAAW,YAAY,KAAK,IAAI,iBAAiB,GAAG;AAChD,mBAAe,aAAa,KAAK,qCAAqC;AACtE,wBAAoB;AACpB,kBAAc;AAAA,EAClB;AACJ,OAAO;AACH,iBAAe,aAAa;AAAA,IACxB,2BAA2B,KAAK,qBAAqB,QAAQ,wBAAwB;AAAA,EACzF;AACJ;AAEA,MAAM,YAAY,IAAI,UAAU,EAAE;AAMlC,MAAM,SAAS,MAAM,WAAW,OAAO,cAAc;AAAA,EACjD,IAAI;AAAA,EACJ,SAAS;AAAA,IACL;AAAA,IACA,uBAAuB;AAAA,MACnB,aAAa,CAAC,YAAY,KAAK,IAAI,YAAY;AAAA,MAC/C,KAAK,YAAY,KAAK,IAAI,YAAY;AAAA,IAC1C;AAAA,IACA,KAAK,YAAY,KAAK,IAAI,YAAY;AAAA;AAAA,EAC1C;AAAA,EACA,eAAe;AAAA,IACX;AAAA,IACA;AAAA,EACJ;AAAA,EACA,oBAAoB;AAAA,IAChB,MAAM;AAAA,IACN,YAAY,aAAa,YAAY,UAAU;AAAA,EACnD;AAAA,EACA,kBAAkB;AAAA,IACd;AAAA,IACA,UAAU,SAAS,QAAQ;AAAA,IAC3B,WAAW;AAAA,IACX;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA,cAAc,eAAe,QAAQ;AAAA,IACrC;AAAA,EACJ;AAAA;AAAA,EAGA,sBAAsB;AAAA,IAClB,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,uBAAuB;AAAA,IACvB,eAAe,oBAAoB,OAAO;AAAA,IAC1C,sBAAsB,oBAAoB,OAAO,qBAAqB,2BAA2B;AAAA,IACjG,UAAU,CAAC,EAAE,WAAsB,WAAW,CAAC,kBAAkB,CAAC;AAAA,IAClE,oBAAoB,oBAAoB,IAAI;AAAA,IAC5C,uBAAuB,oBAAoB,IAAI;AAAA,IAC/C,oBAAoB,qBAAqB,CAAC,cAAc,CAAC,qBAAqB,SAAS,KAAK,CAAC,IAAI;AAAA,IACjG,yBAAyB,qBAAqB,cAAc,EAAE,oBAAoB,KAAK,IAAI;AAAA,IAC3F,eAAe,qBAAqB,cAAc,IAAI;AAAA;AAAA,EAC1D;AAAA,EACA,sBAAsB;AAAA,IAClB,cAAc;AAAA,EAClB;AACJ,CAAC;AAGD,MAAM,WAAW,IAAI,SAAS,aAAa,EAAE,IAAI,QAAQ,CAAC;AAC1D,MAAM,OAAO,IAAI,QAAQ;AAMzB,OAAO,UAAU,aAAa,GAAG,MAAM,QAAQ,IAAI,iDAAiD,CAAC;AAGrG,OAAO,UAAU,eAAe,GAAG,MAAM,QAAQ,IAAI,+CAA+C,CAAC;AAGrG,OAAO,UAAU,OAAO,GAAG,MAAM,QAAQ,IAAI,kBAAkB,CAAC;AAGhE,OAAO,UAAU,QAAQ,GAAG,MAAM,QAAQ,IAAI,mBAAmB,CAAC;AAMlE,OAAO,OAAO,cAAc,eAAe,GAAG,CAAC,aAAa,iBAAiB;AACzE,MAAI,SAAS;AACb,UAAQ,cAAc;AAAA,IAClB,KAAK,aAAa;AACd,eAAS;AACT;AAAA,IACJ,KAAK,aAAa;AACd,eAAS;AACT;AAAA,IACJ,KAAK,aAAa;AACd,eAAS;AACT;AAAA,EACR;AACA,UAAQ,IAAI,uCAAuC,MAAM,SAAS,WAAW,YAAY;AACzF,UAAQ,IAAI,OAAO,MAAM,cAAc,QAAQ,WAAW,CAAC;AAC/D,CAAC;AAMD,OAAO,OAAO,SAAS,OAAO,GAAG,aAAW,QAAQ,IAAI,kBAAkB,OAAO,CAAC;AAKlF,OAAO,OAAO,SAAS,OAAO,GAAG,aAAW,QAAQ,IAAI,kBAAkB,OAAO,CAAC;AAGlF,OAAO,OAAO,SAAS,qBAAqB,GAAG,aAAW;AACtD,UAAQ,IAAI,iCAAiC,OAAO;AACpD,UAAQ,IAAI,0BAA0B,OAAO,MAAM,SAAS,QAAQ;AACxE,CAAC;AAGD,SAAS,OAAO,SAAS,iBAAiB,GAAG,MAAM;AAC/C,UAAQ,IAAI,0DAA0D;AAC1E,CAAC;AAED,SAAS,OAAO,SAAS,gBAAgB,GAAG,MAAM;AAC9C,UAAQ,IAAI,yBAAyB;AACzC,CAAC;AAOD,YAAY,eAAe,YAAY,MAAM,CAAC;AAO9C,MAAM,OAAO,MAAM;AAEnB,QAAQ,IAAI,mBAAmB,OAAO,MAAM,uBAAuB,OAAO;AAK1E,IAAI,CAAC,OAAO,UAAU,gBAAgB;AAClC,QAAM,EAAE,eAAe,kBAAkB,IAAI,OAAO,MAAM,cAAc;AAExE,UAAQ,IAAI,OAAO,IAAI,aAAa,CAAC;AACrC,UAAQ,IAAI,gFAAgF,aAAa,EAAE;AAC3G,UAAQ,IAAI,wBAAwB,iBAAiB,EAAE;AAC3D,OAAO;AACH,UAAQ,IAAI,wEAAwE;AASpF,QAAM,aAAa,SAAS,MAAM,MAAM;AACxC,UAAQ,IAAI,4BAA4B,UAAU,EAAE;AAEpD,MAAI,aAAa,OAAQ;AAErB,UAAM,SAAS,IAAI;AAAA,MACf,OAAO;AAAA,QACH,OAAO,CAAC;AAAA,MACZ;AAAA;AAAA,MAEA,yBAAyB;AAAA,QACrB,cAAc;AAAA,MAClB;AAAA,IACJ,CAAC;AAAA,EACL,OAAO;AAEH,UAAM,SAAS,IAAI;AAAA,MACf,OAAO;AAAA,QACH,OAAO,CAAC;AAAA,MACZ;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;AAKA,QAAQ,GAAG,UAAU,MAAM;AAEvB,SACK,MAAM,EACN,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC,EAC1B,MAAM,SAAO,QAAQ,MAAM,GAAG,CAAC;AACxC,CAAC;",
6
6
  "names": []
7
7
  }
@@ -83,7 +83,7 @@ for (let idx = 1; idx < devices.length; idx++) {
83
83
  console.log("----------------------------");
84
84
  console.log(`QR Code for Device ${i} on port ${port}:`);
85
85
  console.log("----------------------------");
86
- await server.bringOnline();
86
+ await server.start();
87
87
  }
88
88
  function executeCommand(scriptParamName) {
89
89
  const script = Environment.default.vars.string(scriptParamName);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/examples/MultiDeviceNode.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This example shows how to create a new device node that is composed of multiple devices.\n * It creates multiple endpoints on the server. For information on how to add a composed device to a bridge please\n * refer to the bridge example!\n * It can be used as CLI script and starting point for your own device node implementation.\n */\n\n/**\n * Import needed modules from @project-chip/matter-node.js\n */\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { requireMinNodeVersion } from \"@project-chip/matter-node.js/util\";\nimport { DeviceTypeId, VendorId } from \"@project-chip/matter.js/datatype\";\nimport { logEndpoint } from \"@project-chip/matter.js/device\";\nimport { OnOffLightDevice } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { OnOffPlugInUnitDevice } from \"@project-chip/matter.js/devices/OnOffPlugInUnitDevice\";\nimport { Endpoint, EndpointServer } from \"@project-chip/matter.js/endpoint\";\nimport { Environment, StorageService } from \"@project-chip/matter.js/environment\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\nimport { Time } from \"@project-chip/matter.js/time\";\nimport { execSync } from \"child_process\";\n\nrequireMinNodeVersion(16);\n\nconst devices = await getConfiguration();\nfor (let idx = 1; idx < devices.length; idx++) {\n const {\n isSocket,\n deviceName,\n vendorName,\n passcode,\n discriminator,\n vendorId,\n productName,\n productId,\n port,\n uniqueId,\n } = devices[idx];\n const i = idx + 1;\n\n /**\n * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration\n */\n const server = await ServerNode.create({\n // Required: Give the Node a unique ID which is used to store the state of this node\n id: uniqueId,\n\n // Provide Network relevant configuration like the port\n // Optional when operating only one device on a host, Default port is 5540\n network: {\n port,\n },\n\n // Provide Commissioning relevant settings\n // Optional for development/testing purposes\n commissioning: {\n passcode,\n discriminator,\n },\n\n // Provide Node announcement settings\n // Optional: If Ommitted some development defaults are used\n productDescription: {\n name: deviceName,\n deviceType: DeviceTypeId(isSocket ? OnOffPlugInUnitDevice.deviceType : OnOffLightDevice.deviceType),\n },\n\n // Provide defaults for the BasicInformation cluster on the Root endpoint\n // Optional: If Omitted some development defaults are used\n basicInformation: {\n vendorName,\n vendorId: VendorId(vendorId),\n nodeLabel: productName,\n productName,\n productLabel: productName,\n productId,\n serialNumber: `matterjs-${uniqueId}`,\n uniqueId,\n },\n });\n\n console.log(\n `Added device ${i} on port ${port} and unique id ${uniqueId}: Passcode: ${passcode}, Discriminator: ${discriminator}`,\n );\n\n const endpoint = new Endpoint(isSocket ? OnOffPlugInUnitDevice : OnOffLightDevice, { id: \"onoff\" });\n await server.add(endpoint);\n\n /**\n * Register state change handlers of the node for identify and onoff states to react to the commands.\n * If the code in these change handlers fail then the change is also rolled back and not executed and an error is\n * reported back to the controller.\n */\n endpoint.events.identify.startIdentifying.on(() => {\n console.log(`Run identify logic for device ${i}, ideally blink a light every 0.5s ...`);\n });\n\n endpoint.events.identify.stopIdentifying.on(() => {\n console.log(`Stop identify logic for device ${i}...`);\n });\n\n endpoint.events.onOff.onOff$Changed.on(value => {\n executeCommand(value ? `on${i}` : `off${i}`);\n console.log(`OnOff ${i} is now ${value ? \"ON\" : \"OFF\"}`);\n });\n\n /**\n * Log the endpoint structure for debugging reasons and to allow to verify anything is correct\n */\n logEndpoint(EndpointServer.forEndpoint(server));\n\n console.log(\"----------------------------\");\n console.log(`QR Code for Device ${i} on port ${port}:`);\n console.log(\"----------------------------\");\n\n /**\n * In order to start the node and announce it into the network we use the run method which resolves when the node goes\n * offline again because we do not need anything more here. See the Full example for other starting options.\n * The QR Code is printed automatically.\n */\n await server.bringOnline();\n}\n\n/*********************************************************************************************************\n * Convenience Methods\n *********************************************************************************************************/\n\n/**\n * Defines a shell command from an environment variable and execute it and log the response\n */\nfunction executeCommand(scriptParamName: string) {\n const script = Environment.default.vars.string(scriptParamName);\n if (script === undefined) return undefined;\n console.log(`${scriptParamName}: ${execSync(script).toString().slice(0, -1)}`);\n}\n\nasync function getConfiguration() {\n const environment = Environment.default;\n\n const storageService = environment.get(StorageService);\n console.log(`Storage location: ${storageService.location} (Directory)`);\n console.log(\n '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.',\n );\n const deviceStorage = (await storageService.open(\"device\")).createContext(\"data\");\n\n let defaultPasscode = 20202021;\n let defaultDiscriminator = 3840;\n let defaultPort = 5550;\n\n const devices = [];\n const numDevices = environment.vars.number(\"num\") ?? 2;\n for (let i = 1; i <= numDevices; i++) {\n const isSocket = await deviceStorage.get(`isSocket${i}`, environment.vars.string(`type${i}`) === \"socket\");\n if (await deviceStorage.has(`isSocket${i}`)) {\n console.log(`Device type ${isSocket ? \"socket\" : \"light\"} found in storage. --type parameter is ignored.`);\n }\n const deviceName = `Matter ${environment.vars.string(`type${i}`) ?? \"light\"} device ${i}`;\n const vendorName = \"matter-node.js\";\n const passcode =\n environment.vars.number(`passcode${i}`) ?? (await deviceStorage.get(`passcode${i}`, defaultPasscode++));\n const discriminator =\n environment.vars.number(`discriminator${i}`) ??\n (await deviceStorage.get(`discriminator${i}`, defaultDiscriminator++));\n // product name / id and vendor id should match what is in the device certificate\n const vendorId = environment.vars.number(`vendorid${i}`) ?? (await deviceStorage.get(`vendorid${i}`, 0xfff1));\n const productName = `node-matter OnOff-Device ${i}`;\n const productId =\n environment.vars.number(`productid${i}`) ?? (await deviceStorage.get(`productid${i}`, 0x8000));\n\n const port = environment.vars.number(`port${i}`) ?? defaultPort++;\n\n const uniqueId =\n environment.vars.string(`uniqueid${i}`) ??\n (await deviceStorage.get(`uniqueid${i}`, `${i}-${Time.nowMs()}`));\n\n // Persist basic data to keep them also on restart\n await deviceStorage.set(`passcode${i}`, passcode);\n await deviceStorage.set(`discriminator${i}`, discriminator);\n await deviceStorage.set(`vendorid${i}`, vendorId);\n await deviceStorage.set(`productid${i}`, productId);\n await deviceStorage.set(`isSocket${i}`, isSocket);\n await deviceStorage.set(`uniqueid${i}`, uniqueId);\n\n devices.push({\n isSocket,\n deviceName,\n vendorName,\n passcode,\n discriminator,\n vendorId,\n productName,\n productId,\n port,\n uniqueId,\n });\n }\n\n return devices;\n}\n"],
5
- "mappings": ";AACA;AAAA;AAAA;AAAA;AAAA;AAiBA,OAAO;AAEP,SAAS,6BAA6B;AACtC,SAAS,cAAc,gBAAgB;AACvC,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AACjC,SAAS,6BAA6B;AACtC,SAAS,UAAU,sBAAsB;AACzC,SAAS,aAAa,sBAAsB;AAC5C,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AACrB,SAAS,gBAAgB;AAEzB,sBAAsB,EAAE;AAExB,MAAM,UAAU,MAAM,iBAAiB;AACvC,SAAS,MAAM,GAAG,MAAM,QAAQ,QAAQ,OAAO;AAC3C,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ,IAAI,QAAQ,GAAG;AACf,QAAM,IAAI,MAAM;AAKhB,QAAM,SAAS,MAAM,WAAW,OAAO;AAAA;AAAA,IAEnC,IAAI;AAAA;AAAA;AAAA,IAIJ,SAAS;AAAA,MACL;AAAA,IACJ;AAAA;AAAA;AAAA,IAIA,eAAe;AAAA,MACX;AAAA,MACA;AAAA,IACJ;AAAA;AAAA;AAAA,IAIA,oBAAoB;AAAA,MAChB,MAAM;AAAA,MACN,YAAY,aAAa,WAAW,sBAAsB,aAAa,iBAAiB,UAAU;AAAA,IACtG;AAAA;AAAA;AAAA,IAIA,kBAAkB;AAAA,MACd;AAAA,MACA,UAAU,SAAS,QAAQ;AAAA,MAC3B,WAAW;AAAA,MACX;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,cAAc,YAAY,QAAQ;AAAA,MAClC;AAAA,IACJ;AAAA,EACJ,CAAC;AAED,UAAQ;AAAA,IACJ,gBAAgB,CAAC,YAAY,IAAI,kBAAkB,QAAQ,eAAe,QAAQ,oBAAoB,aAAa;AAAA,EACvH;AAEA,QAAM,WAAW,IAAI,SAAS,WAAW,wBAAwB,kBAAkB,EAAE,IAAI,QAAQ,CAAC;AAClG,QAAM,OAAO,IAAI,QAAQ;AAOzB,WAAS,OAAO,SAAS,iBAAiB,GAAG,MAAM;AAC/C,YAAQ,IAAI,iCAAiC,CAAC,wCAAwC;AAAA,EAC1F,CAAC;AAED,WAAS,OAAO,SAAS,gBAAgB,GAAG,MAAM;AAC9C,YAAQ,IAAI,kCAAkC,CAAC,KAAK;AAAA,EACxD,CAAC;AAED,WAAS,OAAO,MAAM,cAAc,GAAG,WAAS;AAC5C,mBAAe,QAAQ,KAAK,CAAC,KAAK,MAAM,CAAC,EAAE;AAC3C,YAAQ,IAAI,SAAS,CAAC,WAAW,QAAQ,OAAO,KAAK,EAAE;AAAA,EAC3D,CAAC;AAKD,cAAY,eAAe,YAAY,MAAM,CAAC;AAE9C,UAAQ,IAAI,8BAA8B;AAC1C,UAAQ,IAAI,sBAAsB,CAAC,YAAY,IAAI,GAAG;AACtD,UAAQ,IAAI,8BAA8B;AAO1C,QAAM,OAAO,YAAY;AAC7B;AASA,SAAS,eAAe,iBAAyB;AAC7C,QAAM,SAAS,YAAY,QAAQ,KAAK,OAAO,eAAe;AAC9D,MAAI,WAAW,OAAW,QAAO;AACjC,UAAQ,IAAI,GAAG,eAAe,KAAK,SAAS,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE;AACjF;AAEA,eAAe,mBAAmB;AAC9B,QAAM,cAAc,YAAY;AAEhC,QAAM,iBAAiB,YAAY,IAAI,cAAc;AACrD,UAAQ,IAAI,qBAAqB,eAAe,QAAQ,cAAc;AACtE,UAAQ;AAAA,IACJ;AAAA,EACJ;AACA,QAAM,iBAAiB,MAAM,eAAe,KAAK,QAAQ,GAAG,cAAc,MAAM;AAEhF,MAAI,kBAAkB;AACtB,MAAI,uBAAuB;AAC3B,MAAI,cAAc;AAElB,QAAMA,WAAU,CAAC;AACjB,QAAM,aAAa,YAAY,KAAK,OAAO,KAAK,KAAK;AACrD,WAAS,IAAI,GAAG,KAAK,YAAY,KAAK;AAClC,UAAM,WAAW,MAAM,cAAc,IAAI,WAAW,CAAC,IAAI,YAAY,KAAK,OAAO,OAAO,CAAC,EAAE,MAAM,QAAQ;AACzG,QAAI,MAAM,cAAc,IAAI,WAAW,CAAC,EAAE,GAAG;AACzC,cAAQ,IAAI,eAAe,WAAW,WAAW,OAAO,iDAAiD;AAAA,IAC7G;AACA,UAAM,aAAa,UAAU,YAAY,KAAK,OAAO,OAAO,CAAC,EAAE,KAAK,OAAO,WAAW,CAAC;AACvF,UAAM,aAAa;AACnB,UAAM,WACF,YAAY,KAAK,OAAO,WAAW,CAAC,EAAE,KAAM,MAAM,cAAc,IAAI,WAAW,CAAC,IAAI,iBAAiB;AACzG,UAAM,gBACF,YAAY,KAAK,OAAO,gBAAgB,CAAC,EAAE,KAC1C,MAAM,cAAc,IAAI,gBAAgB,CAAC,IAAI,sBAAsB;AAExE,UAAM,WAAW,YAAY,KAAK,OAAO,WAAW,CAAC,EAAE,KAAM,MAAM,cAAc,IAAI,WAAW,CAAC,IAAI,KAAM;AAC3G,UAAM,cAAc,4BAA4B,CAAC;AACjD,UAAM,YACF,YAAY,KAAK,OAAO,YAAY,CAAC,EAAE,KAAM,MAAM,cAAc,IAAI,YAAY,CAAC,IAAI,KAAM;AAEhG,UAAM,OAAO,YAAY,KAAK,OAAO,OAAO,CAAC,EAAE,KAAK;AAEpD,UAAM,WACF,YAAY,KAAK,OAAO,WAAW,CAAC,EAAE,KACrC,MAAM,cAAc,IAAI,WAAW,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE;AAGnE,UAAM,cAAc,IAAI,WAAW,CAAC,IAAI,QAAQ;AAChD,UAAM,cAAc,IAAI,gBAAgB,CAAC,IAAI,aAAa;AAC1D,UAAM,cAAc,IAAI,WAAW,CAAC,IAAI,QAAQ;AAChD,UAAM,cAAc,IAAI,YAAY,CAAC,IAAI,SAAS;AAClD,UAAM,cAAc,IAAI,WAAW,CAAC,IAAI,QAAQ;AAChD,UAAM,cAAc,IAAI,WAAW,CAAC,IAAI,QAAQ;AAEhD,IAAAA,SAAQ,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ,CAAC;AAAA,EACL;AAEA,SAAOA;AACX;",
4
+ "sourcesContent": ["#!/usr/bin/env node\n/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * This example shows how to create a new device node that is composed of multiple devices.\n * It creates multiple endpoints on the server. For information on how to add a composed device to a bridge please\n * refer to the bridge example!\n * It can be used as CLI script and starting point for your own device node implementation.\n */\n\n/**\n * Import needed modules from @project-chip/matter-node.js\n */\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { requireMinNodeVersion } from \"@project-chip/matter-node.js/util\";\nimport { DeviceTypeId, VendorId } from \"@project-chip/matter.js/datatype\";\nimport { logEndpoint } from \"@project-chip/matter.js/device\";\nimport { OnOffLightDevice } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { OnOffPlugInUnitDevice } from \"@project-chip/matter.js/devices/OnOffPlugInUnitDevice\";\nimport { Endpoint, EndpointServer } from \"@project-chip/matter.js/endpoint\";\nimport { Environment, StorageService } from \"@project-chip/matter.js/environment\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\nimport { Time } from \"@project-chip/matter.js/time\";\nimport { execSync } from \"child_process\";\n\nrequireMinNodeVersion(16);\n\nconst devices = await getConfiguration();\nfor (let idx = 1; idx < devices.length; idx++) {\n const {\n isSocket,\n deviceName,\n vendorName,\n passcode,\n discriminator,\n vendorId,\n productName,\n productId,\n port,\n uniqueId,\n } = devices[idx];\n const i = idx + 1;\n\n /**\n * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration\n */\n const server = await ServerNode.create({\n // Required: Give the Node a unique ID which is used to store the state of this node\n id: uniqueId,\n\n // Provide Network relevant configuration like the port\n // Optional when operating only one device on a host, Default port is 5540\n network: {\n port,\n },\n\n // Provide Commissioning relevant settings\n // Optional for development/testing purposes\n commissioning: {\n passcode,\n discriminator,\n },\n\n // Provide Node announcement settings\n // Optional: If Ommitted some development defaults are used\n productDescription: {\n name: deviceName,\n deviceType: DeviceTypeId(isSocket ? OnOffPlugInUnitDevice.deviceType : OnOffLightDevice.deviceType),\n },\n\n // Provide defaults for the BasicInformation cluster on the Root endpoint\n // Optional: If Omitted some development defaults are used\n basicInformation: {\n vendorName,\n vendorId: VendorId(vendorId),\n nodeLabel: productName,\n productName,\n productLabel: productName,\n productId,\n serialNumber: `matterjs-${uniqueId}`,\n uniqueId,\n },\n });\n\n console.log(\n `Added device ${i} on port ${port} and unique id ${uniqueId}: Passcode: ${passcode}, Discriminator: ${discriminator}`,\n );\n\n const endpoint = new Endpoint(isSocket ? OnOffPlugInUnitDevice : OnOffLightDevice, { id: \"onoff\" });\n await server.add(endpoint);\n\n /**\n * Register state change handlers of the node for identify and onoff states to react to the commands.\n * If the code in these change handlers fail then the change is also rolled back and not executed and an error is\n * reported back to the controller.\n */\n endpoint.events.identify.startIdentifying.on(() => {\n console.log(`Run identify logic for device ${i}, ideally blink a light every 0.5s ...`);\n });\n\n endpoint.events.identify.stopIdentifying.on(() => {\n console.log(`Stop identify logic for device ${i}...`);\n });\n\n endpoint.events.onOff.onOff$Changed.on(value => {\n executeCommand(value ? `on${i}` : `off${i}`);\n console.log(`OnOff ${i} is now ${value ? \"ON\" : \"OFF\"}`);\n });\n\n /**\n * Log the endpoint structure for debugging reasons and to allow to verify anything is correct\n */\n logEndpoint(EndpointServer.forEndpoint(server));\n\n console.log(\"----------------------------\");\n console.log(`QR Code for Device ${i} on port ${port}:`);\n console.log(\"----------------------------\");\n\n /**\n * In order to start the node and announce it into the network we use the run method which resolves when the node goes\n * offline again because we do not need anything more here. See the Full example for other starting options.\n * The QR Code is printed automatically.\n */\n await server.start();\n}\n\n/*********************************************************************************************************\n * Convenience Methods\n *********************************************************************************************************/\n\n/**\n * Defines a shell command from an environment variable and execute it and log the response\n */\nfunction executeCommand(scriptParamName: string) {\n const script = Environment.default.vars.string(scriptParamName);\n if (script === undefined) return undefined;\n console.log(`${scriptParamName}: ${execSync(script).toString().slice(0, -1)}`);\n}\n\nasync function getConfiguration() {\n const environment = Environment.default;\n\n const storageService = environment.get(StorageService);\n console.log(`Storage location: ${storageService.location} (Directory)`);\n console.log(\n '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.',\n );\n const deviceStorage = (await storageService.open(\"device\")).createContext(\"data\");\n\n let defaultPasscode = 20202021;\n let defaultDiscriminator = 3840;\n let defaultPort = 5550;\n\n const devices = [];\n const numDevices = environment.vars.number(\"num\") ?? 2;\n for (let i = 1; i <= numDevices; i++) {\n const isSocket = await deviceStorage.get(`isSocket${i}`, environment.vars.string(`type${i}`) === \"socket\");\n if (await deviceStorage.has(`isSocket${i}`)) {\n console.log(`Device type ${isSocket ? \"socket\" : \"light\"} found in storage. --type parameter is ignored.`);\n }\n const deviceName = `Matter ${environment.vars.string(`type${i}`) ?? \"light\"} device ${i}`;\n const vendorName = \"matter-node.js\";\n const passcode =\n environment.vars.number(`passcode${i}`) ?? (await deviceStorage.get(`passcode${i}`, defaultPasscode++));\n const discriminator =\n environment.vars.number(`discriminator${i}`) ??\n (await deviceStorage.get(`discriminator${i}`, defaultDiscriminator++));\n // product name / id and vendor id should match what is in the device certificate\n const vendorId = environment.vars.number(`vendorid${i}`) ?? (await deviceStorage.get(`vendorid${i}`, 0xfff1));\n const productName = `node-matter OnOff-Device ${i}`;\n const productId =\n environment.vars.number(`productid${i}`) ?? (await deviceStorage.get(`productid${i}`, 0x8000));\n\n const port = environment.vars.number(`port${i}`) ?? defaultPort++;\n\n const uniqueId =\n environment.vars.string(`uniqueid${i}`) ??\n (await deviceStorage.get(`uniqueid${i}`, `${i}-${Time.nowMs()}`));\n\n // Persist basic data to keep them also on restart\n await deviceStorage.set(`passcode${i}`, passcode);\n await deviceStorage.set(`discriminator${i}`, discriminator);\n await deviceStorage.set(`vendorid${i}`, vendorId);\n await deviceStorage.set(`productid${i}`, productId);\n await deviceStorage.set(`isSocket${i}`, isSocket);\n await deviceStorage.set(`uniqueid${i}`, uniqueId);\n\n devices.push({\n isSocket,\n deviceName,\n vendorName,\n passcode,\n discriminator,\n vendorId,\n productName,\n productId,\n port,\n uniqueId,\n });\n }\n\n return devices;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["devices"]
7
7
  }
@@ -3,7 +3,7 @@ import { OnOffLightDevice } from "@project-chip/matter.js/devices/OnOffLightDevi
3
3
  import { ServerNode } from "@project-chip/matter.js/node";
4
4
  const node = await ServerNode.create();
5
5
  const light = await node.add(OnOffLightDevice);
6
- await node.bringOnline();
6
+ await node.start();
7
7
  await light.act(async (agent) => {
8
8
  await agent.onOff.toggle();
9
9
  console.log("On/off state after first toggle", agent.onOff.state);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/tutorial/example05.ts"],
4
- "sourcesContent": ["import \"@project-chip/matter-node.js\";\nimport { OnOffLightDevice } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\n\nconst node = await ServerNode.create();\n\nconst light = await node.add(OnOffLightDevice);\n\nawait node.bringOnline();\n\nawait light.act(async agent => {\n await agent.onOff.toggle();\n console.log(\"On/off state after first toggle\", agent.onOff.state);\n\n await agent.onOff.toggle();\n console.log(\"On/off state after second toggle\", agent.onOff.state);\n});\n\nawait node.close();\n"],
5
- "mappings": "AAAA,OAAO;AACP,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAE3B,MAAM,OAAO,MAAM,WAAW,OAAO;AAErC,MAAM,QAAQ,MAAM,KAAK,IAAI,gBAAgB;AAE7C,MAAM,KAAK,YAAY;AAEvB,MAAM,MAAM,IAAI,OAAM,UAAS;AAC3B,QAAM,MAAM,MAAM,OAAO;AACzB,UAAQ,IAAI,mCAAmC,MAAM,MAAM,KAAK;AAEhE,QAAM,MAAM,MAAM,OAAO;AACzB,UAAQ,IAAI,oCAAoC,MAAM,MAAM,KAAK;AACrE,CAAC;AAED,MAAM,KAAK,MAAM;",
4
+ "sourcesContent": ["import \"@project-chip/matter-node.js\";\nimport { OnOffLightDevice } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\n\nconst node = await ServerNode.create();\n\nconst light = await node.add(OnOffLightDevice);\n\nawait node.start();\n\nawait light.act(async agent => {\n await agent.onOff.toggle();\n console.log(\"On/off state after first toggle\", agent.onOff.state);\n\n await agent.onOff.toggle();\n console.log(\"On/off state after second toggle\", agent.onOff.state);\n});\n\nawait node.close();\n"],
5
+ "mappings": "AAAA,OAAO;AACP,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAE3B,MAAM,OAAO,MAAM,WAAW,OAAO;AAErC,MAAM,QAAQ,MAAM,KAAK,IAAI,gBAAgB;AAE7C,MAAM,KAAK,MAAM;AAEjB,MAAM,MAAM,IAAI,OAAM,UAAS;AAC3B,QAAM,MAAM,MAAM,OAAO;AACzB,UAAQ,IAAI,mCAAmC,MAAM,MAAM,KAAK;AAEhE,QAAM,MAAM,MAAM,OAAO;AACzB,UAAQ,IAAI,oCAAoC,MAAM,MAAM,KAAK;AACrE,CAAC;AAED,MAAM,KAAK,MAAM;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@project-chip/matter-node.js-examples",
3
- "version": "0.10.0-alpha.0-20240716-446c872f",
3
+ "version": "0.10.0-alpha.0-20240722-39f917c1",
4
4
  "description": "CLI/Reference implementation scripts for Matter protocol for node.js",
5
5
  "keywords": [
6
6
  "iot",
@@ -64,10 +64,10 @@
64
64
  "typescript": "~5.5.3"
65
65
  },
66
66
  "dependencies": {
67
- "@project-chip/matter-node-ble.js": "0.10.0-alpha.0-20240716-446c872f",
68
- "@project-chip/matter-node.js": "0.10.0-alpha.0-20240716-446c872f",
69
- "@project-chip/matter.js": "0.10.0-alpha.0-20240716-446c872f",
70
- "@project-chip/matter.js-tools": "0.10.0-alpha.0-20240716-446c872f"
67
+ "@project-chip/matter-node-ble.js": "0.10.0-alpha.0-20240722-39f917c1",
68
+ "@project-chip/matter-node.js": "0.10.0-alpha.0-20240722-39f917c1",
69
+ "@project-chip/matter.js": "0.10.0-alpha.0-20240722-39f917c1",
70
+ "@project-chip/matter.js-tools": "0.10.0-alpha.0-20240722-39f917c1"
71
71
  },
72
72
  "engines": {
73
73
  "_comment": "For Crypto.hkdf support",
@@ -83,5 +83,5 @@
83
83
  "publishConfig": {
84
84
  "access": "public"
85
85
  },
86
- "gitHead": "59e632443c867a13b9081b1a1540438c7b24d3e2"
86
+ "gitHead": "d9d7133aec5194ebfdb3f019f4caca703a57dcec"
87
87
  }
@@ -140,7 +140,7 @@ for (let idx = 0; idx < isSocket.length; idx++) {
140
140
  * offline again because we do not need anything more here. See the Full example for other starting options.
141
141
  * The QR Code is printed automatically.
142
142
  */
143
- await server.bringOnline();
143
+ await server.start();
144
144
 
145
145
  /**
146
146
  * Log the endpoint structure for debugging reasons and to allow to verify anything is correct
@@ -84,7 +84,7 @@ class ControllerNode {
84
84
  : environment.vars.number("port");
85
85
  const uniqueId = (await controllerStorage.has("uniqueid"))
86
86
  ? await controllerStorage.get<string>("uniqueid")
87
- : environment.vars.string("uniqueid") ?? Time.nowMs().toString();
87
+ : (environment.vars.string("uniqueid") ?? Time.nowMs().toString());
88
88
  await controllerStorage.set("uniqueid", uniqueId);
89
89
 
90
90
  const pairingCode = environment.vars.string("pairingcode");
@@ -386,7 +386,7 @@ logEndpoint(EndpointServer.forEndpoint(server));
386
386
  * node enters his online state. Alternatively, we could also use `await server.run()` which
387
387
  * resolves when the node goes offline again, but we want to execute code afterwards, so we use start() here
388
388
  */
389
- await server.bringOnline();
389
+ await server.start();
390
390
 
391
391
  console.log("Initial Fabrics", server.state.operationalCredentials.fabrics);
392
392
 
@@ -127,7 +127,7 @@ for (let idx = 1; idx < devices.length; idx++) {
127
127
  * offline again because we do not need anything more here. See the Full example for other starting options.
128
128
  * The QR Code is printed automatically.
129
129
  */
130
- await server.bringOnline();
130
+ await server.start();
131
131
  }
132
132
 
133
133
  /*********************************************************************************************************
@@ -6,7 +6,7 @@ const node = await ServerNode.create();
6
6
 
7
7
  const light = await node.add(OnOffLightDevice);
8
8
 
9
- await node.bringOnline();
9
+ await node.start();
10
10
 
11
11
  await light.act(async agent => {
12
12
  await agent.onOff.toggle();