@project-chip/matter-node.js-examples 0.8.2-alpha.0-20240513-927b1bb5 → 0.9.0

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.
@@ -4,48 +4,22 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import "@project-chip/matter-node.js";
7
- import { WindowCoveringServer } from "@project-chip/matter.js/behaviors/window-covering";
7
+ import {
8
+ MovementDirection,
9
+ WindowCoveringServer
10
+ } from "@project-chip/matter.js/behaviors/window-covering";
8
11
  import { OnOffLightDevice, OnOffLightRequirements } from "@project-chip/matter.js/devices/OnOffLightDevice";
9
12
  import { WindowCoveringDevice } from "@project-chip/matter.js/devices/WindowCoveringDevice";
10
13
  import { ServerNode } from "@project-chip/matter.js/node";
11
14
  const LiftingWindowCoveringServer = WindowCoveringServer.with("Lift", "AbsolutePosition", "PositionAwareLift");
12
15
  class RollerShade extends LiftingWindowCoveringServer {
13
- get currentPos() {
14
- return this.state.currentPositionLiftPercent100ths ?? 0;
15
- }
16
- get targetPos() {
17
- return this.state.targetPositionLiftPercent100ths ?? 0;
18
- }
19
- set targetPos(position) {
20
- this.state.targetPositionLiftPercent100ths = position ?? 0;
21
- }
22
- async initialize() {
23
- this.reactTo(this.events.targetPositionLiftPercent100ths$Changed, this.writeTargetToMotor);
24
- await this.readTargetFromMotor();
25
- if (this.targetPos === null) {
26
- this.targetPos = this.currentPos;
27
- }
28
- }
29
- upOrOpen() {
30
- this.targetPos = 0;
31
- }
32
- downOrClose() {
33
- this.targetPos = 1e4;
34
- }
35
- stopMotion() {
36
- this.targetPos = this.currentPos;
37
- }
38
- goToLiftPercentage(request) {
39
- this.targetPos = request.liftPercent100thsValue;
40
- }
41
- async writeTargetToMotor() {
42
- console.log("Window covering target position is now", `${this.targetPos / 100}%`);
43
- }
44
- async readTargetFromMotor() {
45
- this.state.currentPositionLiftPercent100ths = 0;
46
- }
47
- set currentPos(value) {
48
- this.state.currentPositionLiftPercent100ths = value;
16
+ async handleMovement(type, reversed, direction, targetPercent100ths) {
17
+ console.log(
18
+ "Move window shade",
19
+ direction === MovementDirection.Open ? "Open" : "Close",
20
+ targetPercent100ths !== void 0 ? `${targetPercent100ths / 100}%` : ""
21
+ );
22
+ await super.handleMovement(type, reversed, direction, targetPercent100ths);
49
23
  }
50
24
  }
51
25
  class ValanceLight extends OnOffLightRequirements.OnOffServer {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/examples/IlluminatedRollerShade.ts"],
4
- "sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport { GoToLiftPercentageRequest, WindowCoveringServer } from \"@project-chip/matter.js/behaviors/window-covering\";\nimport { OnOffLightDevice, OnOffLightRequirements } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { WindowCoveringDevice } from \"@project-chip/matter.js/devices/WindowCoveringDevice\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\n\n/**\n * This example demonstrates implementation of a \"composed\" device comprising multiple sub-devices\n *\n * Our example device, the Excelsior 1000 EZ-Nite\u2122, is a roller shade with an illuminated valance.\n */\n\nconst LiftingWindowCoveringServer = WindowCoveringServer.with(\"Lift\", \"AbsolutePosition\", \"PositionAwareLift\");\n\n/**\n * Implementation of the Matter WindowCovering cluster for the shade motor.\n *\n * TODO - some of this should probably move to WindowCoveringServer\n */\nclass RollerShade extends LiftingWindowCoveringServer {\n get currentPos() {\n return this.state.currentPositionLiftPercent100ths ?? 0;\n }\n\n get targetPos() {\n return this.state.targetPositionLiftPercent100ths ?? 0;\n }\n\n set targetPos(position: number) {\n this.state.targetPositionLiftPercent100ths = position ?? 0;\n }\n\n override async initialize() {\n this.reactTo(this.events.targetPositionLiftPercent100ths$Changed, this.writeTargetToMotor);\n\n await this.readTargetFromMotor();\n if (this.targetPos === null) {\n this.targetPos = this.currentPos;\n }\n }\n\n override upOrOpen() {\n // 0 = 0%, fully open\n this.targetPos = 0;\n }\n\n override downOrClose() {\n // 10000 = 100%, fully closed\n this.targetPos = 10000;\n }\n\n override stopMotion() {\n this.targetPos = this.currentPos;\n }\n\n override goToLiftPercentage(this: RollerShade, request: GoToLiftPercentageRequest) {\n this.targetPos = request.liftPercent100thsValue;\n }\n\n protected async writeTargetToMotor() {\n // For this contrived example we just log the target position and don't actually animate our fake roller shade\n console.log(\"Window covering target position is now\", `${this.targetPos / 100}%`);\n }\n\n protected async readTargetFromMotor() {\n // Our fake shade is stuck open\n this.state.currentPositionLiftPercent100ths = 0;\n }\n\n protected set currentPos(value: number) {\n this.state.currentPositionLiftPercent100ths = value;\n }\n}\n\n/**\n * Implementation of the OnOff cluster for our valance light.\n */\nclass ValanceLight extends OnOffLightRequirements.OnOffServer {\n override initialize() {\n this.reactTo(this.events.onOff$Changed, this.#stateChanged);\n }\n\n #stateChanged(value: boolean) {\n console.log(`Valance is now ${value ? \"illuminated\" : \"dark\"}`);\n }\n}\n\n/**\n * Our Matter node.\n */\nconst node = new ServerNode({\n id: \"excelsior1000\",\n\n productDescription: {},\n\n commissioning: {\n passcode: 20202021,\n discriminator: 3840,\n },\n\n basicInformation: {\n vendorName: \"Acme Corporation\",\n productName: \"Excelsior 1000 EZ-Nite\u2122\",\n vendorId: 0xfff1,\n productId: 0x8000,\n serialNumber: \"1234-12345-123\",\n },\n\n parts: [\n {\n type: WindowCoveringDevice.with(RollerShade),\n id: \"shade\",\n },\n\n {\n type: OnOffLightDevice.with(ValanceLight),\n id: \"valance\",\n },\n ],\n});\n\nawait node.run();\n"],
5
- "mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,OAAO;AAEP,SAAoC,4BAA4B;AAChE,SAAS,kBAAkB,8BAA8B;AACzD,SAAS,4BAA4B;AACrC,SAAS,kBAAkB;AAQ3B,MAAM,8BAA8B,qBAAqB,KAAK,QAAQ,oBAAoB,mBAAmB;AAO7G,MAAM,oBAAoB,4BAA4B;AAAA,EAClD,IAAI,aAAa;AACb,WAAO,KAAK,MAAM,oCAAoC;AAAA,EAC1D;AAAA,EAEA,IAAI,YAAY;AACZ,WAAO,KAAK,MAAM,mCAAmC;AAAA,EACzD;AAAA,EAEA,IAAI,UAAU,UAAkB;AAC5B,SAAK,MAAM,kCAAkC,YAAY;AAAA,EAC7D;AAAA,EAEA,MAAe,aAAa;AACxB,SAAK,QAAQ,KAAK,OAAO,yCAAyC,KAAK,kBAAkB;AAEzF,UAAM,KAAK,oBAAoB;AAC/B,QAAI,KAAK,cAAc,MAAM;AACzB,WAAK,YAAY,KAAK;AAAA,IAC1B;AAAA,EACJ;AAAA,EAES,WAAW;AAEhB,SAAK,YAAY;AAAA,EACrB;AAAA,EAES,cAAc;AAEnB,SAAK,YAAY;AAAA,EACrB;AAAA,EAES,aAAa;AAClB,SAAK,YAAY,KAAK;AAAA,EAC1B;AAAA,EAES,mBAAsC,SAAoC;AAC/E,SAAK,YAAY,QAAQ;AAAA,EAC7B;AAAA,EAEA,MAAgB,qBAAqB;AAEjC,YAAQ,IAAI,0CAA0C,GAAG,KAAK,YAAY,GAAG,GAAG;AAAA,EACpF;AAAA,EAEA,MAAgB,sBAAsB;AAElC,SAAK,MAAM,mCAAmC;AAAA,EAClD;AAAA,EAEA,IAAc,WAAW,OAAe;AACpC,SAAK,MAAM,mCAAmC;AAAA,EAClD;AACJ;AAKA,MAAM,qBAAqB,uBAAuB,YAAY;AAAA,EACjD,aAAa;AAClB,SAAK,QAAQ,KAAK,OAAO,eAAe,KAAK,aAAa;AAAA,EAC9D;AAAA,EAEA,cAAc,OAAgB;AAC1B,YAAQ,IAAI,kBAAkB,QAAQ,gBAAgB,MAAM,EAAE;AAAA,EAClE;AACJ;AAKA,MAAM,OAAO,IAAI,WAAW;AAAA,EACxB,IAAI;AAAA,EAEJ,oBAAoB,CAAC;AAAA,EAErB,eAAe;AAAA,IACX,UAAU;AAAA,IACV,eAAe;AAAA,EACnB;AAAA,EAEA,kBAAkB;AAAA,IACd,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW;AAAA,IACX,cAAc;AAAA,EAClB;AAAA,EAEA,OAAO;AAAA,IACH;AAAA,MACI,MAAM,qBAAqB,KAAK,WAAW;AAAA,MAC3C,IAAI;AAAA,IACR;AAAA,IAEA;AAAA,MACI,MAAM,iBAAiB,KAAK,YAAY;AAAA,MACxC,IAAI;AAAA,IACR;AAAA,EACJ;AACJ,CAAC;AAED,MAAM,KAAK,IAAI;",
4
+ "sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Include this first to auto-register Crypto, Network and Time Node.js implementations\nimport \"@project-chip/matter-node.js\";\n\nimport {\n MovementDirection,\n MovementType,\n WindowCoveringServer,\n} from \"@project-chip/matter.js/behaviors/window-covering\";\nimport { OnOffLightDevice, OnOffLightRequirements } from \"@project-chip/matter.js/devices/OnOffLightDevice\";\nimport { WindowCoveringDevice } from \"@project-chip/matter.js/devices/WindowCoveringDevice\";\nimport { ServerNode } from \"@project-chip/matter.js/node\";\n\n/**\n * This example demonstrates implementation of a \"composed\" device comprising multiple sub-devices\n *\n * Our example device, the Excelsior 1000 EZ-Nite\u2122, is a roller shade with an illuminated valance.\n */\n\nconst LiftingWindowCoveringServer = WindowCoveringServer.with(\"Lift\", \"AbsolutePosition\", \"PositionAwareLift\");\n\n/**\n * Implementation of the Matter WindowCovering cluster for the shade motor.\n */\nclass RollerShade extends LiftingWindowCoveringServer {\n override async handleMovement(\n type: MovementType,\n reversed: boolean,\n direction: MovementDirection,\n targetPercent100ths?: number,\n ) {\n console.log(\n \"Move window shade\",\n direction === MovementDirection.Open ? \"Open\" : \"Close\",\n targetPercent100ths !== undefined ? `${targetPercent100ths / 100}%` : \"\",\n );\n\n // Updates the shade position\n await super.handleMovement(type, reversed, direction, targetPercent100ths);\n }\n}\n\n/**\n * Implementation of the OnOff cluster for our valance light.\n */\nclass ValanceLight extends OnOffLightRequirements.OnOffServer {\n override initialize() {\n this.reactTo(this.events.onOff$Changed, this.#stateChanged);\n }\n\n #stateChanged(value: boolean) {\n console.log(`Valance is now ${value ? \"illuminated\" : \"dark\"}`);\n }\n}\n\n/**\n * Our Matter node.\n */\nconst node = new ServerNode({\n id: \"excelsior1000\",\n\n productDescription: {},\n\n commissioning: {\n passcode: 20202021,\n discriminator: 3840,\n },\n\n basicInformation: {\n vendorName: \"Acme Corporation\",\n productName: \"Excelsior 1000 EZ-Nite\u2122\",\n vendorId: 0xfff1,\n productId: 0x8000,\n serialNumber: \"1234-12345-123\",\n },\n\n parts: [\n {\n type: WindowCoveringDevice.with(RollerShade),\n id: \"shade\",\n },\n\n {\n type: OnOffLightDevice.with(ValanceLight),\n id: \"valance\",\n },\n ],\n});\n\nawait node.run();\n"],
5
+ "mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,OAAO;AAEP;AAAA,EACI;AAAA,EAEA;AAAA,OACG;AACP,SAAS,kBAAkB,8BAA8B;AACzD,SAAS,4BAA4B;AACrC,SAAS,kBAAkB;AAQ3B,MAAM,8BAA8B,qBAAqB,KAAK,QAAQ,oBAAoB,mBAAmB;AAK7G,MAAM,oBAAoB,4BAA4B;AAAA,EAClD,MAAe,eACX,MACA,UACA,WACA,qBACF;AACE,YAAQ;AAAA,MACJ;AAAA,MACA,cAAc,kBAAkB,OAAO,SAAS;AAAA,MAChD,wBAAwB,SAAY,GAAG,sBAAsB,GAAG,MAAM;AAAA,IAC1E;AAGA,UAAM,MAAM,eAAe,MAAM,UAAU,WAAW,mBAAmB;AAAA,EAC7E;AACJ;AAKA,MAAM,qBAAqB,uBAAuB,YAAY;AAAA,EACjD,aAAa;AAClB,SAAK,QAAQ,KAAK,OAAO,eAAe,KAAK,aAAa;AAAA,EAC9D;AAAA,EAEA,cAAc,OAAgB;AAC1B,YAAQ,IAAI,kBAAkB,QAAQ,gBAAgB,MAAM,EAAE;AAAA,EAClE;AACJ;AAKA,MAAM,OAAO,IAAI,WAAW;AAAA,EACxB,IAAI;AAAA,EAEJ,oBAAoB,CAAC;AAAA,EAErB,eAAe;AAAA,IACX,UAAU;AAAA,IACV,eAAe;AAAA,EACnB;AAAA,EAEA,kBAAkB;AAAA,IACd,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW;AAAA,IACX,cAAc;AAAA,EAClB;AAAA,EAEA,OAAO;AAAA,IACH;AAAA,MACI,MAAM,qBAAqB,KAAK,WAAW;AAAA,MAC3C,IAAI;AAAA,IACR;AAAA,IAEA;AAAA,MACI,MAAM,iBAAiB,KAAK,YAAY;AAAA,MACxC,IAAI;AAAA,IACR;AAAA,EACJ;AACJ,CAAC;AAED,MAAM,KAAK,IAAI;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/examples/cluster/MyFancyOwnFunctionality.ts"],
4
- "sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { ClusterBehavior } from \"@project-chip/matter.js/behavior/cluster\";\nimport {\n Attribute,\n ClusterRegistry,\n Command,\n Event,\n EventPriority,\n MutableCluster,\n} from \"@project-chip/matter.js/cluster\";\nimport { ClusterId, VendorId } from \"@project-chip/matter.js/datatype\";\nimport {\n AttributeElement,\n ClusterElement,\n ClusterModel,\n CommandElement,\n EventElement,\n FieldElement,\n} from \"@project-chip/matter.js/model\";\nimport { TlvField, TlvInt16, TlvNullable, TlvObject, TlvString, TypeFromSchema } from \"@project-chip/matter.js/tlv\";\nimport { Identity, MaybePromise } from \"@project-chip/matter.js/util\";\n\n/** Define the Cluster ID, custom clusters use a special extended formt that also contains the Vendor Id */\nconst myFancyClusterId = ClusterId.buildVendorSpecific(VendorId(0xfff4), 0xfc00);\n\n/**\n * Defines the Cluster on Tlv Schema level in a special namespace structure to match the official cluster\n * structures of matter.js.\n * All places that contains \"MyFancy...\" belong to the custom cluster details, all rest can be left statically like the\n * given names.\n * For more examples and usages of features in such clusters and how the code should look then check the standard\n * cluster Tlv definitions in packages/matter.js/cluster/definitions/*\n */\nexport namespace MyFancyOwnFunctionality {\n /**\n * Input to the MyFancyOwnFunctionality myFancyCommand command\n */\n export const TlvMyFancyCommandRequest = TlvObject({ value: TlvField(0, TlvString) });\n\n /**\n * Response of the MyFancyOwnFunctionality myFancyCommand command\n */\n export const TlvMyFancyCommandResponse = TlvObject({ response: TlvField(0, TlvString) });\n\n /**\n * Event for the MyFancyOwnFunctionality myFancyEvent event\n */\n export const TlvMyFancyEvent = TlvObject({ eventValue: TlvField(0, TlvString) });\n\n /**\n * @see {@link Cluster}\n */\n export const ClusterInstance = MutableCluster({\n id: myFancyClusterId,\n name: \"MyFancyOwnFunctionality\",\n revision: 1,\n\n attributes: {\n /** My fancy attribute */\n myFancyValue: Attribute(0x0, TlvNullable(TlvInt16)),\n },\n\n commands: {\n /** My fancy command */\n myFancyCommand: Command(0x1, TlvMyFancyCommandRequest, 0x2, TlvMyFancyCommandResponse),\n },\n\n events: {\n /** My fancy event */\n myFancyEvent: Event(0x5, EventPriority.Info, TlvMyFancyEvent),\n },\n });\n\n /**\n * My Fancy Cluster\n *\n * This cluster provides an interface to some fancy custom functions.\n */\n export interface Cluster extends Identity<typeof ClusterInstance> {}\n\n export const Cluster: Cluster = ClusterInstance;\n\n export const Complete = Cluster;\n}\n\nexport type MyFancyOwnFunctionalityCluster = MyFancyOwnFunctionality.Cluster;\nexport const MyFancyOwnFunctionalityCluster = MyFancyOwnFunctionality.Cluster;\nClusterRegistry.register(MyFancyOwnFunctionality.Complete);\n\n/**\n * matter.js Model Schema for the cluster, need to match with the Tlv Schema above.\n * See more details in packages/matter.js/behavior/definitions/*\n */\nconst MyFancySchema = ClusterElement({\n name: \"MyFancyOwnFunctionality\",\n id: myFancyClusterId,\n classification: \"application\",\n description: \"My Fancy Functionality\",\n\n children: [\n AttributeElement({ name: \"ClusterRevision\", id: 0xfffd, type: \"ClusterRevision\", default: 1 }),\n\n AttributeElement({\n name: \"MyFancyValue\",\n id: 0x0,\n type: \"int16\",\n access: \"R V\",\n conformance: \"M\",\n quality: \"X\",\n }),\n\n CommandElement({\n name: \"MyFancyCommand\",\n id: 0x1,\n access: \"O\",\n conformance: \"M\",\n direction: \"request\",\n response: \"MyFancyCommandResponse\",\n\n children: [FieldElement({ name: \"value\", id: 0x0, type: \"string\", conformance: \"M\" })],\n }),\n CommandElement({\n name: \"MyFancyCommandResponse\",\n id: 0x2,\n conformance: \"M\",\n direction: \"request\",\n\n children: [FieldElement({ name: \"response\", id: 0x0, type: \"string\", conformance: \"M\" })],\n }),\n\n EventElement({\n name: \"MyFancyEvent\",\n id: 0x5,\n access: \"V\",\n conformance: \"O\",\n priority: \"info\",\n children: [\n FieldElement({\n name: \"EventValue\",\n id: 0x0,\n type: \"string\",\n conformance: \"M\",\n }),\n ],\n }),\n ],\n});\n\n/**\n * Interface definitions - exposes the Implementation interface for the cluster and some types to be used in the\n * cluster implementations.\n */\nexport type MyFancyCommandRequest = TypeFromSchema<typeof MyFancyOwnFunctionality.TlvMyFancyCommandRequest>;\nexport type MyFancyCommandResponse = TypeFromSchema<typeof MyFancyOwnFunctionality.TlvMyFancyCommandResponse>;\nexport type MyFancyEvent = TypeFromSchema<typeof MyFancyOwnFunctionality.TlvMyFancyEvent>;\n\nexport namespace MyFancyOwnFunctionalityInterface {\n export interface Base {\n myFancyCommand(request: MyFancyCommandRequest): MaybePromise<MyFancyCommandResponse>;\n }\n}\n\nexport type MyFancyOwnFunctionalityInterface = {\n components: [{ flags: {}; methods: MyFancyOwnFunctionalityInterface.Base }];\n};\n\n/**\n * Behavior definition for the cluster command handler implementation\n */\nexport const MyFancyOwnFunctionalityBehavior = ClusterBehavior.withInterface<MyFancyOwnFunctionalityInterface>().for(\n MyFancyOwnFunctionality.Cluster,\n new ClusterModel(MyFancySchema),\n);\n\ntype MyFancyOwnFunctionalityBehaviorType = InstanceType<typeof MyFancyOwnFunctionalityBehavior>;\nexport interface TemperatureMeasurementBehavior extends MyFancyOwnFunctionalityBehaviorType {}\ntype StateType = InstanceType<typeof MyFancyOwnFunctionalityBehavior.State>;\nexport namespace MyFancyOwnFunctionalityBehavior {\n export interface State extends StateType {}\n}\n"],
4
+ "sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { ClusterBehavior } from \"@project-chip/matter.js/behavior/cluster\";\nimport {\n Attribute,\n ClusterRegistry,\n Command,\n Event,\n EventPriority,\n MutableCluster,\n} from \"@project-chip/matter.js/cluster\";\nimport { ClusterId, VendorId } from \"@project-chip/matter.js/datatype\";\nimport {\n AttributeElement,\n ClusterElement,\n ClusterModel,\n CommandElement,\n EventElement,\n FieldElement,\n} from \"@project-chip/matter.js/model\";\nimport { TlvField, TlvInt16, TlvNullable, TlvObject, TlvString, TypeFromSchema } from \"@project-chip/matter.js/tlv\";\nimport { Identity, MaybePromise } from \"@project-chip/matter.js/util\";\n\n/** Define the Cluster ID, custom clusters use a special extended formt that also contains the Vendor Id */\nconst myFancyClusterId = ClusterId.buildVendorSpecific(VendorId(0xfff4), 0xfc00);\n\n/**\n * Defines the Cluster on Tlv Schema level in a special namespace structure to match the official cluster\n * structures of matter.js.\n * All places that contains \"MyFancy...\" belong to the custom cluster details, all rest can be left statically like the\n * given names.\n * For more examples and usages of features in such clusters and how the code should look then check the standard\n * cluster Tlv definitions in packages/matter.js/cluster/definitions/*\n */\nexport namespace MyFancyOwnFunctionality {\n /**\n * Input to the MyFancyOwnFunctionality myFancyCommand command\n */\n export const TlvMyFancyCommandRequest = TlvObject({ value: TlvField(0, TlvString) });\n\n /**\n * Response of the MyFancyOwnFunctionality myFancyCommand command\n */\n export const TlvMyFancyCommandResponse = TlvObject({ response: TlvField(0, TlvString) });\n\n /**\n * Event for the MyFancyOwnFunctionality myFancyEvent event\n */\n export const TlvMyFancyEvent = TlvObject({ eventValue: TlvField(0, TlvString) });\n\n /**\n * @see {@link Cluster}\n */\n export const ClusterInstance = MutableCluster({\n id: myFancyClusterId,\n name: \"MyFancyOwnFunctionality\",\n revision: 1,\n\n attributes: {\n /** My fancy attribute */\n myFancyValue: Attribute(0x0, TlvNullable(TlvInt16)),\n },\n\n commands: {\n /** My fancy command */\n myFancyCommand: Command(0x1, TlvMyFancyCommandRequest, 0x2, TlvMyFancyCommandResponse),\n },\n\n events: {\n /** My fancy event */\n myFancyEvent: Event(0x5, EventPriority.Info, TlvMyFancyEvent),\n },\n });\n\n /**\n * My Fancy Cluster\n *\n * This cluster provides an interface to some fancy custom functions.\n */\n export interface Cluster extends Identity<typeof ClusterInstance> {}\n\n export const Cluster: Cluster = ClusterInstance;\n\n export const Complete = Cluster;\n}\n\nexport type MyFancyOwnFunctionalityCluster = MyFancyOwnFunctionality.Cluster;\nexport const MyFancyOwnFunctionalityCluster = MyFancyOwnFunctionality.Cluster;\nClusterRegistry.register(MyFancyOwnFunctionality.Complete);\n\n/**\n * matter.js Model Schema for the cluster, need to match with the Tlv Schema above.\n * See more details in packages/matter.js/behavior/definitions/*\n */\nconst MyFancySchema = ClusterElement({\n name: \"MyFancyOwnFunctionality\",\n id: myFancyClusterId,\n classification: \"application\",\n description: \"My Fancy Functionality\",\n\n children: [\n AttributeElement({ name: \"ClusterRevision\", id: 0xfffd, type: \"ClusterRevision\", default: 1 }),\n\n AttributeElement({\n name: \"MyFancyValue\",\n id: 0x0,\n type: \"int16\",\n access: \"R V\",\n conformance: \"M\",\n quality: \"X\",\n }),\n\n CommandElement({\n name: \"MyFancyCommand\",\n id: 0x1,\n access: \"O\",\n conformance: \"M\",\n direction: \"request\",\n response: \"MyFancyCommandResponse\",\n\n children: [FieldElement({ name: \"value\", id: 0x0, type: \"string\", conformance: \"M\" })],\n }),\n CommandElement({\n name: \"MyFancyCommandResponse\",\n id: 0x2,\n conformance: \"M\",\n direction: \"request\",\n\n children: [FieldElement({ name: \"response\", id: 0x0, type: \"string\", conformance: \"M\" })],\n }),\n\n EventElement({\n name: \"MyFancyEvent\",\n id: 0x5,\n access: \"V\",\n conformance: \"O\",\n priority: \"info\",\n children: [\n FieldElement({\n name: \"EventValue\",\n id: 0x0,\n type: \"string\",\n conformance: \"M\",\n }),\n ],\n }),\n ],\n});\n\n/**\n * Interface definitions - exposes the Implementation interface for the cluster and some types to be used in the\n * cluster implementations.\n */\nexport type MyFancyCommandRequest = TypeFromSchema<typeof MyFancyOwnFunctionality.TlvMyFancyCommandRequest>;\nexport type MyFancyCommandResponse = TypeFromSchema<typeof MyFancyOwnFunctionality.TlvMyFancyCommandResponse>;\nexport type MyFancyEvent = TypeFromSchema<typeof MyFancyOwnFunctionality.TlvMyFancyEvent>;\n\nexport namespace MyFancyOwnFunctionalityInterface {\n export interface Base {\n myFancyCommand(request: MyFancyCommandRequest): MaybePromise<MyFancyCommandResponse>;\n }\n}\n\nexport type MyFancyOwnFunctionalityInterface = {\n components: [{ flags: {}; methods: MyFancyOwnFunctionalityInterface.Base }];\n};\n\n/**\n * Behavior definition for the cluster command handler implementation\n */\nexport const MyFancyOwnFunctionalityBehavior = ClusterBehavior.withInterface<MyFancyOwnFunctionalityInterface>().for(\n MyFancyOwnFunctionality.Cluster,\n new ClusterModel(MyFancySchema),\n);\n\ntype MyFancyOwnFunctionalityBehaviorType = InstanceType<typeof MyFancyOwnFunctionalityBehavior>;\nexport interface MyFancyOwnFunctionalityBehavior extends MyFancyOwnFunctionalityBehaviorType {}\ntype StateType = InstanceType<typeof MyFancyOwnFunctionalityBehavior.State>;\nexport namespace MyFancyOwnFunctionalityBehavior {\n export interface State extends StateType {}\n}\n"],
5
5
  "mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,SAAS,uBAAuB;AAChC;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP,SAAS,WAAW,gBAAgB;AACpC;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP,SAAS,UAAU,UAAU,aAAa,WAAW,iBAAiC;AAItF,MAAM,mBAAmB,UAAU,oBAAoB,SAAS,KAAM,GAAG,KAAM;AAUxE,IAAU;AAAA,CAAV,CAAUA,6BAAV;AAII,EAAMA,yBAAA,2BAA2B,UAAU,EAAE,OAAO,SAAS,GAAG,SAAS,EAAE,CAAC;AAK5E,EAAMA,yBAAA,4BAA4B,UAAU,EAAE,UAAU,SAAS,GAAG,SAAS,EAAE,CAAC;AAKhF,EAAMA,yBAAA,kBAAkB,UAAU,EAAE,YAAY,SAAS,GAAG,SAAS,EAAE,CAAC;AAKxE,EAAMA,yBAAA,kBAAkB,eAAe;AAAA,IAC1C,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IAEV,YAAY;AAAA;AAAA,MAER,cAAc,UAAU,GAAK,YAAY,QAAQ,CAAC;AAAA,IACtD;AAAA,IAEA,UAAU;AAAA;AAAA,MAEN,gBAAgB,QAAQ,GAAKA,yBAAA,0BAA0B,GAAKA,yBAAA,yBAAyB;AAAA,IACzF;AAAA,IAEA,QAAQ;AAAA;AAAA,MAEJ,cAAc,MAAM,GAAK,cAAc,MAAMA,yBAAA,eAAe;AAAA,IAChE;AAAA,EACJ,CAAC;AASM,EAAMA,yBAAA,UAAmBA,yBAAA;AAEzB,EAAMA,yBAAA,WAAWA,yBAAA;AAAA,GAjDX;AAqDV,MAAM,iCAAiC,wBAAwB;AACtE,gBAAgB,SAAS,wBAAwB,QAAQ;AAMzD,MAAM,gBAAgB,eAAe;AAAA,EACjC,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,gBAAgB;AAAA,EAChB,aAAa;AAAA,EAEb,UAAU;AAAA,IACN,iBAAiB,EAAE,MAAM,mBAAmB,IAAI,OAAQ,MAAM,mBAAmB,SAAS,EAAE,CAAC;AAAA,IAE7F,iBAAiB;AAAA,MACb,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,SAAS;AAAA,IACb,CAAC;AAAA,IAED,eAAe;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MAEV,UAAU,CAAC,aAAa,EAAE,MAAM,SAAS,IAAI,GAAK,MAAM,UAAU,aAAa,IAAI,CAAC,CAAC;AAAA,IACzF,CAAC;AAAA,IACD,eAAe;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,WAAW;AAAA,MAEX,UAAU,CAAC,aAAa,EAAE,MAAM,YAAY,IAAI,GAAK,MAAM,UAAU,aAAa,IAAI,CAAC,CAAC;AAAA,IAC5F,CAAC;AAAA,IAED,aAAa;AAAA,MACT,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,UAAU;AAAA,MACV,UAAU;AAAA,QACN,aAAa;AAAA,UACT,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,aAAa;AAAA,QACjB,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAAA,EACL;AACJ,CAAC;AAuBM,MAAM,kCAAkC,gBAAgB,cAAgD,EAAE;AAAA,EAC7G,wBAAwB;AAAA,EACxB,IAAI,aAAa,aAAa;AAClC;",
