import { MessageOrCCLogEntry , MessageRecord , ZWaveError , ZWaveErrorCodes , } from "@zwave-js/core" ; import { CommandClass , SinglecastCC } from "../commandclass/CommandClass" ; import type { ICommandClassContainer } from "../commandclass/ICommandClassContainer" ; import type { Driver } from "../driver/Driver" ; import { FunctionType , MessagePriority , MessageType , } from "../message/Constants" ; import { gotDeserializationOptions , Message , MessageBaseOptions , MessageDeserializationOptions , messageTypes , priority , } from "../message/Message" ; export enum ApplicationCommandStatusFlags { RoutedBusy = 0b1 , LowPower = 0b10 , TypeSingle = 0b0000 , TypeBroad = 0b0100 , TypeMulti = 0b1000 , TypeMask = TypeSingle | TypeBroad | TypeMulti , Explore = 0b10000 , ForeignFrame = 64 , ForeignHomeId = 128 } interface ApplicationCommandRequestOptions extends MessageBaseOptions { command : CommandClass ; frameType ? : ApplicationCommandRequest [ "frameType" ] ; routedBusy ? : boolean ; } @ messageTypes ( MessageType . Request , FunctionType . ApplicationCommand ) @ priority ( MessagePriority . Normal ) export class ApplicationCommandRequest extends Message implements ICommandClassContainer { public constructor ( driver , options ) { super ( driver , options ) ; if ( gotDeserializationOptions ( options ) ) { const status = this . payload [ 0 ] ; this . routedBusy = ! ! ( status & ApplicationCommandStatusFlags . RoutedBusy ) ; switch ( status & ApplicationCommandStatusFlags . TypeMask ) { case ApplicationCommandStatusFlags . TypeMulti : this . frameType = "multicast" ; break ; case ApplicationCommandStatusFlags . TypeBroad : this . frameType = "broadcast" ; break ; default : this . frameType = "singlecast" ; } this . isExploreFrame = this . frameType === "broadcast" && ! ! ( status & ApplicationCommandStatusFlags . Explore ) ; this . isForeignFrame = ! ! ( status & ApplicationCommandStatusFlags . ForeignFrame ) ; this . fromForeignHomeId = ! ! ( status & ApplicationCommandStatusFlags . ForeignHomeId ) ; const nodeId = this . payload [ 1 ] ; const commandLength = this . payload [ 2 ] ; this . command = CommandClass . from ( this . driver , { data : this . payload . slice ( 3 , 3 + commandLength ) , nodeId } ) as SinglecastCC ; } else { if ( ! options . command . isSinglecast ( ) ) { throw new ZWaveError ( `ApplicationCommandRequest can only be used for singlecast CCs` , ZWaveErrorCodes . Argument_Invalid ) ; } this . frameType = options . frameType ?? "singlecast" ; this . routedBusy = ! ! options . routedBusy ; this . command = options . command ; this . isExploreFrame = false ; this . isForeignFrame = false ; this . fromForeignHomeId = false ; } } public readonly routedBusy : boolean ; public readonly frameType : "singlecast" | "broadcast" | "multicast" ; public readonly isExploreFrame : boolean ; public readonly isForeignFrame : boolean ; public readonly fromForeignHomeId : boolean ; public command : SinglecastCC ; public serialize ( ) { const statusByte = ( this . frameType === "broadcast" ? ApplicationCommandStatusFlags . TypeBroad : this . frameType === "multicast" ? ApplicationCommandStatusFlags . TypeMulti : 0 ) | ( this . routedBusy ? ApplicationCommandStatusFlags . RoutedBusy : 0 ) ; const serializedCC = this . command . serialize ( ) ; this . payload = Buffer . concat ( [ Buffer . from ( [ statusByte , this . driver . controller . ownNodeId ! , serializedCC . length , ] ) , serializedCC , ] ) ; return super . serialize ( ) ; } public toLogEntry ( ) { const message = { } ; if ( this . frameType !== "singlecast" ) { message . type = this . frameType ; } return { ... super . toLogEntry ( ) , message } ; } }