import { assertZWaveError , CommandClasses , ZWaveErrorCodes , } from "@zwave-js/core" ; import type { MockSerialPort } from "@zwave-js/serial" ; import { wait } from "alcalzone-shared/async" ; import type { BinarySensorCCAPI } from "../commandclass/BinarySensorCC" ; import { BinarySwitchCCAPI } from "../commandclass/BinarySwitchCC" ; import { ZWaveController } from "../controller/Controller" ; import type { Driver } from "../driver/Driver" ; import { FunctionType } from "../message/Constants" ; import { createAndStartDriver } from "../test/utils" ; import { ZWaveNode } from "./Node" ; function isFunctionSupported ( fn ) { switch ( fn ) { case FunctionType . SendDataBridge : case FunctionType . SendDataMulticastBridge : return false ; } return true ; } describe ( "lib/node/VirtualEndpoint" , ( ) => { let driver ; let serialport ; beforeEach ( async ( ) => { try { ( { driver , serialport } = await createAndStartDriver ( ) ) ; } catch ( e ) { debugger ; } driver [ "_controller" ] = new ZWaveController ( driver ) ; driver [ "_controller" ] . isFunctionSupported = isFunctionSupported ; } ) ; function makePhysicalNode ( nodeId ) { const node = new ZWaveNode ( nodeId , driver ) ; ( driver . controller . nodes as Map < number , ZWaveNode > ) . set ( nodeId , node ) ; return node ; } afterEach ( async ( ) => { await driver . destroy ( ) ; driver . removeAllListeners ( ) ; } ) ; describe ( "createAPI" , ( ) => { it ( "throws if a non-implemented API should be created" , ( ) => { const broadcast = driver . controller . getBroadcastNode ( ) ; assertZWaveError ( ( ) => broadcast . createAPI ( 0xbada55 ) , { errorCode : ZWaveErrorCodes . CC_NoAPI , messageMatches : "no associated API" } ) ; } ) ; it ( "the broadcast API throws when trying to access a non-supported CC" , async ( ) => { makePhysicalNode ( 2 ) ; makePhysicalNode ( 3 ) ; const broadcast = driver . controller . getBroadcastNode ( ) ; const api = broadcast . createAPI ( CommandClasses [ "Binary Switch" ] ) as BinarySensorCCAPI ; api . isSupported ( ) ; await assertZWaveError ( ( ) => api . get ( ) , { errorCode : ZWaveErrorCodes . CC_NotSupported } ) ; } ) ; it ( "the broadcast API should know it is a broadcast API" , async ( ) => { makePhysicalNode ( 2 ) ; makePhysicalNode ( 3 ) ; const broadcast = driver . controller . getBroadcastNode ( ) ; expect ( broadcast . createAPI ( CommandClasses . Basic ) [ "isBroadcast" ] ( ) ) . toBeTrue ( ) ; } ) ; it ( "the multicast API should know it is a multicast API" , async ( ) => { makePhysicalNode ( 2 ) ; makePhysicalNode ( 3 ) ; const multicast = driver . controller . getMulticastGroup ( [ 2 , 3 ] ) ; expect ( multicast . createAPI ( CommandClasses . Basic ) [ "isMulticast" ] ( ) ) . toBeTrue ( ) ; } ) ; } ) ; describe ( "commandClasses dictionary" , ( ) => { let node2 ; let node3 ; beforeEach ( ( ) => { node2 = makePhysicalNode ( 2 ) ; node3 = makePhysicalNode ( 3 ) ; } ) ; it ( "throws when trying to access a non-implemented CC" , ( ) => { const broadcast = driver . controller . getBroadcastNode ( ) ; assertZWaveError ( ( ) => ( broadcast . commandClasses as any ) . FOOBAR , { errorCode : ZWaveErrorCodes . CC_NotImplemented , messageMatches : "FOOBAR is not implemented" } ) ; } ) ; it ( "throws when trying to use a command of an unsupported CC" , ( ) => { const broadcast = driver . controller . getBroadcastNode ( ) ; assertZWaveError ( ( ) => broadcast . commandClasses [ "Binary Switch" ] . set ( true ) , { errorCode : ZWaveErrorCodes . CC_NotSupported , messageMatches : "does not support the Command Class Binary Switch" } ) ; } ) ; it ( "does not throw when checking support of a CC" , ( ) => { const broadcast = driver . controller . getBroadcastNode ( ) ; expect ( broadcast . commandClasses [ "Binary Switch" ] . isSupported ( ) ) . toBeFalse ( ) ; } ) ; it ( "does not throw when accessing the ID of a CC" , ( ) => { const broadcast = driver . controller . getBroadcastNode ( ) ; expect ( broadcast . commandClasses [ "Binary Switch" ] . ccId ) . toBe ( CommandClasses [ "Binary Switch" ] ) ; } ) ; it ( "does not throw when scoping the API options" , ( ) => { const broadcast = driver . controller . getBroadcastNode ( ) ; broadcast . commandClasses [ "Binary Switch" ] . withOptions ( { } ) ; } ) ; it ( "returns all supported CCs when being enumerated" , ( ) => { let broadcast = driver . controller . getBroadcastNode ( ) ; let actual = [ ... broadcast . commandClasses ] ; expect ( actual ) . toEqual ( [ ] ) ; node2 . addCC ( CommandClasses [ "Binary Switch" ] , { isSupported : true } ) ; node2 . addCC ( CommandClasses [ "Wake Up" ] , { isControlled : true } ) ; node3 . addCC ( CommandClasses [ "Binary Switch" ] , { isSupported : true } ) ; node3 . addCC ( CommandClasses . Version , { isSupported : true } ) ; broadcast = driver . controller . getBroadcastNode ( ) ; actual = [ ... broadcast . commandClasses ] ; expect ( actual ) . toHaveLength ( 1 ) ; expect ( actual . map ( ( api ) => api . constructor ) ) . toIncludeAllMembers ( [ BinarySwitchCCAPI , ] ) ; } ) ; it ( "returns [object Object] when turned into a string" , ( ) => { const broadcast = driver . controller . getBroadcastNode ( ) ; expect ( ( broadcast . commandClasses as any ) [ Symbol . toStringTag ] ) . toBe ( "[object Object]" ) ; } ) ; it ( "returns undefined for other symbol properties" , ( ) => { const broadcast = driver . controller . getBroadcastNode ( ) ; expect ( ( broadcast . commandClasses as any ) [ Symbol . unscopables ] ) . toBeUndefined ( ) ; } ) ; } ) ; describe ( "uses the correct commands behind the scenes" , ( ) => { it ( "broadcast" , async ( ) => { makePhysicalNode ( 2 ) ; makePhysicalNode ( 3 ) ; const broadcast = driver . controller . getBroadcastNode ( ) ; broadcast . commandClasses . Basic . set ( 99 ) ; await wait ( 1 ) ; expect ( serialport . lastWrite ) . toEqual ( Buffer . from ( "010a0013ff0320016325017c" , "hex" ) ) ; } ) ; it ( "multicast" , async ( ) => { makePhysicalNode ( 2 ) ; makePhysicalNode ( 3 ) ; const multicast = driver . controller . getMulticastGroup ( [ 2 , 3 ] ) ; multicast . commandClasses . Basic . set ( 99 ) ; await wait ( 1 ) ; expect ( serialport . lastWrite ) . toEqual ( Buffer . from ( "010c001402020303200163250181" , "hex" ) ) ; } ) ; } ) ; } ) ;