import type { Maybe , MessageOrCCLogEntry } from "@zwave-js/core" ; import { CommandClasses , validatePayload } from "@zwave-js/core" ; import type { Driver } from "../driver/Driver" ; import { CCAPI } from "./API" ; import { API , CCCommand , CCCommandOptions , CommandClass , commandClass , CommandClassDeserializationOptions , gotDeserializationOptions , implementedVersion , } from "./CommandClass" ; export enum MultiCommandCommand { CommandEncapsulation = 0x01 } @ API ( CommandClasses [ "Multi Command" ] ) export class MultiCommandCCAPI extends CCAPI { public supportsCommand ( _cmd ) { return true ; } public async send ( commands ) { this . assertSupportsCommand ( MultiCommandCommand , MultiCommandCommand . CommandEncapsulation ) ; const cc = new MultiCommandCCCommandEncapsulation ( this . driver , { nodeId : this . endpoint . nodeId , encapsulated : commands } ) ; cc . endpointIndex = this . endpoint . index ; await this . driver . sendCommand ( cc , this . commandOptions ) ; } } @ commandClass ( CommandClasses [ "Multi Command" ] ) @ implementedVersion ( 1 ) export class MultiCommandCC extends CommandClass { declare ccCommand : MultiCommandCommand ; /** Tests if a command targets a specific endpoint and thus requires encapsulation */ public static requiresEncapsulation ( cc ) { return ( cc . endpointIndex !== 0 && ! ( cc instanceof MultiCommandCCCommandEncapsulation ) ) ; } /** Encapsulates a command that targets a specific endpoint */ public static encapsulate ( driver , CCs ) { return new MultiCommandCCCommandEncapsulation ( driver , { nodeId : CCs [ 0 ] . nodeId , encapsulated : CCs , supervised : CCs . some ( ( cc ) => cc . supervised ) } ) ; } } interface MultiCommandCCCommandEncapsulationOptions extends CCCommandOptions { encapsulated : CommandClass [ ] ; } @ CCCommand ( MultiCommandCommand . CommandEncapsulation ) export class MultiCommandCCCommandEncapsulation extends MultiCommandCC { public constructor ( driver , options ) { super ( driver , options ) ; if ( gotDeserializationOptions ( options ) ) { validatePayload ( this . payload . length >= 1 ) ; const numCommands = this . payload [ 0 ] ; this . encapsulated = [ ] ; let offset = 1 ; for ( let i = 0 ; i < numCommands ; i ++ ) { validatePayload ( this . payload . length >= offset + 1 ) ; const cmdLength = this . payload [ offset ] ; validatePayload ( this . payload . length >= offset + 1 + cmdLength ) ; this . encapsulated . push ( CommandClass . from ( this . driver , { data : this . payload . slice ( offset + 1 , offset + 1 + cmdLength ) , fromEncapsulation : true , encapCC : this } ) ) ; offset += 1 + cmdLength ; } } else { this . encapsulated = options . encapsulated ; for ( const cc of options . encapsulated ) { cc . encapsulatingCC = this as any ; } } } public encapsulated : CommandClass [ ] ; public serialize ( ) { const buffers = [ ] ; buffers . push ( Buffer . from ( [ this . encapsulated . length ] ) ) ; for ( const cmd of this . encapsulated ) { const cmdBuffer = cmd . serialize ( ) ; buffers . push ( Buffer . from ( [ cmdBuffer . length ] ) ) ; buffers . push ( cmdBuffer ) ; } this . payload = Buffer . concat ( buffers ) ; return super . serialize ( ) ; } public toLogEntry ( ) { return { ... super . toLogEntry ( ) , message : undefined } ; } }