6
6
  "names": ["MyFancyOwnFunctionality"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@project-chip/matter-node.js-examples",
3
- "version": "0.8.2-alpha.0-20240513-927b1bb5",
3
+ "version": "0.9.0",
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.4.5"
65
65
  },
66
66
  "dependencies": {
67
- "@project-chip/matter-node-ble.js": "0.8.2-alpha.0-20240513-927b1bb5",
68
- "@project-chip/matter-node.js": "0.8.2-alpha.0-20240513-927b1bb5",
69
- "@project-chip/matter.js": "0.8.2-alpha.0-20240513-927b1bb5",
70
- "@project-chip/matter.js-tools": "0.8.2-alpha.0-20240513-927b1bb5"
67
+ "@project-chip/matter-node-ble.js": "0.9.0",
68
+ "@project-chip/matter-node.js": "0.9.0",
69
+ "@project-chip/matter.js": "0.9.0",
70
+ "@project-chip/matter.js-tools": "0.9.0"
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": "b926ad590e20314be4e761c2c9916f39ca6b5d9c"
86
+ "gitHead": "676b4e34bcfdeda29851757ca279d91b10925409"
87
87
  }
@@ -7,7 +7,11 @@
7
7
  // Include this first to auto-register Crypto, Network and Time Node.js implementations
