import type { ValueID } from "@zwave-js/core" ; import { CommandClasses , enumValuesToMetadataStates , Maybe , MessageOrCCLogEntry , parseBitMask , validatePayload , ValueMetadata , ZWaveError , ZWaveErrorCodes , } from "@zwave-js/core" ; import { getEnumMemberName } from "@zwave-js/shared" ; import type { Driver } from "../driver/Driver" ; import { MessagePriority } from "../message/Constants" ; import { CCAPI , PollValueImplementation , POLL_VALUE , SetValueImplementation , SET_VALUE , throwUnsupportedProperty , throwWrongValueType , } from "./API" ; import { API , CCCommand , CCCommandOptions , ccValue , ccValueMetadata , CommandClass , commandClass , CommandClassDeserializationOptions , expectedCCResponse , gotDeserializationOptions , implementedVersion , } from "./CommandClass" ; export enum HumidityControlModeCommand { Set = 0x01 , Get = 0x02 , Report = 0x03 , SupportedGet = 0x04 , SupportedReport = 0x05 } export enum HumidityControlMode { "Off" = 0x00 , "Humidify" = 0x01 , "De-humidify" = 0x02 , "Auto" = 0x03 } @ API ( CommandClasses [ "Humidity Control Mode" ] ) export class HumidityControlModeCCAPI extends CCAPI { public supportsCommand ( cmd ) { switch ( cmd ) { case HumidityControlModeCommand . Get : case HumidityControlModeCommand . SupportedGet : return this . isSinglecast ( ) ; case HumidityControlModeCommand . Set : return true ; } return super . supportsCommand ( cmd ) ; } protected [ SET_VALUE ] : SetValueImplementation = async ( { property } , value ) : Promise < void > => { if ( property === "mode" ) { if ( typeof value !== "number" ) { throwWrongValueType ( this . ccId , property , "number" , typeof value ) ; } } else { throwUnsupportedProperty ( this . ccId , property ) ; } await this . set ( value ) ; if ( this . isSinglecast ( ) ) { this . schedulePoll ( { property } ) ; } } ; protected [ POLL_VALUE ] : PollValueImplementation = async ( { property , } ) : Promise < unknown > => { switch ( property ) { case "mode" : return this . get ( ) ; default : throwUnsupportedProperty ( this . ccId , property ) ; } } ; public async get ( ) { this . assertSupportsCommand ( HumidityControlModeCommand , HumidityControlModeCommand . Get ) ; const cc = new HumidityControlModeCCGet ( this . driver , { nodeId : this . endpoint . nodeId , endpoint : this . endpoint . index } ) ; const response = await this . driver . sendCommand < HumidityControlModeCCReport > ( cc , this . commandOptions ) ; if ( response ) { return response ?. mode ; } } public async set ( mode ) { this . assertSupportsCommand ( HumidityControlModeCommand , HumidityControlModeCommand . Set ) ; const cc = new HumidityControlModeCCSet ( this . driver , { nodeId : this . endpoint . nodeId , endpoint : this . endpoint . index , mode } ) ; await this . driver . sendCommand ( cc , this . commandOptions ) ; } public async getSupportedModes ( ) { this . assertSupportsCommand ( HumidityControlModeCommand , HumidityControlModeCommand . SupportedGet ) ; const cc = new HumidityControlModeCCSupportedGet ( this . driver , { nodeId : this . endpoint . nodeId , endpoint : this . endpoint . index } ) ; const response = await this . driver . sendCommand < HumidityControlModeCCSupportedReport > ( cc , this . commandOptions ) ; return response ?. supportedModes ; } } @ commandClass ( CommandClasses [ "Humidity Control Mode" ] ) @ implementedVersion ( 2 ) export class HumidityControlModeCC extends CommandClass { declare ccCommand : HumidityControlModeCommand ; public async interview ( ) { const node = this . getNode ( ) ! ; const endpoint = this . getEndpoint ( ) ! ; const api = endpoint . commandClasses [ "Humidity Control Mode" ] . withOptions ( { priority : MessagePriority . NodeQuery } ) ; this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : `Interviewing ${ this . ccName }...` , direction : "none" } ) ; this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : "querying supported humidity control modes..." , direction : "outbound" } ) ; const supportedModes = await api . getSupportedModes ( ) ; if ( supportedModes ) { const logMessage = `received supported humidity control modes:${ supportedModes . map ( ( mode ) => `\n· ${ getEnumMemberName ( HumidityControlMode , mode ) }` ) . join ( "" ) }` ; this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : logMessage , direction : "inbound" } ) ; } else { this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : "Querying supported humidity control modes timed out, skipping interview..." , level : "warn" } ) ; return ; } await this . refreshValues ( ) ; this . interviewComplete = true ; } public async refreshValues ( ) { const node = this . getNode ( ) ! ; const endpoint = this . getEndpoint ( ) ! ; const api = endpoint . commandClasses [ "Humidity Control Mode" ] . withOptions ( { priority : MessagePriority . NodeQuery } ) ; this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : "querying current humidity control mode..." , direction : "outbound" } ) ; const currentMode = await api . get ( ) ; if ( currentMode ) { this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : "received current humidity control mode: " + getEnumMemberName ( HumidityControlMode , currentMode ) , direction : "inbound" } ) ; } } } interface HumidityControlModeCCSetOptions extends CCCommandOptions { mode : HumidityControlMode ; } @ CCCommand ( HumidityControlModeCommand . Set ) export class HumidityControlModeCCSet extends HumidityControlModeCC { public constructor ( driver , options ) { super ( driver , options ) ; if ( gotDeserializationOptions ( options ) ) { throw new ZWaveError ( `${ this . constructor . name }: deserialization not implemented` , ZWaveErrorCodes . Deserialization_NotImplemented ) ; } else { this . mode = options . mode ; } } public mode : HumidityControlMode ; public serialize ( ) { this . payload = Buffer . from ( [ this . mode & 0b1111 ] ) ; return super . serialize ( ) ; } public toLogEntry ( ) { return { ... super . toLogEntry ( ) , message : { mode : getEnumMemberName ( HumidityControlMode , this . mode ) } } ; } } @ CCCommand ( HumidityControlModeCommand . Report ) export class HumidityControlModeCCReport extends HumidityControlModeCC { public constructor ( driver , options ) { super ( driver , options ) ; validatePayload ( this . payload . length >= 1 ) ; this . _mode = this . payload [ 0 ] & 0b1111 ; this . persistValues ( ) ; } private _mode : HumidityControlMode ; @ ccValue ( ) @ ccValueMetadata ( { ... ValueMetadata . UInt8 , states : enumValuesToMetadataStates ( HumidityControlMode ) , label : "Humidity control mode" } ) public get mode ( ) : HumidityControlMode { return this . _mode ; } public toLogEntry ( ) { return { ... super . toLogEntry ( ) , message : { mode : getEnumMemberName ( HumidityControlMode , this . mode ) } } ; } } @ CCCommand ( HumidityControlModeCommand . Get ) @ expectedCCResponse ( HumidityControlModeCCReport ) export class HumidityControlModeCCGet extends HumidityControlModeCC { } @ CCCommand ( HumidityControlModeCommand . SupportedReport ) export class HumidityControlModeCCSupportedReport extends HumidityControlModeCC { public constructor ( driver , options ) { super ( driver , options ) ; validatePayload ( this . payload . length >= 1 ) ; this . _supportedModes = parseBitMask ( this . payload , HumidityControlMode . Off ) ; if ( ! this . _supportedModes . includes ( HumidityControlMode . Off ) ) { this . _supportedModes . unshift ( HumidityControlMode . Off ) ; } const valueId = { commandClass : this . ccId , endpoint : this . endpointIndex , property : "mode" } ; this . getValueDB ( ) . setMetadata ( valueId , { ... ValueMetadata . UInt8 , states : enumValuesToMetadataStates ( HumidityControlMode , this . _supportedModes ) } ) ; this . persistValues ( ) ; } private _supportedModes : HumidityControlMode [ ] ; @ ccValue ( { internal : true } ) public get supportedModes ( ) : readonly HumidityControlMode [ ] { return this . _supportedModes ; } public toLogEntry ( ) { return { ... super . toLogEntry ( ) , message : { "supported modes" : this . supportedModes . map ( ( mode ) => `\n· ${ getEnumMemberName ( HumidityControlMode , mode ) }` ) . join ( "" ) } } ; } } @ CCCommand ( HumidityControlModeCommand . SupportedGet ) @ expectedCCResponse ( HumidityControlModeCCSupportedReport ) export class HumidityControlModeCCSupportedGet extends HumidityControlModeCC { }