import type { Maybe , MessageOrCCLogEntry } from "@zwave-js/core" ; import { CommandClasses , CRC16_CCITT , validatePayload } from "@zwave-js/core" ; import type { Driver } from "../driver/Driver" ; import { CCAPI } from "./API" ; import { API , CCCommand , CCCommandOptions , CommandClass , commandClass , CommandClassDeserializationOptions , expectedCCResponse , gotDeserializationOptions , implementedVersion , } from "./CommandClass" ; export enum CRC16Command { CommandEncapsulation = 0x01 } @ API ( CommandClasses [ "CRC-16 Encapsulation" ] ) export class CRC16CCAPI extends CCAPI { public supportsCommand ( _cmd ) { return true ; } public async sendEncapsulated ( encapsulatedCC ) { this . assertSupportsCommand ( CRC16Command , CRC16Command . CommandEncapsulation ) ; const cc = new CRC16CCCommandEncapsulation ( this . driver , { nodeId : this . endpoint . nodeId , endpoint : this . endpoint . index , encapsulated : encapsulatedCC } ) ; await this . driver . sendCommand ( cc , this . commandOptions ) ; } } @ commandClass ( CommandClasses [ "CRC-16 Encapsulation" ] ) @ implementedVersion ( 1 ) export class CRC16CC extends CommandClass { declare ccCommand : CRC16Command ; /** Encapsulates a command in a CRC-16 CC */ public static encapsulate ( driver , cc ) { return new CRC16CCCommandEncapsulation ( driver , { nodeId : cc . nodeId , encapsulated : cc } ) ; } } interface CRC16CCCommandEncapsulationOptions extends CCCommandOptions { encapsulated : CommandClass ; } function getResponseForCommandEncapsulation ( ) { return CRC16CCCommandEncapsulation ; } @ CCCommand ( CRC16Command . CommandEncapsulation ) @ expectedCCResponse ( getResponseForCommandEncapsulation ) export class CRC16CCCommandEncapsulation extends CRC16CC { public constructor ( driver , options ) { super ( driver , options ) ; if ( gotDeserializationOptions ( options ) ) { validatePayload ( this . payload . length >= 3 ) ; const ccBuffer = this . payload . slice ( 0 , - 2 ) ; let expectedCRC = CRC16_CCITT ( this . headerBuffer ) ; expectedCRC = CRC16_CCITT ( ccBuffer , expectedCRC ) ; const actualCRC = this . payload . readUInt16BE ( this . payload . length - 2 ) ; validatePayload ( expectedCRC === actualCRC ) ; this . encapsulated = CommandClass . from ( this . driver , { data : ccBuffer , fromEncapsulation : true , encapCC : this } ) ; } else { this . encapsulated = options . encapsulated ; options . encapsulated . encapsulatingCC = this as any ; } } public encapsulated : CommandClass ; private readonly headerBuffer = Buffer . from ( [ this . ccId , this . ccCommand ] ) ; public serialize ( ) { const commandBuffer = this . encapsulated . serialize ( ) ; this . payload = Buffer . concat ( [ commandBuffer , Buffer . allocUnsafe ( 2 ) ] ) ; let crc = CRC16_CCITT ( this . headerBuffer ) ; crc = CRC16_CCITT ( commandBuffer , crc ) ; this . payload . writeUInt16BE ( crc , this . payload . length - 2 ) ; return super . serialize ( ) ; } protected computeEncapsulationOverhead ( ) { return super . computeEncapsulationOverhead ( ) + 2 ; } public toLogEntry ( ) { return { ... super . toLogEntry ( ) , message : undefined } ; } }