8
8
  import "@project-chip/matter-node.js";
9
9
 
10
- import { GoToLiftPercentageRequest, WindowCoveringServer } from "@project-chip/matter.js/behaviors/window-covering";
10
+ import {
11
+ MovementDirection,
12
+ MovementType,
13
+ WindowCoveringServer,
14
+ } from "@project-chip/matter.js/behaviors/window-covering";
11
15
  import { OnOffLightDevice, OnOffLightRequirements } from "@project-chip/matter.js/devices/OnOffLightDevice";
12
16
  import { WindowCoveringDevice } from "@project-chip/matter.js/devices/WindowCoveringDevice";
13
17
  import { ServerNode } from "@project-chip/matter.js/node";
@@ -22,61 +26,22 @@ const LiftingWindowCoveringServer = WindowCoveringServer.with("Lift", "AbsoluteP
22
26
 
23
27
  /**
24
28
  * Implementation of the Matter WindowCovering cluster for the shade motor.
25
- *
26
- * TODO - some of this should probably move to WindowCoveringServer
27
29
  */
28
30
  class RollerShade extends LiftingWindowCoveringServer {
29
- get currentPos() {
30
- return this.state.currentPositionLiftPercent100ths ?? 0;
31
- }
32
-
33
- get targetPos() {
34
- return this.state.targetPositionLiftPercent100ths ?? 0;
35
- }
36
-
37
- set targetPos(position: number) {
38
- this.state.targetPositionLiftPercent100ths = position ?? 0;
39
- }
40
-
41
- override async initialize() {
42
- this.reactTo(this.events.targetPositionLiftPercent100ths$Changed, this.writeTargetToMotor);
43
-
44
- await this.readTargetFromMotor();
45
- if (this.targetPos === null) {
46
- this.targetPos = this.currentPos;
47
- }
48
- }
49
-
50
- override upOrOpen() {
51
- // 0 = 0%, fully open
52
- this.targetPos = 0;
53
- }
54
-
55
- override downOrClose() {
56
- // 10000 = 100%, fully closed
57
- this.targetPos = 10000;
58
- }
59
-
60
- override stopMotion() {
61
- this.targetPos = this.currentPos;
62
- }
63
-
64
- override goToLiftPercentage(this: RollerShade, request: GoToLiftPercentageRequest) {
65
- this.targetPos = request.liftPercent100thsValue;
66
- }
67
-
68
- protected async writeTargetToMotor() {
69
- // For this contrived example we just log the target position and don't actually animate our fake roller shade
70
- console.log("Window covering target position is now", `${this.targetPos / 100}%`);
71
- }
72
-
73
- protected async readTargetFromMotor() {
74
- // Our fake shade is stuck open
75
- this.state.currentPositionLiftPercent100ths = 0;
76
- }
77
-
78
- protected set currentPos(value: number) {
79
- this.state.currentPositionLiftPercent100ths = value;
31
+ override async handleMovement(
32
+ type: MovementType,
33
+ reversed: boolean,
34
+ direction: MovementDirection,
35
+ targetPercent100ths?: number,
36
+ ) {
37
+ console.log(
38
+ "Move window shade",
39
+ direction === MovementDirection.Open ? "Open" : "Close",
40
+ targetPercent100ths !== undefined ? `${targetPercent100ths / 100}%` : "",
41
+ );
42
+
43
+ // Updates the shade position
44
+ await super.handleMovement(type, reversed, direction, targetPercent100ths);
80
45
  }
81
46
  }
82
47
 
@@ -178,7 +178,7 @@ export const MyFancyOwnFunctionalityBehavior = ClusterBehavior.withInterface<MyF
178
178
  );
179
179
 
180
180
  type MyFancyOwnFunctionalityBehaviorType = InstanceType<typeof MyFancyOwnFunctionalityBehavior>;
181
- export interface TemperatureMeasurementBehavior extends MyFancyOwnFunctionalityBehaviorType {}
181
+ export interface MyFancyOwnFunctionalityBehavior extends MyFancyOwnFunctionalityBehaviorType {}
182
182
  type StateType = InstanceType<typeof MyFancyOwnFunctionalityBehavior.State>;
183
183
  export namespace MyFancyOwnFunctionalityBehavior {
184
184
  export interface State extends StateType {}