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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 {}