@project-chip/matter-node.js-examples 0.10.0-alpha.0-20240715-a2d7875c → 0.10.0-alpha.0-20240720-471dea8c

Sign up to get free protection for your applications and to get access to all the features.
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
 
@@ -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
  }
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-20240715-a2d7875c",
3
+ "version": "0.10.0-alpha.0-20240720-471dea8c",
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-20240715-a2d7875c",
68
- "@project-chip/matter-node.js": "0.10.0-alpha.0-20240715-a2d7875c",
69
- "@project-chip/matter.js": "0.10.0-alpha.0-20240715-a2d7875c",
70
- "@project-chip/matter.js-tools": "0.10.0-alpha.0-20240715-a2d7875c"
67
+ "@project-chip/matter-node-ble.js": "0.10.0-alpha.0-20240720-471dea8c",
68
+ "@project-chip/matter-node.js": "0.10.0-alpha.0-20240720-471dea8c",
69
+ "@project-chip/matter.js": "0.10.0-alpha.0-20240720-471dea8c",
70
+ "@project-chip/matter.js-tools": "0.10.0-alpha.0-20240720-471dea8c"
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": "5870d5733a78315eb8638ceeaf7e0cf963a4d46d"
86
+ "gitHead": "874b207c9f128628a414c37eb8c6ba7d3963090c"
87
87
  }
@@ -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");