import { padStart } from "alcalzone-shared/strings" ; /**
 * Used to identify errors from this library without relying on the specific wording of the error message
 */ export enum ZWaveErrorCodes { PacketFormat_Truncated , PacketFormat_Invalid , PacketFormat_Checksum , PacketFormat_InvalidPayload , PacketFormat_DecryptionFailed , /** The driver failed to start */ Driver_Failed = 100 , Driver_Reset , Driver_Destroyed , Driver_NotReady , Driver_InvalidDataReceived , Driver_NotSupported , Driver_NoPriority , Driver_InvalidCache , Driver_InvalidOptions , /** The driver tried to do something that requires security */ Driver_NoSecurity , Driver_NoErrorHandler , Driver_FeatureDisabled , /** There was a timeout while waiting for a message from the controller */ Controller_Timeout = 200 , /** There was a timeout while waiting for a response from a node */ Controller_NodeTimeout , Controller_MessageDropped , Controller_ResponseNOK , Controller_CallbackNOK , Controller_InclusionFailed , Controller_ExclusionFailed , /** Tried to do something the controller does not support */ Controller_NotSupported , /** The interview for this node was restarted by the user */ Controller_InterviewRestarted , /** The node with the given node ID was not found */ Controller_NodeNotFound , /** The endpoint with the given index was not found on the node */ Controller_EndpointNotFound , /** The node was removed from the network */ Controller_NodeRemoved , /** Communication with the node will be insecure (no security configured) */ Controller_NodeInsecureCommunication , /** The message has expired (the given timeout has elapsed) */ Controller_MessageExpired , /** A Serial API command resulted in an error response */ Controller_CommandError , /** The given NVM version/format is unsupported */ NVM_NotSupported = 280 , /** Could not parse the JSON representation of an NVM due to invalid data */ NVM_InvalidJSON , /** A required NVM3 object was not found while deserializing the NVM */ NVM_ObjectNotFound , /** The parsed NVM or NVM content has an invalid format */ NVM_InvalidFormat , /** Not enough space in the NVM */ NVM_NoSpace , CC_Invalid = 300 , CC_NoNodeID , CC_NotSupported , CC_NotImplemented , CC_NoAPI , Deserialization_NotImplemented = 320 , Arithmetic , Argument_Invalid , Config_Invalid = 340 , Config_NotFound , /** A compound config file has circular imports */ Config_CircularImport , /** Failed to download the npm registry info for config updates */ Config_Update_RegistryError , /** Could not detect which package manager to use for updates */ Config_Update_PackageManagerNotFound , /** Installing the configuration update failed */ Config_Update_InstallFailed , /** The removal process could not be started or completed due to one or several reasons */ RemoveFailedNode_Failed = 360 , /** The removal process was aborted because the node has responded */ RemoveFailedNode_NodeOK , /** The replace process could not be started or completed due to one or several reasons */ ReplaceFailedNode_Failed , /** The replace process was aborted because the node has responded */ ReplaceFailedNode_NodeOK , /**
     * Used to report the first existing parameter number
     * available in a node's configuration
     */ ConfigurationCC_FirstParameterNumber = 1000 , /**
     * Used to report that a V3+ node should not have its parameters scanned with get/set commands
     */ ConfigurationCC_NoLegacyScanOnNewDevices , /**
     * Used to report that a node using V3 or less MUST not use the resetToDefault flag
     */ ConfigurationCC_NoResetToDefaultOnLegacyDevices , /**
     * Used to report that the command was not executed by the target node
     */ SupervisionCC_CommandFailed = 1100 , /**
     * Used to report that a ManufacturerProprietaryCC could not be instanciated
     * because of a missing manufacturer ID.
     */ ManufacturerProprietaryCC_NoManufacturerId = 1200 , /**
     * Used to report that an invalid group ID was used to address a (Multi Channel) Association
     */ AssociationCC_InvalidGroup = 1300 , /** Cannot add an association because it is not allowed */ AssociationCC_NotAllowed , /** Used to report that no nonce exists */ SecurityCC_NoNonce = 1400 , /** Used to report that no SPAN is established between the nodes yet. The context should be an object that contains the peer node ID */ Security2CC_NoSPAN , /** Used to report that the inner state required for this action was not initialized */ Security2CC_NotInitialized , /** Used to report that secure communication with a node is not possible because the node is not secure */ Security2CC_NotSecure , /** Gets thrown when a Security S2 command is missing a required extension */ Security2CC_MissingExtension , /** Gets thrown when a Security S2 encapsulated command cannot be decoded by the target node */ Security2CC_CannotDecode , /** Gets thrown when parsing an invalid QR code */ Security2CC_InvalidQRCode , /** The firmware update process is already active */ FirmwareUpdateCC_Busy = 1500 , /** The selected firmware target is not upgradable */ FirmwareUpdateCC_NotUpgradable , /** The selected firmware target does not exist */ FirmwareUpdateCC_TargetNotFound , /** The node reported that it could not start the update */ FirmwareUpdateCC_FailedToStart , /** The node did not confirm the aborted update */ FirmwareUpdateCC_FailedToAbort , /** The node did not confirm the completed update or the process stalled for too long */ FirmwareUpdateCC_Timeout , /** An invalid firmware file was provided that cannot be handled by this library */ Invalid_Firmware_File , /** An firmware file with an unsupported format was provided */ Unsupported_Firmware_Format , /** Unsupported target node for a powerlevel test */ PowerlevelCC_UnsupportedTestNode = 1600 } export function getErrorSuffix ( code ) { return `ZW${ padStart ( code . toString ( ) , 4 , "0" ) }` ; } function appendErrorSuffix ( message , code ) { const suffix = ` (${ getErrorSuffix ( code ) })` ; if ( ! message . endsWith ( suffix ) ) message += suffix ; return message ; } /**
 * Errors thrown in this library are of this type. The `code` property identifies what went wrong.
 */ export class ZWaveError extends Error { public constructor ( public readonly message , public readonly code , /** Additional info required to handle this error (e.g. the Z-Wave message indicating the failure) */ public readonly context ? , /** If this error corresponds to a failed transaction, this contains the stack where it was created */ public readonly transactionSource ? ) { super ( ) ; this . message = appendErrorSuffix ( message , code ) ; Object . setPrototypeOf ( this , ZWaveError . prototype ) ; Object . getPrototypeOf ( this ) . name = "ZWaveError" ; if ( typeof transactionSource === "string" ) { this . stack = `ZWaveError: ${ this . message }\n${ transactionSource }` ; } } } export function isZWaveError ( e ) { return e instanceof Error && Object . getPrototypeOf ( e ) . name === "ZWaveError" ; } export function isTransmissionError ( e ) { return ( isZWaveError ( e ) && ( e . code === ZWaveErrorCodes . Controller_Timeout || e . code === ZWaveErrorCodes . Controller_MessageDropped || e . code === ZWaveErrorCodes . Controller_CallbackNOK || e . code === ZWaveErrorCodes . Controller_ResponseNOK || e . code === ZWaveErrorCodes . Controller_NodeTimeout || e . code === ZWaveErrorCodes . Security2CC_CannotDecode ) ) ; } /**
 * Tests is the given error is a "recoverable" error - i.e. something that shouldn't happen unless
 * someone interacted with zwave-js in a weird way, but something we can deal with.
 *
 * This explicitly does not include transmission errors.
 */ export function isRecoverableZWaveError ( e ) { if ( ! isZWaveError ( e ) ) return false ; switch ( e . code ) { case ZWaveErrorCodes . Controller_InterviewRestarted : case ZWaveErrorCodes . Controller_NodeRemoved : return true ; } return false ; }