@zwave-js/cc 15.15.3 → 15.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/cc/AlarmSensorCC.js +1 -1
- package/build/cjs/cc/AlarmSensorCC.js.map +1 -1
- package/build/cjs/cc/ApplicationStatusCC.d.ts +33 -0
- package/build/cjs/cc/ApplicationStatusCC.js +229 -0
- package/build/cjs/cc/ApplicationStatusCC.js.map +7 -0
- package/build/cjs/cc/AssociationCC.js.map +1 -1
- package/build/cjs/cc/AssociationGroupInfoCC.js +4 -4
- package/build/cjs/cc/AssociationGroupInfoCC.js.map +2 -2
- package/build/cjs/cc/BarrierOperatorCC.js +9 -2
- package/build/cjs/cc/BarrierOperatorCC.js.map +2 -2
- package/build/cjs/cc/BasicCC.js +1 -1
- package/build/cjs/cc/BasicCC.js.map +1 -1
- package/build/cjs/cc/BatteryCC.js +6 -2
- package/build/cjs/cc/BatteryCC.js.map +2 -2
- package/build/cjs/cc/BinarySwitchCC.js +1 -1
- package/build/cjs/cc/BinarySwitchCC.js.map +1 -1
- package/build/cjs/cc/CRC16CC.js +2 -2
- package/build/cjs/cc/CRC16CC.js.map +2 -2
- package/build/cjs/cc/CentralSceneCC.js +2 -2
- package/build/cjs/cc/CentralSceneCC.js.map +1 -1
- package/build/cjs/cc/ClimateControlScheduleCC.js +5 -5
- package/build/cjs/cc/ClimateControlScheduleCC.js.map +2 -2
- package/build/cjs/cc/ClockCC.js +1 -1
- package/build/cjs/cc/ClockCC.js.map +1 -1
- package/build/cjs/cc/ColorSwitchCC.js.map +1 -1
- package/build/cjs/cc/ConfigurationCC.d.ts +6 -0
- package/build/cjs/cc/ConfigurationCC.js +52 -4
- package/build/cjs/cc/ConfigurationCC.js.map +2 -2
- package/build/cjs/cc/DoorLockCC.js +3 -3
- package/build/cjs/cc/DoorLockCC.js.map +1 -1
- package/build/cjs/cc/EntryControlCC.d.ts +2 -2
- package/build/cjs/cc/EntryControlCC.js +3 -3
- package/build/cjs/cc/EntryControlCC.js.map +2 -2
- package/build/cjs/cc/FirmwareUpdateMetaDataCC.d.ts +4 -4
- package/build/cjs/cc/FirmwareUpdateMetaDataCC.js.map +2 -2
- package/build/cjs/cc/IndicatorCC.js +5 -5
- package/build/cjs/cc/IndicatorCC.js.map +2 -2
- package/build/cjs/cc/IrrigationCC.js +3 -3
- package/build/cjs/cc/IrrigationCC.js.map +1 -1
- package/build/cjs/cc/LanguageCC.js +1 -1
- package/build/cjs/cc/LanguageCC.js.map +1 -1
- package/build/cjs/cc/ManufacturerProprietaryCC.d.ts +4 -4
- package/build/cjs/cc/ManufacturerProprietaryCC.js +1 -1
- package/build/cjs/cc/ManufacturerProprietaryCC.js.map +2 -2
- package/build/cjs/cc/ManufacturerSpecificCC.js +1 -1
- package/build/cjs/cc/ManufacturerSpecificCC.js.map +1 -1
- package/build/cjs/cc/MeterCC.js +3 -3
- package/build/cjs/cc/MeterCC.js.map +2 -2
- package/build/cjs/cc/MultiChannelAssociationCC.js.map +2 -2
- package/build/cjs/cc/MultiChannelCC.js +8 -8
- package/build/cjs/cc/MultiChannelCC.js.map +2 -2
- package/build/cjs/cc/MultilevelSensorCC.js.map +1 -1
- package/build/cjs/cc/MultilevelSwitchCC.js +1 -1
- package/build/cjs/cc/MultilevelSwitchCC.js.map +1 -1
- package/build/cjs/cc/NodeNamingCC.js.map +2 -2
- package/build/cjs/cc/NotificationCC.d.ts +3 -3
- package/build/cjs/cc/NotificationCC.js +29 -23
- package/build/cjs/cc/NotificationCC.js.map +2 -2
- package/build/cjs/cc/ProtectionCC.js +10 -3
- package/build/cjs/cc/ProtectionCC.js.map +2 -2
- package/build/cjs/cc/SceneActuatorConfigurationCC.js +0 -1
- package/build/cjs/cc/SceneActuatorConfigurationCC.js.map +2 -2
- package/build/cjs/cc/SceneControllerConfigurationCC.js +0 -1
- package/build/cjs/cc/SceneControllerConfigurationCC.js.map +2 -2
- package/build/cjs/cc/ScheduleEntryLockCC.js +1 -1
- package/build/cjs/cc/ScheduleEntryLockCC.js.map +1 -1
- package/build/cjs/cc/Security2CC.d.ts +14 -14
- package/build/cjs/cc/Security2CC.js +6 -5
- package/build/cjs/cc/Security2CC.js.map +2 -2
- package/build/cjs/cc/SecurityCC.d.ts +10 -10
- package/build/cjs/cc/SecurityCC.js +3 -3
- package/build/cjs/cc/SecurityCC.js.map +2 -2
- package/build/cjs/cc/SoundSwitchCC.js +2 -2
- package/build/cjs/cc/SoundSwitchCC.js.map +1 -1
- package/build/cjs/cc/SupervisionCC.js +1 -1
- package/build/cjs/cc/SupervisionCC.js.map +2 -2
- package/build/cjs/cc/ThermostatFanModeCC.js +1 -1
- package/build/cjs/cc/ThermostatFanModeCC.js.map +1 -1
- package/build/cjs/cc/ThermostatFanStateCC.js +1 -1
- package/build/cjs/cc/ThermostatFanStateCC.js.map +1 -1
- package/build/cjs/cc/ThermostatModeCC.d.ts +6 -6
- package/build/cjs/cc/ThermostatModeCC.js +2 -2
- package/build/cjs/cc/ThermostatModeCC.js.map +2 -2
- package/build/cjs/cc/ThermostatSetbackCC.js +1 -1
- package/build/cjs/cc/ThermostatSetbackCC.js.map +1 -1
- package/build/cjs/cc/ThermostatSetpointCC.js.map +1 -1
- package/build/cjs/cc/TimeCC.js +2 -2
- package/build/cjs/cc/TimeCC.js.map +1 -1
- package/build/cjs/cc/TransportServiceCC.d.ts +7 -7
- package/build/cjs/cc/TransportServiceCC.js +1 -1
- package/build/cjs/cc/TransportServiceCC.js.map +2 -2
- package/build/cjs/cc/UserCodeCC.d.ts +14 -6
- package/build/cjs/cc/UserCodeCC.js +16 -4
- package/build/cjs/cc/UserCodeCC.js.map +2 -2
- package/build/cjs/cc/VersionCC.js +3 -3
- package/build/cjs/cc/VersionCC.js.map +2 -2
- package/build/cjs/cc/WakeUpCC.js +2 -2
- package/build/cjs/cc/WakeUpCC.js.map +1 -1
- package/build/cjs/cc/WindowCoveringCC.d.ts +3 -1
- package/build/cjs/cc/WindowCoveringCC.js +28 -8
- package/build/cjs/cc/WindowCoveringCC.js.map +2 -2
- package/build/cjs/cc/ZWavePlusCC.js +1 -1
- package/build/cjs/cc/ZWavePlusCC.js.map +1 -1
- package/build/cjs/cc/ZWaveProtocolCC.d.ts +3 -3
- package/build/cjs/cc/ZWaveProtocolCC.js.map +2 -2
- package/build/cjs/cc/_CCValues.generated.js.map +1 -1
- package/build/cjs/cc/index.d.ts +3 -0
- package/build/cjs/cc/index.js +8 -0
- package/build/cjs/cc/index.js.map +2 -2
- package/build/cjs/cc/manufacturerProprietary/FibaroCC.js +1 -1
- package/build/cjs/cc/manufacturerProprietary/FibaroCC.js.map +1 -1
- package/build/cjs/lib/API.d.ts +2 -0
- package/build/cjs/lib/API.js +2 -2
- package/build/cjs/lib/API.js.map +2 -2
- package/build/cjs/lib/CommandClass.d.ts +7 -7
- package/build/cjs/lib/CommandClass.js +6 -6
- package/build/cjs/lib/CommandClass.js.map +2 -2
- package/build/cjs/lib/NotificationEventPayload.d.ts +2 -1
- package/build/cjs/lib/NotificationEventPayload.js.map +2 -2
- package/build/cjs/lib/Security2/Extension.d.ts +12 -12
- package/build/cjs/lib/Security2/Extension.js.map +2 -2
- package/build/cjs/lib/_Types.d.ts +11 -1
- package/build/cjs/lib/_Types.js +15 -0
- package/build/cjs/lib/_Types.js.map +3 -3
- package/build/cjs/lib/serializers.d.ts +4 -4
- package/build/cjs/lib/serializers.js.map +2 -2
- package/build/cjs/lib/traits.d.ts +5 -0
- package/build/cjs/lib/utils.js +1 -1
- package/build/cjs/lib/utils.js.map +2 -2
- package/build/esm/cc/AlarmSensorCC.js +1 -1
- package/build/esm/cc/AlarmSensorCC.js.map +1 -1
- package/build/esm/cc/ApplicationStatusCC.d.ts +33 -0
- package/build/esm/cc/ApplicationStatusCC.d.ts.map +1 -0
- package/build/esm/cc/ApplicationStatusCC.js +175 -0
- package/build/esm/cc/ApplicationStatusCC.js.map +1 -0
- package/build/esm/cc/AssociationGroupInfoCC.d.ts.map +1 -1
- package/build/esm/cc/AssociationGroupInfoCC.js +4 -4
- package/build/esm/cc/AssociationGroupInfoCC.js.map +1 -1
- package/build/esm/cc/BarrierOperatorCC.d.ts.map +1 -1
- package/build/esm/cc/BarrierOperatorCC.js +13 -2
- package/build/esm/cc/BarrierOperatorCC.js.map +1 -1
- package/build/esm/cc/BasicCC.js +1 -1
- package/build/esm/cc/BasicCC.js.map +1 -1
- package/build/esm/cc/BatteryCC.d.ts.map +1 -1
- package/build/esm/cc/BatteryCC.js +5 -2
- package/build/esm/cc/BatteryCC.js.map +1 -1
- package/build/esm/cc/BinarySwitchCC.js +1 -1
- package/build/esm/cc/BinarySwitchCC.js.map +1 -1
- package/build/esm/cc/CRC16CC.d.ts.map +1 -1
- package/build/esm/cc/CRC16CC.js +2 -2
- package/build/esm/cc/CRC16CC.js.map +1 -1
- package/build/esm/cc/CentralSceneCC.js +2 -2
- package/build/esm/cc/CentralSceneCC.js.map +1 -1
- package/build/esm/cc/ClimateControlScheduleCC.d.ts.map +1 -1
- package/build/esm/cc/ClimateControlScheduleCC.js +5 -5
- package/build/esm/cc/ClimateControlScheduleCC.js.map +1 -1
- package/build/esm/cc/ClockCC.js +1 -1
- package/build/esm/cc/ClockCC.js.map +1 -1
- package/build/esm/cc/ConfigurationCC.d.ts +6 -0
- package/build/esm/cc/ConfigurationCC.d.ts.map +1 -1
- package/build/esm/cc/ConfigurationCC.js +65 -5
- package/build/esm/cc/ConfigurationCC.js.map +1 -1
- package/build/esm/cc/DoorLockCC.js +3 -3
- package/build/esm/cc/DoorLockCC.js.map +1 -1
- package/build/esm/cc/EntryControlCC.d.ts +2 -2
- package/build/esm/cc/EntryControlCC.d.ts.map +1 -1
- package/build/esm/cc/EntryControlCC.js +3 -3
- package/build/esm/cc/EntryControlCC.js.map +1 -1
- package/build/esm/cc/FirmwareUpdateMetaDataCC.d.ts +4 -4
- package/build/esm/cc/FirmwareUpdateMetaDataCC.d.ts.map +1 -1
- package/build/esm/cc/FirmwareUpdateMetaDataCC.js.map +1 -1
- package/build/esm/cc/IndicatorCC.d.ts.map +1 -1
- package/build/esm/cc/IndicatorCC.js +6 -6
- package/build/esm/cc/IndicatorCC.js.map +1 -1
- package/build/esm/cc/IrrigationCC.js +3 -3
- package/build/esm/cc/IrrigationCC.js.map +1 -1
- package/build/esm/cc/LanguageCC.js +1 -1
- package/build/esm/cc/LanguageCC.js.map +1 -1
- package/build/esm/cc/ManufacturerProprietaryCC.d.ts +4 -4
- package/build/esm/cc/ManufacturerProprietaryCC.d.ts.map +1 -1
- package/build/esm/cc/ManufacturerProprietaryCC.js +1 -1
- package/build/esm/cc/ManufacturerProprietaryCC.js.map +1 -1
- package/build/esm/cc/ManufacturerSpecificCC.js +1 -1
- package/build/esm/cc/ManufacturerSpecificCC.js.map +1 -1
- package/build/esm/cc/MeterCC.d.ts.map +1 -1
- package/build/esm/cc/MeterCC.js +3 -3
- package/build/esm/cc/MeterCC.js.map +1 -1
- package/build/esm/cc/MultiChannelAssociationCC.d.ts.map +1 -1
- package/build/esm/cc/MultiChannelAssociationCC.js.map +1 -1
- package/build/esm/cc/MultiChannelCC.d.ts.map +1 -1
- package/build/esm/cc/MultiChannelCC.js +8 -8
- package/build/esm/cc/MultiChannelCC.js.map +1 -1
- package/build/esm/cc/MultilevelSwitchCC.js +1 -1
- package/build/esm/cc/MultilevelSwitchCC.js.map +1 -1
- package/build/esm/cc/NodeNamingCC.d.ts.map +1 -1
- package/build/esm/cc/NodeNamingCC.js.map +1 -1
- package/build/esm/cc/NotificationCC.d.ts +3 -3
- package/build/esm/cc/NotificationCC.d.ts.map +1 -1
- package/build/esm/cc/NotificationCC.js +43 -31
- package/build/esm/cc/NotificationCC.js.map +1 -1
- package/build/esm/cc/ProtectionCC.d.ts.map +1 -1
- package/build/esm/cc/ProtectionCC.js +16 -3
- package/build/esm/cc/ProtectionCC.js.map +1 -1
- package/build/esm/cc/SceneActuatorConfigurationCC.d.ts.map +1 -1
- package/build/esm/cc/SceneActuatorConfigurationCC.js +0 -1
- package/build/esm/cc/SceneActuatorConfigurationCC.js.map +1 -1
- package/build/esm/cc/SceneControllerConfigurationCC.d.ts.map +1 -1
- package/build/esm/cc/SceneControllerConfigurationCC.js +0 -1
- package/build/esm/cc/SceneControllerConfigurationCC.js.map +1 -1
- package/build/esm/cc/ScheduleEntryLockCC.js +1 -1
- package/build/esm/cc/ScheduleEntryLockCC.js.map +1 -1
- package/build/esm/cc/Security2CC.d.ts +14 -14
- package/build/esm/cc/Security2CC.d.ts.map +1 -1
- package/build/esm/cc/Security2CC.js +7 -6
- package/build/esm/cc/Security2CC.js.map +1 -1
- package/build/esm/cc/SecurityCC.d.ts +10 -10
- package/build/esm/cc/SecurityCC.d.ts.map +1 -1
- package/build/esm/cc/SecurityCC.js +4 -4
- package/build/esm/cc/SecurityCC.js.map +1 -1
- package/build/esm/cc/SoundSwitchCC.js +2 -2
- package/build/esm/cc/SoundSwitchCC.js.map +1 -1
- package/build/esm/cc/SupervisionCC.js +1 -1
- package/build/esm/cc/SupervisionCC.js.map +1 -1
- package/build/esm/cc/ThermostatFanModeCC.js +1 -1
- package/build/esm/cc/ThermostatFanModeCC.js.map +1 -1
- package/build/esm/cc/ThermostatFanStateCC.js +1 -1
- package/build/esm/cc/ThermostatFanStateCC.js.map +1 -1
- package/build/esm/cc/ThermostatModeCC.d.ts +6 -6
- package/build/esm/cc/ThermostatModeCC.d.ts.map +1 -1
- package/build/esm/cc/ThermostatModeCC.js +3 -3
- package/build/esm/cc/ThermostatModeCC.js.map +1 -1
- package/build/esm/cc/ThermostatSetbackCC.js +1 -1
- package/build/esm/cc/ThermostatSetbackCC.js.map +1 -1
- package/build/esm/cc/TimeCC.js +2 -2
- package/build/esm/cc/TimeCC.js.map +1 -1
- package/build/esm/cc/TransportServiceCC.d.ts +7 -7
- package/build/esm/cc/TransportServiceCC.d.ts.map +1 -1
- package/build/esm/cc/TransportServiceCC.js +2 -1
- package/build/esm/cc/TransportServiceCC.js.map +1 -1
- package/build/esm/cc/UserCodeCC.d.ts +14 -6
- package/build/esm/cc/UserCodeCC.d.ts.map +1 -1
- package/build/esm/cc/UserCodeCC.js +20 -4
- package/build/esm/cc/UserCodeCC.js.map +1 -1
- package/build/esm/cc/VersionCC.d.ts.map +1 -1
- package/build/esm/cc/VersionCC.js +4 -4
- package/build/esm/cc/VersionCC.js.map +1 -1
- package/build/esm/cc/WakeUpCC.js +2 -2
- package/build/esm/cc/WakeUpCC.js.map +1 -1
- package/build/esm/cc/WindowCoveringCC.d.ts +3 -1
- package/build/esm/cc/WindowCoveringCC.d.ts.map +1 -1
- package/build/esm/cc/WindowCoveringCC.js +30 -9
- package/build/esm/cc/WindowCoveringCC.js.map +1 -1
- package/build/esm/cc/ZWavePlusCC.js +1 -1
- package/build/esm/cc/ZWavePlusCC.js.map +1 -1
- package/build/esm/cc/ZWaveProtocolCC.d.ts +3 -3
- package/build/esm/cc/ZWaveProtocolCC.d.ts.map +1 -1
- package/build/esm/cc/ZWaveProtocolCC.js.map +1 -1
- package/build/esm/cc/index.d.ts +3 -0
- package/build/esm/cc/index.d.ts.map +1 -1
- package/build/esm/cc/index.js +5 -0
- package/build/esm/cc/index.js.map +1 -1
- package/build/esm/cc/manufacturerProprietary/FibaroCC.js +1 -1
- package/build/esm/cc/manufacturerProprietary/FibaroCC.js.map +1 -1
- package/build/esm/lib/API.d.ts +2 -0
- package/build/esm/lib/API.d.ts.map +1 -1
- package/build/esm/lib/API.js +2 -2
- package/build/esm/lib/API.js.map +1 -1
- package/build/esm/lib/CommandClass.d.ts +7 -7
- package/build/esm/lib/CommandClass.d.ts.map +1 -1
- package/build/esm/lib/CommandClass.js +6 -6
- package/build/esm/lib/CommandClass.js.map +1 -1
- package/build/esm/lib/NotificationEventPayload.d.ts +2 -1
- package/build/esm/lib/NotificationEventPayload.d.ts.map +1 -1
- package/build/esm/lib/NotificationEventPayload.js.map +1 -1
- package/build/esm/lib/Security2/Extension.d.ts +12 -12
- package/build/esm/lib/Security2/Extension.d.ts.map +1 -1
- package/build/esm/lib/Security2/Extension.js +1 -1
- package/build/esm/lib/Security2/Extension.js.map +1 -1
- package/build/esm/lib/_Types.d.ts +11 -1
- package/build/esm/lib/_Types.d.ts.map +1 -1
- package/build/esm/lib/_Types.js +11 -0
- package/build/esm/lib/_Types.js.map +1 -1
- package/build/esm/lib/serializers.d.ts +4 -4
- package/build/esm/lib/serializers.d.ts.map +1 -1
- package/build/esm/lib/serializers.js.map +1 -1
- package/build/esm/lib/traits.d.ts +5 -0
- package/build/esm/lib/traits.d.ts.map +1 -1
- package/build/esm/lib/utils.js +1 -1
- package/build/esm/lib/utils.js.map +1 -1
- package/package.json +12 -13
- package/build/cjs/lib/ICommandClassContainer.d.ts +0 -2
- package/build/cjs/lib/ICommandClassContainer.js +0 -17
- package/build/cjs/lib/ICommandClassContainer.js.map +0 -7
- package/build/esm/lib/ICommandClassContainer.d.ts +0 -2
- package/build/esm/lib/ICommandClassContainer.d.ts.map +0 -1
- package/build/esm/lib/ICommandClassContainer.js +0 -2
- package/build/esm/lib/ICommandClassContainer.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cc/MultiChannelCC.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CCEncodingContext, CCParsingContext } from \"@zwave-js/cc\";\nimport {\n\ttype ApplicationNodeInformation,\n\tCommandClasses,\n\ttype GenericDeviceClass,\n\ttype GetValueDB,\n\ttype MaybeNotKnown,\n\ttype MessageOrCCLogEntry,\n\tMessagePriority,\n\ttype MessageRecord,\n\ttype SpecificDeviceClass,\n\ttype WithAddress,\n\tZWaveError,\n\tZWaveErrorCodes,\n\tencodeApplicationNodeInformation,\n\tencodeBitMask,\n\tgetCCName,\n\tgetGenericDeviceClass,\n\tgetSpecificDeviceClass,\n\tparseApplicationNodeInformation,\n\tparseBitMask,\n\tvalidatePayload,\n} from \"@zwave-js/core\";\nimport { Bytes } from \"@zwave-js/shared\";\nimport { validateArgs } from \"@zwave-js/transformers\";\nimport { distinct } from \"alcalzone-shared/arrays\";\nimport { CCAPI } from \"../lib/API.js\";\nimport {\n\ttype CCRaw,\n\tCommandClass,\n\ttype InterviewContext,\n\ttype PersistValuesContext,\n\tgetEffectiveCCVersion,\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 {\n\tisEncapsulatingCommandClass,\n\tisMultiEncapsulatingCommandClass,\n} from \"../lib/EncapsulatingCommandClass.js\";\nimport { V } from \"../lib/Values.js\";\nimport { MultiChannelCommand } from \"../lib/_Types.js\";\n\n// TODO: Handle removal reports of dynamic endpoints\n\nexport const MultiChannelCCValues = V.defineCCValues(\n\tCommandClasses[\"Multi Channel\"],\n\t{\n\t\t...V.staticProperty(\"endpointIndizes\", undefined, {\n\t\t\tinternal: true,\n\t\t\tsupportsEndpoints: false,\n\t\t}),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"individualEndpointCount\",\n\t\t\t\"individualCount\",\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\tinternal: true,\n\t\t\t\tsupportsEndpoints: false,\n\t\t\t},\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"aggregatedEndpointCount\",\n\t\t\t\"aggregatedCount\",\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\tinternal: true,\n\t\t\t\tsupportsEndpoints: false,\n\t\t\t},\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"endpointCountIsDynamic\",\n\t\t\t\"countIsDynamic\",\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\tinternal: true,\n\t\t\t\tsupportsEndpoints: false,\n\t\t\t},\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"endpointsHaveIdenticalCapabilities\",\n\t\t\t\"identicalCapabilities\",\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\tinternal: true,\n\t\t\t\tsupportsEndpoints: false,\n\t\t\t},\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"endpointCCs\",\n\t\t\t\"commandClasses\",\n\t\t\tundefined,\n\t\t\t{ internal: true },\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"endpointDeviceClass\",\n\t\t\t\"deviceClass\",\n\t\t\tundefined,\n\t\t\t{ internal: true },\n\t\t),\n\t\t...V.dynamicPropertyAndKeyWithName(\n\t\t\t\"aggregatedEndpointMembers\",\n\t\t\t\"members\",\n\t\t\t(endpointIndex: number) => endpointIndex,\n\t\t\t({ property, propertyKey }) =>\n\t\t\t\tproperty === \"members\" && typeof propertyKey === \"number\",\n\t\t\tundefined,\n\t\t\t{ internal: true },\n\t\t),\n\t},\n);\n\n// @noSetValueAPI\n\n/**\n * Many devices unnecessarily use endpoints when they could (or do) provide all functionality via the root device.\n * This function gives an estimate if this is the case (i.e. all endpoints have a different device class)\n */\nfunction areEndpointsUnnecessary(\n\tctx: GetValueDB,\n\tnodeId: number,\n\tendpointIndizes: number[],\n): boolean {\n\t// Gather all device classes\n\tconst deviceClasses = new Map<\n\t\tnumber,\n\t\t{\n\t\t\tgeneric: number;\n\t\t\tspecific: number;\n\t\t}\n\t>();\n\tfor (const endpoint of endpointIndizes) {\n\t\tconst devClassValueId = MultiChannelCCValues.endpointDeviceClass\n\t\t\t.endpoint(endpoint);\n\t\tconst deviceClass = ctx.getValueDB(nodeId).getValue<{\n\t\t\tgeneric: number;\n\t\t\tspecific: number;\n\t\t}>(devClassValueId);\n\t\tif (deviceClass) {\n\t\t\tdeviceClasses.set(endpoint, {\n\t\t\t\tgeneric: deviceClass.generic,\n\t\t\t\tspecific: deviceClass.specific,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Endpoints may be useless if all of them have different device classes\n\tconst distinctDeviceClasses = distinct(\n\t\t[...deviceClasses.values()].map(\n\t\t\t({ generic, specific }) => generic * 256 + specific,\n\t\t),\n\t);\n\tif (distinctDeviceClasses.length !== endpointIndizes.length) {\n\t\t// There are endpoints with the same device class, so they are not unnecessary\n\t\treturn false;\n\t}\n\n\t// Endpoints are necessary if more than 1 of them has a switch-type device class\n\tconst switchTypeDeviceClasses = [\n\t\t0x10, // Binary Switch\n\t\t0x11, // Multilevel Switch\n\t\t0x12, // Remote Switch\n\t\t0x13, // Toggle Switch\n\t];\n\tconst numSwitchEndpoints = [...deviceClasses.values()].filter(\n\t\t({ generic }) => switchTypeDeviceClasses.includes(generic),\n\t).length;\n\tif (numSwitchEndpoints > 1) return false;\n\n\treturn true;\n}\n\n@API(CommandClasses[\"Multi Channel\"])\nexport class MultiChannelCCAPI extends CCAPI {\n\tpublic supportsCommand(cmd: MultiChannelCommand): MaybeNotKnown<boolean> {\n\t\tswitch (cmd) {\n\t\t\t// Legacy commands:\n\t\t\tcase MultiChannelCommand.GetV1:\n\t\t\t\treturn this.isSinglecast() && this.version === 1;\n\t\t\tcase MultiChannelCommand.CommandEncapsulationV1:\n\t\t\t\treturn this.version === 1;\n\n\t\t\t// The specs start at version 3 but according to OZW,\n\t\t\t// these do seem to be supported in version 2\n\t\t\tcase MultiChannelCommand.EndPointGet:\n\t\t\tcase MultiChannelCommand.CapabilityGet:\n\t\t\t\treturn this.version >= 2 && this.isSinglecast();\n\t\t\tcase MultiChannelCommand.CommandEncapsulation:\n\t\t\t\treturn this.version >= 2;\n\t\t\tcase MultiChannelCommand.EndPointFind:\n\t\t\t\treturn this.version >= 3 && this.isSinglecast();\n\t\t\tcase MultiChannelCommand.AggregatedMembersGet:\n\t\t\t\treturn this.version >= 4 && this.isSinglecast();\n\t\t}\n\t\treturn super.supportsCommand(cmd);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n\tpublic async getEndpoints() {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.EndPointGet,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCEndPointGet({\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<\n\t\t\tMultiChannelCCEndPointReport\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\tisDynamicEndpointCount: response.countIsDynamic,\n\t\t\t\tidenticalCapabilities: response.identicalCapabilities,\n\t\t\t\tindividualEndpointCount: response.individualCount,\n\t\t\t\taggregatedEndpointCount: response.aggregatedCount,\n\t\t\t};\n\t\t}\n\t}\n\n\t@validateArgs()\n\tpublic async getEndpointCapabilities(\n\t\tendpoint: number,\n\t): Promise<MaybeNotKnown<EndpointCapability>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.CapabilityGet,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCCapabilityGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\trequestedEndpoint: endpoint,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultiChannelCCCapabilityReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (response) {\n\t\t\tconst generic = getGenericDeviceClass(\n\t\t\t\tresponse.genericDeviceClass,\n\t\t\t);\n\t\t\tconst specific = getSpecificDeviceClass(\n\t\t\t\tresponse.genericDeviceClass,\n\t\t\t\tresponse.specificDeviceClass,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tisDynamic: response.isDynamic,\n\t\t\t\twasRemoved: response.wasRemoved,\n\t\t\t\tsupportedCCs: response.supportedCCs,\n\t\t\t\tgeneric,\n\t\t\t\tspecific,\n\t\t\t};\n\t\t}\n\t}\n\n\t@validateArgs()\n\tpublic async findEndpoints(\n\t\tgenericClass: number,\n\t\tspecificClass: number,\n\t): Promise<MaybeNotKnown<readonly number[]>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.EndPointFind,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCEndPointFind({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tgenericClass,\n\t\t\tspecificClass,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultiChannelCCEndPointFindReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.foundEndpoints;\n\t}\n\n\t@validateArgs()\n\tpublic async getAggregatedMembers(\n\t\tendpoint: number,\n\t): Promise<MaybeNotKnown<readonly number[]>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.AggregatedMembersGet,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCAggregatedMembersGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\trequestedEndpoint: endpoint,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultiChannelCCAggregatedMembersReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.members;\n\t}\n\n\t// Encapsulation is used internally and too frequently that we\n\t// want to pay the cost of validating each call\n\t// eslint-disable-next-line @zwave-js/ccapi-validate-args\n\tpublic async sendEncapsulated(\n\t\toptions: MultiChannelCCCommandEncapsulationOptions,\n\t): Promise<void> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.CommandEncapsulation,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCCommandEncapsulation({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\t...options,\n\t\t});\n\t\tawait this.host.sendCommand(cc, this.commandOptions);\n\t}\n\n\t@validateArgs()\n\tpublic async getEndpointCountV1(\n\t\tccId: CommandClasses,\n\t): Promise<MaybeNotKnown<number>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.GetV1,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCV1Get({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\trequestedCC: ccId,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultiChannelCCV1Report\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.endpointCount;\n\t}\n\n\t// Encapsulation is used internally and too frequently that we\n\t// want to pay the cost of validating each call\n\t// eslint-disable-next-line @zwave-js/ccapi-validate-args\n\tpublic async sendEncapsulatedV1(encapsulated: CommandClass): Promise<void> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.CommandEncapsulationV1,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCV1CommandEncapsulation({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tencapsulated,\n\t\t});\n\t\tawait this.host.sendCommand(cc, this.commandOptions);\n\t}\n}\n\nexport interface EndpointCapability {\n\tgeneric: GenericDeviceClass;\n\tspecific: SpecificDeviceClass;\n\tsupportedCCs: CommandClasses[];\n\tisDynamic: boolean;\n\twasRemoved: boolean;\n}\n\n@commandClass(CommandClasses[\"Multi Channel\"])\n@implementedVersion(4)\n@ccValues(MultiChannelCCValues)\nexport class MultiChannelCC extends CommandClass {\n\tdeclare ccCommand: MultiChannelCommand;\n\n\t/** Tests if a command targets a specific endpoint and thus requires encapsulation */\n\tpublic static requiresEncapsulation(cc: CommandClass): boolean {\n\t\treturn (\n\t\t\tcc.endpointIndex !== 0\n\t\t\t&& !(cc instanceof MultiChannelCCCommandEncapsulation)\n\t\t\t&& !(cc instanceof MultiChannelCCV1CommandEncapsulation)\n\t\t);\n\t}\n\n\t/** Encapsulates a command that targets a specific endpoint, with version 2+ of the Multi Channel CC */\n\tpublic static encapsulate(\n\t\tcc: CommandClass,\n\t): MultiChannelCCCommandEncapsulation {\n\t\tconst ret = new MultiChannelCCCommandEncapsulation({\n\t\t\tnodeId: cc.nodeId,\n\t\t\tencapsulated: cc,\n\t\t\tdestination: cc.endpointIndex,\n\t\t});\n\n\t\t// Copy the encapsulation flags from the encapsulated command\n\t\tret.encapsulationFlags = cc.encapsulationFlags;\n\n\t\treturn ret;\n\t}\n\n\t/** Encapsulates a command that targets a specific endpoint, with version 1 of the Multi Channel CC */\n\tpublic static encapsulateV1(\n\t\tcc: CommandClass,\n\t): MultiChannelCCV1CommandEncapsulation {\n\t\tconst ret = new MultiChannelCCV1CommandEncapsulation({\n\t\t\tnodeId: cc.nodeId,\n\t\t\tendpointIndex: cc.endpointIndex,\n\t\t\tencapsulated: cc,\n\t\t});\n\n\t\t// Copy the encapsulation flags from the encapsulated command\n\t\tret.encapsulationFlags = cc.encapsulationFlags;\n\n\t\treturn ret;\n\t}\n\n\tpublic skipEndpointInterview(): boolean {\n\t\t// The endpoints are discovered by querying the root device\n\t\treturn true;\n\t}\n\n\tpublic async interview(ctx: InterviewContext): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\n\t\tconst removeEndpoints = ctx.getDeviceConfig?.(node.id)?.compat\n\t\t\t?.removeEndpoints;\n\t\tif (removeEndpoints === \"*\") {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`Skipping ${this.ccName} interview b/c all endpoints are ignored by the device config file...`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\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// Special interview procedure for legacy nodes\n\t\tconst ccVersion = getEffectiveCCVersion(ctx, this);\n\t\tif (ccVersion === 1) return this.interviewV1(ctx);\n\n\t\tconst endpoint = node.getEndpoint(this.endpointIndex)!;\n\t\tconst api = CCAPI.create(\n\t\t\tCommandClasses[\"Multi Channel\"],\n\t\t\tctx,\n\t\t\tendpoint,\n\t\t).withOptions({\n\t\t\tpriority: MessagePriority.NodeQuery,\n\t\t});\n\t\tconst valueDB = this.getValueDB(ctx);\n\n\t\t// Step 1: Retrieve general information about end points\n\t\tctx.logNode(node.id, {\n\t\t\tendpoint: this.endpointIndex,\n\t\t\tmessage: \"querying device endpoint information...\",\n\t\t\tdirection: \"outbound\",\n\t\t});\n\t\tconst multiResponse = await api.getEndpoints();\n\t\tif (!multiResponse) {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t\"Querying device endpoint information timed out, aborting interview...\",\n\t\t\t\tlevel: \"warn\",\n\t\t\t});\n\t\t\treturn this.throwMissingCriticalInterviewResponse();\n\t\t}\n\n\t\tlet logMessage = `received response for device endpoints:\nendpoint count (individual): ${multiResponse.individualEndpointCount}\ncount is dynamic: ${multiResponse.isDynamicEndpointCount}\nidentical capabilities: ${multiResponse.identicalCapabilities}`;\n\t\tif (multiResponse.aggregatedEndpointCount != undefined) {\n\t\t\tlogMessage +=\n\t\t\t\t`\\nendpoint count (aggregated): ${multiResponse.aggregatedEndpointCount}`;\n\t\t}\n\t\tctx.logNode(node.id, {\n\t\t\tendpoint: this.endpointIndex,\n\t\t\tmessage: logMessage,\n\t\t\tdirection: \"inbound\",\n\t\t});\n\n\t\tlet allEndpoints: number[] = [];\n\t\tconst addSequentialEndpoints = (): void => {\n\t\t\tfor (\n\t\t\t\tlet i = 1;\n\t\t\t\ti\n\t\t\t\t\t<= multiResponse.individualEndpointCount\n\t\t\t\t\t\t+ (multiResponse.aggregatedEndpointCount ?? 0);\n\t\t\t\ti++\n\t\t\t) {\n\t\t\t\tallEndpoints.push(i);\n\t\t\t}\n\t\t};\n\t\tif (api.supportsCommand(MultiChannelCommand.EndPointFind)) {\n\t\t\t// Step 2a: Find all endpoints\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: \"querying all endpoints...\",\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\n\t\t\tconst foundEndpoints = await api.findEndpoints(0xff, 0xff);\n\t\t\tif (foundEndpoints) allEndpoints.push(...foundEndpoints);\n\t\t\tif (!allEndpoints.length) {\n\t\t\t\t// Create a sequential list of endpoints\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Endpoint query returned no results, assuming that endpoints are sequential`,\n\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t});\n\t\t\t\taddSequentialEndpoints();\n\t\t\t} else {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage: `received endpoints: ${\n\t\t\t\t\t\tallEndpoints\n\t\t\t\t\t\t\t.map(String)\n\t\t\t\t\t\t\t.join(\", \")\n\t\t\t\t\t}`,\n\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\t// Step 2b: Assume that the endpoints are in sequential order\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`does not support EndPointFind, assuming that endpoints are sequential`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t\taddSequentialEndpoints();\n\t\t}\n\n\t\t// Step 2.5: remove ignored endpoints\n\t\tif (removeEndpoints?.length) {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`The following endpoints are ignored through the config file: ${\n\t\t\t\t\t\tremoveEndpoints.join(\", \")\n\t\t\t\t\t}`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t\tallEndpoints = allEndpoints.filter(\n\t\t\t\t(e) => !removeEndpoints.includes(e),\n\t\t\t);\n\t\t}\n\n\t\t// Step 3: Query endpoints\n\t\tlet hasQueriedCapabilities = false;\n\t\tfor (const endpoint of allEndpoints) {\n\t\t\tif (\n\t\t\t\tendpoint > multiResponse.individualEndpointCount\n\t\t\t\t&& ccVersion >= 4\n\t\t\t) {\n\t\t\t\t// Find members of aggregated end point\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`querying members of aggregated endpoint #${endpoint}...`,\n\t\t\t\t\tdirection: \"outbound\",\n\t\t\t\t});\n\t\t\t\tconst members = await api.getAggregatedMembers(endpoint);\n\t\t\t\tif (members) {\n\t\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`aggregated endpoint #${endpoint} has members ${\n\t\t\t\t\t\t\t\tmembers\n\t\t\t\t\t\t\t\t\t.map(String)\n\t\t\t\t\t\t\t\t\t.join(\", \")\n\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// When the device reports identical capabilities for all endpoints,\n\t\t\t// we don't need to query them all\n\t\t\tif (multiResponse.identicalCapabilities && hasQueriedCapabilities) {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`all endpoints identical, skipping capability query for endpoint #${endpoint}...`,\n\t\t\t\t\tdirection: \"none\",\n\t\t\t\t});\n\n\t\t\t\t// copy the capabilities from the first endpoint\n\t\t\t\tconst devClass = valueDB.getValue(\n\t\t\t\t\tMultiChannelCCValues.endpointDeviceClass.endpoint(\n\t\t\t\t\t\tallEndpoints[0],\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tvalueDB.setValue(\n\t\t\t\t\tMultiChannelCCValues.endpointDeviceClass.endpoint(endpoint),\n\t\t\t\t\tdevClass,\n\t\t\t\t);\n\t\t\t\tconst ep1Caps = valueDB.getValue<CommandClasses[]>(\n\t\t\t\t\tMultiChannelCCValues.endpointCCs.endpoint(allEndpoints[0]),\n\t\t\t\t)!;\n\t\t\t\tvalueDB.setValue(\n\t\t\t\t\tMultiChannelCCValues.endpointCCs.endpoint(endpoint),\n\t\t\t\t\t[...ep1Caps],\n\t\t\t\t);\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: `querying capabilities for endpoint #${endpoint}...`,\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\t\t\tconst caps = await api.getEndpointCapabilities(endpoint);\n\t\t\tif (caps) {\n\t\t\t\thasQueriedCapabilities = true;\n\t\t\t\tlogMessage =\n\t\t\t\t\t`received response for endpoint capabilities (#${endpoint}):\ngeneric device class: ${caps.generic.label}\nspecific device class: ${caps.specific.label}\nis dynamic end point: ${caps.isDynamic}\nsupported CCs:`;\n\t\t\t\tfor (const cc of caps.supportedCCs) {\n\t\t\t\t\tlogMessage += `\\n \u00B7 ${getCCName(cc)}`;\n\t\t\t\t}\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} else {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Querying endpoint #${endpoint} capabilities timed out, aborting interview...`,\n\t\t\t\t\tlevel: \"warn\",\n\t\t\t\t});\n\t\t\t\treturn this.throwMissingCriticalInterviewResponse();\n\t\t\t}\n\t\t}\n\n\t\t// Now that all endpoints have been interviewed, remember which ones are there\n\t\t// But first figure out if they seem unnecessary and if they do, which ones should be preserved\n\t\tif (\n\t\t\t!multiResponse.identicalCapabilities\n\t\t\t&& areEndpointsUnnecessary(ctx, node.id, allEndpoints)\n\t\t) {\n\t\t\tconst preserve = ctx.getDeviceConfig?.(node.id)?.compat\n\t\t\t\t?.preserveEndpoints;\n\t\t\tif (!preserve) {\n\t\t\t\tallEndpoints = [];\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Endpoints seem unnecessary b/c they have different device classes, ignoring all...`,\n\t\t\t\t});\n\t\t\t} else if (preserve === \"*\") {\n\t\t\t\t// preserve all endpoints, do nothing\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Endpoints seem unnecessary, but are configured to be preserved.`,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tallEndpoints = allEndpoints.filter((ep) =>\n\t\t\t\t\tpreserve.includes(ep)\n\t\t\t\t);\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tmessage: `Endpoints seem unnecessary, but endpoints ${\n\t\t\t\t\t\tallEndpoints.join(\n\t\t\t\t\t\t\t\", \",\n\t\t\t\t\t\t)\n\t\t\t\t\t} are configured to be preserved.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.endpointIndizes,\n\t\t\tallEndpoints,\n\t\t);\n\n\t\t// Remember that the interview is complete\n\t\tthis.setInterviewComplete(ctx, true);\n\t}\n\n\tprivate async interviewV1(ctx: InterviewContext): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\t\tconst endpoint = this.getEndpoint(ctx)!;\n\t\tconst removeEndpoints = ctx.getDeviceConfig?.(node.id)?.compat\n\t\t\t?.removeEndpoints;\n\t\tif (removeEndpoints === \"*\") {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`Skipping ${this.ccName} interview b/c all endpoints are ignored by the device config file...`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst api = CCAPI.create(\n\t\t\tCommandClasses[\"Multi Channel\"],\n\t\t\tctx,\n\t\t\tendpoint,\n\t\t);\n\t\tconst valueDB = this.getValueDB(ctx);\n\n\t\t// V1 works the opposite way - we scan all CCs and remember how many\n\t\t// endpoints they have\n\t\tconst supportedCCs = [...node.getCCs()]\n\t\t\t// Don't query CCs the node only controls\n\t\t\t.filter(([, info]) => info.isSupported)\n\t\t\t.map(([cc]) => cc)\n\t\t\t// Don't query CCs that want to skip the endpoint interview\n\t\t\t.filter(\n\t\t\t\t(cc) =>\n\t\t\t\t\t!CommandClass.createInstanceUnchecked(\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tcc,\n\t\t\t\t\t)?.skipEndpointInterview(),\n\t\t\t);\n\t\tconst endpointCounts = new Map<CommandClasses, number>();\n\t\tfor (const ccId of supportedCCs) {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tmessage: `Querying endpoint count for CommandClass ${\n\t\t\t\t\tgetCCName(\n\t\t\t\t\t\tccId,\n\t\t\t\t\t)\n\t\t\t\t}...`,\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\t\t\tconst endpointCount = await api.getEndpointCountV1(ccId);\n\t\t\tif (endpointCount != undefined) {\n\t\t\t\tendpointCounts.set(ccId, endpointCount);\n\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tmessage: `CommandClass ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tccId,\n\t\t\t\t\t\t)\n\t\t\t\t\t} has ${endpointCount} endpoints`,\n\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Store the collected information\n\t\t// We have only individual and no dynamic and no aggregated endpoints\n\t\tconst numEndpoints = Math.max(...endpointCounts.values());\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.endpointCountIsDynamic,\n\t\t\tfalse,\n\t\t);\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.aggregatedEndpointCount,\n\t\t\t0,\n\t\t);\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.individualEndpointCount,\n\t\t\tnumEndpoints,\n\t\t);\n\t\t// Since we queried all CCs separately, we can assume that all\n\t\t// endpoints have different capabilities\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.endpointsHaveIdenticalCapabilities,\n\t\t\tfalse,\n\t\t);\n\n\t\tif (removeEndpoints?.length) {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`The following endpoints are ignored through the config file: ${\n\t\t\t\t\t\tremoveEndpoints.join(\", \")\n\t\t\t\t\t}`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t}\n\n\t\tconst allEndpoints: number[] = [];\n\t\tfor (let endpoint = 1; endpoint <= numEndpoints; endpoint++) {\n\t\t\t// Skip this endpoint if flagged for removal\n\t\t\tif (!removeEndpoints?.includes(endpoint)) {\n\t\t\t\t// Check which CCs exist on this endpoint\n\t\t\t\tconst endpointCCs = [...endpointCounts.entries()]\n\t\t\t\t\t.filter(([, ccEndpoints]) => ccEndpoints >= endpoint)\n\t\t\t\t\t.map(([ccId]) => ccId);\n\t\t\t\t// And store it per endpoint\n\t\t\t\tvalueDB.setValue(\n\t\t\t\t\tMultiChannelCCValues.endpointCCs.endpoint(endpoint),\n\t\t\t\t\tendpointCCs,\n\t\t\t\t);\n\t\t\t\tallEndpoints.push(endpoint);\n\t\t\t}\n\t\t}\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.endpointIndizes,\n\t\t\tallEndpoints,\n\t\t);\n\n\t\t// Remember that the interview is complete\n\t\tthis.setInterviewComplete(ctx, true);\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCEndPointReportOptions {\n\tcountIsDynamic: boolean;\n\tidenticalCapabilities: boolean;\n\tindividualCount: number;\n\taggregatedCount?: number;\n}\n\n@CCCommand(MultiChannelCommand.EndPointReport)\n@ccValueProperty(\"countIsDynamic\", MultiChannelCCValues.endpointCountIsDynamic)\n@ccValueProperty(\n\t\"identicalCapabilities\",\n\tMultiChannelCCValues.endpointsHaveIdenticalCapabilities,\n)\n@ccValueProperty(\n\t\"individualCount\",\n\tMultiChannelCCValues.individualEndpointCount,\n)\n@ccValueProperty(\n\t\"aggregatedCount\",\n\tMultiChannelCCValues.aggregatedEndpointCount,\n)\nexport class MultiChannelCCEndPointReport extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCEndPointReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.countIsDynamic = options.countIsDynamic;\n\t\tthis.identicalCapabilities = options.identicalCapabilities;\n\t\tthis.individualCount = options.individualCount;\n\t\tthis.aggregatedCount = options.aggregatedCount;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCEndPointReport {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\tconst countIsDynamic = !!(raw.payload[0] & 0b10000000);\n\t\tconst identicalCapabilities = !!(raw.payload[0] & 0b01000000);\n\t\tconst individualCount = raw.payload[1] & 0b01111111;\n\t\tlet aggregatedCount: MaybeNotKnown<number>;\n\n\t\tif (raw.payload.length >= 3) {\n\t\t\taggregatedCount = raw.payload[2] & 0b01111111;\n\t\t}\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tcountIsDynamic,\n\t\t\tidenticalCapabilities,\n\t\t\tindividualCount,\n\t\t\taggregatedCount,\n\t\t});\n\t}\n\n\tpublic countIsDynamic: boolean;\n\n\tpublic identicalCapabilities: boolean;\n\n\tpublic individualCount: number;\n\n\tpublic aggregatedCount: MaybeNotKnown<number>;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([\n\t\t\t(this.countIsDynamic ? 0b10000000 : 0)\n\t\t\t| (this.identicalCapabilities ? 0b01000000 : 0),\n\t\t\tthis.individualCount & 0b01111111,\n\t\t\tthis.aggregatedCount ?? 0,\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\t\"endpoint count (individual)\": this.individualCount,\n\t\t\t\"count is dynamic\": this.countIsDynamic,\n\t\t\t\"identical capabilities\": this.identicalCapabilities,\n\t\t};\n\t\tif (this.aggregatedCount != undefined) {\n\t\t\tmessage[\"endpoint count (aggregated)\"] = this.aggregatedCount;\n\t\t}\n\t\tconst ret = {\n\t\t\t...super.toLogEntry(ctx),\n\t\t\tmessage,\n\t\t};\n\t\treturn ret;\n\t}\n}\n\n@CCCommand(MultiChannelCommand.EndPointGet)\n@expectedCCResponse(MultiChannelCCEndPointReport)\nexport class MultiChannelCCEndPointGet extends MultiChannelCC {}\n\n// @publicAPI\nexport interface MultiChannelCCCapabilityReportOptions {\n\tendpointIndex: number;\n\tgenericDeviceClass: number;\n\tspecificDeviceClass: number;\n\tsupportedCCs: CommandClasses[];\n\tisDynamic: boolean;\n\twasRemoved: boolean;\n}\n\n@CCCommand(MultiChannelCommand.CapabilityReport)\nexport class MultiChannelCCCapabilityReport extends MultiChannelCC\n\timplements ApplicationNodeInformation\n{\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCCapabilityReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.endpointIndex = options.endpointIndex;\n\t\tthis.genericDeviceClass = options.genericDeviceClass;\n\t\tthis.specificDeviceClass = options.specificDeviceClass;\n\t\tthis.supportedCCs = options.supportedCCs;\n\t\tthis.isDynamic = options.isDynamic;\n\t\tthis.wasRemoved = options.wasRemoved;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCCapabilityReport {\n\t\t// Only validate the bytes we expect to see here\n\t\t// parseApplicationNodeInformation does its own validation\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst endpointIndex = raw.payload[0] & 0b01111111;\n\t\tconst isDynamic = !!(raw.payload[0] & 0b10000000);\n\t\tconst NIF = parseApplicationNodeInformation(\n\t\t\traw.payload.subarray(1),\n\t\t);\n\t\tconst genericDeviceClass = NIF.genericDeviceClass;\n\t\tconst specificDeviceClass = NIF.specificDeviceClass;\n\t\tconst supportedCCs: CommandClasses[] = NIF.supportedCCs;\n\n\t\t// Removal reports have very specific information\n\t\tconst wasRemoved: boolean = isDynamic\n\t\t\t&& genericDeviceClass === 0xff // \"Non-Interoperable\"\n\t\t\t&& specificDeviceClass === 0x00;\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tendpointIndex,\n\t\t\tisDynamic,\n\t\t\tgenericDeviceClass,\n\t\t\tspecificDeviceClass,\n\t\t\tsupportedCCs,\n\t\t\twasRemoved,\n\t\t});\n\t}\n\n\tpublic persistValues(ctx: PersistValuesContext): boolean {\n\t\tif (!super.persistValues(ctx)) return false;\n\n\t\tconst deviceClassValue = MultiChannelCCValues.endpointDeviceClass;\n\t\tconst ccsValue = MultiChannelCCValues.endpointCCs;\n\n\t\tif (this.wasRemoved) {\n\t\t\tthis.removeValue(ctx, deviceClassValue);\n\t\t\tthis.removeValue(ctx, ccsValue);\n\t\t} else {\n\t\t\tthis.setValue(ctx, deviceClassValue, {\n\t\t\t\tgeneric: this.genericDeviceClass,\n\t\t\t\tspecific: this.specificDeviceClass,\n\t\t\t});\n\t\t\tthis.setValue(ctx, ccsValue, this.supportedCCs);\n\t\t}\n\t\treturn true;\n\t}\n\n\t// The endpoint index must be overridden to be able to attribute the information to the correct endpoint\n\tpublic readonly genericDeviceClass: number;\n\tpublic readonly specificDeviceClass: number;\n\tpublic readonly supportedCCs: CommandClasses[];\n\tpublic readonly isDynamic: boolean;\n\tpublic readonly wasRemoved: boolean;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([\n\t\t\t\t(this.endpointIndex & 0b01111111)\n\t\t\t\t| (this.isDynamic ? 0b10000000 : 0),\n\t\t\t]),\n\t\t\tencodeApplicationNodeInformation(this),\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\t\"endpoint index\": this.endpointIndex,\n\t\t\t\t\"generic device class\": getGenericDeviceClass(\n\t\t\t\t\tthis.genericDeviceClass,\n\t\t\t\t).label,\n\t\t\t\t\"specific device class\": getSpecificDeviceClass(\n\t\t\t\t\tthis.genericDeviceClass,\n\t\t\t\t\tthis.specificDeviceClass,\n\t\t\t\t).label,\n\t\t\t\t\"is dynamic end point\": this.isDynamic,\n\t\t\t\t\"supported CCs\": this.supportedCCs\n\t\t\t\t\t.map((cc) => `\\n\u00B7 ${getCCName(cc)}`)\n\t\t\t\t\t.join(\"\"),\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCCapabilityGetOptions {\n\trequestedEndpoint: number;\n}\n\nfunction testResponseForMultiChannelCapabilityGet(\n\tsent: MultiChannelCCCapabilityGet,\n\treceived: MultiChannelCCCapabilityReport,\n) {\n\treturn received.endpointIndex === sent.requestedEndpoint;\n}\n\n@CCCommand(MultiChannelCommand.CapabilityGet)\n@expectedCCResponse(\n\tMultiChannelCCCapabilityReport,\n\ttestResponseForMultiChannelCapabilityGet,\n)\nexport class MultiChannelCCCapabilityGet extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCCapabilityGetOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.requestedEndpoint = options.requestedEndpoint;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCCapabilityGet {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst requestedEndpoint = raw.payload[0] & 0b01111111;\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\trequestedEndpoint,\n\t\t});\n\t}\n\n\tpublic requestedEndpoint: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.requestedEndpoint & 0b01111111]);\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: { endpoint: this.requestedEndpoint },\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCEndPointFindReportOptions {\n\tgenericClass: number;\n\tspecificClass: number;\n\tfoundEndpoints: number[];\n\treportsToFollow: number;\n}\n\n@CCCommand(MultiChannelCommand.EndPointFindReport)\nexport class MultiChannelCCEndPointFindReport extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCEndPointFindReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.genericClass = options.genericClass;\n\t\tthis.specificClass = options.specificClass;\n\t\tthis.foundEndpoints = options.foundEndpoints;\n\t\tthis.reportsToFollow = options.reportsToFollow;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCEndPointFindReport {\n\t\tvalidatePayload(raw.payload.length >= 3);\n\t\tconst reportsToFollow = raw.payload[0];\n\t\tconst genericClass = raw.payload[1];\n\t\tconst specificClass = raw.payload[2];\n\n\t\t// Some devices omit the endpoint list although that is not allowed in the specs\n\t\t// therefore don't validatePayload here.\n\t\tconst foundEndpoints = [...raw.payload.subarray(3)]\n\t\t\t.map((e) => e & 0b01111111)\n\t\t\t.filter((e) => e !== 0);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\treportsToFollow,\n\t\t\tgenericClass,\n\t\t\tspecificClass,\n\t\t\tfoundEndpoints,\n\t\t});\n\t}\n\n\tpublic genericClass: number;\n\tpublic specificClass: number;\n\tpublic foundEndpoints: number[];\n\tpublic reportsToFollow: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([\n\t\t\t\tthis.reportsToFollow,\n\t\t\t\tthis.genericClass,\n\t\t\t\tthis.specificClass,\n\t\t\t]),\n\t\t\tBytes.from(this.foundEndpoints.map((e) => e & 0b01111111)),\n\t\t]);\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic getPartialCCSessionId(): Record<string, any> | undefined {\n\t\t// Distinguish sessions by the requested device classes\n\t\treturn {\n\t\t\tgenericClass: this.genericClass,\n\t\t\tspecificClass: this.specificClass,\n\t\t};\n\t}\n\n\tpublic expectMoreMessages(): boolean {\n\t\treturn this.reportsToFollow > 0;\n\t}\n\n\tpublic mergePartialCCs(\n\t\tpartials: MultiChannelCCEndPointFindReport[],\n\t\t_ctx: CCParsingContext,\n\t): Promise<void> {\n\t\t// Concat the list of end points\n\t\tthis.foundEndpoints = [...partials, this]\n\t\t\t.map((report) => report.foundEndpoints)\n\t\t\t.reduce((prev, cur) => prev.concat(...cur), []);\n\t\treturn Promise.resolve();\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\t\"generic device class\": getGenericDeviceClass(\n\t\t\t\t\tthis.genericClass,\n\t\t\t\t).label,\n\t\t\t\t\"specific device class\": getSpecificDeviceClass(\n\t\t\t\t\tthis.genericClass,\n\t\t\t\t\tthis.specificClass,\n\t\t\t\t).label,\n\t\t\t\t\"found endpoints\": this.foundEndpoints.join(\", \"),\n\t\t\t\t\"# of reports to follow\": this.reportsToFollow,\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCEndPointFindOptions {\n\tgenericClass: number;\n\tspecificClass: number;\n}\n\n@CCCommand(MultiChannelCommand.EndPointFind)\n@expectedCCResponse(MultiChannelCCEndPointFindReport)\nexport class MultiChannelCCEndPointFind extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCEndPointFindOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.genericClass = options.genericClass;\n\t\tthis.specificClass = options.specificClass;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCEndPointFind {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\tconst genericClass = raw.payload[0];\n\t\tconst specificClass = raw.payload[1];\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tgenericClass,\n\t\t\tspecificClass,\n\t\t});\n\t}\n\n\tpublic genericClass: number;\n\tpublic specificClass: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.genericClass, this.specificClass]);\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\t\"generic device class\":\n\t\t\t\t\tgetGenericDeviceClass(this.genericClass).label,\n\t\t\t\t\"specific device class\": getSpecificDeviceClass(\n\t\t\t\t\tthis.genericClass,\n\t\t\t\t\tthis.specificClass,\n\t\t\t\t).label,\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCAggregatedMembersReportOptions {\n\taggregatedEndpointIndex: number;\n\tmembers: number[];\n}\n\n@CCCommand(MultiChannelCommand.AggregatedMembersReport)\n@ccValueProperty(\n\t\"members\",\n\tMultiChannelCCValues.aggregatedEndpointMembers,\n\t(self) => [self.aggregatedEndpointIndex],\n)\nexport class MultiChannelCCAggregatedMembersReport extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCAggregatedMembersReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\t// TODO: Check implementation:\n\t\tthis.aggregatedEndpointIndex = options.aggregatedEndpointIndex;\n\t\tthis.members = options.members;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCAggregatedMembersReport {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\tconst aggregatedEndpointIndex = raw.payload[0] & 0b0111_1111;\n\t\tconst bitMaskLength = raw.payload[1];\n\t\tvalidatePayload(raw.payload.length >= 2 + bitMaskLength);\n\t\tconst bitMask = raw.payload.subarray(2, 2 + bitMaskLength);\n\t\tconst members = parseBitMask(bitMask);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\taggregatedEndpointIndex,\n\t\t\tmembers,\n\t\t});\n\t}\n\n\tpublic readonly aggregatedEndpointIndex: number;\n\n\tpublic readonly members: readonly number[];\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\t\"aggregated endpoint\": this.aggregatedEndpointIndex,\n\t\t\t\tmembers: this.members.join(\", \"),\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCAggregatedMembersGetOptions {\n\trequestedEndpoint: number;\n}\n\n@CCCommand(MultiChannelCommand.AggregatedMembersGet)\n@expectedCCResponse(MultiChannelCCAggregatedMembersReport)\nexport class MultiChannelCCAggregatedMembersGet extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCAggregatedMembersGetOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.requestedEndpoint = options.requestedEndpoint;\n\t}\n\n\tpublic static from(\n\t\t_raw: CCRaw,\n\t\t_ctx: CCParsingContext,\n\t): MultiChannelCCAggregatedMembersGet {\n\t\t// TODO: Deserialize payload\n\t\tthrow new ZWaveError(\n\t\t\t`${this.name}: deserialization not implemented`,\n\t\t\tZWaveErrorCodes.Deserialization_NotImplemented,\n\t\t);\n\n\t\t// return new MultiChannelCCAggregatedMembersGet({\n\t\t// \tnodeId: ctx.sourceNodeId,\n\t\t// });\n\t}\n\n\tpublic requestedEndpoint: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.requestedEndpoint & 0b0111_1111]);\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: { endpoint: this.requestedEndpoint },\n\t\t};\n\t}\n}\n\ntype MultiChannelCCDestination = number | (1 | 2 | 3 | 4 | 5 | 6 | 7)[];\n\n// @publicAPI\nexport interface MultiChannelCCCommandEncapsulationOptions {\n\tencapsulated: CommandClass;\n\tdestination: MultiChannelCCDestination;\n}\n\n// SDS13783: A receiving node MAY respond to a Multi Channel encapsulated command if the Destination\n// End Point field specifies a single End Point. In that case, the response MUST be Multi Channel\n// encapsulated.\n// A receiving node MUST NOT respond to a Multi Channel encapsulated command if the\n// Destination End Point field specifies multiple End Points via bit mask addressing.\n\nfunction getCCResponseForCommandEncapsulation(\n\tsent: MultiChannelCCCommandEncapsulation,\n) {\n\tif (\n\t\ttypeof sent.destination === \"number\"\n\t\t&& sent.encapsulated.expectsCCResponse()\n\t) {\n\t\t// Allow both versions of the encapsulation command\n\t\t// Our implementation check is a bit too strict, so change the return type\n\t\treturn [\n\t\t\tMultiChannelCCCommandEncapsulation,\n\t\t\tMultiChannelCCV1CommandEncapsulation,\n\t\t] as any as (typeof MultiChannelCCCommandEncapsulation)[];\n\t}\n}\n\nfunction testResponseForCommandEncapsulation(\n\tsent: MultiChannelCCCommandEncapsulation,\n\treceived:\n\t\t| MultiChannelCCCommandEncapsulation\n\t\t| MultiChannelCCV1CommandEncapsulation,\n) {\n\tif (\n\t\ttypeof sent.destination === \"number\"\n\t\t&& sent.destination === received.endpointIndex\n\t) {\n\t\treturn \"checkEncapsulated\";\n\t}\n\treturn false;\n}\n\n@CCCommand(MultiChannelCommand.CommandEncapsulation)\n@expectedCCResponse(\n\tgetCCResponseForCommandEncapsulation,\n\ttestResponseForCommandEncapsulation,\n)\nexport class MultiChannelCCCommandEncapsulation extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCCommandEncapsulationOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.encapsulated = options.encapsulated;\n\t\tthis.encapsulated.encapsulatingCC = this as any;\n\t\t// Propagate the endpoint index all the way down\n\t\tlet cur: CommandClass = this;\n\t\twhile (cur) {\n\t\t\tif (isMultiEncapsulatingCommandClass(cur)) {\n\t\t\t\tfor (const cc of cur.encapsulated) {\n\t\t\t\t\tcc.endpointIndex = this.endpointIndex;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else if (isEncapsulatingCommandClass(cur)) {\n\t\t\t\tcur.encapsulated.endpointIndex = this.endpointIndex;\n\t\t\t\tcur = cur.encapsulated;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.destination = options.destination;\n\t}\n\n\tpublic static async from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): Promise<MultiChannelCCCommandEncapsulation> {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\n\t\tlet endpointIndex: number;\n\t\tlet destination: MultiChannelCCDestination;\n\n\t\tif (\n\t\t\tctx.getDeviceConfig?.(ctx.sourceNodeId)\n\t\t\t\t?.compat?.treatDestinationEndpointAsSource\n\t\t) {\n\t\t\t// This device incorrectly uses the destination field to indicate the source endpoint\n\t\t\tendpointIndex = raw.payload[1] & 0b0111_1111;\n\t\t\tdestination = 0;\n\t\t} else {\n\t\t\t// Parse normally\n\t\t\tendpointIndex = raw.payload[0] & 0b0111_1111;\n\t\t\tconst isBitMask = !!(raw.payload[1] & 0b1000_0000);\n\t\t\tdestination = raw.payload[1] & 0b0111_1111;\n\t\t\tif (isBitMask) {\n\t\t\t\tdestination = parseBitMask(\n\t\t\t\t\tBytes.from([destination]),\n\t\t\t\t) as any;\n\t\t\t}\n\t\t}\n\t\t// No need to validate further, each CC does it for itself\n\t\tconst encapsulated = await CommandClass.parse(\n\t\t\traw.payload.subarray(2),\n\t\t\tctx,\n\t\t);\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tendpointIndex,\n\t\t\tdestination,\n\t\t\tencapsulated,\n\t\t});\n\t}\n\n\tpublic encapsulated: CommandClass;\n\t/** The destination end point (0-127) or an array of destination end points (1-7) */\n\tpublic destination: MultiChannelCCDestination;\n\n\tpublic async serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tif (\n\t\t\tctx.getDeviceConfig?.(this.nodeId as number)?.compat\n\t\t\t\t?.treatDestinationEndpointAsSource\n\t\t) {\n\t\t\t// This device incorrectly responds from the endpoint we've passed as our source endpoint\n\t\t\tif (typeof this.destination === \"number\") {\n\t\t\t\tthis.endpointIndex = this.destination;\n\t\t\t}\n\t\t}\n\n\t\tconst destination = typeof this.destination === \"number\"\n\t\t\t// The destination is a single number\n\t\t\t? this.destination & 0b0111_1111\n\t\t\t// The destination is a bit mask\n\t\t\t: encodeBitMask(this.destination, 7)[0] | 0b1000_0000;\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([this.endpointIndex & 0b0111_1111, destination]),\n\t\t\tawait this.encapsulated.serialize(ctx),\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\tsource: this.endpointIndex,\n\t\t\t\tdestination: typeof this.destination === \"number\"\n\t\t\t\t\t? this.destination\n\t\t\t\t\t: this.destination.join(\", \"),\n\t\t\t},\n\t\t};\n\t}\n\n\tprotected computeEncapsulationOverhead(): number {\n\t\t// Multi Channel CC adds two bytes for the source and destination endpoint\n\t\treturn super.computeEncapsulationOverhead() + 2;\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCV1ReportOptions {\n\trequestedCC: CommandClasses;\n\tendpointCount: number;\n}\n\n@CCCommand(MultiChannelCommand.ReportV1)\nexport class MultiChannelCCV1Report extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCV1ReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\t// TODO: Check implementation:\n\t\tthis.requestedCC = options.requestedCC;\n\t\tthis.endpointCount = options.endpointCount;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCV1Report {\n\t\t// V1 won't be extended in the future, so do an exact check\n\t\tvalidatePayload(raw.payload.length === 2);\n\t\tconst requestedCC: CommandClasses = raw.payload[0];\n\t\tconst endpointCount = raw.payload[1];\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\trequestedCC,\n\t\t\tendpointCount,\n\t\t});\n\t}\n\n\tpublic readonly requestedCC: CommandClasses;\n\tpublic readonly endpointCount: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([\n\t\t\tthis.requestedCC,\n\t\t\tthis.endpointCount,\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\tCC: getCCName(this.requestedCC),\n\t\t\t\t\"# of endpoints\": this.endpointCount,\n\t\t\t},\n\t\t};\n\t}\n}\n\nfunction testResponseForMultiChannelV1Get(\n\tsent: MultiChannelCCV1Get,\n\treceived: MultiChannelCCV1Report,\n) {\n\treturn sent.requestedCC === received.requestedCC;\n}\n\n// @publicAPI\nexport interface MultiChannelCCV1GetOptions {\n\trequestedCC: CommandClasses;\n}\n\n@CCCommand(MultiChannelCommand.GetV1)\n@expectedCCResponse(MultiChannelCCV1Report, testResponseForMultiChannelV1Get)\nexport class MultiChannelCCV1Get extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCV1GetOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.requestedCC = options.requestedCC;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCV1Get {\n\t\t// V1 won't be extended in the future, so do an exact check\n\t\tvalidatePayload(raw.payload.length === 1);\n\t\tconst requestedCC: CommandClasses = raw.payload[0];\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\trequestedCC,\n\t\t});\n\t}\n\n\tpublic requestedCC: CommandClasses;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.requestedCC]);\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: { CC: getCCName(this.requestedCC) },\n\t\t};\n\t}\n}\n\nfunction getResponseForV1CommandEncapsulation(\n\tsent: MultiChannelCCV1CommandEncapsulation,\n) {\n\tif (sent.encapsulated.expectsCCResponse()) {\n\t\treturn MultiChannelCCV1CommandEncapsulation;\n\t}\n}\n\nfunction testResponseForV1CommandEncapsulation(\n\tsent: MultiChannelCCV1CommandEncapsulation,\n\treceived: MultiChannelCCV1CommandEncapsulation,\n) {\n\tif (sent.endpointIndex === received.endpointIndex) {\n\t\treturn \"checkEncapsulated\";\n\t}\n\treturn false;\n}\n\n// @publicAPI\nexport interface MultiChannelCCV1CommandEncapsulationOptions {\n\tencapsulated: CommandClass;\n}\n\n@CCCommand(MultiChannelCommand.CommandEncapsulationV1)\n@expectedCCResponse(\n\tgetResponseForV1CommandEncapsulation,\n\ttestResponseForV1CommandEncapsulation,\n)\nexport class MultiChannelCCV1CommandEncapsulation extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCV1CommandEncapsulationOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.encapsulated = options.encapsulated;\n\t\tthis.encapsulated.encapsulatingCC = this as any;\n\t\t// Propagate the endpoint index all the way down\n\t\tlet cur: CommandClass = this;\n\t\twhile (cur) {\n\t\t\tif (isMultiEncapsulatingCommandClass(cur)) {\n\t\t\t\tfor (const cc of cur.encapsulated) {\n\t\t\t\t\tcc.endpointIndex = this.endpointIndex;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else if (isEncapsulatingCommandClass(cur)) {\n\t\t\t\tcur.encapsulated.endpointIndex = this.endpointIndex;\n\t\t\t\tcur = cur.encapsulated;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static async from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): Promise<MultiChannelCCV1CommandEncapsulation> {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst endpointIndex = raw.payload[0];\n\n\t\t// Some devices send invalid reports, i.e. MultiChannelCCV1CommandEncapsulation, but with V2+ binary format\n\t\t// This would be a NoOp CC, but it makes no sense to encapsulate that.\n\t\tconst isV2withV1Header = raw.payload.length >= 2\n\t\t\t&& raw.payload[1] === 0x00;\n\n\t\t// No need to validate further, each CC does it for itself\n\t\tconst encapsulated = await CommandClass.parse(\n\t\t\traw.payload.subarray(isV2withV1Header ? 2 : 1),\n\t\t\tctx,\n\t\t);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tendpointIndex,\n\t\t\tencapsulated,\n\t\t});\n\t}\n\n\tpublic encapsulated!: CommandClass;\n\n\tpublic async serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([this.endpointIndex]),\n\t\t\tawait this.encapsulated.serialize(ctx),\n\t\t]);\n\t\treturn super.serialize(ctx);\n\t}\n\n\tprotected computeEncapsulationOverhead(): number {\n\t\t// Multi Channel CC V1 adds one byte for the endpoint index\n\t\treturn super.computeEncapsulationOverhead() + 1;\n\t}\n\n\tpublic toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry {\n\t\treturn {\n\t\t\t...super.toLogEntry(ctx),\n\t\t\tmessage: { source: this.endpointIndex },\n\t\t};\n\t}\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { CCEncodingContext, CCParsingContext } from \"@zwave-js/cc\";\nimport {\n\ttype ApplicationNodeInformation,\n\tCommandClasses,\n\ttype GenericDeviceClass,\n\ttype GetNode,\n\ttype GetValueDB,\n\ttype MaybeNotKnown,\n\ttype MessageOrCCLogEntry,\n\tMessagePriority,\n\ttype MessageRecord,\n\ttype NodeId,\n\ttype SpecificDeviceClass,\n\ttype SupportsCC,\n\ttype WithAddress,\n\tZWaveError,\n\tZWaveErrorCodes,\n\tencodeApplicationNodeInformation,\n\tencodeBitMask,\n\tgetCCName,\n\tgetGenericDeviceClass,\n\tgetSpecificDeviceClass,\n\tparseApplicationNodeInformation,\n\tparseBitMask,\n\tvalidatePayload,\n} from \"@zwave-js/core\";\nimport { Bytes } from \"@zwave-js/shared\";\nimport { validateArgs } from \"@zwave-js/transformers\";\nimport { distinct } from \"alcalzone-shared/arrays\";\nimport { CCAPI } from \"../lib/API.js\";\nimport {\n\ttype CCRaw,\n\tCommandClass,\n\ttype InterviewContext,\n\ttype PersistValuesContext,\n\tgetEffectiveCCVersion,\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 {\n\tisEncapsulatingCommandClass,\n\tisMultiEncapsulatingCommandClass,\n} from \"../lib/EncapsulatingCommandClass.js\";\nimport { V } from \"../lib/Values.js\";\nimport { MultiChannelCommand } from \"../lib/_Types.js\";\n\n// TODO: Handle removal reports of dynamic endpoints\n\nexport const MultiChannelCCValues = V.defineCCValues(\n\tCommandClasses[\"Multi Channel\"],\n\t{\n\t\t...V.staticProperty(\"endpointIndizes\", undefined, {\n\t\t\tinternal: true,\n\t\t\tsupportsEndpoints: false,\n\t\t}),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"individualEndpointCount\",\n\t\t\t\"individualCount\",\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\tinternal: true,\n\t\t\t\tsupportsEndpoints: false,\n\t\t\t},\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"aggregatedEndpointCount\",\n\t\t\t\"aggregatedCount\",\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\tinternal: true,\n\t\t\t\tsupportsEndpoints: false,\n\t\t\t},\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"endpointCountIsDynamic\",\n\t\t\t\"countIsDynamic\",\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\tinternal: true,\n\t\t\t\tsupportsEndpoints: false,\n\t\t\t},\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"endpointsHaveIdenticalCapabilities\",\n\t\t\t\"identicalCapabilities\",\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\tinternal: true,\n\t\t\t\tsupportsEndpoints: false,\n\t\t\t},\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"endpointCCs\",\n\t\t\t\"commandClasses\",\n\t\t\tundefined,\n\t\t\t{ internal: true },\n\t\t),\n\t\t...V.staticPropertyWithName(\n\t\t\t\"endpointDeviceClass\",\n\t\t\t\"deviceClass\",\n\t\t\tundefined,\n\t\t\t{ internal: true },\n\t\t),\n\t\t...V.dynamicPropertyAndKeyWithName(\n\t\t\t\"aggregatedEndpointMembers\",\n\t\t\t\"members\",\n\t\t\t(endpointIndex: number) => endpointIndex,\n\t\t\t({ property, propertyKey }) =>\n\t\t\t\tproperty === \"members\" && typeof propertyKey === \"number\",\n\t\t\tundefined,\n\t\t\t{ internal: true },\n\t\t),\n\t},\n);\n\n// @noSetValueAPI\n\n/**\n * Many devices unnecessarily use endpoints when they could (or do) provide all functionality via the root device.\n * This function gives an estimate if this is the case (i.e. all endpoints have a different device class)\n */\nfunction areEndpointsUnnecessary(\n\tctx: GetValueDB,\n\tnodeId: number,\n\tendpointIndizes: number[],\n): boolean {\n\t// Gather all device classes\n\tconst deviceClasses = new Map<\n\t\tnumber,\n\t\t{\n\t\t\tgeneric: number;\n\t\t\tspecific: number;\n\t\t}\n\t>();\n\tfor (const endpoint of endpointIndizes) {\n\t\tconst devClassValueId = MultiChannelCCValues.endpointDeviceClass\n\t\t\t.endpoint(endpoint);\n\t\tconst deviceClass = ctx.getValueDB(nodeId).getValue<{\n\t\t\tgeneric: number;\n\t\t\tspecific: number;\n\t\t}>(devClassValueId);\n\t\tif (deviceClass) {\n\t\t\tdeviceClasses.set(endpoint, {\n\t\t\t\tgeneric: deviceClass.generic,\n\t\t\t\tspecific: deviceClass.specific,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Endpoints may be useless if all of them have different device classes\n\tconst distinctDeviceClasses = distinct(\n\t\t[...deviceClasses.values()].map(\n\t\t\t({ generic, specific }) => generic * 256 + specific,\n\t\t),\n\t);\n\tif (distinctDeviceClasses.length !== endpointIndizes.length) {\n\t\t// There are endpoints with the same device class, so they are not unnecessary\n\t\treturn false;\n\t}\n\n\t// Endpoints are necessary if more than 1 of them has a switch-type device class\n\tconst switchTypeDeviceClasses = new Set([\n\t\t0x10, // Binary Switch\n\t\t0x11, // Multilevel Switch\n\t\t0x12, // Remote Switch\n\t\t0x13, // Toggle Switch\n\t]);\n\tconst numSwitchEndpoints = [...deviceClasses.values()].filter(\n\t\t({ generic }) => switchTypeDeviceClasses.has(generic),\n\t).length;\n\tif (numSwitchEndpoints > 1) return false;\n\n\treturn true;\n}\n\n@API(CommandClasses[\"Multi Channel\"])\nexport class MultiChannelCCAPI extends CCAPI {\n\tpublic supportsCommand(cmd: MultiChannelCommand): MaybeNotKnown<boolean> {\n\t\tswitch (cmd) {\n\t\t\t// Legacy commands:\n\t\t\tcase MultiChannelCommand.GetV1:\n\t\t\t\treturn this.isSinglecast() && this.version === 1;\n\t\t\tcase MultiChannelCommand.CommandEncapsulationV1:\n\t\t\t\treturn this.version === 1;\n\n\t\t\t// The specs start at version 3 but according to OZW,\n\t\t\t// these do seem to be supported in version 2\n\t\t\tcase MultiChannelCommand.EndPointGet:\n\t\t\tcase MultiChannelCommand.CapabilityGet:\n\t\t\t\treturn this.version >= 2 && this.isSinglecast();\n\t\t\tcase MultiChannelCommand.CommandEncapsulation:\n\t\t\t\treturn this.version >= 2;\n\t\t\tcase MultiChannelCommand.EndPointFind:\n\t\t\t\treturn this.version >= 3 && this.isSinglecast();\n\t\t\tcase MultiChannelCommand.AggregatedMembersGet:\n\t\t\t\treturn this.version >= 4 && this.isSinglecast();\n\t\t}\n\t\treturn super.supportsCommand(cmd);\n\t}\n\n\t// oxlint-disable-next-line typescript/explicit-module-boundary-types\n\tpublic async getEndpoints() {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.EndPointGet,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCEndPointGet({\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<\n\t\t\tMultiChannelCCEndPointReport\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\tisDynamicEndpointCount: response.countIsDynamic,\n\t\t\t\tidenticalCapabilities: response.identicalCapabilities,\n\t\t\t\tindividualEndpointCount: response.individualCount,\n\t\t\t\taggregatedEndpointCount: response.aggregatedCount,\n\t\t\t};\n\t\t}\n\t}\n\n\t@validateArgs()\n\tpublic async getEndpointCapabilities(\n\t\tendpoint: number,\n\t): Promise<MaybeNotKnown<EndpointCapability>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.CapabilityGet,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCCapabilityGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\trequestedEndpoint: endpoint,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultiChannelCCCapabilityReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (response) {\n\t\t\tconst generic = getGenericDeviceClass(\n\t\t\t\tresponse.genericDeviceClass,\n\t\t\t);\n\t\t\tconst specific = getSpecificDeviceClass(\n\t\t\t\tresponse.genericDeviceClass,\n\t\t\t\tresponse.specificDeviceClass,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tisDynamic: response.isDynamic,\n\t\t\t\twasRemoved: response.wasRemoved,\n\t\t\t\tsupportedCCs: response.supportedCCs,\n\t\t\t\tgeneric,\n\t\t\t\tspecific,\n\t\t\t};\n\t\t}\n\t}\n\n\t@validateArgs()\n\tpublic async findEndpoints(\n\t\tgenericClass: number,\n\t\tspecificClass: number,\n\t): Promise<MaybeNotKnown<readonly number[]>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.EndPointFind,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCEndPointFind({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tgenericClass,\n\t\t\tspecificClass,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultiChannelCCEndPointFindReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.foundEndpoints;\n\t}\n\n\t@validateArgs()\n\tpublic async getAggregatedMembers(\n\t\tendpoint: number,\n\t): Promise<MaybeNotKnown<readonly number[]>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.AggregatedMembersGet,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCAggregatedMembersGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\trequestedEndpoint: endpoint,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultiChannelCCAggregatedMembersReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.members;\n\t}\n\n\t// Encapsulation is used internally and too frequently that we\n\t// want to pay the cost of validating each call\n\t// eslint-disable-next-line @zwave-js/ccapi-validate-args\n\tpublic async sendEncapsulated(\n\t\toptions: MultiChannelCCCommandEncapsulationOptions,\n\t): Promise<void> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.CommandEncapsulation,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCCommandEncapsulation({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\t...options,\n\t\t});\n\t\tawait this.host.sendCommand(cc, this.commandOptions);\n\t}\n\n\t@validateArgs()\n\tpublic async getEndpointCountV1(\n\t\tccId: CommandClasses,\n\t): Promise<MaybeNotKnown<number>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.GetV1,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCV1Get({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\trequestedCC: ccId,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultiChannelCCV1Report\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.endpointCount;\n\t}\n\n\t// Encapsulation is used internally and too frequently that we\n\t// want to pay the cost of validating each call\n\t// eslint-disable-next-line @zwave-js/ccapi-validate-args\n\tpublic async sendEncapsulatedV1(encapsulated: CommandClass): Promise<void> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultiChannelCommand,\n\t\t\tMultiChannelCommand.CommandEncapsulationV1,\n\t\t);\n\n\t\tconst cc = new MultiChannelCCV1CommandEncapsulation({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tencapsulated,\n\t\t});\n\t\tawait this.host.sendCommand(cc, this.commandOptions);\n\t}\n}\n\nexport interface EndpointCapability {\n\tgeneric: GenericDeviceClass;\n\tspecific: SpecificDeviceClass;\n\tsupportedCCs: CommandClasses[];\n\tisDynamic: boolean;\n\twasRemoved: boolean;\n}\n\n@commandClass(CommandClasses[\"Multi Channel\"])\n@implementedVersion(4)\n@ccValues(MultiChannelCCValues)\nexport class MultiChannelCC extends CommandClass {\n\tdeclare ccCommand: MultiChannelCommand;\n\n\t/** Tests if a command targets a specific endpoint and thus requires encapsulation */\n\tpublic static requiresEncapsulation(cc: CommandClass): boolean {\n\t\treturn (\n\t\t\tcc.endpointIndex !== 0\n\t\t\t&& !(cc instanceof MultiChannelCCCommandEncapsulation)\n\t\t\t&& !(cc instanceof MultiChannelCCV1CommandEncapsulation)\n\t\t);\n\t}\n\n\t/** Encapsulates a command that targets a specific endpoint, with version 2+ of the Multi Channel CC */\n\tpublic static encapsulate(\n\t\tcc: CommandClass,\n\t): MultiChannelCCCommandEncapsulation {\n\t\tconst ret = new MultiChannelCCCommandEncapsulation({\n\t\t\tnodeId: cc.nodeId,\n\t\t\tencapsulated: cc,\n\t\t\tdestination: cc.endpointIndex,\n\t\t});\n\n\t\t// Copy the encapsulation flags from the encapsulated command\n\t\tret.encapsulationFlags = cc.encapsulationFlags;\n\n\t\treturn ret;\n\t}\n\n\t/** Encapsulates a command that targets a specific endpoint, with version 1 of the Multi Channel CC */\n\tpublic static encapsulateV1(\n\t\tcc: CommandClass,\n\t): MultiChannelCCV1CommandEncapsulation {\n\t\tconst ret = new MultiChannelCCV1CommandEncapsulation({\n\t\t\tnodeId: cc.nodeId,\n\t\t\tendpointIndex: cc.endpointIndex,\n\t\t\tencapsulated: cc,\n\t\t});\n\n\t\t// Copy the encapsulation flags from the encapsulated command\n\t\tret.encapsulationFlags = cc.encapsulationFlags;\n\n\t\treturn ret;\n\t}\n\n\tpublic skipEndpointInterview(): boolean {\n\t\t// The endpoints are discovered by querying the root device\n\t\treturn true;\n\t}\n\n\tpublic async interview(ctx: InterviewContext): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\n\t\tconst removeEndpoints = ctx.getDeviceConfig?.(node.id)?.compat\n\t\t\t?.removeEndpoints;\n\t\tif (removeEndpoints === \"*\") {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`Skipping ${this.ccName} interview b/c all endpoints are ignored by the device config file...`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\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// Special interview procedure for legacy nodes\n\t\tconst ccVersion = getEffectiveCCVersion(ctx, this);\n\t\tif (ccVersion === 1) return this.interviewV1(ctx);\n\n\t\tconst endpoint = node.getEndpoint(this.endpointIndex)!;\n\t\tconst api = CCAPI.create(\n\t\t\tCommandClasses[\"Multi Channel\"],\n\t\t\tctx,\n\t\t\tendpoint,\n\t\t).withOptions({\n\t\t\tpriority: MessagePriority.NodeQuery,\n\t\t});\n\t\tconst valueDB = this.getValueDB(ctx);\n\n\t\t// Step 1: Retrieve general information about end points\n\t\tctx.logNode(node.id, {\n\t\t\tendpoint: this.endpointIndex,\n\t\t\tmessage: \"querying device endpoint information...\",\n\t\t\tdirection: \"outbound\",\n\t\t});\n\t\tconst multiResponse = await api.getEndpoints();\n\t\tif (!multiResponse) {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t\"Querying device endpoint information timed out, aborting interview...\",\n\t\t\t\tlevel: \"warn\",\n\t\t\t});\n\t\t\treturn this.throwMissingCriticalInterviewResponse();\n\t\t}\n\n\t\tlet logMessage = `received response for device endpoints:\nendpoint count (individual): ${multiResponse.individualEndpointCount}\ncount is dynamic: ${multiResponse.isDynamicEndpointCount}\nidentical capabilities: ${multiResponse.identicalCapabilities}`;\n\t\tif (multiResponse.aggregatedEndpointCount != undefined) {\n\t\t\tlogMessage +=\n\t\t\t\t`\\nendpoint count (aggregated): ${multiResponse.aggregatedEndpointCount}`;\n\t\t}\n\t\tctx.logNode(node.id, {\n\t\t\tendpoint: this.endpointIndex,\n\t\t\tmessage: logMessage,\n\t\t\tdirection: \"inbound\",\n\t\t});\n\n\t\tlet allEndpoints: number[] = [];\n\t\tconst addSequentialEndpoints = (): void => {\n\t\t\tfor (\n\t\t\t\tlet i = 1;\n\t\t\t\ti\n\t\t\t\t\t<= multiResponse.individualEndpointCount\n\t\t\t\t\t\t+ (multiResponse.aggregatedEndpointCount ?? 0);\n\t\t\t\ti++\n\t\t\t) {\n\t\t\t\tallEndpoints.push(i);\n\t\t\t}\n\t\t};\n\t\tif (api.supportsCommand(MultiChannelCommand.EndPointFind)) {\n\t\t\t// Step 2a: Find all endpoints\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: \"querying all endpoints...\",\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\n\t\t\tconst foundEndpoints = await api.findEndpoints(0xff, 0xff);\n\t\t\tif (foundEndpoints) allEndpoints.push(...foundEndpoints);\n\t\t\tif (!allEndpoints.length) {\n\t\t\t\t// Create a sequential list of endpoints\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Endpoint query returned no results, assuming that endpoints are sequential`,\n\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t});\n\t\t\t\taddSequentialEndpoints();\n\t\t\t} else {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage: `received endpoints: ${\n\t\t\t\t\t\tallEndpoints\n\t\t\t\t\t\t\t.map(String)\n\t\t\t\t\t\t\t.join(\", \")\n\t\t\t\t\t}`,\n\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\t// Step 2b: Assume that the endpoints are in sequential order\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`does not support EndPointFind, assuming that endpoints are sequential`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t\taddSequentialEndpoints();\n\t\t}\n\n\t\t// Step 2.5: remove ignored endpoints\n\t\tif (removeEndpoints?.length) {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`The following endpoints are ignored through the config file: ${\n\t\t\t\t\t\tremoveEndpoints.join(\", \")\n\t\t\t\t\t}`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t\tallEndpoints = allEndpoints.filter(\n\t\t\t\t(e) => !removeEndpoints.includes(e),\n\t\t\t);\n\t\t}\n\n\t\t// Step 3: Query endpoints\n\t\tlet hasQueriedCapabilities = false;\n\t\tfor (const endpoint of allEndpoints) {\n\t\t\tif (\n\t\t\t\tendpoint > multiResponse.individualEndpointCount\n\t\t\t\t&& ccVersion >= 4\n\t\t\t) {\n\t\t\t\t// Find members of aggregated end point\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`querying members of aggregated endpoint #${endpoint}...`,\n\t\t\t\t\tdirection: \"outbound\",\n\t\t\t\t});\n\t\t\t\tconst members = await api.getAggregatedMembers(endpoint);\n\t\t\t\tif (members) {\n\t\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`aggregated endpoint #${endpoint} has members ${\n\t\t\t\t\t\t\t\tmembers\n\t\t\t\t\t\t\t\t\t.map(String)\n\t\t\t\t\t\t\t\t\t.join(\", \")\n\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// When the device reports identical capabilities for all endpoints,\n\t\t\t// we don't need to query them all\n\t\t\tif (multiResponse.identicalCapabilities && hasQueriedCapabilities) {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`all endpoints identical, skipping capability query for endpoint #${endpoint}...`,\n\t\t\t\t\tdirection: \"none\",\n\t\t\t\t});\n\n\t\t\t\t// copy the capabilities from the first endpoint\n\t\t\t\tconst devClass = valueDB.getValue(\n\t\t\t\t\tMultiChannelCCValues.endpointDeviceClass.endpoint(\n\t\t\t\t\t\tallEndpoints[0],\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tvalueDB.setValue(\n\t\t\t\t\tMultiChannelCCValues.endpointDeviceClass.endpoint(endpoint),\n\t\t\t\t\tdevClass,\n\t\t\t\t);\n\t\t\t\tconst ep1Caps = valueDB.getValue<CommandClasses[]>(\n\t\t\t\t\tMultiChannelCCValues.endpointCCs.endpoint(allEndpoints[0]),\n\t\t\t\t)!;\n\t\t\t\tvalueDB.setValue(\n\t\t\t\t\tMultiChannelCCValues.endpointCCs.endpoint(endpoint),\n\t\t\t\t\t[...ep1Caps],\n\t\t\t\t);\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: `querying capabilities for endpoint #${endpoint}...`,\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\t\t\tconst caps = await api.getEndpointCapabilities(endpoint);\n\t\t\tif (caps) {\n\t\t\t\thasQueriedCapabilities = true;\n\t\t\t\tlogMessage =\n\t\t\t\t\t`received response for endpoint capabilities (#${endpoint}):\ngeneric device class: ${caps.generic.label}\nspecific device class: ${caps.specific.label}\nis dynamic end point: ${caps.isDynamic}\nsupported CCs:`;\n\t\t\t\tfor (const cc of caps.supportedCCs) {\n\t\t\t\t\tlogMessage += `\\n \u00B7 ${getCCName(cc)}`;\n\t\t\t\t}\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} else {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Querying endpoint #${endpoint} capabilities timed out, aborting interview...`,\n\t\t\t\t\tlevel: \"warn\",\n\t\t\t\t});\n\t\t\t\treturn this.throwMissingCriticalInterviewResponse();\n\t\t\t}\n\t\t}\n\n\t\t// Now that all endpoints have been interviewed, remember which ones are there\n\t\t// But first figure out if they seem unnecessary and if they do, which ones should be preserved\n\t\tif (\n\t\t\t!multiResponse.identicalCapabilities\n\t\t\t&& areEndpointsUnnecessary(ctx, node.id, allEndpoints)\n\t\t) {\n\t\t\tconst preserve = ctx.getDeviceConfig?.(node.id)?.compat\n\t\t\t\t?.preserveEndpoints;\n\t\t\tif (!preserve) {\n\t\t\t\tallEndpoints = [];\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Endpoints seem unnecessary b/c they have different device classes, ignoring all...`,\n\t\t\t\t});\n\t\t\t} else if (preserve === \"*\") {\n\t\t\t\t// preserve all endpoints, do nothing\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Endpoints seem unnecessary, but are configured to be preserved.`,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tallEndpoints = allEndpoints.filter((ep) =>\n\t\t\t\t\tpreserve.includes(ep)\n\t\t\t\t);\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tmessage: `Endpoints seem unnecessary, but endpoints ${\n\t\t\t\t\t\tallEndpoints.join(\n\t\t\t\t\t\t\t\", \",\n\t\t\t\t\t\t)\n\t\t\t\t\t} are configured to be preserved.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.endpointIndizes,\n\t\t\tallEndpoints,\n\t\t);\n\n\t\t// Remember that the interview is complete\n\t\tthis.setInterviewComplete(ctx, true);\n\t}\n\n\tprivate async interviewV1(ctx: InterviewContext): Promise<void> {\n\t\tconst node = this.getNode(ctx)!;\n\t\tconst endpoint = this.getEndpoint(ctx)!;\n\t\tconst removeEndpoints = ctx.getDeviceConfig?.(node.id)?.compat\n\t\t\t?.removeEndpoints;\n\t\tif (removeEndpoints === \"*\") {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`Skipping ${this.ccName} interview b/c all endpoints are ignored by the device config file...`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst api = CCAPI.create(\n\t\t\tCommandClasses[\"Multi Channel\"],\n\t\t\tctx,\n\t\t\tendpoint,\n\t\t);\n\t\tconst valueDB = this.getValueDB(ctx);\n\n\t\t// V1 works the opposite way - we scan all CCs and remember how many\n\t\t// endpoints they have\n\t\tconst supportedCCs = [...node.getCCs()]\n\t\t\t// Don't query CCs the node only controls\n\t\t\t.filter(([, info]) => info.isSupported)\n\t\t\t.map(([cc]) => cc)\n\t\t\t// Don't query CCs that want to skip the endpoint interview\n\t\t\t.filter(\n\t\t\t\t(cc) =>\n\t\t\t\t\t!CommandClass.createInstanceUnchecked(\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tcc,\n\t\t\t\t\t)?.skipEndpointInterview(),\n\t\t\t);\n\t\tconst endpointCounts = new Map<CommandClasses, number>();\n\t\tfor (const ccId of supportedCCs) {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tmessage: `Querying endpoint count for CommandClass ${\n\t\t\t\t\tgetCCName(\n\t\t\t\t\t\tccId,\n\t\t\t\t\t)\n\t\t\t\t}...`,\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\t\t\tconst endpointCount = await api.getEndpointCountV1(ccId);\n\t\t\tif (endpointCount != undefined) {\n\t\t\t\tendpointCounts.set(ccId, endpointCount);\n\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tmessage: `CommandClass ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tccId,\n\t\t\t\t\t\t)\n\t\t\t\t\t} has ${endpointCount} endpoints`,\n\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Store the collected information\n\t\t// We have only individual and no dynamic and no aggregated endpoints\n\t\tconst numEndpoints = Math.max(...endpointCounts.values());\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.endpointCountIsDynamic,\n\t\t\tfalse,\n\t\t);\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.aggregatedEndpointCount,\n\t\t\t0,\n\t\t);\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.individualEndpointCount,\n\t\t\tnumEndpoints,\n\t\t);\n\t\t// Since we queried all CCs separately, we can assume that all\n\t\t// endpoints have different capabilities\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.endpointsHaveIdenticalCapabilities,\n\t\t\tfalse,\n\t\t);\n\n\t\tif (removeEndpoints?.length) {\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`The following endpoints are ignored through the config file: ${\n\t\t\t\t\t\tremoveEndpoints.join(\", \")\n\t\t\t\t\t}`,\n\t\t\t\tdirection: \"none\",\n\t\t\t});\n\t\t}\n\n\t\tconst allEndpoints: number[] = [];\n\t\tfor (let endpoint = 1; endpoint <= numEndpoints; endpoint++) {\n\t\t\t// Skip this endpoint if flagged for removal\n\t\t\tif (!removeEndpoints?.includes(endpoint)) {\n\t\t\t\t// Check which CCs exist on this endpoint\n\t\t\t\tconst endpointCCs = [...endpointCounts.entries()]\n\t\t\t\t\t.filter(([, ccEndpoints]) => ccEndpoints >= endpoint)\n\t\t\t\t\t.map(([ccId]) => ccId);\n\t\t\t\t// And store it per endpoint\n\t\t\t\tvalueDB.setValue(\n\t\t\t\t\tMultiChannelCCValues.endpointCCs.endpoint(endpoint),\n\t\t\t\t\tendpointCCs,\n\t\t\t\t);\n\t\t\t\tallEndpoints.push(endpoint);\n\t\t\t}\n\t\t}\n\t\tthis.setValue(\n\t\t\tctx,\n\t\t\tMultiChannelCCValues.endpointIndizes,\n\t\t\tallEndpoints,\n\t\t);\n\n\t\t// Remember that the interview is complete\n\t\tthis.setInterviewComplete(ctx, true);\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCEndPointReportOptions {\n\tcountIsDynamic: boolean;\n\tidenticalCapabilities: boolean;\n\tindividualCount: number;\n\taggregatedCount?: number;\n}\n\n@CCCommand(MultiChannelCommand.EndPointReport)\n@ccValueProperty(\"countIsDynamic\", MultiChannelCCValues.endpointCountIsDynamic)\n@ccValueProperty(\n\t\"identicalCapabilities\",\n\tMultiChannelCCValues.endpointsHaveIdenticalCapabilities,\n)\n@ccValueProperty(\n\t\"individualCount\",\n\tMultiChannelCCValues.individualEndpointCount,\n)\n@ccValueProperty(\n\t\"aggregatedCount\",\n\tMultiChannelCCValues.aggregatedEndpointCount,\n)\nexport class MultiChannelCCEndPointReport extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCEndPointReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.countIsDynamic = options.countIsDynamic;\n\t\tthis.identicalCapabilities = options.identicalCapabilities;\n\t\tthis.individualCount = options.individualCount;\n\t\tthis.aggregatedCount = options.aggregatedCount;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCEndPointReport {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\tconst countIsDynamic = !!(raw.payload[0] & 0b10000000);\n\t\tconst identicalCapabilities = !!(raw.payload[0] & 0b01000000);\n\t\tconst individualCount = raw.payload[1] & 0b01111111;\n\t\tlet aggregatedCount: MaybeNotKnown<number>;\n\n\t\tif (raw.payload.length >= 3) {\n\t\t\taggregatedCount = raw.payload[2] & 0b01111111;\n\t\t}\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tcountIsDynamic,\n\t\t\tidenticalCapabilities,\n\t\t\tindividualCount,\n\t\t\taggregatedCount,\n\t\t});\n\t}\n\n\tpublic countIsDynamic: boolean;\n\n\tpublic identicalCapabilities: boolean;\n\n\tpublic individualCount: number;\n\n\tpublic aggregatedCount: MaybeNotKnown<number>;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([\n\t\t\t(this.countIsDynamic ? 0b10000000 : 0)\n\t\t\t| (this.identicalCapabilities ? 0b01000000 : 0),\n\t\t\tthis.individualCount & 0b01111111,\n\t\t\tthis.aggregatedCount ?? 0,\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\t\"endpoint count (individual)\": this.individualCount,\n\t\t\t\"count is dynamic\": this.countIsDynamic,\n\t\t\t\"identical capabilities\": this.identicalCapabilities,\n\t\t};\n\t\tif (this.aggregatedCount != undefined) {\n\t\t\tmessage[\"endpoint count (aggregated)\"] = this.aggregatedCount;\n\t\t}\n\t\tconst ret = {\n\t\t\t...super.toLogEntry(ctx),\n\t\t\tmessage,\n\t\t};\n\t\treturn ret;\n\t}\n}\n\n@CCCommand(MultiChannelCommand.EndPointGet)\n@expectedCCResponse(MultiChannelCCEndPointReport)\nexport class MultiChannelCCEndPointGet extends MultiChannelCC {}\n\n// @publicAPI\nexport interface MultiChannelCCCapabilityReportOptions {\n\tendpointIndex: number;\n\tgenericDeviceClass: number;\n\tspecificDeviceClass: number;\n\tsupportedCCs: CommandClasses[];\n\tisDynamic: boolean;\n\twasRemoved: boolean;\n}\n\n@CCCommand(MultiChannelCommand.CapabilityReport)\nexport class MultiChannelCCCapabilityReport extends MultiChannelCC\n\timplements ApplicationNodeInformation\n{\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCCapabilityReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.endpointIndex = options.endpointIndex;\n\t\tthis.genericDeviceClass = options.genericDeviceClass;\n\t\tthis.specificDeviceClass = options.specificDeviceClass;\n\t\tthis.supportedCCs = options.supportedCCs;\n\t\tthis.isDynamic = options.isDynamic;\n\t\tthis.wasRemoved = options.wasRemoved;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCCapabilityReport {\n\t\t// Only validate the bytes we expect to see here\n\t\t// parseApplicationNodeInformation does its own validation\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst endpointIndex = raw.payload[0] & 0b01111111;\n\t\tconst isDynamic = !!(raw.payload[0] & 0b10000000);\n\t\tconst NIF = parseApplicationNodeInformation(\n\t\t\traw.payload.subarray(1),\n\t\t);\n\t\tconst genericDeviceClass = NIF.genericDeviceClass;\n\t\tconst specificDeviceClass = NIF.specificDeviceClass;\n\t\tconst supportedCCs: CommandClasses[] = NIF.supportedCCs;\n\n\t\t// Removal reports have very specific information\n\t\tconst wasRemoved: boolean = isDynamic\n\t\t\t&& genericDeviceClass === 0xff // \"Non-Interoperable\"\n\t\t\t&& specificDeviceClass === 0x00;\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tendpointIndex,\n\t\t\tisDynamic,\n\t\t\tgenericDeviceClass,\n\t\t\tspecificDeviceClass,\n\t\t\tsupportedCCs,\n\t\t\twasRemoved,\n\t\t});\n\t}\n\n\tpublic persistValues(ctx: PersistValuesContext): boolean {\n\t\tif (!super.persistValues(ctx)) return false;\n\n\t\tconst deviceClassValue = MultiChannelCCValues.endpointDeviceClass;\n\t\tconst ccsValue = MultiChannelCCValues.endpointCCs;\n\n\t\tif (this.wasRemoved) {\n\t\t\tthis.removeValue(ctx, deviceClassValue);\n\t\t\tthis.removeValue(ctx, ccsValue);\n\t\t} else {\n\t\t\tthis.setValue(ctx, deviceClassValue, {\n\t\t\t\tgeneric: this.genericDeviceClass,\n\t\t\t\tspecific: this.specificDeviceClass,\n\t\t\t});\n\t\t\tthis.setValue(ctx, ccsValue, this.supportedCCs);\n\t\t}\n\t\treturn true;\n\t}\n\n\t// The endpoint index must be overridden to be able to attribute the information to the correct endpoint\n\tpublic readonly genericDeviceClass: number;\n\tpublic readonly specificDeviceClass: number;\n\tpublic readonly supportedCCs: CommandClasses[];\n\tpublic readonly isDynamic: boolean;\n\tpublic readonly wasRemoved: boolean;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([\n\t\t\t\t(this.endpointIndex & 0b01111111)\n\t\t\t\t| (this.isDynamic ? 0b10000000 : 0),\n\t\t\t]),\n\t\t\tencodeApplicationNodeInformation(this),\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\t\"endpoint index\": this.endpointIndex,\n\t\t\t\t\"generic device class\": getGenericDeviceClass(\n\t\t\t\t\tthis.genericDeviceClass,\n\t\t\t\t).label,\n\t\t\t\t\"specific device class\": getSpecificDeviceClass(\n\t\t\t\t\tthis.genericDeviceClass,\n\t\t\t\t\tthis.specificDeviceClass,\n\t\t\t\t).label,\n\t\t\t\t\"is dynamic end point\": this.isDynamic,\n\t\t\t\t\"supported CCs\": this.supportedCCs\n\t\t\t\t\t.map((cc) => `\\n\u00B7 ${getCCName(cc)}`)\n\t\t\t\t\t.join(\"\"),\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCCapabilityGetOptions {\n\trequestedEndpoint: number;\n}\n\nfunction testResponseForMultiChannelCapabilityGet(\n\tsent: MultiChannelCCCapabilityGet,\n\treceived: MultiChannelCCCapabilityReport,\n) {\n\treturn received.endpointIndex === sent.requestedEndpoint;\n}\n\n@CCCommand(MultiChannelCommand.CapabilityGet)\n@expectedCCResponse(\n\tMultiChannelCCCapabilityReport,\n\ttestResponseForMultiChannelCapabilityGet,\n)\nexport class MultiChannelCCCapabilityGet extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCCapabilityGetOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.requestedEndpoint = options.requestedEndpoint;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCCapabilityGet {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst requestedEndpoint = raw.payload[0] & 0b01111111;\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\trequestedEndpoint,\n\t\t});\n\t}\n\n\tpublic requestedEndpoint: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.requestedEndpoint & 0b01111111]);\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: { endpoint: this.requestedEndpoint },\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCEndPointFindReportOptions {\n\tgenericClass: number;\n\tspecificClass: number;\n\tfoundEndpoints: number[];\n\treportsToFollow: number;\n}\n\n@CCCommand(MultiChannelCommand.EndPointFindReport)\nexport class MultiChannelCCEndPointFindReport extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCEndPointFindReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.genericClass = options.genericClass;\n\t\tthis.specificClass = options.specificClass;\n\t\tthis.foundEndpoints = options.foundEndpoints;\n\t\tthis.reportsToFollow = options.reportsToFollow;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCEndPointFindReport {\n\t\tvalidatePayload(raw.payload.length >= 3);\n\t\tconst reportsToFollow = raw.payload[0];\n\t\tconst genericClass = raw.payload[1];\n\t\tconst specificClass = raw.payload[2];\n\n\t\t// Some devices omit the endpoint list although that is not allowed in the specs\n\t\t// therefore don't validatePayload here.\n\t\tconst foundEndpoints = [...raw.payload.subarray(3)]\n\t\t\t.map((e) => e & 0b01111111)\n\t\t\t.filter((e) => e !== 0);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\treportsToFollow,\n\t\t\tgenericClass,\n\t\t\tspecificClass,\n\t\t\tfoundEndpoints,\n\t\t});\n\t}\n\n\tpublic genericClass: number;\n\tpublic specificClass: number;\n\tpublic foundEndpoints: number[];\n\tpublic reportsToFollow: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([\n\t\t\t\tthis.reportsToFollow,\n\t\t\t\tthis.genericClass,\n\t\t\t\tthis.specificClass,\n\t\t\t]),\n\t\t\tBytes.from(this.foundEndpoints.map((e) => e & 0b01111111)),\n\t\t]);\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic getPartialCCSessionId(): Record<string, any> | undefined {\n\t\t// Distinguish sessions by the requested device classes\n\t\treturn {\n\t\t\tgenericClass: this.genericClass,\n\t\t\tspecificClass: this.specificClass,\n\t\t};\n\t}\n\n\tpublic expectMoreMessages(): boolean {\n\t\treturn this.reportsToFollow > 0;\n\t}\n\n\tpublic mergePartialCCs(\n\t\tpartials: MultiChannelCCEndPointFindReport[],\n\t\t_ctx: CCParsingContext,\n\t): Promise<void> {\n\t\t// Concat the list of end points\n\t\tthis.foundEndpoints = [...partials, this]\n\t\t\t.map((report) => report.foundEndpoints)\n\t\t\t.reduce((prev, cur) => prev.concat(...cur), []);\n\t\treturn Promise.resolve();\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\t\"generic device class\": getGenericDeviceClass(\n\t\t\t\t\tthis.genericClass,\n\t\t\t\t).label,\n\t\t\t\t\"specific device class\": getSpecificDeviceClass(\n\t\t\t\t\tthis.genericClass,\n\t\t\t\t\tthis.specificClass,\n\t\t\t\t).label,\n\t\t\t\t\"found endpoints\": this.foundEndpoints.join(\", \"),\n\t\t\t\t\"# of reports to follow\": this.reportsToFollow,\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCEndPointFindOptions {\n\tgenericClass: number;\n\tspecificClass: number;\n}\n\n@CCCommand(MultiChannelCommand.EndPointFind)\n@expectedCCResponse(MultiChannelCCEndPointFindReport)\nexport class MultiChannelCCEndPointFind extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCEndPointFindOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.genericClass = options.genericClass;\n\t\tthis.specificClass = options.specificClass;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCEndPointFind {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\tconst genericClass = raw.payload[0];\n\t\tconst specificClass = raw.payload[1];\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tgenericClass,\n\t\t\tspecificClass,\n\t\t});\n\t}\n\n\tpublic genericClass: number;\n\tpublic specificClass: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.genericClass, this.specificClass]);\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\t\"generic device class\":\n\t\t\t\t\tgetGenericDeviceClass(this.genericClass).label,\n\t\t\t\t\"specific device class\": getSpecificDeviceClass(\n\t\t\t\t\tthis.genericClass,\n\t\t\t\t\tthis.specificClass,\n\t\t\t\t).label,\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCAggregatedMembersReportOptions {\n\taggregatedEndpointIndex: number;\n\tmembers: number[];\n}\n\n@CCCommand(MultiChannelCommand.AggregatedMembersReport)\n@ccValueProperty(\n\t\"members\",\n\tMultiChannelCCValues.aggregatedEndpointMembers,\n\t(self) => [self.aggregatedEndpointIndex],\n)\nexport class MultiChannelCCAggregatedMembersReport extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCAggregatedMembersReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\t// TODO: Check implementation:\n\t\tthis.aggregatedEndpointIndex = options.aggregatedEndpointIndex;\n\t\tthis.members = options.members;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCAggregatedMembersReport {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\tconst aggregatedEndpointIndex = raw.payload[0] & 0b0111_1111;\n\t\tconst bitMaskLength = raw.payload[1];\n\t\tvalidatePayload(raw.payload.length >= 2 + bitMaskLength);\n\t\tconst bitMask = raw.payload.subarray(2, 2 + bitMaskLength);\n\t\tconst members = parseBitMask(bitMask);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\taggregatedEndpointIndex,\n\t\t\tmembers,\n\t\t});\n\t}\n\n\tpublic readonly aggregatedEndpointIndex: number;\n\n\tpublic readonly members: readonly number[];\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\t\"aggregated endpoint\": this.aggregatedEndpointIndex,\n\t\t\t\tmembers: this.members.join(\", \"),\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCAggregatedMembersGetOptions {\n\trequestedEndpoint: number;\n}\n\n@CCCommand(MultiChannelCommand.AggregatedMembersGet)\n@expectedCCResponse(MultiChannelCCAggregatedMembersReport)\nexport class MultiChannelCCAggregatedMembersGet extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCAggregatedMembersGetOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.requestedEndpoint = options.requestedEndpoint;\n\t}\n\n\tpublic static from(\n\t\t_raw: CCRaw,\n\t\t_ctx: CCParsingContext,\n\t): MultiChannelCCAggregatedMembersGet {\n\t\t// TODO: Deserialize payload\n\t\tthrow new ZWaveError(\n\t\t\t`${this.name}: deserialization not implemented`,\n\t\t\tZWaveErrorCodes.Deserialization_NotImplemented,\n\t\t);\n\n\t\t// return new MultiChannelCCAggregatedMembersGet({\n\t\t// \tnodeId: ctx.sourceNodeId,\n\t\t// });\n\t}\n\n\tpublic requestedEndpoint: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.requestedEndpoint & 0b0111_1111]);\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: { endpoint: this.requestedEndpoint },\n\t\t};\n\t}\n}\n\ntype MultiChannelCCDestination = number | (1 | 2 | 3 | 4 | 5 | 6 | 7)[];\n\n// @publicAPI\nexport interface MultiChannelCCCommandEncapsulationOptions {\n\tencapsulated: CommandClass;\n\tdestination: MultiChannelCCDestination;\n}\n\n// SDS13783: A receiving node MAY respond to a Multi Channel encapsulated command if the Destination\n// End Point field specifies a single End Point. In that case, the response MUST be Multi Channel\n// encapsulated.\n// A receiving node MUST NOT respond to a Multi Channel encapsulated command if the\n// Destination End Point field specifies multiple End Points via bit mask addressing.\n\nfunction getCCResponseForCommandEncapsulation(\n\tctx: GetNode<NodeId & SupportsCC>,\n\tsent: MultiChannelCCCommandEncapsulation,\n) {\n\tif (\n\t\ttypeof sent.destination === \"number\"\n\t\t&& sent.encapsulated.expectsCCResponse(ctx)\n\t) {\n\t\t// Allow both versions of the encapsulation command\n\t\t// Our implementation check is a bit too strict, so change the return type\n\t\treturn [\n\t\t\tMultiChannelCCCommandEncapsulation,\n\t\t\tMultiChannelCCV1CommandEncapsulation,\n\t\t] as any as (typeof MultiChannelCCCommandEncapsulation)[];\n\t}\n}\n\nfunction testResponseForCommandEncapsulation(\n\tsent: MultiChannelCCCommandEncapsulation,\n\treceived:\n\t\t| MultiChannelCCCommandEncapsulation\n\t\t| MultiChannelCCV1CommandEncapsulation,\n) {\n\tif (\n\t\ttypeof sent.destination === \"number\"\n\t\t&& sent.destination === received.endpointIndex\n\t) {\n\t\treturn \"checkEncapsulated\";\n\t}\n\treturn false;\n}\n\n@CCCommand(MultiChannelCommand.CommandEncapsulation)\n@expectedCCResponse(\n\tgetCCResponseForCommandEncapsulation,\n\ttestResponseForCommandEncapsulation,\n)\nexport class MultiChannelCCCommandEncapsulation extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCCommandEncapsulationOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.encapsulated = options.encapsulated;\n\t\tthis.encapsulated.encapsulatingCC = this as any;\n\t\t// Propagate the endpoint index all the way down\n\t\tlet cur: CommandClass = this;\n\t\twhile (cur) {\n\t\t\tif (isMultiEncapsulatingCommandClass(cur)) {\n\t\t\t\tfor (const cc of cur.encapsulated) {\n\t\t\t\t\tcc.endpointIndex = this.endpointIndex;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else if (isEncapsulatingCommandClass(cur)) {\n\t\t\t\tcur.encapsulated.endpointIndex = this.endpointIndex;\n\t\t\t\tcur = cur.encapsulated;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.destination = options.destination;\n\t}\n\n\tpublic static async from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): Promise<MultiChannelCCCommandEncapsulation> {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\n\t\tlet endpointIndex: number;\n\t\tlet destination: MultiChannelCCDestination;\n\n\t\tif (\n\t\t\tctx.getDeviceConfig?.(ctx.sourceNodeId)\n\t\t\t\t?.compat?.treatDestinationEndpointAsSource\n\t\t) {\n\t\t\t// This device incorrectly uses the destination field to indicate the source endpoint\n\t\t\tendpointIndex = raw.payload[1] & 0b0111_1111;\n\t\t\tdestination = 0;\n\t\t} else {\n\t\t\t// Parse normally\n\t\t\tendpointIndex = raw.payload[0] & 0b0111_1111;\n\t\t\tconst isBitMask = !!(raw.payload[1] & 0b1000_0000);\n\t\t\tdestination = raw.payload[1] & 0b0111_1111;\n\t\t\tif (isBitMask) {\n\t\t\t\tdestination = parseBitMask(\n\t\t\t\t\tBytes.from([destination]),\n\t\t\t\t) as any;\n\t\t\t}\n\t\t}\n\t\t// No need to validate further, each CC does it for itself\n\t\tconst encapsulated = await CommandClass.parse(\n\t\t\traw.payload.subarray(2),\n\t\t\tctx,\n\t\t);\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tendpointIndex,\n\t\t\tdestination,\n\t\t\tencapsulated,\n\t\t});\n\t}\n\n\tpublic encapsulated: CommandClass;\n\t/** The destination end point (0-127) or an array of destination end points (1-7) */\n\tpublic destination: MultiChannelCCDestination;\n\n\tpublic async serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tif (\n\t\t\tctx.getDeviceConfig?.(this.nodeId as number)?.compat\n\t\t\t\t?.treatDestinationEndpointAsSource\n\t\t) {\n\t\t\t// This device incorrectly responds from the endpoint we've passed as our source endpoint\n\t\t\tif (typeof this.destination === \"number\") {\n\t\t\t\tthis.endpointIndex = this.destination;\n\t\t\t}\n\t\t}\n\n\t\tconst destination = typeof this.destination === \"number\"\n\t\t\t// The destination is a single number\n\t\t\t? this.destination & 0b0111_1111\n\t\t\t// The destination is a bit mask\n\t\t\t: encodeBitMask(this.destination, 7)[0] | 0b1000_0000;\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([this.endpointIndex & 0b0111_1111, destination]),\n\t\t\tawait this.encapsulated.serialize(ctx),\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\tsource: this.endpointIndex,\n\t\t\t\tdestination: typeof this.destination === \"number\"\n\t\t\t\t\t? this.destination\n\t\t\t\t\t: this.destination.join(\", \"),\n\t\t\t},\n\t\t};\n\t}\n\n\tprotected computeEncapsulationOverhead(): number {\n\t\t// Multi Channel CC adds two bytes for the source and destination endpoint\n\t\treturn super.computeEncapsulationOverhead() + 2;\n\t}\n}\n\n// @publicAPI\nexport interface MultiChannelCCV1ReportOptions {\n\trequestedCC: CommandClasses;\n\tendpointCount: number;\n}\n\n@CCCommand(MultiChannelCommand.ReportV1)\nexport class MultiChannelCCV1Report extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCV1ReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\t// TODO: Check implementation:\n\t\tthis.requestedCC = options.requestedCC;\n\t\tthis.endpointCount = options.endpointCount;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCV1Report {\n\t\t// V1 won't be extended in the future, so do an exact check\n\t\tvalidatePayload(raw.payload.length === 2);\n\t\tconst requestedCC: CommandClasses = raw.payload[0];\n\t\tconst endpointCount = raw.payload[1];\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\trequestedCC,\n\t\t\tendpointCount,\n\t\t});\n\t}\n\n\tpublic readonly requestedCC: CommandClasses;\n\tpublic readonly endpointCount: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([\n\t\t\tthis.requestedCC,\n\t\t\tthis.endpointCount,\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\tCC: getCCName(this.requestedCC),\n\t\t\t\t\"# of endpoints\": this.endpointCount,\n\t\t\t},\n\t\t};\n\t}\n}\n\nfunction testResponseForMultiChannelV1Get(\n\tsent: MultiChannelCCV1Get,\n\treceived: MultiChannelCCV1Report,\n) {\n\treturn sent.requestedCC === received.requestedCC;\n}\n\n// @publicAPI\nexport interface MultiChannelCCV1GetOptions {\n\trequestedCC: CommandClasses;\n}\n\n@CCCommand(MultiChannelCommand.GetV1)\n@expectedCCResponse(MultiChannelCCV1Report, testResponseForMultiChannelV1Get)\nexport class MultiChannelCCV1Get extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCV1GetOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.requestedCC = options.requestedCC;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultiChannelCCV1Get {\n\t\t// V1 won't be extended in the future, so do an exact check\n\t\tvalidatePayload(raw.payload.length === 1);\n\t\tconst requestedCC: CommandClasses = raw.payload[0];\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\trequestedCC,\n\t\t});\n\t}\n\n\tpublic requestedCC: CommandClasses;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.requestedCC]);\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: { CC: getCCName(this.requestedCC) },\n\t\t};\n\t}\n}\n\nfunction getResponseForV1CommandEncapsulation(\n\tctx: GetNode<NodeId & SupportsCC>,\n\tsent: MultiChannelCCV1CommandEncapsulation,\n) {\n\tif (sent.encapsulated.expectsCCResponse(ctx)) {\n\t\treturn MultiChannelCCV1CommandEncapsulation;\n\t}\n}\n\nfunction testResponseForV1CommandEncapsulation(\n\tsent: MultiChannelCCV1CommandEncapsulation,\n\treceived: MultiChannelCCV1CommandEncapsulation,\n) {\n\tif (sent.endpointIndex === received.endpointIndex) {\n\t\treturn \"checkEncapsulated\";\n\t}\n\treturn false;\n}\n\n// @publicAPI\nexport interface MultiChannelCCV1CommandEncapsulationOptions {\n\tencapsulated: CommandClass;\n}\n\n@CCCommand(MultiChannelCommand.CommandEncapsulationV1)\n@expectedCCResponse(\n\tgetResponseForV1CommandEncapsulation,\n\ttestResponseForV1CommandEncapsulation,\n)\nexport class MultiChannelCCV1CommandEncapsulation extends MultiChannelCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultiChannelCCV1CommandEncapsulationOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.encapsulated = options.encapsulated;\n\t\tthis.encapsulated.encapsulatingCC = this as any;\n\t\t// Propagate the endpoint index all the way down\n\t\tlet cur: CommandClass = this;\n\t\twhile (cur) {\n\t\t\tif (isMultiEncapsulatingCommandClass(cur)) {\n\t\t\t\tfor (const cc of cur.encapsulated) {\n\t\t\t\t\tcc.endpointIndex = this.endpointIndex;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else if (isEncapsulatingCommandClass(cur)) {\n\t\t\t\tcur.encapsulated.endpointIndex = this.endpointIndex;\n\t\t\t\tcur = cur.encapsulated;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static async from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): Promise<MultiChannelCCV1CommandEncapsulation> {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst endpointIndex = raw.payload[0];\n\n\t\t// Some devices send invalid reports, i.e. MultiChannelCCV1CommandEncapsulation, but with V2+ binary format\n\t\t// This would be a NoOp CC, but it makes no sense to encapsulate that.\n\t\tconst isV2withV1Header = raw.payload.length >= 2\n\t\t\t&& raw.payload[1] === 0x00;\n\n\t\t// No need to validate further, each CC does it for itself\n\t\tconst encapsulated = await CommandClass.parse(\n\t\t\traw.payload.subarray(isV2withV1Header ? 2 : 1),\n\t\t\tctx,\n\t\t);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tendpointIndex,\n\t\t\tencapsulated,\n\t\t});\n\t}\n\n\tpublic encapsulated!: CommandClass;\n\n\tpublic async serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([this.endpointIndex]),\n\t\t\tawait this.encapsulated.serialize(ctx),\n\t\t]);\n\t\treturn super.serialize(ctx);\n\t}\n\n\tprotected computeEncapsulationOverhead(): number {\n\t\t// Multi Channel CC V1 adds one byte for the endpoint index\n\t\treturn super.computeEncapsulationOverhead() + 1;\n\t}\n\n\tpublic toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry {\n\t\treturn {\n\t\t\t...super.toLogEntry(ctx),\n\t\t\tmessage: { source: this.endpointIndex },\n\t\t};\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["endpoint"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cc/MultilevelSensorCC.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CCEncodingContext, CCParsingContext } from \"@zwave-js/cc\";\nimport type { GetDeviceConfig } from \"@zwave-js/config\";\nimport {\n\tCommandClasses,\n\ttype ControlsCC,\n\ttype EndpointId,\n\ttype GetEndpoint,\n\ttype GetNode,\n\ttype GetSupportedCCVersion,\n\ttype GetValueDB,\n\ttype LogNode,\n\ttype MaybeNotKnown,\n\ttype MessageOrCCLogEntry,\n\tMessagePriority,\n\ttype MessageRecord,\n\ttype NodeId,\n\ttype Scale,\n\ttype SinglecastCC,\n\ttype SupervisionResult,\n\ttype SupportsCC,\n\ttype ValueID,\n\tValueMetadata,\n\ttype WithAddress,\n\tencodeBitMask,\n\tencodeFloatWithScale,\n\tgetSensor,\n\tgetSensorName,\n\tgetSensorScale,\n\tgetUnknownScale,\n\tparseBitMask,\n\tparseFloatWithScale,\n\ttimespan,\n\tvalidatePayload,\n} from \"@zwave-js/core\";\nimport { type AllOrNone, Bytes, num2hex } from \"@zwave-js/shared\";\nimport { validateArgs } from \"@zwave-js/transformers\";\nimport {\n\tCCAPI,\n\tPOLL_VALUE,\n\tPhysicalCCAPI,\n\ttype PollValueImplementation,\n\tthrowUnsupportedProperty,\n} from \"../lib/API.js\";\nimport {\n\ttype CCRaw,\n\ttype CCResponsePredicate,\n\tCommandClass,\n\ttype InterviewContext,\n\ttype PersistValuesContext,\n\ttype RefreshValuesContext,\n\tgetEffectiveCCVersion,\n} from \"../lib/CommandClass.js\";\nimport {\n\tAPI,\n\tCCCommand,\n\tccValueProperty,\n\tccValues,\n\tcommandClass,\n\texpectedCCResponse,\n\timplementedVersion,\n\tuseSupervision,\n} from \"../lib/CommandClassDecorators.js\";\nimport { V } from \"../lib/Values.js\";\nimport {\n\tMultilevelSensorCommand,\n\ttype MultilevelSensorValue,\n} from \"../lib/_Types.js\";\nimport type { GetUserPreferences } from \"../lib/traits.js\";\n\nexport const MultilevelSensorCCValues = V.defineCCValues(\n\tCommandClasses[\"Multilevel Sensor\"],\n\t{\n\t\t...V.staticProperty(\"supportedSensorTypes\", undefined, {\n\t\t\tinternal: true,\n\t\t}),\n\t\t...V.dynamicPropertyAndKeyWithName(\n\t\t\t\"supportedScales\",\n\t\t\t\"supportedScales\",\n\t\t\t(sensorType: number) => sensorType,\n\t\t\t({ property, propertyKey }) =>\n\t\t\t\tproperty === \"supportedScales\"\n\t\t\t\t&& typeof propertyKey === \"number\",\n\t\t\tundefined,\n\t\t\t{ internal: true },\n\t\t),\n\t\t...V.dynamicPropertyWithName(\n\t\t\t\"value\",\n\t\t\t// This should have been the sensor type, but it is too late to change now\n\t\t\t// Maybe we can migrate this without breaking in the future\n\t\t\t(sensorTypeName: string) => sensorTypeName,\n\t\t\t({ property, propertyKey }) =>\n\t\t\t\ttypeof property === \"string\"\n\t\t\t\t&& property !== \"supportedSensorTypes\"\n\t\t\t\t&& property !== \"supportedScales\"\n\t\t\t\t&& propertyKey == undefined,\n\t\t\t(sensorTypeName: string) => ({\n\t\t\t\t// Just the base metadata, to be extended using a config manager\n\t\t\t\t...ValueMetadata.ReadOnlyNumber,\n\t\t\t\tlabel: sensorTypeName,\n\t\t\t} as const),\n\t\t),\n\t},\n);\n\n/**\n * Determine the scale to use to query a sensor reading. Uses the user-preferred scale if given,\n * followed by the most recently used scale, otherwile falls back to the first supported one.\n */\nfunction getPreferredSensorScale(\n\tctx: GetValueDB & GetUserPreferences & LogNode,\n\tnodeId: number,\n\tendpointIndex: number,\n\tsensorType: number,\n\tsupportedScales: readonly number[],\n): number {\n\tconst preferences = ctx.getUserPreferences();\n\tconst sensor = getSensor(sensorType);\n\t// If the sensor type is unknown, we have no default. Use the user-provided scale or 0\n\tif (!sensor) {\n\t\tconst preferred = preferences?.scales[sensorType];\n\t\t// We cannot look up strings for unknown sensor types, so this must be a number or we use the fallback\n\t\tif (typeof preferred !== \"number\") return 0;\n\t\treturn preferred;\n\t}\n\n\t// Look up the preference for the scale\n\tlet preferred: number | string | undefined;\n\t// Named scales apply to multiple sensor types. To be able to override the scale for single types\n\t// we need to look at the preferences by sensor type first\n\tpreferred = preferences?.scales[sensorType];\n\t// If the scale is named, we can then try to use the named preference\n\tconst scaleGroupName = sensor.scaleGroupName;\n\tif (preferred == undefined && scaleGroupName) {\n\t\tpreferred = preferences?.scales[scaleGroupName];\n\t}\n\t// Then attempt reading the scale from the corresponding value\n\tif (preferred == undefined) {\n\t\tconst sensorName = getSensorName(sensorType);\n\t\tconst sensorValue = MultilevelSensorCCValues.value(sensorName);\n\t\tconst metadata = ctx\n\t\t\t.tryGetValueDB(nodeId)\n\t\t\t?.getMetadata(sensorValue.endpoint(endpointIndex));\n\t\tconst scale = metadata?.ccSpecific?.scale;\n\t\tif (typeof scale === \"number\" && supportedScales.includes(scale)) {\n\t\t\tpreferred = scale;\n\t\t\tctx.logNode(nodeId, {\n\t\t\t\tendpoint: endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`No scale preference for sensor type ${sensorType}, using the last-used scale ${preferred}`,\n\t\t\t});\n\t\t}\n\t}\n\t// Then fall back to the first supported scale\n\tif (preferred == undefined) {\n\t\tpreferred = supportedScales[0] ?? 0;\n\t\tctx.logNode(nodeId, {\n\t\t\tendpoint: endpointIndex,\n\t\t\tmessage:\n\t\t\t\t`No scale preference for sensor type ${sensorType}, using the first supported scale ${preferred}`,\n\t\t});\n\t\treturn preferred;\n\t}\n\n\t// If the scale name or unit was given, try to look it up\n\tif (typeof preferred === \"string\") {\n\t\tfor (const [key, scale] of Object.entries(sensor.scales)) {\n\t\t\tif (scale.label === preferred || scale.unit === preferred) {\n\t\t\t\tpreferred = parseInt(key, 10);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (typeof preferred === \"string\") {\n\t\t// Looking up failed\n\t\tctx.logNode(nodeId, {\n\t\t\tendpoint: endpointIndex,\n\t\t\tmessage:\n\t\t\t\t`Preferred scale \"${preferred}\" for sensor type ${sensorType} not found, using the first supported scale ${\n\t\t\t\t\tsupportedScales[0] ?? 0\n\t\t\t\t}`,\n\t\t});\n\t\treturn supportedScales[0] ?? 0;\n\t}\n\n\t// We have a numeric scale key, nothing to look up. Make sure it is supported though\n\tif (!supportedScales.length) {\n\t\t// No info about supported scales, just use the preferred one\n\t\treturn preferred;\n\t} else if (!supportedScales.includes(preferred)) {\n\t\tctx.logNode(nodeId, {\n\t\t\tendpoint: endpointIndex,\n\t\t\tmessage:\n\t\t\t\t`Preferred scale ${preferred} not supported for sensor type ${sensorType}, using the first supported scale`,\n\t\t});\n\t\treturn supportedScales[0];\n\t} else {\n\t\treturn preferred;\n\t}\n}\n\n// @noSetValueAPI This CC is read-only\n\n@API(CommandClasses[\"Multilevel Sensor\"])\nexport class MultilevelSensorCCAPI extends PhysicalCCAPI {\n\tpublic supportsCommand(\n\t\tcmd: MultilevelSensorCommand,\n\t): MaybeNotKnown<boolean> {\n\t\tswitch (cmd) {\n\t\t\tcase MultilevelSensorCommand.Get:\n\t\t\tcase MultilevelSensorCommand.Report:\n\t\t\t\treturn true; // This is mandatory\n\t\t\tcase MultilevelSensorCommand.GetSupportedSensor:\n\t\t\tcase MultilevelSensorCommand.GetSupportedScale:\n\t\t\t\treturn this.version >= 5;\n\t\t}\n\t\treturn super.supportsCommand(cmd);\n\t}\n\n\tprotected get [POLL_VALUE](): PollValueImplementation {\n\t\treturn async function(this: MultilevelSensorCCAPI, { property }) {\n\t\t\t// Look up the necessary information\n\t\t\tconst valueId: ValueID = {\n\t\t\t\tcommandClass: CommandClasses[\"Multilevel Sensor\"],\n\t\t\t\tendpoint: this.endpoint.index,\n\t\t\t\tproperty,\n\t\t\t};\n\t\t\tconst ccSpecific = this.tryGetValueDB()?.getMetadata(valueId)\n\t\t\t\t?.ccSpecific;\n\t\t\tif (!ccSpecific) {\n\t\t\t\tthrowUnsupportedProperty(this.ccId, property);\n\t\t\t}\n\n\t\t\tconst { sensorType, scale } = ccSpecific;\n\t\t\treturn this.get(sensorType, scale);\n\t\t};\n\t}\n\n\t/** Query the default sensor value */\n\tpublic async get(): Promise<\n\t\tMaybeNotKnown<MultilevelSensorValue & { type: number }>\n\t>;\n\t/** Query the sensor value for the given sensor type using the preferred sensor scale */\n\tpublic async get(\n\t\tsensorType: number,\n\t): Promise<MaybeNotKnown<MultilevelSensorValue>>;\n\t/** Query the sensor value for the given sensor type using the given sensor scale */\n\tpublic async get(\n\t\tsensorType: number,\n\t\tscale: number,\n\t): Promise<MaybeNotKnown<number>>;\n\n\t@validateArgs()\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n\tpublic async get(sensorType?: number, scale?: number) {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultilevelSensorCommand,\n\t\t\tMultilevelSensorCommand.Get,\n\t\t);\n\n\t\t// Figure out the preferred scale if none was given\n\t\tlet preferredScale: number | undefined;\n\t\tif (sensorType != undefined && scale == undefined) {\n\t\t\tconst supportedScales: readonly number[] =\n\t\t\t\tthis.tryGetValueDB()?.getValue({\n\t\t\t\t\tcommandClass: this.ccId,\n\t\t\t\t\tendpoint: this.endpoint.index,\n\t\t\t\t\tproperty: \"supportedScales\",\n\t\t\t\t\tpropertyKey: sensorType,\n\t\t\t\t}) ?? [];\n\n\t\t\tpreferredScale = getPreferredSensorScale(\n\t\t\t\tthis.host,\n\t\t\t\tthis.endpoint.nodeId,\n\t\t\t\tthis.endpoint.index,\n\t\t\t\tsensorType,\n\t\t\t\tsupportedScales,\n\t\t\t);\n\t\t}\n\n\t\tconst cc = new MultilevelSensorCCGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tsensorType: sensorType!,\n\t\t\tscale: (scale ?? preferredScale)!,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultilevelSensorCCReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (!response) return;\n\n\t\tconst responseScale = getSensorScale(response.type, response.scale);\n\n\t\tif (sensorType == undefined) {\n\t\t\t// Overload #1: return the full response\n\t\t\treturn {\n\t\t\t\ttype: response.type,\n\t\t\t\tvalue: response.value,\n\t\t\t\tscale: responseScale,\n\t\t\t};\n\t\t} else if (scale == undefined) {\n\t\t\t// Overload #2: return value and scale\n\t\t\treturn {\n\t\t\t\tvalue: response.value,\n\t\t\t\tscale: responseScale,\n\t\t\t};\n\t\t} else {\n\t\t\t// Overload #3: return only the value\n\t\t\treturn response.value;\n\t\t}\n\t}\n\n\tpublic async getSupportedSensorTypes(): Promise<\n\t\tMaybeNotKnown<readonly number[]>\n\t> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultilevelSensorCommand,\n\t\t\tMultilevelSensorCommand.GetSupportedSensor,\n\t\t);\n\n\t\tconst cc = new MultilevelSensorCCGetSupportedSensor({\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<\n\t\t\tMultilevelSensorCCSupportedSensorReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.supportedSensorTypes;\n\t}\n\n\t@validateArgs()\n\tpublic async getSupportedScales(\n\t\tsensorType: number,\n\t): Promise<MaybeNotKnown<readonly number[]>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultilevelSensorCommand,\n\t\t\tMultilevelSensorCommand.GetSupportedScale,\n\t\t);\n\n\t\tconst cc = new MultilevelSensorCCGetSupportedScale({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tsensorType,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultilevelSensorCCSupportedScaleReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.supportedScales;\n\t}\n\n\t@validateArgs()\n\tpublic async sendReport(\n\t\tsensorType: number,\n\t\tscale: number | Scale,\n\t\tvalue: number,\n\t): Promise<SupervisionResult | undefined> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultilevelSensorCommand,\n\t\t\tMultilevelSensorCommand.Report,\n\t\t);\n\n\t\tconst cc = new MultilevelSensorCCReport({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\ttype: sensorType,\n\t\t\tscale,\n\t\t\tvalue,\n\t\t});\n\t\treturn this.host.sendCommand(cc, this.commandOptions);\n\t}\n}\n\n@commandClass(CommandClasses[\"Multilevel Sensor\"])\n@implementedVersion(11)\n@ccValues(MultilevelSensorCCValues)\nexport class MultilevelSensorCC extends CommandClass {\n\tdeclare ccCommand: MultilevelSensorCommand;\n\n\tpublic async interview(\n\t\tctx: InterviewContext,\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[\"Multilevel Sensor\"],\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: `Interviewing ${this.ccName}...`,\n\t\t\tdirection: \"none\",\n\t\t});\n\n\t\tif (api.version >= 5) {\n\t\t\t// Query the supported sensor types\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: \"retrieving supported sensor types...\",\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\t\t\tconst sensorTypes = await api.getSupportedSensorTypes();\n\t\t\tif (sensorTypes) {\n\t\t\t\tconst logMessage = \"received supported sensor types:\\n\"\n\t\t\t\t\t+ sensorTypes\n\t\t\t\t\t\t.map((t) => getSensorName(t))\n\t\t\t\t\t\t.map((name) => `\u00B7 ${name}`)\n\t\t\t\t\t\t.join(\"\\n\");\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} else {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"Querying supported sensor types timed out, skipping interview...\",\n\t\t\t\t\tlevel: \"warn\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// As well as the supported scales for each sensor\n\n\t\t\tfor (const type of sensorTypes) {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage: `querying supported scales for ${\n\t\t\t\t\t\tgetSensorName(type)\n\t\t\t\t\t} sensor`,\n\t\t\t\t\tdirection: \"outbound\",\n\t\t\t\t});\n\t\t\t\tconst sensorScales = await api.getSupportedScales(type);\n\t\t\t\tif (sensorScales) {\n\t\t\t\t\tconst logMessage = \"received supported scales:\\n\"\n\t\t\t\t\t\t+ sensorScales\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\t\t\t(getSensorScale(type, s)\n\t\t\t\t\t\t\t\t\t\t?? getUnknownScale(s)).label,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.map((name) => `\u00B7 ${name}`)\n\t\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\t\tmessage: logMessage,\n\t\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\"Querying supported scales timed out, skipping interview...\",\n\t\t\t\t\t\tlevel: \"warn\",\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\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[\"Multilevel Sensor\"],\n\t\t\tctx,\n\t\t\tendpoint,\n\t\t).withOptions({\n\t\t\tpriority: MessagePriority.NodeQuery,\n\t\t});\n\t\tconst valueDB = this.getValueDB(ctx);\n\n\t\tif (api.version <= 4) {\n\t\t\t// Sensors up to V4 only support a single value\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: \"querying current sensor reading...\",\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\t\t\tconst mlsResponse = await api.get();\n\t\t\tif (mlsResponse) {\n\t\t\t\tconst sensorScale = getSensorScale(\n\t\t\t\t\tmlsResponse.type,\n\t\t\t\t\tmlsResponse.scale.key,\n\t\t\t\t);\n\t\t\t\tconst logMessage = `received current sensor reading:\nsensor type: ${getSensorName(mlsResponse.type)}\nvalue: ${mlsResponse.value}${\n\t\t\t\t\tsensorScale?.unit ? ` ${sensorScale.unit}` : \"\"\n\t\t\t\t}`;\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} else {\n\t\t\t// Query all sensor values\n\t\t\tconst sensorTypes: readonly number[] = valueDB.getValue({\n\t\t\t\tcommandClass: this.ccId,\n\t\t\t\tproperty: \"supportedSensorTypes\",\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t}) || [];\n\n\t\t\tfor (const type of sensorTypes) {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage: `querying ${\n\t\t\t\t\t\tgetSensorName(type)\n\t\t\t\t\t} sensor reading...`,\n\t\t\t\t\tdirection: \"outbound\",\n\t\t\t\t});\n\n\t\t\t\tconst value = await api.get(type);\n\t\t\t\tif (value) {\n\t\t\t\t\tconst logMessage = `received current ${\n\t\t\t\t\t\tgetSensorName(type)\n\t\t\t\t\t} sensor reading: ${value.value} ${value.scale.unit || \"\"}`;\n\t\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\t\tmessage: logMessage,\n\t\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t\t});\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// Poll the device when all of the supported values were last updated longer than 6 hours ago.\n\t\t// This may lead to some values not being updated, but the user may have disabled some unnecessary\n\t\t// reports to reduce traffic.\n\t\tconst valueDB = ctx.tryGetValueDB(this.nodeId);\n\t\tif (!valueDB) return true;\n\n\t\tconst values = this.getDefinedValueIDs(ctx).filter((v) =>\n\t\t\tMultilevelSensorCCValues.value.is(v)\n\t\t);\n\t\treturn values.every((v) => {\n\t\t\tconst lastUpdated = valueDB.getTimestamp(v);\n\t\t\treturn (\n\t\t\t\tlastUpdated == undefined\n\t\t\t\t|| Date.now() - lastUpdated > timespan.hours(6)\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Returns which sensor types are supported.\n\t * This only works AFTER the interview process\n\t */\n\tpublic static getSupportedSensorTypesCached(\n\t\tctx: GetValueDB,\n\t\tendpoint: EndpointId,\n\t): MaybeNotKnown<number[]> {\n\t\treturn ctx\n\t\t\t.getValueDB(endpoint.nodeId)\n\t\t\t.getValue(\n\t\t\t\tMultilevelSensorCCValues.supportedSensorTypes.endpoint(\n\t\t\t\t\tendpoint.index,\n\t\t\t\t),\n\t\t\t);\n\t}\n\n\t/**\n\t * Returns which scales are supported for a given sensor type.\n\t * This only works AFTER the interview process\n\t */\n\tpublic static getSupportedScalesCached(\n\t\tctx: GetValueDB,\n\t\tendpoint: EndpointId,\n\t\tsensorType: number,\n\t): MaybeNotKnown<number[]> {\n\t\treturn ctx\n\t\t\t.getValueDB(endpoint.nodeId)\n\t\t\t.getValue(\n\t\t\t\tMultilevelSensorCCValues.supportedScales(sensorType).endpoint(\n\t\t\t\t\tendpoint.index,\n\t\t\t\t),\n\t\t\t);\n\t}\n\n\tpublic translatePropertyKey(\n\t\tctx: GetValueDB,\n\t\tproperty: string | number,\n\t\tpropertyKey: string | number,\n\t): string | undefined {\n\t\t// TODO: check this\n\t\tif (property === \"values\" && typeof propertyKey === \"number\") {\n\t\t\tconst sensor = getSensor(propertyKey);\n\t\t\tif (sensor) return sensor.label;\n\t\t}\n\t\treturn super.translatePropertyKey(ctx, property, propertyKey);\n\t}\n}\n\n// @publicAPI\nexport interface MultilevelSensorCCReportOptions {\n\ttype: number;\n\tscale: number | Scale;\n\tvalue: number;\n}\n\n@CCCommand(MultilevelSensorCommand.Report)\n@useSupervision()\nexport class MultilevelSensorCCReport extends MultilevelSensorCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.type = options.type;\n\t\tthis.value = options.value;\n\t\tthis.scale = typeof options.scale === \"number\"\n\t\t\t? options.scale\n\t\t\t: options.scale.key;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCReport {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst type = raw.payload[0];\n\n\t\t// parseFloatWithScale does its own validation\n\t\tconst { value, scale } = parseFloatWithScale(\n\t\t\traw.payload.subarray(1),\n\t\t);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\ttype,\n\t\t\tvalue,\n\t\t\tscale,\n\t\t});\n\t}\n\n\tpublic persistValues(ctx: PersistValuesContext): boolean {\n\t\tif (!super.persistValues(ctx)) return false;\n\n\t\tconst sensor = getSensor(this.type);\n\t\tconst scale = getSensorScale(\n\t\t\tthis.type,\n\t\t\tthis.scale,\n\t\t) ?? getUnknownScale(this.scale);\n\n\t\t// Filter out unknown sensor types and scales, unless the strict validation is disabled\n\t\tconst measurementValidation = !ctx.getDeviceConfig?.(\n\t\t\tthis.nodeId as number,\n\t\t)?.compat?.disableStrictMeasurementValidation;\n\n\t\tconst ccVersion = getEffectiveCCVersion(ctx, this);\n\n\t\tif (measurementValidation) {\n\t\t\t// Filter out unsupported sensor types and scales if possible\n\t\t\tif (ccVersion >= 5) {\n\t\t\t\tconst supportedSensorTypes = this.getValue<number[]>(\n\t\t\t\t\tctx,\n\t\t\t\t\tMultilevelSensorCCValues.supportedSensorTypes,\n\t\t\t\t);\n\t\t\t\tif (supportedSensorTypes?.length) {\n\t\t\t\t\tvalidatePayload.withReason(\n\t\t\t\t\t\t`Unsupported sensor type ${\n\t\t\t\t\t\t\tgetSensorName(this.type)\n\t\t\t\t\t\t} or corrupted data`,\n\t\t\t\t\t)(supportedSensorTypes.includes(this.type));\n\t\t\t\t}\n\n\t\t\t\tconst supportedScales = this.getValue<number[]>(\n\t\t\t\t\tctx,\n\t\t\t\t\tMultilevelSensorCCValues.supportedScales(this.type),\n\t\t\t\t);\n\t\t\t\tif (supportedScales?.length) {\n\t\t\t\t\tvalidatePayload.withReason(\n\t\t\t\t\t\t`Unsupported scale ${scale.label} or corrupted data`,\n\t\t\t\t\t)(supportedScales.includes(scale.key));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We support a higher CC version than the device, so any types and scales it uses should be known to us\n\t\t\t\t// Filter out unknown ones.\n\t\t\t\tvalidatePayload.withReason(\n\t\t\t\t\t`Unknown sensor type ${\n\t\t\t\t\t\tnum2hex(\n\t\t\t\t\t\t\tthis.type,\n\t\t\t\t\t\t)\n\t\t\t\t\t} or corrupted data`,\n\t\t\t\t)(!!sensor);\n\t\t\t\tvalidatePayload.withReason(\n\t\t\t\t\t`Unknown scale ${num2hex(this.scale)} or corrupted data`,\n\t\t\t\t)(scale.label !== getUnknownScale(this.scale).label);\n\t\t\t}\n\t\t}\n\n\t\tconst sensorName = getSensorName(this.type);\n\t\tconst sensorValue = MultilevelSensorCCValues.value(sensorName);\n\n\t\tthis.setMetadata(ctx, sensorValue, {\n\t\t\t...sensorValue.meta,\n\t\t\tunit: scale.unit,\n\t\t\tccSpecific: {\n\t\t\t\tsensorType: this.type,\n\t\t\t\tscale: scale.key,\n\t\t\t},\n\t\t});\n\t\tthis.setValue(ctx, sensorValue, this.value);\n\n\t\treturn true;\n\t}\n\n\tpublic type: number;\n\tpublic scale: number;\n\tpublic value: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([this.type]),\n\t\t\tencodeFloatWithScale(this.value, this.scale),\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\t\"sensor type\": getSensorName(this.type),\n\t\t\t\tscale: (getSensorScale(this.type, this.scale)\n\t\t\t\t\t?? getUnknownScale(this.scale)).label,\n\t\t\t\tvalue: this.value,\n\t\t\t},\n\t\t};\n\t}\n}\n\nconst testResponseForMultilevelSensorGet: CCResponsePredicate<\n\tMultilevelSensorCCGet,\n\tMultilevelSensorCCReport\n> = (sent, received) => {\n\t// We expect a Multilevel Sensor Report that matches the requested sensor type (if a type was requested)\n\treturn sent.sensorType == undefined || received.type === sent.sensorType;\n};\n\n// These options are supported starting in V5\n// @publicAPI\nexport type MultilevelSensorCCGetOptions = AllOrNone<{\n\tsensorType: number;\n\tscale: number;\n}>;\n\n@CCCommand(MultilevelSensorCommand.Get)\n@expectedCCResponse(\n\tMultilevelSensorCCReport,\n\ttestResponseForMultilevelSensorGet,\n)\nexport class MultilevelSensorCCGet extends MultilevelSensorCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCGetOptions>,\n\t) {\n\t\tsuper(options);\n\t\tif (\"sensorType\" in options) {\n\t\t\tthis.sensorType = options.sensorType;\n\t\t\tthis.scale = options.scale;\n\t\t}\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCGet {\n\t\tif (raw.payload.length >= 2) {\n\t\t\tconst sensorType = raw.payload[0];\n\t\t\tconst scale = (raw.payload[1] >> 3) & 0b11;\n\t\t\treturn new this({\n\t\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\t\tsensorType,\n\t\t\t\tscale,\n\t\t\t});\n\t\t} else {\n\t\t\treturn new this({\n\t\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic sensorType: number | undefined;\n\tpublic scale: number | undefined;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tif (\n\t\t\tthis.sensorType != undefined\n\t\t\t&& this.scale != undefined\n\t\t) {\n\t\t\tthis.payload = Bytes.from([\n\t\t\t\tthis.sensorType,\n\t\t\t\t(this.scale & 0b11) << 3,\n\t\t\t]);\n\t\t}\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry {\n\t\tlet message: MessageRecord = {};\n\t\tif (\n\t\t\tthis.sensorType != undefined\n\t\t\t&& this.scale != undefined\n\t\t) {\n\t\t\tmessage = {\n\t\t\t\t\"sensor type\": getSensorName(\n\t\t\t\t\tthis.sensorType,\n\t\t\t\t),\n\t\t\t\tscale: (getSensorScale(\n\t\t\t\t\tthis.sensorType,\n\t\t\t\t\tthis.scale,\n\t\t\t\t) ?? getUnknownScale(this.scale)).label,\n\t\t\t};\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// @publicAPI\nexport interface MultilevelSensorCCSupportedSensorReportOptions {\n\tsupportedSensorTypes: readonly number[];\n}\n\n@CCCommand(MultilevelSensorCommand.SupportedSensorReport)\n@ccValueProperty(\n\t\"supportedSensorTypes\",\n\tMultilevelSensorCCValues.supportedSensorTypes,\n)\nexport class MultilevelSensorCCSupportedSensorReport\n\textends MultilevelSensorCC\n{\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCSupportedSensorReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.supportedSensorTypes = options.supportedSensorTypes;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCSupportedSensorReport {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst supportedSensorTypes = parseBitMask(raw.payload);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tsupportedSensorTypes,\n\t\t});\n\t}\n\n\t// TODO: Use this during interview to precreate values\n\n\tpublic supportedSensorTypes: readonly number[];\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = encodeBitMask(this.supportedSensorTypes);\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\t\"supported sensor types\": this.supportedSensorTypes\n\t\t\t\t\t.map((t) => `\\n\u00B7 ${getSensorName(t)}`)\n\t\t\t\t\t.join(\"\"),\n\t\t\t},\n\t\t};\n\t}\n}\n\n@CCCommand(MultilevelSensorCommand.GetSupportedSensor)\n@expectedCCResponse(MultilevelSensorCCSupportedSensorReport)\nexport class MultilevelSensorCCGetSupportedSensor extends MultilevelSensorCC {}\n\n// @publicAPI\nexport interface MultilevelSensorCCSupportedScaleReportOptions {\n\tsensorType: number;\n\tsupportedScales: readonly number[];\n}\n\n@CCCommand(MultilevelSensorCommand.SupportedScaleReport)\n@ccValueProperty(\n\t\"supportedScales\",\n\tMultilevelSensorCCValues.supportedScales,\n\t(self) => [self.sensorType],\n)\nexport class MultilevelSensorCCSupportedScaleReport extends MultilevelSensorCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCSupportedScaleReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.sensorType = options.sensorType;\n\t\tthis.supportedScales = options.supportedScales;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCSupportedScaleReport {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\tconst sensorType = raw.payload[0];\n\t\tconst supportedScales = parseBitMask(\n\t\t\tBytes.from([raw.payload[1] & 0b1111]),\n\t\t\t0,\n\t\t);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tsensorType,\n\t\t\tsupportedScales,\n\t\t});\n\t}\n\n\tpublic readonly sensorType: number;\n\n\tpublic readonly supportedScales: readonly number[];\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([this.sensorType]),\n\t\t\tencodeBitMask(this.supportedScales, 4, 0),\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\t\"sensor type\": getSensorName(this.sensorType),\n\t\t\t\t\"supported scales\": this.supportedScales\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\t`\\n\u00B7 ${\n\t\t\t\t\t\t\t\t(getSensorScale(this.sensorType, s)\n\t\t\t\t\t\t\t\t\t?? getUnknownScale(s)).label\n\t\t\t\t\t\t\t}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join(\"\"),\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultilevelSensorCCGetSupportedScaleOptions {\n\tsensorType: number;\n}\n\n@CCCommand(MultilevelSensorCommand.GetSupportedScale)\n@expectedCCResponse(MultilevelSensorCCSupportedScaleReport)\nexport class MultilevelSensorCCGetSupportedScale extends MultilevelSensorCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCGetSupportedScaleOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.sensorType = options.sensorType;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCGetSupportedScale {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst sensorType = raw.payload[0];\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tsensorType,\n\t\t});\n\t}\n\n\tpublic sensorType: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.sensorType]);\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\t\"sensor type\": getSensorName(this.sensorType),\n\t\t\t},\n\t\t};\n\t}\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { CCEncodingContext, CCParsingContext } from \"@zwave-js/cc\";\nimport type { GetDeviceConfig } from \"@zwave-js/config\";\nimport {\n\tCommandClasses,\n\ttype ControlsCC,\n\ttype EndpointId,\n\ttype GetEndpoint,\n\ttype GetNode,\n\ttype GetSupportedCCVersion,\n\ttype GetValueDB,\n\ttype LogNode,\n\ttype MaybeNotKnown,\n\ttype MessageOrCCLogEntry,\n\tMessagePriority,\n\ttype MessageRecord,\n\ttype NodeId,\n\ttype Scale,\n\ttype SinglecastCC,\n\ttype SupervisionResult,\n\ttype SupportsCC,\n\ttype ValueID,\n\tValueMetadata,\n\ttype WithAddress,\n\tencodeBitMask,\n\tencodeFloatWithScale,\n\tgetSensor,\n\tgetSensorName,\n\tgetSensorScale,\n\tgetUnknownScale,\n\tparseBitMask,\n\tparseFloatWithScale,\n\ttimespan,\n\tvalidatePayload,\n} from \"@zwave-js/core\";\nimport { type AllOrNone, Bytes, num2hex } from \"@zwave-js/shared\";\nimport { validateArgs } from \"@zwave-js/transformers\";\nimport {\n\tCCAPI,\n\tPOLL_VALUE,\n\tPhysicalCCAPI,\n\ttype PollValueImplementation,\n\tthrowUnsupportedProperty,\n} from \"../lib/API.js\";\nimport {\n\ttype CCRaw,\n\ttype CCResponsePredicate,\n\tCommandClass,\n\ttype InterviewContext,\n\ttype PersistValuesContext,\n\ttype RefreshValuesContext,\n\tgetEffectiveCCVersion,\n} from \"../lib/CommandClass.js\";\nimport {\n\tAPI,\n\tCCCommand,\n\tccValueProperty,\n\tccValues,\n\tcommandClass,\n\texpectedCCResponse,\n\timplementedVersion,\n\tuseSupervision,\n} from \"../lib/CommandClassDecorators.js\";\nimport { V } from \"../lib/Values.js\";\nimport {\n\tMultilevelSensorCommand,\n\ttype MultilevelSensorValue,\n} from \"../lib/_Types.js\";\nimport type { GetUserPreferences } from \"../lib/traits.js\";\n\nexport const MultilevelSensorCCValues = V.defineCCValues(\n\tCommandClasses[\"Multilevel Sensor\"],\n\t{\n\t\t...V.staticProperty(\"supportedSensorTypes\", undefined, {\n\t\t\tinternal: true,\n\t\t}),\n\t\t...V.dynamicPropertyAndKeyWithName(\n\t\t\t\"supportedScales\",\n\t\t\t\"supportedScales\",\n\t\t\t(sensorType: number) => sensorType,\n\t\t\t({ property, propertyKey }) =>\n\t\t\t\tproperty === \"supportedScales\"\n\t\t\t\t&& typeof propertyKey === \"number\",\n\t\t\tundefined,\n\t\t\t{ internal: true },\n\t\t),\n\t\t...V.dynamicPropertyWithName(\n\t\t\t\"value\",\n\t\t\t// This should have been the sensor type, but it is too late to change now\n\t\t\t// Maybe we can migrate this without breaking in the future\n\t\t\t(sensorTypeName: string) => sensorTypeName,\n\t\t\t({ property, propertyKey }) =>\n\t\t\t\ttypeof property === \"string\"\n\t\t\t\t&& property !== \"supportedSensorTypes\"\n\t\t\t\t&& property !== \"supportedScales\"\n\t\t\t\t&& propertyKey == undefined,\n\t\t\t(sensorTypeName: string) => ({\n\t\t\t\t// Just the base metadata, to be extended using a config manager\n\t\t\t\t...ValueMetadata.ReadOnlyNumber,\n\t\t\t\tlabel: sensorTypeName,\n\t\t\t} as const),\n\t\t),\n\t},\n);\n\n/**\n * Determine the scale to use to query a sensor reading. Uses the user-preferred scale if given,\n * followed by the most recently used scale, otherwile falls back to the first supported one.\n */\nfunction getPreferredSensorScale(\n\tctx: GetValueDB & GetUserPreferences & LogNode,\n\tnodeId: number,\n\tendpointIndex: number,\n\tsensorType: number,\n\tsupportedScales: readonly number[],\n): number {\n\tconst preferences = ctx.getUserPreferences();\n\tconst sensor = getSensor(sensorType);\n\t// If the sensor type is unknown, we have no default. Use the user-provided scale or 0\n\tif (!sensor) {\n\t\tconst preferred = preferences?.scales[sensorType];\n\t\t// We cannot look up strings for unknown sensor types, so this must be a number or we use the fallback\n\t\tif (typeof preferred !== \"number\") return 0;\n\t\treturn preferred;\n\t}\n\n\t// Look up the preference for the scale\n\tlet preferred: number | string | undefined;\n\t// Named scales apply to multiple sensor types. To be able to override the scale for single types\n\t// we need to look at the preferences by sensor type first\n\tpreferred = preferences?.scales[sensorType];\n\t// If the scale is named, we can then try to use the named preference\n\tconst scaleGroupName = sensor.scaleGroupName;\n\tif (preferred == undefined && scaleGroupName) {\n\t\tpreferred = preferences?.scales[scaleGroupName];\n\t}\n\t// Then attempt reading the scale from the corresponding value\n\tif (preferred == undefined) {\n\t\tconst sensorName = getSensorName(sensorType);\n\t\tconst sensorValue = MultilevelSensorCCValues.value(sensorName);\n\t\tconst metadata = ctx\n\t\t\t.tryGetValueDB(nodeId)\n\t\t\t?.getMetadata(sensorValue.endpoint(endpointIndex));\n\t\tconst scale = metadata?.ccSpecific?.scale;\n\t\tif (typeof scale === \"number\" && supportedScales.includes(scale)) {\n\t\t\tpreferred = scale;\n\t\t\tctx.logNode(nodeId, {\n\t\t\t\tendpoint: endpointIndex,\n\t\t\t\tmessage:\n\t\t\t\t\t`No scale preference for sensor type ${sensorType}, using the last-used scale ${preferred}`,\n\t\t\t});\n\t\t}\n\t}\n\t// Then fall back to the first supported scale\n\tif (preferred == undefined) {\n\t\tpreferred = supportedScales[0] ?? 0;\n\t\tctx.logNode(nodeId, {\n\t\t\tendpoint: endpointIndex,\n\t\t\tmessage:\n\t\t\t\t`No scale preference for sensor type ${sensorType}, using the first supported scale ${preferred}`,\n\t\t});\n\t\treturn preferred;\n\t}\n\n\t// If the scale name or unit was given, try to look it up\n\tif (typeof preferred === \"string\") {\n\t\tfor (const [key, scale] of Object.entries(sensor.scales)) {\n\t\t\tif (scale.label === preferred || scale.unit === preferred) {\n\t\t\t\tpreferred = parseInt(key, 10);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (typeof preferred === \"string\") {\n\t\t// Looking up failed\n\t\tctx.logNode(nodeId, {\n\t\t\tendpoint: endpointIndex,\n\t\t\tmessage:\n\t\t\t\t`Preferred scale \"${preferred}\" for sensor type ${sensorType} not found, using the first supported scale ${\n\t\t\t\t\tsupportedScales[0] ?? 0\n\t\t\t\t}`,\n\t\t});\n\t\treturn supportedScales[0] ?? 0;\n\t}\n\n\t// We have a numeric scale key, nothing to look up. Make sure it is supported though\n\tif (!supportedScales.length) {\n\t\t// No info about supported scales, just use the preferred one\n\t\treturn preferred;\n\t} else if (!supportedScales.includes(preferred)) {\n\t\tctx.logNode(nodeId, {\n\t\t\tendpoint: endpointIndex,\n\t\t\tmessage:\n\t\t\t\t`Preferred scale ${preferred} not supported for sensor type ${sensorType}, using the first supported scale`,\n\t\t});\n\t\treturn supportedScales[0];\n\t} else {\n\t\treturn preferred;\n\t}\n}\n\n// @noSetValueAPI This CC is read-only\n\n@API(CommandClasses[\"Multilevel Sensor\"])\nexport class MultilevelSensorCCAPI extends PhysicalCCAPI {\n\tpublic supportsCommand(\n\t\tcmd: MultilevelSensorCommand,\n\t): MaybeNotKnown<boolean> {\n\t\tswitch (cmd) {\n\t\t\tcase MultilevelSensorCommand.Get:\n\t\t\tcase MultilevelSensorCommand.Report:\n\t\t\t\treturn true; // This is mandatory\n\t\t\tcase MultilevelSensorCommand.GetSupportedSensor:\n\t\t\tcase MultilevelSensorCommand.GetSupportedScale:\n\t\t\t\treturn this.version >= 5;\n\t\t}\n\t\treturn super.supportsCommand(cmd);\n\t}\n\n\tprotected get [POLL_VALUE](): PollValueImplementation {\n\t\treturn async function(this: MultilevelSensorCCAPI, { property }) {\n\t\t\t// Look up the necessary information\n\t\t\tconst valueId: ValueID = {\n\t\t\t\tcommandClass: CommandClasses[\"Multilevel Sensor\"],\n\t\t\t\tendpoint: this.endpoint.index,\n\t\t\t\tproperty,\n\t\t\t};\n\t\t\tconst ccSpecific = this.tryGetValueDB()?.getMetadata(valueId)\n\t\t\t\t?.ccSpecific;\n\t\t\tif (!ccSpecific) {\n\t\t\t\tthrowUnsupportedProperty(this.ccId, property);\n\t\t\t}\n\n\t\t\tconst { sensorType, scale } = ccSpecific;\n\t\t\treturn this.get(sensorType, scale);\n\t\t};\n\t}\n\n\t/** Query the default sensor value */\n\tpublic async get(): Promise<\n\t\tMaybeNotKnown<MultilevelSensorValue & { type: number }>\n\t>;\n\t/** Query the sensor value for the given sensor type using the preferred sensor scale */\n\tpublic async get(\n\t\tsensorType: number,\n\t): Promise<MaybeNotKnown<MultilevelSensorValue>>;\n\t/** Query the sensor value for the given sensor type using the given sensor scale */\n\tpublic async get(\n\t\tsensorType: number,\n\t\tscale: number,\n\t): Promise<MaybeNotKnown<number>>;\n\n\t@validateArgs()\n\t// oxlint-disable-next-line typescript/explicit-module-boundary-types\n\tpublic async get(sensorType?: number, scale?: number) {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultilevelSensorCommand,\n\t\t\tMultilevelSensorCommand.Get,\n\t\t);\n\n\t\t// Figure out the preferred scale if none was given\n\t\tlet preferredScale: number | undefined;\n\t\tif (sensorType != undefined && scale == undefined) {\n\t\t\tconst supportedScales: readonly number[] =\n\t\t\t\tthis.tryGetValueDB()?.getValue({\n\t\t\t\t\tcommandClass: this.ccId,\n\t\t\t\t\tendpoint: this.endpoint.index,\n\t\t\t\t\tproperty: \"supportedScales\",\n\t\t\t\t\tpropertyKey: sensorType,\n\t\t\t\t}) ?? [];\n\n\t\t\tpreferredScale = getPreferredSensorScale(\n\t\t\t\tthis.host,\n\t\t\t\tthis.endpoint.nodeId,\n\t\t\t\tthis.endpoint.index,\n\t\t\t\tsensorType,\n\t\t\t\tsupportedScales,\n\t\t\t);\n\t\t}\n\n\t\tconst cc = new MultilevelSensorCCGet({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tsensorType: sensorType!,\n\t\t\tscale: (scale ?? preferredScale)!,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultilevelSensorCCReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\tif (!response) return;\n\n\t\tconst responseScale = getSensorScale(response.type, response.scale);\n\n\t\tif (sensorType == undefined) {\n\t\t\t// Overload #1: return the full response\n\t\t\treturn {\n\t\t\t\ttype: response.type,\n\t\t\t\tvalue: response.value,\n\t\t\t\tscale: responseScale,\n\t\t\t};\n\t\t} else if (scale == undefined) {\n\t\t\t// Overload #2: return value and scale\n\t\t\treturn {\n\t\t\t\tvalue: response.value,\n\t\t\t\tscale: responseScale,\n\t\t\t};\n\t\t} else {\n\t\t\t// Overload #3: return only the value\n\t\t\treturn response.value;\n\t\t}\n\t}\n\n\tpublic async getSupportedSensorTypes(): Promise<\n\t\tMaybeNotKnown<readonly number[]>\n\t> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultilevelSensorCommand,\n\t\t\tMultilevelSensorCommand.GetSupportedSensor,\n\t\t);\n\n\t\tconst cc = new MultilevelSensorCCGetSupportedSensor({\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<\n\t\t\tMultilevelSensorCCSupportedSensorReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.supportedSensorTypes;\n\t}\n\n\t@validateArgs()\n\tpublic async getSupportedScales(\n\t\tsensorType: number,\n\t): Promise<MaybeNotKnown<readonly number[]>> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultilevelSensorCommand,\n\t\t\tMultilevelSensorCommand.GetSupportedScale,\n\t\t);\n\n\t\tconst cc = new MultilevelSensorCCGetSupportedScale({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\tsensorType,\n\t\t});\n\t\tconst response = await this.host.sendCommand<\n\t\t\tMultilevelSensorCCSupportedScaleReport\n\t\t>(\n\t\t\tcc,\n\t\t\tthis.commandOptions,\n\t\t);\n\t\treturn response?.supportedScales;\n\t}\n\n\t@validateArgs()\n\tpublic async sendReport(\n\t\tsensorType: number,\n\t\tscale: number | Scale,\n\t\tvalue: number,\n\t): Promise<SupervisionResult | undefined> {\n\t\tthis.assertSupportsCommand(\n\t\t\tMultilevelSensorCommand,\n\t\t\tMultilevelSensorCommand.Report,\n\t\t);\n\n\t\tconst cc = new MultilevelSensorCCReport({\n\t\t\tnodeId: this.endpoint.nodeId,\n\t\t\tendpointIndex: this.endpoint.index,\n\t\t\ttype: sensorType,\n\t\t\tscale,\n\t\t\tvalue,\n\t\t});\n\t\treturn this.host.sendCommand(cc, this.commandOptions);\n\t}\n}\n\n@commandClass(CommandClasses[\"Multilevel Sensor\"])\n@implementedVersion(11)\n@ccValues(MultilevelSensorCCValues)\nexport class MultilevelSensorCC extends CommandClass {\n\tdeclare ccCommand: MultilevelSensorCommand;\n\n\tpublic async interview(\n\t\tctx: InterviewContext,\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[\"Multilevel Sensor\"],\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: `Interviewing ${this.ccName}...`,\n\t\t\tdirection: \"none\",\n\t\t});\n\n\t\tif (api.version >= 5) {\n\t\t\t// Query the supported sensor types\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: \"retrieving supported sensor types...\",\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\t\t\tconst sensorTypes = await api.getSupportedSensorTypes();\n\t\t\tif (sensorTypes) {\n\t\t\t\tconst logMessage = \"received supported sensor types:\\n\"\n\t\t\t\t\t+ sensorTypes\n\t\t\t\t\t\t.map((t) => getSensorName(t))\n\t\t\t\t\t\t.map((name) => `\u00B7 ${name}`)\n\t\t\t\t\t\t.join(\"\\n\");\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} else {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"Querying supported sensor types timed out, skipping interview...\",\n\t\t\t\t\tlevel: \"warn\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// As well as the supported scales for each sensor\n\n\t\t\tfor (const type of sensorTypes) {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage: `querying supported scales for ${\n\t\t\t\t\t\tgetSensorName(type)\n\t\t\t\t\t} sensor`,\n\t\t\t\t\tdirection: \"outbound\",\n\t\t\t\t});\n\t\t\t\tconst sensorScales = await api.getSupportedScales(type);\n\t\t\t\tif (sensorScales) {\n\t\t\t\t\tconst logMessage = \"received supported scales:\\n\"\n\t\t\t\t\t\t+ sensorScales\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\t\t\t(getSensorScale(type, s)\n\t\t\t\t\t\t\t\t\t\t?? getUnknownScale(s)).label,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.map((name) => `\u00B7 ${name}`)\n\t\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\t\tmessage: logMessage,\n\t\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\"Querying supported scales timed out, skipping interview...\",\n\t\t\t\t\t\tlevel: \"warn\",\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\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[\"Multilevel Sensor\"],\n\t\t\tctx,\n\t\t\tendpoint,\n\t\t).withOptions({\n\t\t\tpriority: MessagePriority.NodeQuery,\n\t\t});\n\t\tconst valueDB = this.getValueDB(ctx);\n\n\t\tif (api.version <= 4) {\n\t\t\t// Sensors up to V4 only support a single value\n\t\t\tctx.logNode(node.id, {\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\tmessage: \"querying current sensor reading...\",\n\t\t\t\tdirection: \"outbound\",\n\t\t\t});\n\t\t\tconst mlsResponse = await api.get();\n\t\t\tif (mlsResponse) {\n\t\t\t\tconst sensorScale = getSensorScale(\n\t\t\t\t\tmlsResponse.type,\n\t\t\t\t\tmlsResponse.scale.key,\n\t\t\t\t);\n\t\t\t\tconst logMessage = `received current sensor reading:\nsensor type: ${getSensorName(mlsResponse.type)}\nvalue: ${mlsResponse.value}${\n\t\t\t\t\tsensorScale?.unit ? ` ${sensorScale.unit}` : \"\"\n\t\t\t\t}`;\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} else {\n\t\t\t// Query all sensor values\n\t\t\tconst sensorTypes: readonly number[] = valueDB.getValue({\n\t\t\t\tcommandClass: this.ccId,\n\t\t\t\tproperty: \"supportedSensorTypes\",\n\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t}) || [];\n\n\t\t\tfor (const type of sensorTypes) {\n\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\tmessage: `querying ${\n\t\t\t\t\t\tgetSensorName(type)\n\t\t\t\t\t} sensor reading...`,\n\t\t\t\t\tdirection: \"outbound\",\n\t\t\t\t});\n\n\t\t\t\tconst value = await api.get(type);\n\t\t\t\tif (value) {\n\t\t\t\t\tconst logMessage = `received current ${\n\t\t\t\t\t\tgetSensorName(type)\n\t\t\t\t\t} sensor reading: ${value.value} ${value.scale.unit || \"\"}`;\n\t\t\t\t\tctx.logNode(node.id, {\n\t\t\t\t\t\tendpoint: this.endpointIndex,\n\t\t\t\t\t\tmessage: logMessage,\n\t\t\t\t\t\tdirection: \"inbound\",\n\t\t\t\t\t});\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// Poll the device when all of the supported values were last updated longer than 6 hours ago.\n\t\t// This may lead to some values not being updated, but the user may have disabled some unnecessary\n\t\t// reports to reduce traffic.\n\t\tconst valueDB = ctx.tryGetValueDB(this.nodeId);\n\t\tif (!valueDB) return true;\n\n\t\tconst values = this.getDefinedValueIDs(ctx).filter((v) =>\n\t\t\tMultilevelSensorCCValues.value.is(v)\n\t\t);\n\t\treturn values.every((v) => {\n\t\t\tconst lastUpdated = valueDB.getTimestamp(v);\n\t\t\treturn (\n\t\t\t\tlastUpdated == undefined\n\t\t\t\t|| Date.now() - lastUpdated > timespan.hours(6)\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Returns which sensor types are supported.\n\t * This only works AFTER the interview process\n\t */\n\tpublic static getSupportedSensorTypesCached(\n\t\tctx: GetValueDB,\n\t\tendpoint: EndpointId,\n\t): MaybeNotKnown<number[]> {\n\t\treturn ctx\n\t\t\t.getValueDB(endpoint.nodeId)\n\t\t\t.getValue(\n\t\t\t\tMultilevelSensorCCValues.supportedSensorTypes.endpoint(\n\t\t\t\t\tendpoint.index,\n\t\t\t\t),\n\t\t\t);\n\t}\n\n\t/**\n\t * Returns which scales are supported for a given sensor type.\n\t * This only works AFTER the interview process\n\t */\n\tpublic static getSupportedScalesCached(\n\t\tctx: GetValueDB,\n\t\tendpoint: EndpointId,\n\t\tsensorType: number,\n\t): MaybeNotKnown<number[]> {\n\t\treturn ctx\n\t\t\t.getValueDB(endpoint.nodeId)\n\t\t\t.getValue(\n\t\t\t\tMultilevelSensorCCValues.supportedScales(sensorType).endpoint(\n\t\t\t\t\tendpoint.index,\n\t\t\t\t),\n\t\t\t);\n\t}\n\n\tpublic translatePropertyKey(\n\t\tctx: GetValueDB,\n\t\tproperty: string | number,\n\t\tpropertyKey: string | number,\n\t): string | undefined {\n\t\t// TODO: check this\n\t\tif (property === \"values\" && typeof propertyKey === \"number\") {\n\t\t\tconst sensor = getSensor(propertyKey);\n\t\t\tif (sensor) return sensor.label;\n\t\t}\n\t\treturn super.translatePropertyKey(ctx, property, propertyKey);\n\t}\n}\n\n// @publicAPI\nexport interface MultilevelSensorCCReportOptions {\n\ttype: number;\n\tscale: number | Scale;\n\tvalue: number;\n}\n\n@CCCommand(MultilevelSensorCommand.Report)\n@useSupervision()\nexport class MultilevelSensorCCReport extends MultilevelSensorCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.type = options.type;\n\t\tthis.value = options.value;\n\t\tthis.scale = typeof options.scale === \"number\"\n\t\t\t? options.scale\n\t\t\t: options.scale.key;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCReport {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst type = raw.payload[0];\n\n\t\t// parseFloatWithScale does its own validation\n\t\tconst { value, scale } = parseFloatWithScale(\n\t\t\traw.payload.subarray(1),\n\t\t);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\ttype,\n\t\t\tvalue,\n\t\t\tscale,\n\t\t});\n\t}\n\n\tpublic persistValues(ctx: PersistValuesContext): boolean {\n\t\tif (!super.persistValues(ctx)) return false;\n\n\t\tconst sensor = getSensor(this.type);\n\t\tconst scale = getSensorScale(\n\t\t\tthis.type,\n\t\t\tthis.scale,\n\t\t) ?? getUnknownScale(this.scale);\n\n\t\t// Filter out unknown sensor types and scales, unless the strict validation is disabled\n\t\tconst measurementValidation = !ctx.getDeviceConfig?.(\n\t\t\tthis.nodeId as number,\n\t\t)?.compat?.disableStrictMeasurementValidation;\n\n\t\tconst ccVersion = getEffectiveCCVersion(ctx, this);\n\n\t\tif (measurementValidation) {\n\t\t\t// Filter out unsupported sensor types and scales if possible\n\t\t\tif (ccVersion >= 5) {\n\t\t\t\tconst supportedSensorTypes = this.getValue<number[]>(\n\t\t\t\t\tctx,\n\t\t\t\t\tMultilevelSensorCCValues.supportedSensorTypes,\n\t\t\t\t);\n\t\t\t\tif (supportedSensorTypes?.length) {\n\t\t\t\t\tvalidatePayload.withReason(\n\t\t\t\t\t\t`Unsupported sensor type ${\n\t\t\t\t\t\t\tgetSensorName(this.type)\n\t\t\t\t\t\t} or corrupted data`,\n\t\t\t\t\t)(supportedSensorTypes.includes(this.type));\n\t\t\t\t}\n\n\t\t\t\tconst supportedScales = this.getValue<number[]>(\n\t\t\t\t\tctx,\n\t\t\t\t\tMultilevelSensorCCValues.supportedScales(this.type),\n\t\t\t\t);\n\t\t\t\tif (supportedScales?.length) {\n\t\t\t\t\tvalidatePayload.withReason(\n\t\t\t\t\t\t`Unsupported scale ${scale.label} or corrupted data`,\n\t\t\t\t\t)(supportedScales.includes(scale.key));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We support a higher CC version than the device, so any types and scales it uses should be known to us\n\t\t\t\t// Filter out unknown ones.\n\t\t\t\tvalidatePayload.withReason(\n\t\t\t\t\t`Unknown sensor type ${\n\t\t\t\t\t\tnum2hex(\n\t\t\t\t\t\t\tthis.type,\n\t\t\t\t\t\t)\n\t\t\t\t\t} or corrupted data`,\n\t\t\t\t)(!!sensor);\n\t\t\t\tvalidatePayload.withReason(\n\t\t\t\t\t`Unknown scale ${num2hex(this.scale)} or corrupted data`,\n\t\t\t\t)(scale.label !== getUnknownScale(this.scale).label);\n\t\t\t}\n\t\t}\n\n\t\tconst sensorName = getSensorName(this.type);\n\t\tconst sensorValue = MultilevelSensorCCValues.value(sensorName);\n\n\t\tthis.setMetadata(ctx, sensorValue, {\n\t\t\t...sensorValue.meta,\n\t\t\tunit: scale.unit,\n\t\t\tccSpecific: {\n\t\t\t\tsensorType: this.type,\n\t\t\t\tscale: scale.key,\n\t\t\t},\n\t\t});\n\t\tthis.setValue(ctx, sensorValue, this.value);\n\n\t\treturn true;\n\t}\n\n\tpublic type: number;\n\tpublic scale: number;\n\tpublic value: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([this.type]),\n\t\t\tencodeFloatWithScale(this.value, this.scale),\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\t\"sensor type\": getSensorName(this.type),\n\t\t\t\tscale: (getSensorScale(this.type, this.scale)\n\t\t\t\t\t?? getUnknownScale(this.scale)).label,\n\t\t\t\tvalue: this.value,\n\t\t\t},\n\t\t};\n\t}\n}\n\nconst testResponseForMultilevelSensorGet: CCResponsePredicate<\n\tMultilevelSensorCCGet,\n\tMultilevelSensorCCReport\n> = (sent, received) => {\n\t// We expect a Multilevel Sensor Report that matches the requested sensor type (if a type was requested)\n\treturn sent.sensorType == undefined || received.type === sent.sensorType;\n};\n\n// These options are supported starting in V5\n// @publicAPI\nexport type MultilevelSensorCCGetOptions = AllOrNone<{\n\tsensorType: number;\n\tscale: number;\n}>;\n\n@CCCommand(MultilevelSensorCommand.Get)\n@expectedCCResponse(\n\tMultilevelSensorCCReport,\n\ttestResponseForMultilevelSensorGet,\n)\nexport class MultilevelSensorCCGet extends MultilevelSensorCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCGetOptions>,\n\t) {\n\t\tsuper(options);\n\t\tif (\"sensorType\" in options) {\n\t\t\tthis.sensorType = options.sensorType;\n\t\t\tthis.scale = options.scale;\n\t\t}\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCGet {\n\t\tif (raw.payload.length >= 2) {\n\t\t\tconst sensorType = raw.payload[0];\n\t\t\tconst scale = (raw.payload[1] >> 3) & 0b11;\n\t\t\treturn new this({\n\t\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\t\tsensorType,\n\t\t\t\tscale,\n\t\t\t});\n\t\t} else {\n\t\t\treturn new this({\n\t\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic sensorType: number | undefined;\n\tpublic scale: number | undefined;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tif (\n\t\t\tthis.sensorType != undefined\n\t\t\t&& this.scale != undefined\n\t\t) {\n\t\t\tthis.payload = Bytes.from([\n\t\t\t\tthis.sensorType,\n\t\t\t\t(this.scale & 0b11) << 3,\n\t\t\t]);\n\t\t}\n\t\treturn super.serialize(ctx);\n\t}\n\n\tpublic toLogEntry(ctx?: GetValueDB): MessageOrCCLogEntry {\n\t\tlet message: MessageRecord = {};\n\t\tif (\n\t\t\tthis.sensorType != undefined\n\t\t\t&& this.scale != undefined\n\t\t) {\n\t\t\tmessage = {\n\t\t\t\t\"sensor type\": getSensorName(\n\t\t\t\t\tthis.sensorType,\n\t\t\t\t),\n\t\t\t\tscale: (getSensorScale(\n\t\t\t\t\tthis.sensorType,\n\t\t\t\t\tthis.scale,\n\t\t\t\t) ?? getUnknownScale(this.scale)).label,\n\t\t\t};\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// @publicAPI\nexport interface MultilevelSensorCCSupportedSensorReportOptions {\n\tsupportedSensorTypes: readonly number[];\n}\n\n@CCCommand(MultilevelSensorCommand.SupportedSensorReport)\n@ccValueProperty(\n\t\"supportedSensorTypes\",\n\tMultilevelSensorCCValues.supportedSensorTypes,\n)\nexport class MultilevelSensorCCSupportedSensorReport\n\textends MultilevelSensorCC\n{\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCSupportedSensorReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.supportedSensorTypes = options.supportedSensorTypes;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCSupportedSensorReport {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst supportedSensorTypes = parseBitMask(raw.payload);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tsupportedSensorTypes,\n\t\t});\n\t}\n\n\t// TODO: Use this during interview to precreate values\n\n\tpublic supportedSensorTypes: readonly number[];\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = encodeBitMask(this.supportedSensorTypes);\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\t\"supported sensor types\": this.supportedSensorTypes\n\t\t\t\t\t.map((t) => `\\n\u00B7 ${getSensorName(t)}`)\n\t\t\t\t\t.join(\"\"),\n\t\t\t},\n\t\t};\n\t}\n}\n\n@CCCommand(MultilevelSensorCommand.GetSupportedSensor)\n@expectedCCResponse(MultilevelSensorCCSupportedSensorReport)\nexport class MultilevelSensorCCGetSupportedSensor extends MultilevelSensorCC {}\n\n// @publicAPI\nexport interface MultilevelSensorCCSupportedScaleReportOptions {\n\tsensorType: number;\n\tsupportedScales: readonly number[];\n}\n\n@CCCommand(MultilevelSensorCommand.SupportedScaleReport)\n@ccValueProperty(\n\t\"supportedScales\",\n\tMultilevelSensorCCValues.supportedScales,\n\t(self) => [self.sensorType],\n)\nexport class MultilevelSensorCCSupportedScaleReport extends MultilevelSensorCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCSupportedScaleReportOptions>,\n\t) {\n\t\tsuper(options);\n\n\t\tthis.sensorType = options.sensorType;\n\t\tthis.supportedScales = options.supportedScales;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCSupportedScaleReport {\n\t\tvalidatePayload(raw.payload.length >= 2);\n\t\tconst sensorType = raw.payload[0];\n\t\tconst supportedScales = parseBitMask(\n\t\t\tBytes.from([raw.payload[1] & 0b1111]),\n\t\t\t0,\n\t\t);\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tsensorType,\n\t\t\tsupportedScales,\n\t\t});\n\t}\n\n\tpublic readonly sensorType: number;\n\n\tpublic readonly supportedScales: readonly number[];\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.concat([\n\t\t\tBytes.from([this.sensorType]),\n\t\t\tencodeBitMask(this.supportedScales, 4, 0),\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\t\"sensor type\": getSensorName(this.sensorType),\n\t\t\t\t\"supported scales\": this.supportedScales\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\t`\\n\u00B7 ${\n\t\t\t\t\t\t\t\t(getSensorScale(this.sensorType, s)\n\t\t\t\t\t\t\t\t\t?? getUnknownScale(s)).label\n\t\t\t\t\t\t\t}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join(\"\"),\n\t\t\t},\n\t\t};\n\t}\n}\n\n// @publicAPI\nexport interface MultilevelSensorCCGetSupportedScaleOptions {\n\tsensorType: number;\n}\n\n@CCCommand(MultilevelSensorCommand.GetSupportedScale)\n@expectedCCResponse(MultilevelSensorCCSupportedScaleReport)\nexport class MultilevelSensorCCGetSupportedScale extends MultilevelSensorCC {\n\tpublic constructor(\n\t\toptions: WithAddress<MultilevelSensorCCGetSupportedScaleOptions>,\n\t) {\n\t\tsuper(options);\n\t\tthis.sensorType = options.sensorType;\n\t}\n\n\tpublic static from(\n\t\traw: CCRaw,\n\t\tctx: CCParsingContext,\n\t): MultilevelSensorCCGetSupportedScale {\n\t\tvalidatePayload(raw.payload.length >= 1);\n\t\tconst sensorType = raw.payload[0];\n\n\t\treturn new this({\n\t\t\tnodeId: ctx.sourceNodeId,\n\t\t\tsensorType,\n\t\t});\n\t}\n\n\tpublic sensorType: number;\n\n\tpublic serialize(ctx: CCEncodingContext): Promise<Bytes> {\n\t\tthis.payload = Bytes.from([this.sensorType]);\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\t\"sensor type\": getSensorName(this.sensorType),\n\t\t\t},\n\t\t};\n\t}\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["preferred"]
|
|
7
7
|
}
|
|
@@ -131,7 +131,7 @@ let MultilevelSwitchCCAPI = (() => {
|
|
|
131
131
|
}
|
|
132
132
|
return super.supportsCommand(cmd);
|
|
133
133
|
}
|
|
134
|
-
//
|
|
134
|
+
// oxlint-disable-next-line typescript/explicit-module-boundary-types
|
|
135
135
|
async get() {
|
|
136
136
|
this.assertSupportsCommand(import_Types.MultilevelSwitchCommand, import_Types.MultilevelSwitchCommand.Get);
|
|
137
137
|
const cc = new MultilevelSwitchCCGet({
|