@zwave-js/cc 15.1.0 → 15.1.1

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.
@@ -106,6 +106,7 @@ export declare const BatteryCCValues: Readonly<{
106
106
  is: (valueId: import("@zwave-js/core").ValueID) => boolean;
107
107
  readonly meta: {
108
108
  readonly label: "Temperature";
109
+ readonly unit: "°C";
109
110
  readonly writeable: false;
110
111
  readonly min: -128;
111
112
  readonly max: 127;
@@ -392,10 +393,10 @@ export interface BatteryCCHealthReportOptions {
392
393
  export declare class BatteryCCHealthReport extends BatteryCC {
393
394
  constructor(options: WithAddress<BatteryCCHealthReportOptions>);
394
395
  static from(raw: CCRaw, ctx: CCParsingContext): BatteryCCHealthReport;
395
- persistValues(ctx: PersistValuesContext): boolean;
396
396
  readonly maximumCapacity: number | undefined;
397
397
  readonly temperature: number | undefined;
398
398
  private readonly temperatureScale;
399
+ serialize(ctx: CCEncodingContext): Promise<Bytes>;
399
400
  toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry;
400
401
  }
401
402
  export declare class BatteryCCHealthGet extends BatteryCC {
@@ -472,19 +472,17 @@ let BatteryCCHealthReport = (() => {
472
472
  temperatureScale
473
473
  });
474
474
  }
475
- persistValues(ctx) {
476
- if (!super.persistValues(ctx))
477
- return false;
478
- const temperatureValue = import_CCValues_generated.BatteryCCValues.temperature;
479
- this.setMetadata(ctx, temperatureValue, {
480
- ...temperatureValue.meta,
481
- unit: this.temperatureScale === 0 ? "\xB0C" : void 0
482
- });
483
- return true;
484
- }
485
475
  maximumCapacity;
486
476
  temperature;
487
477
  temperatureScale;
478
+ serialize(ctx) {
479
+ const temperature = this.temperature != void 0 ? (0, import_core.encodeFloatWithScale)(this.temperature, this.temperatureScale ?? 0) : import_safe2.Bytes.from([0]);
480
+ this.payload = import_safe2.Bytes.concat([
481
+ [this.maximumCapacity ?? 255],
482
+ temperature
483
+ ]);
484
+ return super.serialize(ctx);
485
+ }
488
486
  toLogEntry(ctx) {
489
487
  return {
490
488
  ...super.toLogEntry(ctx),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cc/BatteryCC.ts"],
4
- "sourcesContent": ["import { type CCEncodingContext, type CCParsingContext } from \"@zwave-js/cc\";\nimport { type GetDeviceConfig } from \"@zwave-js/config\";\nimport {\n\ttype GetNode,\n\ttype GetSupportedCCVersion,\n\ttype GetValueDB,\n\ttype WithAddress,\n\ttimespan,\n} from \"@zwave-js/core\";\nimport type {\n\tControlsCC,\n\tEndpointId,\n\tGetEndpoint,\n\tMessageOrCCLogEntry,\n\tMessageRecord,\n\tNodeId,\n\tSinglecastCC,\n\tSupportsCC,\n} from \"@zwave-js/core/safe\";\nimport {\n\tCommandClasses,\n\ttype MaybeNotKnown,\n\tMessagePriority,\n\tValueMetadata,\n\tenumValuesToMetadataStates,\n\tparseFloatWithScale,\n\tvalidatePayload,\n} from \"@zwave-js/core/safe\";\nimport { Bytes } from \"@zwave-js/shared/safe\";\nimport { type AllOrNone, getEnumMemberName, pick } from \"@zwave-js/shared/safe\";\nimport {\n\tCCAPI,\n\tPOLL_VALUE,\n\tPhysicalCCAPI,\n\ttype PollValueImplementation,\n\tthrowUnsupportedProperty,\n} from \"../lib/API.js\";\nimport {\n\ttype CCRaw,\n\tCommandClass,\n\ttype InterviewContext,\n\ttype PersistValuesContext,\n\ttype RefreshValuesContext,\n} from \"../lib/CommandClass.js\";\nimport {\n\tAPI,\n\tCCCommand,\n\tccValueProperty,\n\tccValues,\n\tcommandClass,\n\texpectedCCResponse,\n\timplementedVersion,\n} from \"../lib/CommandClassDecorators.js\";\nimport { V } from \"../lib/Values.js\";\nimport {\n\tBatteryChargingStatus,\n\tBatteryCommand,\n\tBatteryReplacementStatus,\n} from \"../lib/_Types.js\";\nimport { NotificationCCValues } from \"./NotificationCC.js\";\n\nexport const BatteryCCValues = V.defineCCValues(CommandClasses.Battery, {\n\t...V.staticProperty(\n\t\t\"level\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyUInt8,\n\t\t\tmax: 100,\n\t\t\tunit: \"%\",\n\t\t\tlabel: \"Battery level\",\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"isLow\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Low battery level\",\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"maximumCapacity\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyUInt8,\n\t\t\tmax: 100,\n\t\t\tunit: \"%\",\n\t\t\tlabel: \"Maximum capacity\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"temperature\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyInt8,\n\t\t\tlabel: \"Temperature\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"chargingStatus\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyUInt8,\n\t\t\tlabel: \"Charging status\",\n\t\t\tstates: enumValuesToMetadataStates(BatteryChargingStatus),\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"rechargeable\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Rechargeable\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"backup\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Used as backup\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"overheating\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Overheating\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"lowFluid\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Fluid is low\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"rechargeOrReplace\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyUInt8,\n\t\t\tlabel: \"Recharge or replace\",\n\t\t\tstates: enumValuesToMetadataStates(BatteryReplacementStatus),\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"disconnected\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Battery is disconnected\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"lowTemperatureStatus\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Battery temperature is low\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 3,\n\t\t} as const,\n\t),\n});\n\n// @noSetValueAPI This CC is read-only\n\n@API(CommandClasses.Battery)\nexport class BatteryCCAPI extends PhysicalCCAPI {\n\tpublic supportsCommand(cmd: BatteryCommand): MaybeNotKnown<boolean> {\n\t\tswitch (cmd) {\n\t\t\tcase BatteryCommand.Get:\n\t\t\t\treturn true; // This is mandatory\n\t\t\tcase BatteryCommand.HealthGet:\n\t\t\t\treturn this.version >= 2;\n\t\t}\n\t\treturn super.supportsCommand(cmd);\n\t}\n\n\tprotected get [POLL_VALUE](): PollValueImplementation {\n\t\treturn async function(this: BatteryCCAPI, { property }) {\n\t\t\tswitch (property) {\n\t\t\t\tcase \"level\":\n\t\t\t\tcase \"isLow\":\n\t\t\t\tcase \"chargingStatus\":\n\t\t\t\tcase \"rechargeable\":\n\t\t\t\tcase \"backup\":\n\t\t\t\tcase \"overheating\":\n\t\t\t\tcase \"lowFluid\":\n\t\t\t\tcase \"rechargeOrReplace\":\n\t\t\t\tcase \"lowTemperatureStatus\":\n\t\t\t\tcase \"disconnected\":\n\t\t\t\t\treturn (await this.get())?.[property];\n\n\t\t\t\tcase \"maximumCapacity\":\n\t\t\t\tcase \"temperature\":\n\t\t\t\t\treturn (await this.getHealth())?.[property];\n\n\t\t\t\tdefault:\n\t\t\t\t\tthrowUnsupportedProperty(this.ccId, property);\n\t\t\t}\n\t\t};\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n\tpublic async get() {\n\t\tthis.assertSupportsCommand(BatteryCommand, BatteryCommand.Get);\n\n\t\tconst cc = new BatteryCCGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t});\n\t\tconst response = await this.host.sendCommand<BatteryCCReport>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (response) {\n\t\t\treturn pick(response, [\n\t\t\t\t\"level\",\n\t\t\t\t\"isLow\",\n\t\t\t\t\"chargingStatus\",\n\t\t\t\t\"rechargeable\",\n\t\t\t\t\"backup\",\n\t\t\t\t\"overheating\",\n\t\t\t\t\"lowFluid\",\n\t\t\t\t\"rechargeOrReplace\",\n\t\t\t\t\"lowTemperatureStatus\",\n\t\t\t\t\"disconnected\",\n\t\t\t]);\n\t\t}\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n\tpublic async getHealth() {\n\t\tthis.assertSupportsCommand(BatteryCommand, BatteryCommand.HealthGet);\n\n\t\tconst cc = new BatteryCCHealthGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t});\n\t\tconst response = await this.host.sendCommand<BatteryCCHealthReport>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (response) {\n\t\t\treturn pick(response, [\"maximumCapacity\", \"temperature\"]);\n\t\t}\n\t}\n}\n\n@commandClass(CommandClasses.Battery)\n@implementedVersion(3)\n@ccValues(BatteryCCValues)\nexport class BatteryCC extends CommandClass {\n\tdeclare ccCommand: BatteryCommand;\n\n\tpublic async interview(\n\t\tctx: InterviewContext,\n\t): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\n\t\tctx.logNode(node.id, {\n\t\t\tendpoint: this.endpointIndex,\n\t\t\tmessage: `Interviewing ${this.ccName}...`,\n\t\t\tdirection: \"none\",\n\t\t});\n\n\t\t// Query the Battery status\n\t\tawait this.refreshValues(ctx);\n\n\t\t// Remember that the interview is complete\n\t\tthis.setInterviewComplete(ctx, true);\n\t}\n\n\tpublic async refreshValues(\n\t\tctx: RefreshValuesContext,\n\t): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\t\tconst endpoint = this.getEndpoint(ctx)!;\n\t\tconst api = CCAPI.create(\n\t\t\tCommandClasses.Battery,\n\t\t\tctx,\n\t\t\tendpoint,\n\t\t).withOptions({\n\t\t\tpriority: MessagePriority.NodeQuery,\n\t\t});\n\n\t\tctx.logNode(node.id, {\n\t\t\tendpoint: this.endpointIndex,\n\t\t\tmessage: \"querying battery status...\",\n\t\t\tdirection: \"outbound\",\n\t\t});\n\n\t\tconst batteryStatus = await api.get();\n\t\tif (batteryStatus) {\n\t\t\tlet logMessage = `received response for battery information:\nlevel: ${batteryStatus.level}${\n\t\t\t\tbatteryStatus.isLow ? \" (low)\" : \"\"\n\t\t\t}`;\n\t\t\tif (api.version >= 2) {\n\t\t\t\tlogMessage += `\nstatus: ${\n\t\t\t\t\tBatteryChargingStatus[batteryStatus.chargingStatus!]\n\t\t\t\t}\nrechargeable: ${batteryStatus.rechargeable}\nis backup: ${batteryStatus.backup}\nis overheating: ${batteryStatus.overheating}\nfluid is low: ${batteryStatus.lowFluid}\nneeds to be replaced or charged: ${\n\t\t\t\t\tBatteryReplacementStatus[batteryStatus.rechargeOrReplace!]\n\t\t\t\t}\nis low temperature ${batteryStatus.lowTemperatureStatus}\nis disconnected: ${batteryStatus.disconnected}`;\n\t\t\t}\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: logMessage,\n\t\t\t\tdirection: \"inbound\",\n\t\t\t});\n\t\t}\n\n\t\tif (api.version >= 2) {\n\t\t\t// always query the health\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: \"querying battery health...\",\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\n\t\t\tconst batteryHealth = await api.getHealth();\n\t\t\tif (batteryHealth) {\n\t\t\t\tconst logMessage = `received response for battery health:\nmax. capacity: ${batteryHealth.maximumCapacity} %\ntemperature: ${batteryHealth.temperature} \u00B0C`;\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage: logMessage,\n\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic shouldRefreshValues(\n\t\tthis: SinglecastCC<this>,\n\t\tctx:\n\t\t\t& GetValueDB\n\t\t\t& GetSupportedCCVersion\n\t\t\t& GetDeviceConfig\n\t\t\t& GetNode<\n\t\t\t\tNodeId & GetEndpoint<EndpointId & SupportsCC & ControlsCC>\n\t\t\t>,\n\t): boolean {\n\t\t// Check when the battery state was last updated\n\t\tconst valueDB = ctx.tryGetValueDB(this.nodeId);\n\t\tif (!valueDB) return true;\n\n\t\tconst lastUpdated = valueDB.getTimestamp(\n\t\t\tBatteryCCValues.level.endpoint(this.endpointIndex),\n\t\t);\n\t\treturn (\n\t\t\tlastUpdated == undefined\n\t\t\t// The specs say once per month, but that's a bit too unfrequent IMO\n\t\t\t// Also the maximum that setInterval supports is ~24.85 days\n\t\t\t|| Date.now() - lastUpdated > timespan.days(7)\n\t\t);\n\t}\n}\n\n// @publicAPI\nexport type BatteryCCReportOptions =\n\t& (\n\t\t| {\n\t\t\tisLow?: false;\n\t\t\tlevel: number;\n\t\t}\n\t\t| {\n\t\t\tisLow: true;\n\t\t\tlevel?: undefined;\n\t\t}\n\t)\n\t& AllOrNone<{\n\t\t// V2+\n\t\tchargingStatus: BatteryChargingStatus;\n\t\trechargeable: boolean;\n\t\tbackup: boolean;\n\t\toverheating: boolean;\n\t\tlowFluid: boolean;\n\t\trechargeOrReplace: BatteryReplacementStatus;\n\t\tdisconnected: boolean;\n\t}>\n\t& AllOrNone<{\n\t\t// V3+\n\t\tlowTemperatureStatus: boolean;\n\t}>;\n\n@CCCommand(BatteryCommand.Report)\n@ccValueProperty(\"level\", BatteryCCValues.level)\n@ccValueProperty(\"isLow\", BatteryCCValues.isLow)\n@ccValueProperty(\"chargingStatus\", BatteryCCValues.chargingStatus)\n@ccValueProperty(\"rechargeable\", BatteryCCValues.rechargeable)\n@ccValueProperty(\"backup\", BatteryCCValues.backup)\n@ccValueProperty(\"overheating\", BatteryCCValues.overheating)\n@ccValueProperty(\"lowFluid\", BatteryCCValues.lowFluid)\n@ccValueProperty(\"rechargeOrReplace\", BatteryCCValues.rechargeOrReplace)\n@ccValueProperty(\"disconnected\", BatteryCCValues.disconnected)\n@ccValueProperty(\"lowTemperatureStatus\", BatteryCCValues.lowTemperatureStatus)\nexport class BatteryCCReport extends BatteryCC {\n\tpublic constructor(\n\t\toptions: WithAddress<BatteryCCReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.level = options.isLow ? 0 : options.level;\n\t\tthis.isLow = !!options.isLow;\n\t\tthis.chargingStatus = options.chargingStatus;\n\t\tthis.rechargeable = options.rechargeable;\n\t\tthis.backup = options.backup;\n\t\tthis.overheating = options.overheating;\n\t\tthis.lowFluid = options.lowFluid;\n\t\tthis.rechargeOrReplace = options.rechargeOrReplace;\n\t\tthis.disconnected = options.disconnected;\n\t\tthis.lowTemperatureStatus = options.lowTemperatureStatus;\n\t}\n\n\tpublic static from(raw: CCRaw, ctx: CCParsingContext): BatteryCCReport {\n\t\tlet ccOptions: BatteryCCReportOptions;\n\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst level = raw.payload[0];\n\n\t\tif (level === 0xff) {\n\t\t\tccOptions = {\n\t\t\t\tisLow: true,\n\t\t\t};\n\t\t} else {\n\t\t\tccOptions = {\n\t\t\t\tisLow: false,\n\t\t\t\tlevel,\n\t\t\t};\n\t\t}\n\n\t\tif (raw.payload.length >= 3) {\n\t\t\t// Starting with V2\n\t\t\tconst chargingStatus: BatteryChargingStatus = raw.payload[1] >>> 6;\n\t\t\tconst rechargeable = !!(raw.payload[1] & 0b0010_0000);\n\t\t\tconst backup = !!(raw.payload[1] & 0b0001_0000);\n\t\t\tconst overheating = !!(raw.payload[1] & 0b1000);\n\t\t\tconst lowFluid = !!(raw.payload[1] & 0b0100);\n\t\t\tconst rechargeOrReplace: BatteryReplacementStatus =\n\t\t\t\t!!(raw.payload[1] & 0b10)\n\t\t\t\t\t? BatteryReplacementStatus.Now\n\t\t\t\t\t: !!(raw.payload[1] & 0b1)\n\t\t\t\t\t? BatteryReplacementStatus.Soon\n\t\t\t\t\t: BatteryReplacementStatus.No;\n\t\t\tconst lowTemperatureStatus = !!(raw.payload[2] & 0b10);\n\t\t\tconst disconnected = !!(raw.payload[2] & 0b1);\n\n\t\t\tccOptions = {\n\t\t\t\t...ccOptions,\n\t\t\t\tchargingStatus,\n\t\t\t\trechargeable,\n\t\t\t\tbackup,\n\t\t\t\toverheating,\n\t\t\t\tlowFluid,\n\t\t\t\trechargeOrReplace,\n\t\t\t\tlowTemperatureStatus,\n\t\t\t\tdisconnected,\n\t\t\t};\n\t\t}\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\t...ccOptions,\n\t\t});\n\t}\n\n\tpublic persistValues(ctx: PersistValuesContext): boolean {\n\t\tif (!super.persistValues(ctx)) return false;\n\n\t\t// Na\u00EFve heuristic for a full battery\n\t\tif (this.level >= 90) {\n\t\t\t// Some devices send Notification CC Reports with battery information,\n\t\t\t// or this information is mapped from legacy V1 alarm values.\n\t\t\t// We may need to idle the corresponding values when the battery is full\n\t\t\tconst notificationCCVersion = ctx.getSupportedCCVersion(\n\t\t\t\tCommandClasses.Notification,\n\t\t\t\tthis.nodeId as number,\n\t\t\t\tthis.endpointIndex,\n\t\t\t);\n\t\t\tif (\n\t\t\t\t// supported\n\t\t\t\tnotificationCCVersion > 0\n\t\t\t\t// but idling is not required\n\t\t\t\t&& notificationCCVersion < 8\n\t\t\t) {\n\t\t\t\tconst batteryLevelStatusValue = NotificationCCValues\n\t\t\t\t\t.notificationVariable(\n\t\t\t\t\t\t\"Power Management\",\n\t\t\t\t\t\t\"Battery level status\",\n\t\t\t\t\t);\n\t\t\t\t// If not undefined and not idle\n\t\t\t\tif (this.getValue(ctx, batteryLevelStatusValue)) {\n\t\t\t\t\tthis.setValue(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\tbatteryLevelStatusValue,\n\t\t\t\t\t\t0, /* idle */\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic readonly level: number;\n\n\tpublic readonly isLow: boolean;\n\n\tpublic readonly chargingStatus: BatteryChargingStatus | undefined;\n\n\tpublic readonly rechargeable: boolean | undefined;\n\n\tpublic readonly backup: boolean | undefined;\n\n\tpublic readonly overheating: boolean | undefined;\n\n\tpublic readonly lowFluid: boolean | undefined;\n\n\tpublic readonly rechargeOrReplace: BatteryReplacementStatus | undefined;\n\n\tpublic readonly disconnected: boolean | undefined;\n\n\tpublic readonly lowTemperatureStatus: boolean | undefined;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.isLow ? 0xff : this.level]);\n\t\tif (this.chargingStatus != undefined) {\n\t\t\tthis.payload = Bytes.concat([\n\t\t\t\tthis.payload,\n\t\t\t\tBytes.from([\n\t\t\t\t\t(this.chargingStatus << 6)\n\t\t\t\t\t+ (this.rechargeable ? 0b0010_0000 : 0)\n\t\t\t\t\t+ (this.backup ? 0b0001_0000 : 0)\n\t\t\t\t\t+ (this.overheating ? 0b1000 : 0)\n\t\t\t\t\t+ (this.lowFluid ? 0b0100 : 0)\n\t\t\t\t\t+ (this.rechargeOrReplace === BatteryReplacementStatus.Now\n\t\t\t\t\t\t? 0b10\n\t\t\t\t\t\t: this.rechargeOrReplace\n\t\t\t\t\t\t\t\t=== BatteryReplacementStatus.Soon\n\t\t\t\t\t\t? 0b1\n\t\t\t\t\t\t: 0),\n\t\t\t\t\t(this.lowTemperatureStatus ? 0b10 : 0)\n\t\t\t\t\t+ (this.disconnected ? 0b1 : 0),\n\t\t\t\t]),\n\t\t\t]);\n\t\t}\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry {\n\t\tconst message: MessageRecord = {\n\t\t\tlevel: this.level,\n\t\t\t\"is low\": this.isLow,\n\t\t};\n\t\tif (this.chargingStatus != undefined) {\n\t\t\tmessage[\"charging status\"] = getEnumMemberName(\n\t\t\t\tBatteryChargingStatus,\n\t\t\t\tthis.chargingStatus,\n\t\t\t);\n\t\t}\n\t\tif (this.rechargeable != undefined) {\n\t\t\tmessage.rechargeable = this.rechargeable;\n\t\t}\n\t\tif (this.backup != undefined) {\n\t\t\tmessage.backup = this.backup;\n\t\t}\n\t\tif (this.overheating != undefined) {\n\t\t\tmessage.overheating = this.overheating;\n\t\t}\n\t\tif (this.lowFluid != undefined) {\n\t\t\tmessage[\"low fluid\"] = this.lowFluid;\n\t\t}\n\t\tif (this.rechargeOrReplace != undefined) {\n\t\t\tmessage[\"recharge or replace\"] = getEnumMemberName(\n\t\t\t\tBatteryReplacementStatus,\n\t\t\t\tthis.rechargeOrReplace,\n\t\t\t);\n\t\t}\n\t\tif (this.lowTemperatureStatus != undefined) {\n\t\t\tmessage.lowTemperatureStatus = this.lowTemperatureStatus;\n\t\t}\n\t\tif (this.disconnected != undefined) {\n\t\t\tmessage.disconnected = this.disconnected;\n\t\t}\n\t\treturn {\n\t\t\t...super.toLogEntry(ctx),\n\t\t\tmessage,\n\t\t};\n\t}\n}\n\n@CCCommand(BatteryCommand.Get)\n@expectedCCResponse(BatteryCCReport)\nexport class BatteryCCGet extends BatteryCC {}\n\n// @publicAPI\nexport interface BatteryCCHealthReportOptions {\n\tmaximumCapacity?: number;\n\ttemperature?: number;\n\ttemperatureScale?: number;\n}\n\n@CCCommand(BatteryCommand.HealthReport)\n@ccValueProperty(\"maximumCapacity\", BatteryCCValues.maximumCapacity)\n@ccValueProperty(\"temperature\", BatteryCCValues.temperature)\nexport class BatteryCCHealthReport extends BatteryCC {\n\tpublic constructor(\n\t\toptions: WithAddress<BatteryCCHealthReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\t// TODO: Check implementation:\n\t\tthis.maximumCapacity = options.maximumCapacity;\n\t\tthis.temperature = options.temperature;\n\t\tthis.temperatureScale = options.temperatureScale;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): BatteryCCHealthReport {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\t// Parse maximum capacity. 0xff means unknown\n\t\tlet maximumCapacity: number | undefined = raw.payload[0];\n\t\tif (maximumCapacity === 0xff) maximumCapacity = undefined;\n\t\tconst {\n\t\t\tvalue: temperature,\n\t\t\tscale: temperatureScale,\n\t\t} = parseFloatWithScale(\n\t\t\traw.payload.subarray(1),\n\t\t\ttrue, // The temperature field may be omitted\n\t\t);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tmaximumCapacity,\n\t\t\ttemperature,\n\t\t\ttemperatureScale,\n\t\t});\n\t}\n\n\tpublic persistValues(ctx: PersistValuesContext): boolean {\n\t\tif (!super.persistValues(ctx)) return false;\n\n\t\t// Update the temperature unit in the value DB\n\t\tconst temperatureValue = BatteryCCValues.temperature;\n\t\tthis.setMetadata(ctx, temperatureValue, {\n\t\t\t...temperatureValue.meta,\n\t\t\tunit: this.temperatureScale === 0x00 ? \"\u00B0C\" : undefined,\n\t\t});\n\n\t\treturn true;\n\t}\n\n\tpublic readonly maximumCapacity: number | undefined;\n\n\tpublic readonly temperature: number | undefined;\n\n\tprivate readonly temperatureScale: number | undefined;\n\n\tpublic toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry {\n\t\treturn {\n\t\t\t...super.toLogEntry(ctx),\n\t\t\tmessage: {\n\t\t\t\ttemperature: this.temperature != undefined\n\t\t\t\t\t? this.temperature\n\t\t\t\t\t: \"unknown\",\n\t\t\t\t\"max capacity\": this.maximumCapacity != undefined\n\t\t\t\t\t? `${this.maximumCapacity} %`\n\t\t\t\t\t: \"unknown\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n@CCCommand(BatteryCommand.HealthGet)\n@expectedCCResponse(BatteryCCHealthReport)\nexport class BatteryCCHealthGet extends BatteryCC {}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { type CCEncodingContext, type CCParsingContext } from \"@zwave-js/cc\";\nimport { type GetDeviceConfig } from \"@zwave-js/config\";\nimport {\n\ttype GetNode,\n\ttype GetSupportedCCVersion,\n\ttype GetValueDB,\n\ttype WithAddress,\n\tencodeFloatWithScale,\n\ttimespan,\n} from \"@zwave-js/core\";\nimport type {\n\tControlsCC,\n\tEndpointId,\n\tGetEndpoint,\n\tMessageOrCCLogEntry,\n\tMessageRecord,\n\tNodeId,\n\tSinglecastCC,\n\tSupportsCC,\n} from \"@zwave-js/core/safe\";\nimport {\n\tCommandClasses,\n\ttype MaybeNotKnown,\n\tMessagePriority,\n\tValueMetadata,\n\tenumValuesToMetadataStates,\n\tparseFloatWithScale,\n\tvalidatePayload,\n} from \"@zwave-js/core/safe\";\nimport { Bytes } from \"@zwave-js/shared/safe\";\nimport { type AllOrNone, getEnumMemberName, pick } from \"@zwave-js/shared/safe\";\nimport {\n\tCCAPI,\n\tPOLL_VALUE,\n\tPhysicalCCAPI,\n\ttype PollValueImplementation,\n\tthrowUnsupportedProperty,\n} from \"../lib/API.js\";\nimport {\n\ttype CCRaw,\n\tCommandClass,\n\ttype InterviewContext,\n\ttype PersistValuesContext,\n\ttype RefreshValuesContext,\n} from \"../lib/CommandClass.js\";\nimport {\n\tAPI,\n\tCCCommand,\n\tccValueProperty,\n\tccValues,\n\tcommandClass,\n\texpectedCCResponse,\n\timplementedVersion,\n} from \"../lib/CommandClassDecorators.js\";\nimport { V } from \"../lib/Values.js\";\nimport {\n\tBatteryChargingStatus,\n\tBatteryCommand,\n\tBatteryReplacementStatus,\n} from \"../lib/_Types.js\";\nimport { NotificationCCValues } from \"./NotificationCC.js\";\n\nexport const BatteryCCValues = V.defineCCValues(CommandClasses.Battery, {\n\t...V.staticProperty(\n\t\t\"level\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyUInt8,\n\t\t\tmax: 100,\n\t\t\tunit: \"%\",\n\t\t\tlabel: \"Battery level\",\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"isLow\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Low battery level\",\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"maximumCapacity\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyUInt8,\n\t\t\tmax: 100,\n\t\t\tunit: \"%\",\n\t\t\tlabel: \"Maximum capacity\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"temperature\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyInt8,\n\t\t\tlabel: \"Temperature\",\n\t\t\t// For now, only \u00B0C is specified as a valid unit\n\t\t\t// If this ever changes, update the unit in persistValues on the fly\n\t\t\tunit: \"\u00B0C\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"chargingStatus\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyUInt8,\n\t\t\tlabel: \"Charging status\",\n\t\t\tstates: enumValuesToMetadataStates(BatteryChargingStatus),\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"rechargeable\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Rechargeable\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"backup\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Used as backup\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"overheating\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Overheating\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"lowFluid\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Fluid is low\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"rechargeOrReplace\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyUInt8,\n\t\t\tlabel: \"Recharge or replace\",\n\t\t\tstates: enumValuesToMetadataStates(BatteryReplacementStatus),\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"disconnected\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Battery is disconnected\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 2,\n\t\t} as const,\n\t),\n\n\t...V.staticProperty(\n\t\t\"lowTemperatureStatus\",\n\t\t{\n\t\t\t...ValueMetadata.ReadOnlyBoolean,\n\t\t\tlabel: \"Battery temperature is low\",\n\t\t} as const,\n\t\t{\n\t\t\tminVersion: 3,\n\t\t} as const,\n\t),\n});\n\n// @noSetValueAPI This CC is read-only\n\n@API(CommandClasses.Battery)\nexport class BatteryCCAPI extends PhysicalCCAPI {\n\tpublic supportsCommand(cmd: BatteryCommand): MaybeNotKnown<boolean> {\n\t\tswitch (cmd) {\n\t\t\tcase BatteryCommand.Get:\n\t\t\t\treturn true; // This is mandatory\n\t\t\tcase BatteryCommand.HealthGet:\n\t\t\t\treturn this.version >= 2;\n\t\t}\n\t\treturn super.supportsCommand(cmd);\n\t}\n\n\tprotected get [POLL_VALUE](): PollValueImplementation {\n\t\treturn async function(this: BatteryCCAPI, { property }) {\n\t\t\tswitch (property) {\n\t\t\t\tcase \"level\":\n\t\t\t\tcase \"isLow\":\n\t\t\t\tcase \"chargingStatus\":\n\t\t\t\tcase \"rechargeable\":\n\t\t\t\tcase \"backup\":\n\t\t\t\tcase \"overheating\":\n\t\t\t\tcase \"lowFluid\":\n\t\t\t\tcase \"rechargeOrReplace\":\n\t\t\t\tcase \"lowTemperatureStatus\":\n\t\t\t\tcase \"disconnected\":\n\t\t\t\t\treturn (await this.get())?.[property];\n\n\t\t\t\tcase \"maximumCapacity\":\n\t\t\t\tcase \"temperature\":\n\t\t\t\t\treturn (await this.getHealth())?.[property];\n\n\t\t\t\tdefault:\n\t\t\t\t\tthrowUnsupportedProperty(this.ccId, property);\n\t\t\t}\n\t\t};\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n\tpublic async get() {\n\t\tthis.assertSupportsCommand(BatteryCommand, BatteryCommand.Get);\n\n\t\tconst cc = new BatteryCCGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t});\n\t\tconst response = await this.host.sendCommand<BatteryCCReport>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (response) {\n\t\t\treturn pick(response, [\n\t\t\t\t\"level\",\n\t\t\t\t\"isLow\",\n\t\t\t\t\"chargingStatus\",\n\t\t\t\t\"rechargeable\",\n\t\t\t\t\"backup\",\n\t\t\t\t\"overheating\",\n\t\t\t\t\"lowFluid\",\n\t\t\t\t\"rechargeOrReplace\",\n\t\t\t\t\"lowTemperatureStatus\",\n\t\t\t\t\"disconnected\",\n\t\t\t]);\n\t\t}\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n\tpublic async getHealth() {\n\t\tthis.assertSupportsCommand(BatteryCommand, BatteryCommand.HealthGet);\n\n\t\tconst cc = new BatteryCCHealthGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t});\n\t\tconst response = await this.host.sendCommand<BatteryCCHealthReport>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (response) {\n\t\t\treturn pick(response, [\"maximumCapacity\", \"temperature\"]);\n\t\t}\n\t}\n}\n\n@commandClass(CommandClasses.Battery)\n@implementedVersion(3)\n@ccValues(BatteryCCValues)\nexport class BatteryCC extends CommandClass {\n\tdeclare ccCommand: BatteryCommand;\n\n\tpublic async interview(\n\t\tctx: InterviewContext,\n\t): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\n\t\tctx.logNode(node.id, {\n\t\t\tendpoint: this.endpointIndex,\n\t\t\tmessage: `Interviewing ${this.ccName}...`,\n\t\t\tdirection: \"none\",\n\t\t});\n\n\t\t// Query the Battery status\n\t\tawait this.refreshValues(ctx);\n\n\t\t// Remember that the interview is complete\n\t\tthis.setInterviewComplete(ctx, true);\n\t}\n\n\tpublic async refreshValues(\n\t\tctx: RefreshValuesContext,\n\t): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\t\tconst endpoint = this.getEndpoint(ctx)!;\n\t\tconst api = CCAPI.create(\n\t\t\tCommandClasses.Battery,\n\t\t\tctx,\n\t\t\tendpoint,\n\t\t).withOptions({\n\t\t\tpriority: MessagePriority.NodeQuery,\n\t\t});\n\n\t\tctx.logNode(node.id, {\n\t\t\tendpoint: this.endpointIndex,\n\t\t\tmessage: \"querying battery status...\",\n\t\t\tdirection: \"outbound\",\n\t\t});\n\n\t\tconst batteryStatus = await api.get();\n\t\tif (batteryStatus) {\n\t\t\tlet logMessage = `received response for battery information:\nlevel: ${batteryStatus.level}${\n\t\t\t\tbatteryStatus.isLow ? \" (low)\" : \"\"\n\t\t\t}`;\n\t\t\tif (api.version >= 2) {\n\t\t\t\tlogMessage += `\nstatus: ${\n\t\t\t\t\tBatteryChargingStatus[batteryStatus.chargingStatus!]\n\t\t\t\t}\nrechargeable: ${batteryStatus.rechargeable}\nis backup: ${batteryStatus.backup}\nis overheating: ${batteryStatus.overheating}\nfluid is low: ${batteryStatus.lowFluid}\nneeds to be replaced or charged: ${\n\t\t\t\t\tBatteryReplacementStatus[batteryStatus.rechargeOrReplace!]\n\t\t\t\t}\nis low temperature ${batteryStatus.lowTemperatureStatus}\nis disconnected: ${batteryStatus.disconnected}`;\n\t\t\t}\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: logMessage,\n\t\t\t\tdirection: \"inbound\",\n\t\t\t});\n\t\t}\n\n\t\tif (api.version >= 2) {\n\t\t\t// always query the health\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: \"querying battery health...\",\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\n\t\t\tconst batteryHealth = await api.getHealth();\n\t\t\tif (batteryHealth) {\n\t\t\t\tconst logMessage = `received response for battery health:\nmax. capacity: ${batteryHealth.maximumCapacity} %\ntemperature: ${batteryHealth.temperature} \u00B0C`;\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage: logMessage,\n\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic shouldRefreshValues(\n\t\tthis: SinglecastCC<this>,\n\t\tctx:\n\t\t\t& GetValueDB\n\t\t\t& GetSupportedCCVersion\n\t\t\t& GetDeviceConfig\n\t\t\t& GetNode<\n\t\t\t\tNodeId & GetEndpoint<EndpointId & SupportsCC & ControlsCC>\n\t\t\t>,\n\t): boolean {\n\t\t// Check when the battery state was last updated\n\t\tconst valueDB = ctx.tryGetValueDB(this.nodeId);\n\t\tif (!valueDB) return true;\n\n\t\tconst lastUpdated = valueDB.getTimestamp(\n\t\t\tBatteryCCValues.level.endpoint(this.endpointIndex),\n\t\t);\n\t\treturn (\n\t\t\tlastUpdated == undefined\n\t\t\t// The specs say once per month, but that's a bit too unfrequent IMO\n\t\t\t// Also the maximum that setInterval supports is ~24.85 days\n\t\t\t|| Date.now() - lastUpdated > timespan.days(7)\n\t\t);\n\t}\n}\n\n// @publicAPI\nexport type BatteryCCReportOptions =\n\t& (\n\t\t| {\n\t\t\tisLow?: false;\n\t\t\tlevel: number;\n\t\t}\n\t\t| {\n\t\t\tisLow: true;\n\t\t\tlevel?: undefined;\n\t\t}\n\t)\n\t& AllOrNone<{\n\t\t// V2+\n\t\tchargingStatus: BatteryChargingStatus;\n\t\trechargeable: boolean;\n\t\tbackup: boolean;\n\t\toverheating: boolean;\n\t\tlowFluid: boolean;\n\t\trechargeOrReplace: BatteryReplacementStatus;\n\t\tdisconnected: boolean;\n\t}>\n\t& AllOrNone<{\n\t\t// V3+\n\t\tlowTemperatureStatus: boolean;\n\t}>;\n\n@CCCommand(BatteryCommand.Report)\n@ccValueProperty(\"level\", BatteryCCValues.level)\n@ccValueProperty(\"isLow\", BatteryCCValues.isLow)\n@ccValueProperty(\"chargingStatus\", BatteryCCValues.chargingStatus)\n@ccValueProperty(\"rechargeable\", BatteryCCValues.rechargeable)\n@ccValueProperty(\"backup\", BatteryCCValues.backup)\n@ccValueProperty(\"overheating\", BatteryCCValues.overheating)\n@ccValueProperty(\"lowFluid\", BatteryCCValues.lowFluid)\n@ccValueProperty(\"rechargeOrReplace\", BatteryCCValues.rechargeOrReplace)\n@ccValueProperty(\"disconnected\", BatteryCCValues.disconnected)\n@ccValueProperty(\"lowTemperatureStatus\", BatteryCCValues.lowTemperatureStatus)\nexport class BatteryCCReport extends BatteryCC {\n\tpublic constructor(\n\t\toptions: WithAddress<BatteryCCReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.level = options.isLow ? 0 : options.level;\n\t\tthis.isLow = !!options.isLow;\n\t\tthis.chargingStatus = options.chargingStatus;\n\t\tthis.rechargeable = options.rechargeable;\n\t\tthis.backup = options.backup;\n\t\tthis.overheating = options.overheating;\n\t\tthis.lowFluid = options.lowFluid;\n\t\tthis.rechargeOrReplace = options.rechargeOrReplace;\n\t\tthis.disconnected = options.disconnected;\n\t\tthis.lowTemperatureStatus = options.lowTemperatureStatus;\n\t}\n\n\tpublic static from(raw: CCRaw, ctx: CCParsingContext): BatteryCCReport {\n\t\tlet ccOptions: BatteryCCReportOptions;\n\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst level = raw.payload[0];\n\n\t\tif (level === 0xff) {\n\t\t\tccOptions = {\n\t\t\t\tisLow: true,\n\t\t\t};\n\t\t} else {\n\t\t\tccOptions = {\n\t\t\t\tisLow: false,\n\t\t\t\tlevel,\n\t\t\t};\n\t\t}\n\n\t\tif (raw.payload.length >= 3) {\n\t\t\t// Starting with V2\n\t\t\tconst chargingStatus: BatteryChargingStatus = raw.payload[1] >>> 6;\n\t\t\tconst rechargeable = !!(raw.payload[1] & 0b0010_0000);\n\t\t\tconst backup = !!(raw.payload[1] & 0b0001_0000);\n\t\t\tconst overheating = !!(raw.payload[1] & 0b1000);\n\t\t\tconst lowFluid = !!(raw.payload[1] & 0b0100);\n\t\t\tconst rechargeOrReplace: BatteryReplacementStatus =\n\t\t\t\t!!(raw.payload[1] & 0b10)\n\t\t\t\t\t? BatteryReplacementStatus.Now\n\t\t\t\t\t: !!(raw.payload[1] & 0b1)\n\t\t\t\t\t? BatteryReplacementStatus.Soon\n\t\t\t\t\t: BatteryReplacementStatus.No;\n\t\t\tconst lowTemperatureStatus = !!(raw.payload[2] & 0b10);\n\t\t\tconst disconnected = !!(raw.payload[2] & 0b1);\n\n\t\t\tccOptions = {\n\t\t\t\t...ccOptions,\n\t\t\t\tchargingStatus,\n\t\t\t\trechargeable,\n\t\t\t\tbackup,\n\t\t\t\toverheating,\n\t\t\t\tlowFluid,\n\t\t\t\trechargeOrReplace,\n\t\t\t\tlowTemperatureStatus,\n\t\t\t\tdisconnected,\n\t\t\t};\n\t\t}\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\t...ccOptions,\n\t\t});\n\t}\n\n\tpublic persistValues(ctx: PersistValuesContext): boolean {\n\t\tif (!super.persistValues(ctx)) return false;\n\n\t\t// Na\u00EFve heuristic for a full battery\n\t\tif (this.level >= 90) {\n\t\t\t// Some devices send Notification CC Reports with battery information,\n\t\t\t// or this information is mapped from legacy V1 alarm values.\n\t\t\t// We may need to idle the corresponding values when the battery is full\n\t\t\tconst notificationCCVersion = ctx.getSupportedCCVersion(\n\t\t\t\tCommandClasses.Notification,\n\t\t\t\tthis.nodeId as number,\n\t\t\t\tthis.endpointIndex,\n\t\t\t);\n\t\t\tif (\n\t\t\t\t// supported\n\t\t\t\tnotificationCCVersion > 0\n\t\t\t\t// but idling is not required\n\t\t\t\t&& notificationCCVersion < 8\n\t\t\t) {\n\t\t\t\tconst batteryLevelStatusValue = NotificationCCValues\n\t\t\t\t\t.notificationVariable(\n\t\t\t\t\t\t\"Power Management\",\n\t\t\t\t\t\t\"Battery level status\",\n\t\t\t\t\t);\n\t\t\t\t// If not undefined and not idle\n\t\t\t\tif (this.getValue(ctx, batteryLevelStatusValue)) {\n\t\t\t\t\tthis.setValue(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\tbatteryLevelStatusValue,\n\t\t\t\t\t\t0, /* idle */\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic readonly level: number;\n\n\tpublic readonly isLow: boolean;\n\n\tpublic readonly chargingStatus: BatteryChargingStatus | undefined;\n\n\tpublic readonly rechargeable: boolean | undefined;\n\n\tpublic readonly backup: boolean | undefined;\n\n\tpublic readonly overheating: boolean | undefined;\n\n\tpublic readonly lowFluid: boolean | undefined;\n\n\tpublic readonly rechargeOrReplace: BatteryReplacementStatus | undefined;\n\n\tpublic readonly disconnected: boolean | undefined;\n\n\tpublic readonly lowTemperatureStatus: boolean | undefined;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.isLow ? 0xff : this.level]);\n\t\tif (this.chargingStatus != undefined) {\n\t\t\tthis.payload = Bytes.concat([\n\t\t\t\tthis.payload,\n\t\t\t\tBytes.from([\n\t\t\t\t\t(this.chargingStatus << 6)\n\t\t\t\t\t+ (this.rechargeable ? 0b0010_0000 : 0)\n\t\t\t\t\t+ (this.backup ? 0b0001_0000 : 0)\n\t\t\t\t\t+ (this.overheating ? 0b1000 : 0)\n\t\t\t\t\t+ (this.lowFluid ? 0b0100 : 0)\n\t\t\t\t\t+ (this.rechargeOrReplace === BatteryReplacementStatus.Now\n\t\t\t\t\t\t? 0b10\n\t\t\t\t\t\t: this.rechargeOrReplace\n\t\t\t\t\t\t\t\t=== BatteryReplacementStatus.Soon\n\t\t\t\t\t\t? 0b1\n\t\t\t\t\t\t: 0),\n\t\t\t\t\t(this.lowTemperatureStatus ? 0b10 : 0)\n\t\t\t\t\t+ (this.disconnected ? 0b1 : 0),\n\t\t\t\t]),\n\t\t\t]);\n\t\t}\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry {\n\t\tconst message: MessageRecord = {\n\t\t\tlevel: this.level,\n\t\t\t\"is low\": this.isLow,\n\t\t};\n\t\tif (this.chargingStatus != undefined) {\n\t\t\tmessage[\"charging status\"] = getEnumMemberName(\n\t\t\t\tBatteryChargingStatus,\n\t\t\t\tthis.chargingStatus,\n\t\t\t);\n\t\t}\n\t\tif (this.rechargeable != undefined) {\n\t\t\tmessage.rechargeable = this.rechargeable;\n\t\t}\n\t\tif (this.backup != undefined) {\n\t\t\tmessage.backup = this.backup;\n\t\t}\n\t\tif (this.overheating != undefined) {\n\t\t\tmessage.overheating = this.overheating;\n\t\t}\n\t\tif (this.lowFluid != undefined) {\n\t\t\tmessage[\"low fluid\"] = this.lowFluid;\n\t\t}\n\t\tif (this.rechargeOrReplace != undefined) {\n\t\t\tmessage[\"recharge or replace\"] = getEnumMemberName(\n\t\t\t\tBatteryReplacementStatus,\n\t\t\t\tthis.rechargeOrReplace,\n\t\t\t);\n\t\t}\n\t\tif (this.lowTemperatureStatus != undefined) {\n\t\t\tmessage.lowTemperatureStatus = this.lowTemperatureStatus;\n\t\t}\n\t\tif (this.disconnected != undefined) {\n\t\t\tmessage.disconnected = this.disconnected;\n\t\t}\n\t\treturn {\n\t\t\t...super.toLogEntry(ctx),\n\t\t\tmessage,\n\t\t};\n\t}\n}\n\n@CCCommand(BatteryCommand.Get)\n@expectedCCResponse(BatteryCCReport)\nexport class BatteryCCGet extends BatteryCC {}\n\n// @publicAPI\nexport interface BatteryCCHealthReportOptions {\n\tmaximumCapacity?: number;\n\ttemperature?: number;\n\ttemperatureScale?: number;\n}\n\n@CCCommand(BatteryCommand.HealthReport)\n@ccValueProperty(\"maximumCapacity\", BatteryCCValues.maximumCapacity)\n@ccValueProperty(\"temperature\", BatteryCCValues.temperature)\nexport class BatteryCCHealthReport extends BatteryCC {\n\tpublic constructor(\n\t\toptions: WithAddress<BatteryCCHealthReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\t// TODO: Check implementation:\n\t\tthis.maximumCapacity = options.maximumCapacity;\n\t\tthis.temperature = options.temperature;\n\t\tthis.temperatureScale = options.temperatureScale;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): BatteryCCHealthReport {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\t// Parse maximum capacity. 0xff means unknown\n\t\tlet maximumCapacity: number | undefined = raw.payload[0];\n\t\tif (maximumCapacity === 0xff) maximumCapacity = undefined;\n\t\tconst {\n\t\t\tvalue: temperature,\n\t\t\tscale: temperatureScale,\n\t\t} = parseFloatWithScale(\n\t\t\traw.payload.subarray(1),\n\t\t\ttrue, // The temperature field may be omitted\n\t\t);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tmaximumCapacity,\n\t\t\ttemperature,\n\t\t\ttemperatureScale,\n\t\t});\n\t}\n\n\tpublic readonly maximumCapacity: number | undefined;\n\tpublic readonly temperature: number | undefined;\n\tprivate readonly temperatureScale: number | undefined;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tconst temperature = this.temperature != undefined\n\t\t\t? encodeFloatWithScale(\n\t\t\t\tthis.temperature,\n\t\t\t\tthis.temperatureScale ?? 0x00,\n\t\t\t)\n\t\t\t// size, precision and scale must be 0 if the temperature is omitted\n\t\t\t: Bytes.from([0x00]);\n\n\t\tthis.payload = Bytes.concat([\n\t\t\t[this.maximumCapacity ?? 0xff],\n\t\t\ttemperature,\n\t\t]);\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry {\n\t\treturn {\n\t\t\t...super.toLogEntry(ctx),\n\t\t\tmessage: {\n\t\t\t\ttemperature: this.temperature != undefined\n\t\t\t\t\t? this.temperature\n\t\t\t\t\t: \"unknown\",\n\t\t\t\t\"max capacity\": this.maximumCapacity != undefined\n\t\t\t\t\t? `${this.maximumCapacity} %`\n\t\t\t\t\t: \"unknown\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n@CCCommand(BatteryCommand.HealthGet)\n@expectedCCResponse(BatteryCCHealthReport)\nexport class BatteryCCHealthGet extends BatteryCC {}\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_safe"]
7
7
  }
@@ -17,6 +17,7 @@ export declare class ManufacturerProprietaryCCAPI extends CCAPI {
17
17
  export interface ManufacturerProprietaryCCOptions {
18
18
  manufacturerId?: number;
19
19
  unspecifiedExpectsResponse?: boolean;
20
+ payload?: Uint8Array;
20
21
  }
21
22
  export declare class ManufacturerProprietaryCC extends CommandClass {
22
23
  ccCommand: undefined;
@@ -185,12 +185,14 @@ let ManufacturerProprietaryCC = (() => {
185
185
  (0, import_safe.validatePayload)(raw.payload.length >= 1);
186
186
  const manufacturerId = raw.payload.readUInt16BE(0);
187
187
  const PCConstructor = (0, import_Decorators.getManufacturerProprietaryCCConstructor)(manufacturerId);
188
+ const payload = raw.payload.subarray(2);
188
189
  if (PCConstructor) {
189
- return PCConstructor.from(raw.withPayload(raw.payload.subarray(2)), ctx);
190
+ return PCConstructor.from(raw.withPayload(payload), ctx);
190
191
  }
191
192
  return new ManufacturerProprietaryCC2({
192
193
  nodeId: ctx.sourceNodeId,
193
- manufacturerId
194
+ manufacturerId,
195
+ payload
194
196
  });
195
197
  }
196
198
  manufacturerId;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cc/ManufacturerProprietaryCC.ts"],
4
- "sourcesContent": ["import { type CCEncodingContext, type CCParsingContext } from \"@zwave-js/cc\";\nimport {\n\tCommandClasses,\n\ttype WithAddress,\n\tZWaveError,\n\tZWaveErrorCodes,\n\tvalidatePayload,\n} from \"@zwave-js/core/safe\";\nimport { Bytes } from \"@zwave-js/shared/safe\";\nimport { validateArgs } from \"@zwave-js/transformers\";\nimport { CCAPI, type CCAPIEndpoint, type CCAPIHost } from \"../lib/API.js\";\nimport {\n\ttype CCRaw,\n\tCommandClass,\n\ttype InterviewContext,\n\ttype RefreshValuesContext,\n} from \"../lib/CommandClass.js\";\nimport {\n\tAPI,\n\tcommandClass,\n\texpectedCCResponse,\n\timplementedVersion,\n} from \"../lib/CommandClassDecorators.js\";\nimport { ManufacturerSpecificCCValues } from \"./ManufacturerSpecificCC.js\";\nimport {\n\tgetManufacturerId,\n\tgetManufacturerProprietaryAPI,\n\tgetManufacturerProprietaryCCConstructor,\n} from \"./manufacturerProprietary/Decorators.js\";\n\nexport type ManufacturerProprietaryCCConstructor<\n\tT extends typeof ManufacturerProprietaryCC =\n\t\ttypeof ManufacturerProprietaryCC,\n> = T & {\n\t// I don't like the any, but we need it to support half-implemented CCs (e.g. report classes)\n\tnew (options: any): InstanceType<T>;\n};\n\n@API(CommandClasses[\"Manufacturer Proprietary\"])\nexport class ManufacturerProprietaryCCAPI extends CCAPI {\n\tpublic constructor(\n\t\thost: CCAPIHost,\n\t\tendpoint: CCAPIEndpoint,\n\t) {\n\t\tsuper(host, endpoint);\n\n\t\t// Read the manufacturer ID from Manufacturer Specific CC\n\t\tconst manufacturerId = this.getValueDB().getValue<number>(\n\t\t\tManufacturerSpecificCCValues.manufacturerId.id,\n\t\t);\n\t\t// If possible, try to defer to a specific subclass of this API\n\t\tif (manufacturerId != undefined) {\n\t\t\tconst SpecificAPIConstructor = getManufacturerProprietaryAPI(\n\t\t\t\tmanufacturerId,\n\t\t\t);\n\t\t\tif (\n\t\t\t\tSpecificAPIConstructor != undefined\n\t\t\t\t&& new.target !== SpecificAPIConstructor\n\t\t\t) {\n\t\t\t\treturn new SpecificAPIConstructor(host, endpoint);\n\t\t\t}\n\t\t}\n\t}\n\n\t@validateArgs()\n\tpublic async sendData(\n\t\tmanufacturerId: number,\n\t\tdata?: Uint8Array,\n\t): Promise<void> {\n\t\tconst cc = new ManufacturerProprietaryCC({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tmanufacturerId,\n\t\t});\n\t\tcc.payload = data ? Bytes.view(data) : new Bytes();\n\n\t\tawait this.host.sendCommand(cc, this.commandOptions);\n\t}\n\n\t@validateArgs()\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n\tpublic async sendAndReceiveData(manufacturerId: number, data?: Uint8Array) {\n\t\tconst cc = new ManufacturerProprietaryCC({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tmanufacturerId,\n\t\t\tunspecifiedExpectsResponse: true,\n\t\t});\n\t\tcc.payload = data ? Bytes.view(data) : new Bytes();\n\n\t\tconst response = await this.host.sendCommand<\n\t\t\tManufacturerProprietaryCC\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (response) {\n\t\t\treturn {\n\t\t\t\tmanufacturerId: response.manufacturerId,\n\t\t\t\tdata: response.payload,\n\t\t\t};\n\t\t}\n\t}\n}\n\n// @publicAPI\nexport interface ManufacturerProprietaryCCOptions {\n\tmanufacturerId?: number;\n\tunspecifiedExpectsResponse?: boolean;\n}\n\nfunction getReponseForManufacturerProprietary(cc: ManufacturerProprietaryCC) {\n\treturn cc.unspecifiedExpectsResponse\n\t\t? ManufacturerProprietaryCC\n\t\t: undefined;\n}\n\nfunction testResponseForManufacturerProprietaryRequest(\n\tsent: ManufacturerProprietaryCC,\n\treceived: ManufacturerProprietaryCC,\n): boolean {\n\t// We expect a Manufacturer Proprietary response that has the same manufacturer ID as the request\n\treturn sent.manufacturerId === received.manufacturerId;\n}\n\n@commandClass(CommandClasses[\"Manufacturer Proprietary\"])\n@implementedVersion(1)\n@expectedCCResponse(\n\tgetReponseForManufacturerProprietary,\n\ttestResponseForManufacturerProprietaryRequest,\n)\nexport class ManufacturerProprietaryCC extends CommandClass {\n\tdeclare ccCommand: undefined;\n\n\tpublic constructor(\n\t\toptions: WithAddress<ManufacturerProprietaryCCOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.manufacturerId = options.manufacturerId\n\t\t\t?? getManufacturerId(this);\n\t\tthis.unspecifiedExpectsResponse = options.unspecifiedExpectsResponse;\n\n\t\t// To use this CC, a manufacturer ID must exist in the value DB\n\t\t// If it doesn't, the interview procedure will throw.\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): ManufacturerProprietaryCC {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst manufacturerId = raw.payload.readUInt16BE(0);\n\t\t// Try to parse the proprietary command\n\t\tconst PCConstructor = getManufacturerProprietaryCCConstructor(\n\t\t\tmanufacturerId,\n\t\t);\n\t\tif (PCConstructor) {\n\t\t\treturn PCConstructor.from(\n\t\t\t\traw.withPayload(raw.payload.subarray(2)),\n\t\t\t\tctx,\n\t\t\t);\n\t\t}\n\n\t\treturn new ManufacturerProprietaryCC({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tmanufacturerId,\n\t\t});\n\t}\n\n\tpublic manufacturerId?: number;\n\n\t/**\n\t * @internal\n\t * This is used to indicate that an unspecified Manufacturer Proprietary CC instance expects a response.\n\t * Subclasses should roll their own `@expectedCCResponse` instead.\n\t */\n\tpublic readonly unspecifiedExpectsResponse?: boolean;\n\n\tprivate getManufacturerIdOrThrow(): number {\n\t\tif (this.manufacturerId == undefined) {\n\t\t\tthrow new ZWaveError(\n\t\t\t\t`To use an instance of ManufacturerProprietaryCC, the manufacturer ID must be stored in the value DB`,\n\t\t\t\tZWaveErrorCodes.ManufacturerProprietaryCC_NoManufacturerId,\n\t\t\t);\n\t\t}\n\t\treturn this.manufacturerId;\n\t}\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tconst manufacturerId = this.getManufacturerIdOrThrow();\n\t\t// ManufacturerProprietaryCC has no CC command, so the first byte\n\t\t// is stored in ccCommand\n\t\t(this.ccCommand as unknown as number) = (manufacturerId >>> 8) & 0xff;\n\t\t// The 2nd byte is in the payload\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([\n\t\t\t\t// 2nd byte of manufacturerId\n\t\t\t\tmanufacturerId & 0xff,\n\t\t\t]),\n\t\t\tthis.payload,\n\t\t]);\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic createSpecificInstance(): ManufacturerProprietaryCC | undefined {\n\t\t// Try to defer to the correct subclass\n\t\tif (this.manufacturerId != undefined) {\n\t\t\tconst PCConstructor = getManufacturerProprietaryCCConstructor(\n\t\t\t\tthis.manufacturerId,\n\t\t\t);\n\t\t\tif (PCConstructor) {\n\t\t\t\treturn new PCConstructor({\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async interview(\n\t\tctx: InterviewContext,\n\t): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\n\t\t// Read the manufacturer ID from Manufacturer Specific CC\n\t\tthis.manufacturerId = this.getValue(\n\t\t\tctx,\n\t\t\tManufacturerSpecificCCValues.manufacturerId,\n\t\t)!;\n\t\tconst pcInstance = this.createSpecificInstance();\n\t\tif (pcInstance) {\n\t\t\tawait pcInstance.interview(ctx);\n\t\t} else {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tmessage:\n\t\t\t\t\t`${this.constructor.name}: skipping interview refresh because the matching proprietary CC is not implemented...`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t}\n\n\t\t// Remember that the interview is complete\n\t\tthis.setInterviewComplete(ctx, true);\n\t}\n\n\tpublic async refreshValues(\n\t\tctx: RefreshValuesContext,\n\t): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\n\t\tif (this.manufacturerId == undefined) {\n\t\t\t// Read the manufacturer ID from Manufacturer Specific CC\n\t\t\tthis.manufacturerId = this.getValue(\n\t\t\t\tctx,\n\t\t\t\tManufacturerSpecificCCValues.manufacturerId,\n\t\t\t)!;\n\t\t}\n\t\tconst pcInstance = this.createSpecificInstance();\n\t\tif (pcInstance) {\n\t\t\tawait pcInstance.refreshValues(ctx);\n\t\t} else {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tmessage:\n\t\t\t\t\t`${this.constructor.name}: skipping value refresh because the matching proprietary CC is not implemented...`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t}\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { type CCEncodingContext, type CCParsingContext } from \"@zwave-js/cc\";\nimport {\n\tCommandClasses,\n\ttype WithAddress,\n\tZWaveError,\n\tZWaveErrorCodes,\n\tvalidatePayload,\n} from \"@zwave-js/core/safe\";\nimport { Bytes } from \"@zwave-js/shared/safe\";\nimport { validateArgs } from \"@zwave-js/transformers\";\nimport { CCAPI, type CCAPIEndpoint, type CCAPIHost } from \"../lib/API.js\";\nimport {\n\ttype CCRaw,\n\tCommandClass,\n\ttype InterviewContext,\n\ttype RefreshValuesContext,\n} from \"../lib/CommandClass.js\";\nimport {\n\tAPI,\n\tcommandClass,\n\texpectedCCResponse,\n\timplementedVersion,\n} from \"../lib/CommandClassDecorators.js\";\nimport { ManufacturerSpecificCCValues } from \"./ManufacturerSpecificCC.js\";\nimport {\n\tgetManufacturerId,\n\tgetManufacturerProprietaryAPI,\n\tgetManufacturerProprietaryCCConstructor,\n} from \"./manufacturerProprietary/Decorators.js\";\n\nexport type ManufacturerProprietaryCCConstructor<\n\tT extends typeof ManufacturerProprietaryCC =\n\t\ttypeof ManufacturerProprietaryCC,\n> = T & {\n\t// I don't like the any, but we need it to support half-implemented CCs (e.g. report classes)\n\tnew (options: any): InstanceType<T>;\n};\n\n@API(CommandClasses[\"Manufacturer Proprietary\"])\nexport class ManufacturerProprietaryCCAPI extends CCAPI {\n\tpublic constructor(\n\t\thost: CCAPIHost,\n\t\tendpoint: CCAPIEndpoint,\n\t) {\n\t\tsuper(host, endpoint);\n\n\t\t// Read the manufacturer ID from Manufacturer Specific CC\n\t\tconst manufacturerId = this.getValueDB().getValue<number>(\n\t\t\tManufacturerSpecificCCValues.manufacturerId.id,\n\t\t);\n\t\t// If possible, try to defer to a specific subclass of this API\n\t\tif (manufacturerId != undefined) {\n\t\t\tconst SpecificAPIConstructor = getManufacturerProprietaryAPI(\n\t\t\t\tmanufacturerId,\n\t\t\t);\n\t\t\tif (\n\t\t\t\tSpecificAPIConstructor != undefined\n\t\t\t\t&& new.target !== SpecificAPIConstructor\n\t\t\t) {\n\t\t\t\treturn new SpecificAPIConstructor(host, endpoint);\n\t\t\t}\n\t\t}\n\t}\n\n\t@validateArgs()\n\tpublic async sendData(\n\t\tmanufacturerId: number,\n\t\tdata?: Uint8Array,\n\t): Promise<void> {\n\t\tconst cc = new ManufacturerProprietaryCC({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tmanufacturerId,\n\t\t});\n\t\tcc.payload = data ? Bytes.view(data) : new Bytes();\n\n\t\tawait this.host.sendCommand(cc, this.commandOptions);\n\t}\n\n\t@validateArgs()\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n\tpublic async sendAndReceiveData(manufacturerId: number, data?: Uint8Array) {\n\t\tconst cc = new ManufacturerProprietaryCC({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tmanufacturerId,\n\t\t\tunspecifiedExpectsResponse: true,\n\t\t});\n\t\tcc.payload = data ? Bytes.view(data) : new Bytes();\n\n\t\tconst response = await this.host.sendCommand<\n\t\t\tManufacturerProprietaryCC\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (response) {\n\t\t\treturn {\n\t\t\t\tmanufacturerId: response.manufacturerId,\n\t\t\t\tdata: response.payload,\n\t\t\t};\n\t\t}\n\t}\n}\n\n// @publicAPI\nexport interface ManufacturerProprietaryCCOptions {\n\tmanufacturerId?: number;\n\tunspecifiedExpectsResponse?: boolean;\n\t// Needed to support unknown proprietary commands\n\tpayload?: Uint8Array;\n}\n\nfunction getReponseForManufacturerProprietary(cc: ManufacturerProprietaryCC) {\n\treturn cc.unspecifiedExpectsResponse\n\t\t? ManufacturerProprietaryCC\n\t\t: undefined;\n}\n\nfunction testResponseForManufacturerProprietaryRequest(\n\tsent: ManufacturerProprietaryCC,\n\treceived: ManufacturerProprietaryCC,\n): boolean {\n\t// We expect a Manufacturer Proprietary response that has the same manufacturer ID as the request\n\treturn sent.manufacturerId === received.manufacturerId;\n}\n\n@commandClass(CommandClasses[\"Manufacturer Proprietary\"])\n@implementedVersion(1)\n@expectedCCResponse(\n\tgetReponseForManufacturerProprietary,\n\ttestResponseForManufacturerProprietaryRequest,\n)\nexport class ManufacturerProprietaryCC extends CommandClass {\n\tdeclare ccCommand: undefined;\n\n\tpublic constructor(\n\t\toptions: WithAddress<ManufacturerProprietaryCCOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.manufacturerId = options.manufacturerId\n\t\t\t?? getManufacturerId(this);\n\t\tthis.unspecifiedExpectsResponse = options.unspecifiedExpectsResponse;\n\n\t\t// To use this CC, a manufacturer ID must exist in the value DB\n\t\t// If it doesn't, the interview procedure will throw.\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): ManufacturerProprietaryCC {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst manufacturerId = raw.payload.readUInt16BE(0);\n\t\t// Try to parse the proprietary command\n\t\tconst PCConstructor = getManufacturerProprietaryCCConstructor(\n\t\t\tmanufacturerId,\n\t\t);\n\t\tconst payload = raw.payload.subarray(2);\n\t\tif (PCConstructor) {\n\t\t\treturn PCConstructor.from(\n\t\t\t\traw.withPayload(payload),\n\t\t\t\tctx,\n\t\t\t);\n\t\t}\n\n\t\treturn new ManufacturerProprietaryCC({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tmanufacturerId,\n\t\t\tpayload,\n\t\t});\n\t}\n\n\tpublic manufacturerId?: number;\n\n\t/**\n\t * @internal\n\t * This is used to indicate that an unspecified Manufacturer Proprietary CC instance expects a response.\n\t * Subclasses should roll their own `@expectedCCResponse` instead.\n\t */\n\tpublic readonly unspecifiedExpectsResponse?: boolean;\n\n\tprivate getManufacturerIdOrThrow(): number {\n\t\tif (this.manufacturerId == undefined) {\n\t\t\tthrow new ZWaveError(\n\t\t\t\t`To use an instance of ManufacturerProprietaryCC, the manufacturer ID must be stored in the value DB`,\n\t\t\t\tZWaveErrorCodes.ManufacturerProprietaryCC_NoManufacturerId,\n\t\t\t);\n\t\t}\n\t\treturn this.manufacturerId;\n\t}\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tconst manufacturerId = this.getManufacturerIdOrThrow();\n\t\t// ManufacturerProprietaryCC has no CC command, so the first byte\n\t\t// is stored in ccCommand\n\t\t(this.ccCommand as unknown as number) = (manufacturerId >>> 8) & 0xff;\n\t\t// The 2nd byte is in the payload\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([\n\t\t\t\t// 2nd byte of manufacturerId\n\t\t\t\tmanufacturerId & 0xff,\n\t\t\t]),\n\t\t\tthis.payload,\n\t\t]);\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic createSpecificInstance(): ManufacturerProprietaryCC | undefined {\n\t\t// Try to defer to the correct subclass\n\t\tif (this.manufacturerId != undefined) {\n\t\t\tconst PCConstructor = getManufacturerProprietaryCCConstructor(\n\t\t\t\tthis.manufacturerId,\n\t\t\t);\n\t\t\tif (PCConstructor) {\n\t\t\t\treturn new PCConstructor({\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async interview(\n\t\tctx: InterviewContext,\n\t): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\n\t\t// Read the manufacturer ID from Manufacturer Specific CC\n\t\tthis.manufacturerId = this.getValue(\n\t\t\tctx,\n\t\t\tManufacturerSpecificCCValues.manufacturerId,\n\t\t)!;\n\t\tconst pcInstance = this.createSpecificInstance();\n\t\tif (pcInstance) {\n\t\t\tawait pcInstance.interview(ctx);\n\t\t} else {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tmessage:\n\t\t\t\t\t`${this.constructor.name}: skipping interview refresh because the matching proprietary CC is not implemented...`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t}\n\n\t\t// Remember that the interview is complete\n\t\tthis.setInterviewComplete(ctx, true);\n\t}\n\n\tpublic async refreshValues(\n\t\tctx: RefreshValuesContext,\n\t): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\n\t\tif (this.manufacturerId == undefined) {\n\t\t\t// Read the manufacturer ID from Manufacturer Specific CC\n\t\t\tthis.manufacturerId = this.getValue(\n\t\t\t\tctx,\n\t\t\t\tManufacturerSpecificCCValues.manufacturerId,\n\t\t\t)!;\n\t\t}\n\t\tconst pcInstance = this.createSpecificInstance();\n\t\tif (pcInstance) {\n\t\t\tawait pcInstance.refreshValues(ctx);\n\t\t} else {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tmessage:\n\t\t\t\t\t`${this.constructor.name}: skipping value refresh because the matching proprietary CC is not implemented...`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t}\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_safe", "ManufacturerProprietaryCC"]
7
7
  }
@@ -367,6 +367,7 @@ export declare class MultiChannelCCV1Report extends MultiChannelCC {
367
367
  static from(raw: CCRaw, ctx: CCParsingContext): MultiChannelCCV1Report;
368
368
  readonly requestedCC: CommandClasses;
369
369
  readonly endpointCount: number;
370
+ serialize(ctx: CCEncodingContext): Promise<Bytes>;
370
371
  toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry;
371
372
  }
372
373
  export interface MultiChannelCCV1GetOptions {
@@ -374,7 +375,7 @@ export interface MultiChannelCCV1GetOptions {
374
375
  }
375
376
  export declare class MultiChannelCCV1Get extends MultiChannelCC {
376
377
  constructor(options: WithAddress<MultiChannelCCV1GetOptions>);
377
- static from(_raw: CCRaw, _ctx: CCParsingContext): MultiChannelCCV1Get;
378
+ static from(raw: CCRaw, ctx: CCParsingContext): MultiChannelCCV1Get;
378
379
  requestedCC: CommandClasses;
379
380
  serialize(ctx: CCEncodingContext): Promise<Bytes>;
380
381
  toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry;
@@ -318,6 +318,7 @@ let MultiChannelCC = (() => {
318
318
  static encapsulateV1(cc) {
319
319
  const ret = new MultiChannelCCV1CommandEncapsulation({
320
320
  nodeId: cc.nodeId,
321
+ endpointIndex: cc.endpointIndex,
321
322
  encapsulated: cc
322
323
  });
323
324
  ret.encapsulationFlags = cc.encapsulationFlags;
@@ -506,6 +507,15 @@ supported CCs:`;
506
507
  async interviewV1(ctx) {
507
508
  const node = this.getNode(ctx);
508
509
  const endpoint = this.getEndpoint(ctx);
510
+ const removeEndpoints = ctx.getDeviceConfig?.(node.id)?.compat?.removeEndpoints;
511
+ if (removeEndpoints === "*") {
512
+ ctx.logNode(node.id, {
513
+ endpoint: this.endpointIndex,
514
+ message: `Skipping ${this.ccName} interview b/c all endpoints are ignored by the device config file...`,
515
+ direction: "none"
516
+ });
517
+ return;
518
+ }
509
519
  const api = import_API.CCAPI.create(import_safe.CommandClasses["Multi Channel"], ctx, endpoint);
510
520
  const valueDB = this.getValueDB(ctx);
511
521
  const supportedCCs = [...node.getCCs()].filter(([, info]) => info.isSupported).map(([cc]) => cc).filter((cc) => !import_CommandClass.CommandClass.createInstanceUnchecked(node, cc)?.skipEndpointInterview());
@@ -529,10 +539,22 @@ supported CCs:`;
529
539
  this.setValue(ctx, import_CCValues_generated.MultiChannelCCValues.aggregatedEndpointCount, 0);
530
540
  this.setValue(ctx, import_CCValues_generated.MultiChannelCCValues.individualEndpointCount, numEndpoints);
531
541
  this.setValue(ctx, import_CCValues_generated.MultiChannelCCValues.endpointsHaveIdenticalCapabilities, false);
542
+ if (removeEndpoints?.length) {
543
+ ctx.logNode(node.id, {
544
+ endpoint: this.endpointIndex,
545
+ message: `The following endpoints are ignored through the config file: ${removeEndpoints.join(", ")}`,
546
+ direction: "none"
547
+ });
548
+ }
549
+ const allEndpoints = [];
532
550
  for (let endpoint2 = 1; endpoint2 <= numEndpoints; endpoint2++) {
533
- const endpointCCs = [...endpointCounts.entries()].filter(([, ccEndpoints]) => ccEndpoints >= endpoint2).map(([ccId]) => ccId);
534
- valueDB.setValue(import_CCValues_generated.MultiChannelCCValues.endpointCCs.endpoint(endpoint2), endpointCCs);
551
+ if (!removeEndpoints?.includes(endpoint2)) {
552
+ const endpointCCs = [...endpointCounts.entries()].filter(([, ccEndpoints]) => ccEndpoints >= endpoint2).map(([ccId]) => ccId);
553
+ valueDB.setValue(import_CCValues_generated.MultiChannelCCValues.endpointCCs.endpoint(endpoint2), endpointCCs);
554
+ allEndpoints.push(endpoint2);
555
+ }
535
556
  }
557
+ this.setValue(ctx, import_CCValues_generated.MultiChannelCCValues.endpointIndizes, allEndpoints);
536
558
  this.setInterviewComplete(ctx, true);
537
559
  }
538
560
  };
@@ -1157,6 +1179,13 @@ let MultiChannelCCV1Report = (() => {
1157
1179
  }
1158
1180
  requestedCC;
1159
1181
  endpointCount;
1182
+ serialize(ctx) {
1183
+ this.payload = import_safe2.Bytes.from([
1184
+ this.requestedCC,
1185
+ this.endpointCount
1186
+ ]);
1187
+ return super.serialize(ctx);
1188
+ }
1160
1189
  toLogEntry(ctx) {
1161
1190
  return {
1162
1191
  ...super.toLogEntry(ctx),
@@ -1197,8 +1226,13 @@ let MultiChannelCCV1Get = (() => {
1197
1226
  super(options);
1198
1227
  this.requestedCC = options.requestedCC;
1199
1228
  }
1200
- static from(_raw, _ctx) {
1201
- throw new import_safe.ZWaveError(`${this.name}: deserialization not implemented`, import_safe.ZWaveErrorCodes.Deserialization_NotImplemented);
1229
+ static from(raw, ctx) {
1230
+ (0, import_safe.validatePayload)(raw.payload.length === 1);
1231
+ const requestedCC = raw.payload[0];
1232
+ return new this({
1233
+ nodeId: ctx.sourceNodeId,
1234
+ requestedCC
1235
+ });
1202
1236
  }
1203
1237
  requestedCC;
1204
1238
  serialize(ctx) {
@@ -1250,7 +1284,21 @@ let MultiChannelCCV1CommandEncapsulation = (() => {
1250
1284
  constructor(options) {
1251
1285
  super(options);
1252
1286
  this.encapsulated = options.encapsulated;
1253
- this.endpointIndex = this.encapsulated.endpointIndex;
1287
+ this.encapsulated.encapsulatingCC = this;
1288
+ let cur = this;
1289
+ while (cur) {
1290
+ if ((0, import_EncapsulatingCommandClass.isMultiEncapsulatingCommandClass)(cur)) {
1291
+ for (const cc of cur.encapsulated) {
1292
+ cc.endpointIndex = this.endpointIndex;
1293
+ }
1294
+ break;
1295
+ } else if ((0, import_EncapsulatingCommandClass.isEncapsulatingCommandClass)(cur)) {
1296
+ cur.encapsulated.endpointIndex = this.endpointIndex;
1297
+ cur = cur.encapsulated;
1298
+ } else {
1299
+ break;
1300
+ }
1301
+ }
1254
1302
  }
1255
1303
  static async from(raw, ctx) {
1256
1304
  (0, import_safe.validatePayload)(raw.payload.length >= 1);