import type { Maybe , MessageOrCCLogEntry } from "@zwave-js/core" ; import { CommandClasses , validatePayload , ValueMetadata , ZWaveError , ZWaveErrorCodes , } from "@zwave-js/core" ; import { getEnumMemberName , pick } from "@zwave-js/shared" ; import type { Driver } from "../driver/Driver" ; import { MessagePriority } from "../message/Constants" ; import { decodeSetbackState , encodeSetbackState , SetbackState , } from "../values/SetbackState" ; import { CCAPI , PollValueImplementation , POLL_VALUE , throwUnsupportedProperty , } from "./API" ; import { API , CCCommand , CCCommandOptions , ccValue , ccValueMetadata , CommandClass , commandClass , CommandClassDeserializationOptions , expectedCCResponse , gotDeserializationOptions , implementedVersion , } from "./CommandClass" ; export enum ThermostatSetbackCommand { Set = 0x01 , Get = 0x02 , Report = 0x03 } publicAPI export enum SetbackType { None = 0x00 , Temporary = 0x01 , Permanent = 0x02 } @ API ( CommandClasses [ "Thermostat Setback" ] ) export class ThermostatSetbackCCAPI extends CCAPI { public supportsCommand ( cmd ) { switch ( cmd ) { case ThermostatSetbackCommand . Get : return this . isSinglecast ( ) ; case ThermostatSetbackCommand . Set : return true ; } return super . supportsCommand ( cmd ) ; } protected [ POLL_VALUE ] : PollValueImplementation = async ( { property , } ) : Promise < unknown > => { switch ( property ) { case "setbackType" : case "setbackState" : return ( await this . get ( ) ) ?. [ property ] ; default : throwUnsupportedProperty ( this . ccId , property ) ; } } ; public async get ( ) { this . assertSupportsCommand ( ThermostatSetbackCommand , ThermostatSetbackCommand . Get ) ; const cc = new ThermostatSetbackCCGet ( this . driver , { nodeId : this . endpoint . nodeId , endpoint : this . endpoint . index } ) ; const response = await this . driver . sendCommand < ThermostatSetbackCCReport > ( cc , this . commandOptions ) ; if ( response ) { return pick ( response , [ "setbackType" , "setbackState" ] ) ; } } public async set ( setbackType , setbackState ) { this . assertSupportsCommand ( ThermostatSetbackCommand , ThermostatSetbackCommand . Get ) ; const cc = new ThermostatSetbackCCSet ( this . driver , { nodeId : this . endpoint . nodeId , endpoint : this . endpoint . index , setbackType , setbackState } ) ; await this . driver . sendCommand ( cc , this . commandOptions ) ; } } @ commandClass ( CommandClasses [ "Thermostat Setback" ] ) @ implementedVersion ( 1 ) export class ThermostatSetbackCC extends CommandClass { declare ccCommand : ThermostatSetbackCommand ; public async interview ( ) { const node = this . getNode ( ) ! ; this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : `Interviewing ${ this . ccName }...` , direction : "none" } ) ; await this . refreshValues ( ) ; this . interviewComplete = true ; } public async refreshValues ( ) { const node = this . getNode ( ) ! ; const endpoint = this . getEndpoint ( ) ! ; const api = endpoint . commandClasses [ "Thermostat Setback" ] . withOptions ( { priority : MessagePriority . NodeQuery } ) ; this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : "querying the current thermostat state..." , direction : "outbound" } ) ; const setbackResp = await api . get ( ) ; if ( setbackResp ) { const logMessage = `received current state:
setback type:  ${ getEnumMemberName ( SetbackType , setbackResp . setbackType ) }
setback state: ${ setbackResp . setbackState }` ; this . driver . controllerLog . logNode ( node . id , { endpoint : this . endpointIndex , message : logMessage , direction : "inbound" } ) ; } } } interface ThermostatSetbackCCSetOptions extends CCCommandOptions { setbackType : SetbackType ; setbackState : SetbackState ; } @ CCCommand ( ThermostatSetbackCommand . Set ) export class ThermostatSetbackCCSet extends ThermostatSetbackCC { public constructor ( driver , options ) { super ( driver , options ) ; if ( gotDeserializationOptions ( options ) ) { throw new ZWaveError ( `${ this . constructor . name }: deserialization not implemented` , ZWaveErrorCodes . Deserialization_NotImplemented ) ; } else { this . setbackType = options . setbackType ; this . setbackState = options . setbackState ; } } public setbackType : SetbackType ; /** The offset from the setpoint in 0.1 Kelvin or a special mode */ public setbackState : SetbackState ; public serialize ( ) { this . payload = Buffer . from ( [ this . setbackType & 0b11 , encodeSetbackState ( this . setbackState ) , ] ) ; return super . serialize ( ) ; } public toLogEntry ( ) { return { ... super . toLogEntry ( ) , message : { "setback type" : getEnumMemberName ( SetbackType , this . setbackType ) , "setback state" : this . setbackState } } ; } } @ CCCommand ( ThermostatSetbackCommand . Report ) export class ThermostatSetbackCCReport extends ThermostatSetbackCC { public constructor ( driver , options ) { super ( driver , options ) ; validatePayload ( this . payload . length >= 2 ) ; this . _setbackType = this . payload [ 0 ] & 0b11 ; this . _setbackState = decodeSetbackState ( this . payload [ 1 ] ) || this . payload [ 1 ] ; this . persistValues ( ) ; } private _setbackType : SetbackType ; @ ccValue ( ) @ ccValueMetadata ( { ... ValueMetadata . Any , label : "Setback type" } ) public get setbackType ( ) : SetbackType { return this . _setbackType ; } private _setbackState : SetbackState ; /** The offset from the setpoint in 0.1 Kelvin or a special mode */ @ ccValue ( ) @ ccValueMetadata ( { ... ValueMetadata . Int8 , min : - 12.8 , max : 12 , label : "Setback state" } ) public get setbackState ( ) : SetbackState { return this . _setbackState ; } public toLogEntry ( ) { return { ... super . toLogEntry ( ) , message : { "setback type" : getEnumMemberName ( SetbackType , this . setbackType ) , "setback state" : this . setbackState } } ; } } @ CCCommand ( ThermostatSetbackCommand . Get ) @ expectedCCResponse ( ThermostatSetbackCCReport ) export class ThermostatSetbackCCGet extends ThermostatSetbackCC { }