"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var Security2CC_exports = {};
__export(Security2CC_exports, {
  Security2CC: () => Security2CC,
  Security2CCAPI: () => Security2CCAPI,
  Security2CCCommandsSupportedGet: () => Security2CCCommandsSupportedGet,
  Security2CCCommandsSupportedReport: () => Security2CCCommandsSupportedReport,
  Security2CCKEXFail: () => Security2CCKEXFail,
  Security2CCKEXGet: () => Security2CCKEXGet,
  Security2CCKEXReport: () => Security2CCKEXReport,
  Security2CCKEXSet: () => Security2CCKEXSet,
  Security2CCMessageEncapsulation: () => Security2CCMessageEncapsulation,
  Security2CCNetworkKeyGet: () => Security2CCNetworkKeyGet,
  Security2CCNetworkKeyReport: () => Security2CCNetworkKeyReport,
  Security2CCNetworkKeyVerify: () => Security2CCNetworkKeyVerify,
  Security2CCNonceGet: () => Security2CCNonceGet,
  Security2CCNonceReport: () => Security2CCNonceReport,
  Security2CCPublicKeyReport: () => Security2CCPublicKeyReport,
  Security2CCTransferEnd: () => Security2CCTransferEnd
});
module.exports = __toCommonJS(Security2CC_exports);
var import_tslib = require("tslib");
var import_core = require("@zwave-js/core");
var import_shared = require("@zwave-js/shared");
var import_async = require("alcalzone-shared/async");
var import_typeguards = require("alcalzone-shared/typeguards");
var import_API = require("../lib/API.js");
var import_CommandClass = require("../lib/CommandClass.js");
var import_CommandClassDecorators = require("../lib/CommandClassDecorators.js");
var import_Extension = require("../lib/Security2/Extension.js");
var import_shared2 = require("../lib/Security2/shared.js");
var import_Types = require("../lib/_Types.js");
var import_CRC16CC = require("./CRC16CC.js");
var import_MultiChannelCC = require("./MultiChannelCC.js");
var import_SecurityCC = require("./SecurityCC.js");
var import_TransportServiceCC = require("./TransportServiceCC.js");
function securityClassToBitMask(key) {
  return (0, import_core.encodeBitMask)([key], import_core.SecurityClass.S0_Legacy, import_core.SecurityClass.S2_Unauthenticated);
}
__name(securityClassToBitMask, "securityClassToBitMask");
function bitMaskToSecurityClass(buffer, offset) {
  const keys = (0, import_core.parseBitMask)(buffer.subarray(offset, offset + 1), import_core.SecurityClass.S2_Unauthenticated);
  (0, import_core.validatePayload)(keys.length === 1);
  return keys[0];
}
__name(bitMaskToSecurityClass, "bitMaskToSecurityClass");
const SECURITY_S2_AUTH_TAG_LENGTH = 8;
function getAuthenticationData(sendingNodeId, destination, homeId, commandLength, unencryptedPayload) {
  const nodeIdSize = (0, import_core.isLongRangeNodeId)(sendingNodeId) || (0, import_core.isLongRangeNodeId)(destination) ? 2 : 1;
  const ret = new import_shared.Bytes(2 * nodeIdSize + 6 + unencryptedPayload.length);
  let offset = 0;
  ret.writeUIntBE(sendingNodeId, offset, nodeIdSize);
  offset += nodeIdSize;
  ret.writeUIntBE(destination, offset, nodeIdSize);
  offset += nodeIdSize;
  ret.writeUInt32BE(homeId, offset);
  offset += 4;
  ret.writeUInt16BE(commandLength, offset);
  offset += 2;
  ret.set(unencryptedPayload, offset);
  return ret;
}
__name(getAuthenticationData, "getAuthenticationData");
function getSecurityManager(ownNodeId, securityManagers, otherNodeId) {
  const longRange = (0, import_core.isLongRangeNodeId)(ownNodeId) || (0, import_core.isLongRangeNodeId)((0, import_typeguards.isArray)(otherNodeId) ? otherNodeId[0] : otherNodeId);
  return longRange ? securityManagers.securityManagerLR : securityManagers.securityManager2;
}
__name(getSecurityManager, "getSecurityManager");
function validateSequenceNumber(securityManager, sourceNodeId, sequenceNumber) {
  import_core.validatePayload.withReason(`Duplicate command (sequence number ${sequenceNumber})`)(!securityManager.isDuplicateSinglecast(sourceNodeId, sequenceNumber));
  return securityManager.storeSequenceNumber(sourceNodeId, sequenceNumber);
}
__name(validateSequenceNumber, "validateSequenceNumber");
const MAX_DECRYPT_ATTEMPTS_SINGLECAST = 5;
const MAX_DECRYPT_ATTEMPTS_MULTICAST = 5;
const MAX_DECRYPT_ATTEMPTS_SC_FOLLOWUP = 1;
function assertSecurityRX(ctx) {
  if (!ctx.ownNodeId) {
    throw new import_core.ZWaveError(`Secure commands (S2) can only be decoded when the controller's node id is known!`, import_core.ZWaveErrorCodes.Driver_NotReady);
  }
  const ret = getSecurityManager(ctx.ownNodeId, ctx, ctx.sourceNodeId);
  if (!ret) {
    throw new import_core.ZWaveError(`Secure commands (S2) can only be decoded when the security manager is set up!`, import_core.ZWaveErrorCodes.Driver_NoSecurity);
  }
  return ret;
}
__name(assertSecurityRX, "assertSecurityRX");
function assertSecurityTX(ctx, destination) {
  if (!ctx.ownNodeId) {
    throw new import_core.ZWaveError(`Secure commands (S2) can only be sent when the controller's node id is known!`, import_core.ZWaveErrorCodes.Driver_NotReady);
  }
  const ret = getSecurityManager(ctx.ownNodeId, ctx, destination);
  if (!ret) {
    throw new import_core.ZWaveError(`Secure commands (S2) can only be sent when the security manager is set up!`, import_core.ZWaveErrorCodes.Driver_NoSecurity);
  }
  return ret;
}
__name(assertSecurityTX, "assertSecurityTX");
async function decryptSinglecast(ctx, securityManager, sendingNodeId, curSequenceNumber, prevSequenceNumber, ciphertext, authData, authTag, spanState, extensions) {
  const decryptWithNonce = /* @__PURE__ */ __name(async (nonce) => {
    const { keyCCM: key } = securityManager.getKeysForNode(sendingNodeId);
    const iv = nonce;
    const ret = await (0, import_core.decryptAES128CCM)(ciphertext, key, iv, authData, authTag);
    return {
      key,
      iv,
      ...ret
    };
  }, "decryptWithNonce");
  const getNonceAndDecrypt = /* @__PURE__ */ __name(async () => {
    const iv = await securityManager.nextNonce(sendingNodeId);
    return decryptWithNonce(iv);
  }, "getNonceAndDecrypt");
  if (spanState.type === import_core.SPANState.SPAN) {
    if (
      // The previous SPAN is still known, i.e. the node didn't send another command that was successfully decrypted
      !!spanState.currentSPAN && spanState.currentSPAN.expires > (0, import_core.highResTimestamp)() && prevSequenceNumber != void 0 && curSequenceNumber === (prevSequenceNumber + 1 & 255) && !ctx.__internalIsMockNode
    ) {
      const nonce = spanState.currentSPAN.nonce;
      spanState.currentSPAN = void 0;
      const result = await decryptWithNonce(nonce);
      if (result.authOK) {
        return {
          ...result,
          securityClass: spanState.securityClass
        };
      }
    } else {
      spanState.currentSPAN = void 0;
    }
    return {
      ...await getNonceAndDecrypt(),
      securityClass: spanState.securityClass
    };
  } else if (spanState.type === import_core.SPANState.LocalEI) {
    const senderEI = getSenderEI(extensions);
    if (!senderEI)
      failNoSPAN();
    const receiverEI = spanState.receiverEI;
    const isBootstrappingNode = securityManager.tempKeys.has(sendingNodeId);
    if (isBootstrappingNode) {
      await securityManager.initializeTempSPAN(sendingNodeId, senderEI, receiverEI);
      const ret = await getNonceAndDecrypt();
      if (ret.authOK) {
        return {
          ...ret,
          securityClass: import_core.SecurityClass.Temporary
        };
      }
      securityManager.setSPANState(sendingNodeId, spanState);
    }
    const possibleSecurityClasses = isBootstrappingNode ? [ctx.getHighestSecurityClass(sendingNodeId)] : import_core.securityClassOrder.filter((s) => ctx.hasSecurityClass(sendingNodeId, s) !== false);
    for (const secClass of possibleSecurityClasses) {
      if (!securityManager.hasKeysForSecurityClass(secClass)) {
        continue;
      }
      await securityManager.initializeSPAN(sendingNodeId, secClass, senderEI, receiverEI);
      const ret = await getNonceAndDecrypt();
      if (ret.authOK) {
        if (ctx.hasSecurityClass(sendingNodeId, secClass) === void 0) {
          ctx.setSecurityClass(sendingNodeId, secClass, true);
        }
        return {
          ...ret,
          securityClass: secClass
        };
      } else {
        securityManager.setSPANState(sendingNodeId, spanState);
      }
    }
  }
  return {
    plaintext: new Uint8Array(),
    authOK: false,
    securityClass: void 0
  };
}
__name(decryptSinglecast, "decryptSinglecast");
async function decryptMulticast(sendingNodeId, securityManager, groupId, ciphertext, authData, authTag) {
  const iv = await securityManager.nextPeerMPAN(sendingNodeId, groupId);
  const { keyCCM: key } = securityManager.getKeysForNode(sendingNodeId);
  return {
    key,
    iv,
    ...await (0, import_core.decryptAES128CCM)(ciphertext, key, iv, authData, authTag),
    // The security class is irrelevant when decrypting multicast commands
    securityClass: void 0
  };
}
__name(decryptMulticast, "decryptMulticast");
function parseExtensions(buffer, wasEncrypted) {
  const extensions = [];
  let mustDiscardCommand = false;
  let offset = 0;
  parsing: while (true) {
    if (buffer.length < offset + 2) {
      mustDiscardCommand = true;
      break parsing;
    }
    const { actual: actualLength, expected: expectedLength } = import_Extension.Security2Extension.getExtensionLength(buffer.subarray(offset));
    const extensionLength = expectedLength ?? actualLength;
    if (extensionLength < 2) {
      mustDiscardCommand = true;
      break parsing;
    } else if (extensionLength > buffer.length - offset - (wasEncrypted ? 0 : SECURITY_S2_AUTH_TAG_LENGTH)) {
      mustDiscardCommand = true;
      break parsing;
    }
    const extensionData = buffer.subarray(offset, offset + extensionLength);
    offset += extensionLength;
    const ext = import_Extension.Security2Extension.parse(extensionData);
    switch ((0, import_Extension.validateS2Extension)(ext, wasEncrypted)) {
      case import_Extension.ValidateS2ExtensionResult.OK:
        if (expectedLength != void 0 && actualLength !== expectedLength) {
        } else {
          extensions.push(ext);
        }
        break;
      case import_Extension.ValidateS2ExtensionResult.DiscardExtension:
        break;
      case import_Extension.ValidateS2ExtensionResult.DiscardCommand:
        mustDiscardCommand = true;
        break;
    }
    if (!ext.moreToFollow)
      break parsing;
  }
  return {
    extensions,
    mustDiscardCommand,
    bytesRead: offset
  };
}
__name(parseExtensions, "parseExtensions");
function getDestinationIDTX() {
  if (this.isSinglecast())
    return this.nodeId;
  const ret = getMulticastGroupId(this.extensions);
  if (ret == void 0) {
    throw new import_core.ZWaveError("Multicast Security S2 encapsulation requires the MGRP extension", import_core.ZWaveErrorCodes.Security2CC_MissingExtension);
  }
  return ret;
}
__name(getDestinationIDTX, "getDestinationIDTX");
function getDestinationIDRX(ctx, extensions) {
  if (ctx.frameType === "singlecast") {
    return ctx.ownNodeId;
  }
  const ret = getMulticastGroupId(extensions);
  if (ret == void 0) {
    throw new import_core.ZWaveError("Multicast Security S2 encapsulation requires the MGRP extension", import_core.ZWaveErrorCodes.Security2CC_MissingExtension);
  }
  return ret;
}
__name(getDestinationIDRX, "getDestinationIDRX");
function getMulticastGroupId(extensions) {
  const mgrpExtension = extensions.find((e) => e instanceof import_Extension.MGRPExtension);
  return mgrpExtension?.groupId;
}
__name(getMulticastGroupId, "getMulticastGroupId");
function getSenderEI(extensions) {
  const spanExtension = extensions.find((e) => e instanceof import_Extension.SPANExtension);
  return spanExtension?.senderEI;
}
__name(getSenderEI, "getSenderEI");
let Security2CCAPI = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.API)(import_core.CommandClasses["Security 2"])];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = import_API.CCAPI;
  var Security2CCAPI2 = class extends _classSuper {
    static {
      __name(this, "Security2CCAPI");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCAPI2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    supportsCommand(_cmd) {
      return true;
    }
    /**
     * Sends a nonce to the node, either in response to a NonceGet request or a message that failed to decrypt. The message is sent without any retransmission etc.
     * The return value indicates whether a nonce was successfully sent
     */
    async sendNonce() {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.NonceReport);
      this.assertPhysicalEndpoint(this.endpoint);
      const securityManager = getSecurityManager(this.host.ownNodeId, this.host, this.endpoint.nodeId);
      if (!securityManager) {
        throw new import_core.ZWaveError(`Nonces can only be sent if secure communication is set up!`, import_core.ZWaveErrorCodes.Driver_NoSecurity);
      }
      const receiverEI = await securityManager.generateNonce(this.endpoint.nodeId);
      const cc = new Security2CCNonceReport({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        SOS: true,
        MOS: false,
        receiverEI
      });
      try {
        await this.host.sendCommand(cc, {
          ...this.commandOptions,
          // Seems we need these options or some nodes won't accept the nonce
          transmitOptions: import_core.TransmitOptions.ACK | import_core.TransmitOptions.AutoRoute,
          // Only try sending a nonce once
          maxSendAttempts: 1,
          // Nonce requests must be handled immediately
          priority: import_core.MessagePriority.Immediate,
          // We don't want failures causing us to treat the node as asleep or dead
          changeNodeStatusOnMissingACK: false
          // And we need to react to
        });
      } catch (e) {
        if ((0, import_core.isTransmissionError)(e)) {
          securityManager.deleteNonce(this.endpoint.nodeId);
          return false;
        } else {
          throw e;
        }
      }
      return true;
    }
    /** Notifies the target node that the MPAN state is out of sync */
    async sendMOS() {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.NonceReport);
      this.assertPhysicalEndpoint(this.endpoint);
      const cc = new Security2CCNonceReport({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        SOS: false,
        MOS: true
      });
      try {
        await this.host.sendCommand(cc, {
          ...this.commandOptions,
          // Seems we need these options or some nodes won't accept the nonce
          transmitOptions: import_core.TransmitOptions.ACK | import_core.TransmitOptions.AutoRoute,
          // Only try sending a nonce once
          maxSendAttempts: 1,
          // Nonce requests must be handled immediately
          priority: import_core.MessagePriority.Immediate,
          // We don't want failures causing us to treat the node as asleep or dead
          changeNodeStatusOnMissingACK: false
        });
      } catch (e) {
        if ((0, import_core.isTransmissionError)(e)) {
          return false;
        } else {
          throw e;
        }
      }
      return true;
    }
    /** Sends the given MPAN to the node */
    async sendMPAN(groupId, innerMPANState) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.MessageEncapsulation);
      this.assertPhysicalEndpoint(this.endpoint);
      const cc = new Security2CCMessageEncapsulation({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        extensions: [
          new import_Extension.MPANExtension({
            groupId,
            innerMPANState
          })
        ]
      });
      try {
        await this.host.sendCommand(cc, {
          ...this.commandOptions,
          // Seems we need these options or some nodes won't accept the nonce
          transmitOptions: import_core.TransmitOptions.ACK | import_core.TransmitOptions.AutoRoute,
          // Only try sending a nonce once
          maxSendAttempts: 1,
          // Nonce requests must be handled immediately
          priority: import_core.MessagePriority.Immediate,
          // We don't want failures causing us to treat the node as asleep or dead
          changeNodeStatusOnMissingACK: false
        });
      } catch (e) {
        if ((0, import_core.isTransmissionError)(e)) {
          return false;
        } else {
          throw e;
        }
      }
      return true;
    }
    /**
     * Queries the securely supported commands for the current security class
     * @param securityClass Can be used to overwrite the security class to use. If this doesn't match the current one, new nonces will need to be exchanged.
     */
    async getSupportedCommands(securityClass) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.CommandsSupportedGet);
      let cc = new Security2CCCommandsSupportedGet({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index
      });
      if (import_MultiChannelCC.MultiChannelCC.requiresEncapsulation(cc)) {
        const multiChannelCCVersion = this.host.getSupportedCCVersion(import_core.CommandClasses["Multi Channel"], this.endpoint.nodeId);
        cc = multiChannelCCVersion === 1 ? import_MultiChannelCC.MultiChannelCC.encapsulateV1(cc) : import_MultiChannelCC.MultiChannelCC.encapsulate(cc);
      }
      cc = Security2CC.encapsulate(cc, this.host.ownNodeId, this.host, { securityClass });
      const response = await this.host.sendCommand(cc, {
        ...this.commandOptions,
        autoEncapsulate: false
      });
      return response?.supportedCCs;
    }
    async reportSupportedCommands(supportedCCs) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.CommandsSupportedReport);
      const cc = new Security2CCCommandsSupportedReport({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        supportedCCs
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    // oxlint-disable-next-line typescript/explicit-module-boundary-types
    async getKeyExchangeParameters() {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.KEXGet);
      const cc = new Security2CCKEXGet({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index
      });
      const response = await this.host.sendCommand(cc, this.commandOptions);
      if (response) {
        return (0, import_shared.pick)(response, [
          "requestCSA",
          "echo",
          "supportedKEXSchemes",
          "supportedECDHProfiles",
          "requestedKeys",
          "_reserved"
        ]);
      }
    }
    /** Requests the given keys from an including node */
    async requestKeys(params) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.KEXReport);
      const cc = new Security2CCKEXReport({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        ...params,
        echo: false
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    /** Grants the joining node the given keys */
    async grantKeys(params) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.KEXSet);
      const cc = new Security2CCKEXSet({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        ...params,
        echo: false
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    /** Confirms the keys that were requested by a node */
    async confirmRequestedKeys(params) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.KEXReport);
      const cc = new Security2CCKEXReport({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        ...params,
        echo: true
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    /** Confirms the keys that were granted by the including node */
    async confirmGrantedKeys(params) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.KEXSet);
      const cc = new Security2CCKEXSet({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        ...params,
        echo: true
      });
      return this.host.sendCommand(cc, this.commandOptions);
    }
    /** Notifies the other node that the ongoing key exchange was aborted */
    async abortKeyExchange(failType) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.KEXFail);
      const cc = new Security2CCKEXFail({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        failType
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    async sendPublicKey(publicKey, includingNode = true) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.PublicKeyReport);
      const cc = new Security2CCPublicKeyReport({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        includingNode,
        publicKey
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    async requestNetworkKey(securityClass) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.NetworkKeyGet);
      const cc = new Security2CCNetworkKeyGet({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        requestedKey: securityClass
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    async sendNetworkKey(securityClass, networkKey) {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.NetworkKeyReport);
      const cc = new Security2CCNetworkKeyReport({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        grantedKey: securityClass,
        networkKey
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    async verifyNetworkKey() {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.NetworkKeyVerify);
      const cc = new Security2CCNetworkKeyVerify({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
    async confirmKeyVerification() {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.TransferEnd);
      const cc = new Security2CCTransferEnd({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        keyVerified: true,
        keyRequestComplete: false
      });
      await this.host.sendCommand(cc, {
        ...this.commandOptions,
        // Don't wait for an ACK from the node
        transmitOptions: import_core.TransmitOptions.DEFAULT & ~import_core.TransmitOptions.ACK
      });
    }
    async endKeyExchange() {
      this.assertSupportsCommand(import_Types.Security2Command, import_Types.Security2Command.TransferEnd);
      const cc = new Security2CCTransferEnd({
        nodeId: this.endpoint.nodeId,
        endpointIndex: this.endpoint.index,
        keyVerified: false,
        keyRequestComplete: true
      });
      await this.host.sendCommand(cc, this.commandOptions);
    }
  };
  return Security2CCAPI2 = _classThis;
})();
let Security2CC = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.commandClass)(import_core.CommandClasses["Security 2"]), (0, import_CommandClassDecorators.implementedVersion)(1)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = import_CommandClass.CommandClass;
  var Security2CC2 = class extends _classSuper {
    static {
      __name(this, "Security2CC");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CC2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    async interview(ctx) {
      const securityManager = getSecurityManager(ctx.ownNodeId, ctx, this.nodeId);
      const node = this.getNode(ctx);
      const endpoint = this.getEndpoint(ctx);
      const api = import_API.CCAPI.create(import_core.CommandClasses["Security 2"], ctx, endpoint).withOptions({
        priority: import_core.MessagePriority.NodeQuery
      });
      const secClass = node.getHighestSecurityClass();
      let hasReceivedSecureCommands = false;
      let possibleSecurityClasses;
      if ((0, import_core.securityClassIsS2)(secClass)) {
        possibleSecurityClasses = [secClass];
      } else if (endpoint.index === 0) {
        possibleSecurityClasses = [
          import_core.SecurityClass.S2_Unauthenticated,
          import_core.SecurityClass.S2_Authenticated,
          import_core.SecurityClass.S2_AccessControl
        ];
      } else {
        ctx.logNode(node.id, {
          endpoint: endpoint.index,
          message: `Cannot query securely supported commands for endpoint because the node's security class isn't known...`,
          level: "error"
        });
        return;
      }
      for (const secClass2 of possibleSecurityClasses) {
        if (node.hasSecurityClass(secClass2) === false)
          continue;
        if (!securityManager?.hasKeysForSecurityClass(secClass2)) {
          ctx.logNode(node.id, {
            endpoint: endpoint.index,
            message: `Cannot query securely supported commands (${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, secClass2)}) - network key is not configured...`,
            level: "warn"
          });
          continue;
        }
        ctx.logNode(node.id, {
          endpoint: endpoint.index,
          message: `Querying securely supported commands (${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, secClass2)})...`,
          direction: "outbound"
        });
        let supportedCCs;
        const MAX_ATTEMPTS = this.endpointIndex === 0 ? 3 : 1;
        for (let attempts = 1; attempts <= MAX_ATTEMPTS; attempts++) {
          try {
            supportedCCs = await api.getSupportedCommands(secClass2);
          } catch (e) {
            if ((0, import_core.isZWaveError)(e) && e.code === import_core.ZWaveErrorCodes.Security2CC_CannotDecode) {
              supportedCCs = void 0;
            } else {
              throw e;
            }
          }
          if (supportedCCs == void 0 && possibleSecurityClasses.length === 1) {
            if (attempts < MAX_ATTEMPTS) {
              ctx.logNode(node.id, {
                endpoint: endpoint.index,
                message: `Querying securely supported commands (${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, secClass2)}), attempt ${attempts}/${MAX_ATTEMPTS} failed. Retrying in 500ms...`,
                level: "warn"
              });
              await (0, import_async.wait)(500);
              continue;
            } else if (endpoint.index > 0) {
              ctx.logNode(node.id, {
                endpoint: endpoint.index,
                message: `Querying securely supported commands (${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, secClass2)}) failed. Assuming the endpoint supports all its mandatory CCs securely...`,
                level: "warn"
              });
              for (const [ccId] of endpoint.getCCs()) {
                endpoint.addCC(ccId, { secure: true });
              }
              break;
            } else {
              ctx.logNode(node.id, {
                endpoint: endpoint.index,
                message: `Querying securely supported commands (${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, secClass2)}) failed. Let's hope for the best...`,
                level: "warn"
              });
              break;
            }
          } else {
            break;
          }
        }
        if (supportedCCs == void 0) {
          if (endpoint.index === 0 && possibleSecurityClasses.length > 1) {
            node.setSecurityClass(secClass2, false);
            ctx.logNode(node.id, {
              message: `The node was NOT granted the security class ${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, secClass2)}`,
              direction: "inbound"
            });
          }
          continue;
        }
        if (endpoint.index === 0 && possibleSecurityClasses.length > 1) {
          node.setSecurityClass(secClass2, true);
          ctx.logNode(node.id, {
            message: `The node was granted the security class ${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, secClass2)}`,
            direction: "inbound"
          });
        }
        if (!hasReceivedSecureCommands && supportedCCs.length > 0) {
          hasReceivedSecureCommands = true;
          const logLines = [
            `received secure commands (${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, secClass2)})`,
            "supported CCs:"
          ];
          for (const cc of supportedCCs) {
            logLines.push(`\xB7 ${(0, import_core.getCCName)(cc)}`);
          }
          ctx.logNode(node.id, {
            endpoint: endpoint.index,
            message: logLines.join("\n"),
            direction: "inbound"
          });
          for (const cc of supportedCCs) {
            if (cc === import_core.CommandClasses.Basic) {
              endpoint.addCC(cc, { secure: true });
            } else {
              endpoint.addCC(cc, {
                isSupported: true,
                secure: true
              });
            }
          }
        }
      }
      this.setInterviewComplete(ctx, true);
    }
    /** Tests if a command should be sent secure and thus requires encapsulation */
    static requiresEncapsulation(cc) {
      if (!(cc.encapsulationFlags & import_core.EncapsulationFlags.Security)) {
        return false;
      }
      if (cc instanceof import_SecurityCC.SecurityCC || cc instanceof import_CRC16CC.CRC16CC || cc instanceof import_TransportServiceCC.TransportServiceCC) {
        return false;
      }
      if (cc instanceof Security2CC2) {
        switch (cc.ccCommand) {
          case import_Types.Security2Command.CommandsSupportedGet:
          case import_Types.Security2Command.CommandsSupportedReport:
          case import_Types.Security2Command.NetworkKeyGet:
          case import_Types.Security2Command.NetworkKeyReport:
          case import_Types.Security2Command.NetworkKeyVerify:
          case import_Types.Security2Command.TransferEnd:
            return true;
          case import_Types.Security2Command.KEXSet:
          case import_Types.Security2Command.KEXReport:
            return cc.echo;
          case import_Types.Security2Command.KEXFail: {
            switch (cc.failType) {
              case import_shared2.KEXFailType.Decrypt:
              case import_shared2.KEXFailType.WrongSecurityLevel:
              case import_shared2.KEXFailType.KeyNotGranted:
              case import_shared2.KEXFailType.NoVerify:
                return true;
              default:
                return false;
            }
          }
        }
        return false;
      }
      return true;
    }
    /** Encapsulates a command that should be sent encrypted */
    static encapsulate(cc, ownNodeId, securityManagers, options) {
      const extensions = [];
      if (options?.multicastOutOfSync) {
        extensions.push(new import_Extension.MOSExtension());
      }
      if (options?.multicastGroupId != void 0) {
        extensions.push(new import_Extension.MGRPExtension({ groupId: options.multicastGroupId }));
      }
      let nodeId;
      if (cc.isMulticast()) {
        if (cc.nodeId.some((nodeId2) => (0, import_core.isLongRangeNodeId)(nodeId2))) {
          nodeId = import_core.NODE_ID_BROADCAST_LR;
        } else {
          nodeId = import_core.NODE_ID_BROADCAST;
        }
      } else {
        nodeId = cc.nodeId;
      }
      const ret = new Security2CCMessageEncapsulation({
        nodeId,
        encapsulated: cc,
        securityClass: options?.securityClass,
        extensions,
        verifyDelivery: options?.verifyDelivery
      });
      ret.encapsulationFlags = cc.encapsulationFlags & ~import_core.EncapsulationFlags.Security;
      return ret;
    }
  };
  return Security2CC2 = _classThis;
})();
function failNoSPAN() {
  import_core.validatePayload.fail(import_core.ZWaveErrorCodes.Security2CC_NoSPAN);
}
__name(failNoSPAN, "failNoSPAN");
function failNoMPAN() {
  import_core.validatePayload.fail(import_core.ZWaveErrorCodes.Security2CC_NoMPAN);
}
__name(failNoMPAN, "failNoMPAN");
function getCCResponseForMessageEncapsulation(ctx, sent) {
  if (sent.encapsulated?.expectsCCResponse(ctx)) {
    const ret = [
      Security2CCMessageEncapsulation,
      Security2CCNonceReport
    ];
    if (sent.encapsulated instanceof Security2CCKEXSet || sent.encapsulated instanceof Security2CCKEXReport || sent.encapsulated instanceof Security2CCNetworkKeyGet || sent.encapsulated instanceof Security2CCNetworkKeyReport || sent.encapsulated instanceof Security2CCNetworkKeyVerify) {
      ret.push(Security2CCKEXFail);
    }
    return ret;
  }
}
__name(getCCResponseForMessageEncapsulation, "getCCResponseForMessageEncapsulation");
function testCCResponseForMessageEncapsulation(sent, received) {
  if (received instanceof Security2CCMessageEncapsulation) {
    return "checkEncapsulated";
  } else if (received instanceof Security2CCKEXFail) {
    return true;
  } else {
    return received.SOS && !!received.receiverEI;
  }
}
__name(testCCResponseForMessageEncapsulation, "testCCResponseForMessageEncapsulation");
let Security2CCMessageEncapsulation = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.MessageEncapsulation), (0, import_CommandClassDecorators.expectedCCResponse)(getCCResponseForMessageEncapsulation, testCCResponseForMessageEncapsulation)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCMessageEncapsulation2 = class extends _classSuper {
    static {
      __name(this, "Security2CCMessageEncapsulation");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCMessageEncapsulation2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      if (!options.encapsulated && !options.extensions?.length) {
        throw new import_core.ZWaveError("Security S2 encapsulation requires an encapsulated CC and/or extensions", import_core.ZWaveErrorCodes.Argument_Invalid);
      }
      this.sequenceNumber = options.sequenceNumber;
      this.securityClass = options.securityClass;
      if (options.encapsulated) {
        this.encapsulated = options.encapsulated;
        options.encapsulated.encapsulatingCC = this;
      }
      this.verifyDelivery = options.verifyDelivery !== false;
      this.extensions = options.extensions ?? [];
      if (typeof this.nodeId !== "number" && !this.extensions.some((e) => e instanceof import_Extension.MGRPExtension)) {
        throw new import_core.ZWaveError("Multicast Security S2 encapsulation requires the MGRP extension", import_core.ZWaveErrorCodes.Security2CC_MissingExtension);
      }
    }
    static async from(raw, ctx) {
      const securityManager = assertSecurityRX(ctx);
      (0, import_core.validatePayload)(raw.payload.length >= 2);
      const sequenceNumber = raw.payload[0];
      import_core.validatePayload.withReason("No security class granted")(ctx.getHighestSecurityClass(ctx.sourceNodeId) !== import_core.SecurityClass.None);
      const hasExtensions = !!(raw.payload[1] & 1);
      const hasEncryptedExtensions = !!(raw.payload[1] & 2);
      let offset = 2;
      const extensions = [];
      let mustDiscardCommand = false;
      if (hasExtensions) {
        const parseResult = parseExtensions(raw.payload.subarray(offset), false);
        extensions.push(...parseResult.extensions);
        offset += parseResult.bytesRead;
        mustDiscardCommand = parseResult.mustDiscardCommand;
      }
      const mcctx = (() => {
        const multicastGroupId = getMulticastGroupId(extensions);
        if (ctx.frameType === "multicast" || ctx.frameType === "broadcast") {
          if (multicastGroupId == void 0) {
            import_core.validatePayload.fail("Multicast frames without MGRP extension");
          }
          return {
            isMulticast: true,
            groupId: multicastGroupId
          };
        } else {
          return { isMulticast: false, groupId: multicastGroupId };
        }
      })();
      if (mustDiscardCommand) {
        if (mcctx.isMulticast) {
          await securityManager.nextPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
        } else {
          await securityManager.nextNonce(ctx.sourceNodeId);
        }
        import_core.validatePayload.fail("Invalid S2 extension");
      }
      let prevSequenceNumber;
      let mpanState;
      if (mcctx.isMulticast) {
        mpanState = securityManager.getPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
      } else {
        prevSequenceNumber = validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
        if (mcctx.groupId == void 0) {
          securityManager.resetOutOfSyncMPANs(ctx.sourceNodeId);
        }
      }
      const unencryptedPayload = raw.payload.subarray(0, offset);
      const ciphertext = raw.payload.subarray(offset, -SECURITY_S2_AUTH_TAG_LENGTH);
      const authTag = raw.payload.subarray(-SECURITY_S2_AUTH_TAG_LENGTH);
      const messageLength = 2 + raw.payload.length;
      const authData = getAuthenticationData(ctx.sourceNodeId, getDestinationIDRX(ctx, extensions), ctx.homeId, messageLength, unencryptedPayload);
      let decrypt;
      if (mcctx.isMulticast) {
        if (mpanState?.type !== import_core.MPANState.MPAN) {
          securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: import_core.MPANState.OutOfSync });
          failNoMPAN();
        }
        decrypt = /* @__PURE__ */ __name(() => decryptMulticast(ctx.sourceNodeId, securityManager, mcctx.groupId, ciphertext, authData, authTag), "decrypt");
      } else {
        const spanState = securityManager.getSPANState(ctx.sourceNodeId);
        if (spanState.type === import_core.SPANState.None) {
          failNoSPAN();
        } else if (spanState.type === import_core.SPANState.RemoteEI) {
          failNoSPAN();
        }
        decrypt = /* @__PURE__ */ __name(() => decryptSinglecast(ctx, securityManager, ctx.sourceNodeId, sequenceNumber, prevSequenceNumber, ciphertext, authData, authTag, spanState, extensions), "decrypt");
      }
      let plaintext;
      let authOK = false;
      let key;
      let iv;
      let decryptionSecurityClass;
      const decryptAttempts = mcctx.isMulticast ? MAX_DECRYPT_ATTEMPTS_MULTICAST : mcctx.groupId != void 0 ? MAX_DECRYPT_ATTEMPTS_SC_FOLLOWUP : MAX_DECRYPT_ATTEMPTS_SINGLECAST;
      for (let i = 0; i < decryptAttempts; i++) {
        ({
          plaintext,
          authOK,
          key,
          iv,
          securityClass: decryptionSecurityClass
        } = await decrypt());
        if (!!authOK && !!plaintext)
          break;
        if (!!getSenderEI(extensions))
          break;
      }
      if (!authOK || !plaintext) {
        if (mcctx.isMulticast) {
          securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: import_core.MPANState.OutOfSync });
          import_core.validatePayload.fail(import_core.ZWaveErrorCodes.Security2CC_CannotDecodeMulticast);
        } else {
          import_core.validatePayload.fail(import_core.ZWaveErrorCodes.Security2CC_CannotDecode);
        }
      } else if (!mcctx.isMulticast && mcctx.groupId != void 0) {
        securityManager.tryIncrementPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
      }
      const securityClass = decryptionSecurityClass;
      offset = 0;
      if (hasEncryptedExtensions) {
        const parseResult = parseExtensions(plaintext, true);
        extensions.push(...parseResult.extensions);
        offset += parseResult.bytesRead;
        mustDiscardCommand = parseResult.mustDiscardCommand;
      }
      if (mustDiscardCommand) {
        import_core.validatePayload.fail("Invalid extension");
      }
      const mpanExtension = extensions.find((e) => e instanceof import_Extension.MPANExtension);
      if (mcctx.groupId != void 0 && mpanExtension) {
        import_core.validatePayload.fail("Invalid combination of extensions");
      }
      if (!mcctx.isMulticast) {
        const mpanExtension2 = extensions.find((e) => e instanceof import_Extension.MPANExtension);
        if (mpanExtension2) {
          securityManager.storePeerMPAN(ctx.sourceNodeId, mpanExtension2.groupId, {
            type: import_core.MPANState.MPAN,
            currentMPAN: mpanExtension2.innerMPANState
          });
        }
      }
      const decryptedCCBytes = plaintext.subarray(offset);
      let encapsulated;
      if (decryptedCCBytes.length > 0) {
        (0, import_core.validatePayload)(decryptedCCBytes.length >= 2);
        encapsulated = await import_CommandClass.CommandClass.parse(decryptedCCBytes, ctx);
      }
      const ret = new Security2CCMessageEncapsulation2({
        nodeId: ctx.sourceNodeId,
        sequenceNumber,
        securityClass,
        extensions,
        encapsulated
      });
      ret.key = key;
      ret.iv = iv;
      ret.authData = authData;
      ret.authTag = authTag;
      ret.plaintext = decryptedCCBytes;
      return ret;
    }
    securityClass;
    // Only used for testing/debugging purposes
    key;
    iv;
    authData;
    authTag;
    ciphertext;
    plaintext;
    verifyDelivery = true;
    sequenceNumber;
    ensureSequenceNumber(securityManager) {
      if (this.sequenceNumber == void 0) {
        if (this.isSinglecast()) {
          this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
        } else {
          const groupId = getDestinationIDTX.call(this);
          this.sequenceNumber = securityManager.nextMulticastSequenceNumber(groupId);
        }
      }
    }
    encapsulated;
    extensions;
    prepareRetransmission() {
      super.prepareRetransmission();
      this.sequenceNumber = void 0;
    }
    hasMOSExtension() {
      return this.extensions.some((e) => e instanceof import_Extension.MOSExtension);
    }
    /** Returns the Sender's Entropy Input if this command contains an SPAN extension */
    getSenderEI() {
      return getSenderEI(this.extensions);
    }
    /** Returns the multicast group ID if this command contains an MGRP extension */
    getMulticastGroupId() {
      return getMulticastGroupId(this.extensions);
    }
    async maybeAddSPANExtension(ctx, securityManager) {
      if (!this.isSinglecast())
        return;
      const receiverNodeId = this.nodeId;
      const spanState = securityManager.getSPANState(receiverNodeId);
      if (spanState.type === import_core.SPANState.None || spanState.type === import_core.SPANState.LocalEI) {
        throw new import_core.ZWaveError(`Security S2 CC requires the receiver's nonce to be sent!`, import_core.ZWaveErrorCodes.Security2CC_NoSPAN);
      } else if (spanState.type === import_core.SPANState.RemoteEI) {
        const senderEI = await securityManager.generateNonce(void 0);
        const receiverEI = spanState.receiverEI;
        if (this.securityClass == void 0 && securityManager.tempKeys.has(receiverNodeId)) {
          await securityManager.initializeTempSPAN(receiverNodeId, senderEI, receiverEI);
        } else {
          const securityClass = this.securityClass ?? ctx.getHighestSecurityClass(receiverNodeId);
          if (securityClass == void 0) {
            throw new import_core.ZWaveError("No security class defined for this command!", import_core.ZWaveErrorCodes.Security2CC_NoSPAN);
          }
          await securityManager.initializeSPAN(receiverNodeId, securityClass, senderEI, receiverEI);
        }
        let spanExtension = this.extensions.find((e) => e instanceof import_Extension.SPANExtension);
        if (spanExtension) {
          spanExtension.senderEI = senderEI;
        } else {
          spanExtension = new import_Extension.SPANExtension({ senderEI });
          this.extensions.push(spanExtension);
        }
      }
    }
    async serialize(ctx) {
      const securityManager = assertSecurityTX(ctx, this.nodeId);
      this.ensureSequenceNumber(securityManager);
      await this.maybeAddSPANExtension(ctx, securityManager);
      const unencryptedExtensions = this.extensions.filter((e) => !e.isEncrypted());
      const encryptedExtensions = this.extensions.filter((e) => e.isEncrypted());
      const unencryptedPayload = import_shared.Bytes.concat([
        [
          this.sequenceNumber,
          (encryptedExtensions.length > 0 ? 2 : 0) | (unencryptedExtensions.length > 0 ? 1 : 0)
        ],
        ...unencryptedExtensions.map((e, index) => e.serialize(index < unencryptedExtensions.length - 1))
      ]);
      const serializedCC = await this.encapsulated?.serialize(ctx) ?? new import_shared.Bytes();
      const plaintextPayload = import_shared.Bytes.concat([
        ...encryptedExtensions.map((e, index) => e.serialize(index < encryptedExtensions.length - 1)),
        serializedCC
      ]);
      const destinationTag = getDestinationIDTX.call(this);
      const messageLength = this.computeEncapsulationOverhead() + serializedCC.length;
      const authData = getAuthenticationData(ctx.ownNodeId, destinationTag, ctx.homeId, messageLength, unencryptedPayload);
      let key;
      let iv;
      if (this.isSinglecast()) {
        iv = await securityManager.nextNonce(this.nodeId, true);
        const { keyCCM } = (
          // Prefer the overridden security class if it was given
          this.securityClass != void 0 ? securityManager.getKeysForSecurityClass(this.securityClass) : securityManager.getKeysForNode(this.nodeId)
        );
        key = keyCCM;
      } else {
        const keyAndIV = await securityManager.getMulticastKeyAndIV(destinationTag);
        key = keyAndIV.key;
        iv = keyAndIV.iv;
      }
      const { ciphertext: ciphertextPayload, authTag } = await (0, import_core.encryptAES128CCM)(plaintextPayload, key, iv, authData, SECURITY_S2_AUTH_TAG_LENGTH);
      this.key = key;
      this.iv = iv;
      this.authData = authData;
      this.authTag = authTag;
      this.ciphertext = ciphertextPayload;
      this.payload = import_shared.Bytes.concat([
        unencryptedPayload,
        ciphertextPayload,
        authTag
      ]);
      return super.serialize(ctx);
    }
    computeEncapsulationOverhead() {
      const extensionBytes = this.extensions.map((e) => e.computeLength()).reduce((a, b) => a + b, 0);
      return super.computeEncapsulationOverhead() + 2 + SECURITY_S2_AUTH_TAG_LENGTH + extensionBytes;
    }
    toLogEntry(ctx) {
      const message = {
        "sequence number": this.sequenceNumber ?? "(not set)"
      };
      if (this.extensions.length > 0) {
        message.extensions = this.extensions.map((e) => e.toLogEntry()).join("");
      }
      if (process.env.NODE_ENV === "test" || process.env.NODE_ENV === "development") {
        if (this.key) {
          message.key = (0, import_shared.buffer2hex)(this.key);
        }
        if (this.iv) {
          message.IV = (0, import_shared.buffer2hex)(this.iv);
        }
        if (this.ciphertext) {
          message.ciphertext = (0, import_shared.buffer2hex)(this.ciphertext);
        } else if (this.plaintext) {
          message.plaintext = (0, import_shared.buffer2hex)(this.plaintext);
        }
        if (this.authData) {
          message["auth data"] = (0, import_shared.buffer2hex)(this.authData);
        }
        if (this.authTag) {
          message["auth tag"] = (0, import_shared.buffer2hex)(this.authTag);
        }
      }
      if (this.securityClass != void 0) {
        message["security class"] = (0, import_shared.getEnumMemberName)(import_core.SecurityClass, this.securityClass);
      }
      return {
        ...super.toLogEntry(ctx),
        message
      };
    }
  };
  return Security2CCMessageEncapsulation2 = _classThis;
})();
let Security2CCNonceReport = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.NonceReport)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCNonceReport2 = class extends _classSuper {
    static {
      __name(this, "Security2CCNonceReport");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCNonceReport2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.SOS = options.SOS;
      this.MOS = options.MOS;
      this.sequenceNumber = options.sequenceNumber;
      if (options.SOS)
        this.receiverEI = options.receiverEI;
    }
    static from(raw, ctx) {
      const securityManager = assertSecurityRX(ctx);
      (0, import_core.validatePayload)(raw.payload.length >= 2);
      const sequenceNumber = raw.payload[0];
      validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
      const MOS = !!(raw.payload[1] & 2);
      const SOS = !!(raw.payload[1] & 1);
      if (SOS) {
        (0, import_core.validatePayload)(raw.payload.length >= 18);
        const receiverEI = raw.payload.subarray(2, 18);
        securityManager.storeRemoteEI(ctx.sourceNodeId, receiverEI);
        return new this({
          nodeId: ctx.sourceNodeId,
          sequenceNumber,
          MOS,
          SOS,
          receiverEI
        });
      } else if (MOS) {
        return new this({
          nodeId: ctx.sourceNodeId,
          sequenceNumber,
          MOS,
          SOS: false
        });
      } else {
        import_core.validatePayload.fail("Either MOS or SOS must be set");
      }
    }
    sequenceNumber;
    ensureSequenceNumber(securityManager) {
      if (this.sequenceNumber == void 0) {
        this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
      }
    }
    SOS;
    MOS;
    receiverEI;
    serialize(ctx) {
      const securityManager = assertSecurityTX(ctx, this.nodeId);
      this.ensureSequenceNumber(securityManager);
      this.payload = import_shared.Bytes.from([
        this.sequenceNumber,
        (this.MOS ? 2 : 0) + (this.SOS ? 1 : 0)
      ]);
      if (this.SOS) {
        this.payload = import_shared.Bytes.concat([this.payload, this.receiverEI]);
      }
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      const message = {
        "sequence number": this.sequenceNumber ?? "(not set)",
        SOS: this.SOS,
        MOS: this.MOS
      };
      if (this.receiverEI) {
        message["receiver entropy"] = (0, import_shared.buffer2hex)(this.receiverEI);
      }
      return {
        ...super.toLogEntry(ctx),
        message
      };
    }
  };
  return Security2CCNonceReport2 = _classThis;
})();
let Security2CCNonceGet = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.NonceGet), (0, import_CommandClassDecorators.expectedCCResponse)(Security2CCNonceReport)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCNonceGet2 = class extends _classSuper {
    static {
      __name(this, "Security2CCNonceGet");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCNonceGet2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    // TODO: A node sending this command MUST accept a delay up to <Previous Round-trip-time to peer node> +
    // 250 ms before receiving the Security 2 Nonce Report Command.
    constructor(options) {
      super(options);
      this.sequenceNumber = options.sequenceNumber;
    }
    static from(raw, ctx) {
      const securityManager = assertSecurityRX(ctx);
      (0, import_core.validatePayload)(raw.payload.length >= 1);
      const sequenceNumber = raw.payload[0];
      validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
      return new this({
        nodeId: ctx.sourceNodeId,
        sequenceNumber
      });
    }
    sequenceNumber;
    ensureSequenceNumber(securityManager) {
      if (this.sequenceNumber == void 0) {
        this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
      }
    }
    serialize(ctx) {
      const securityManager = assertSecurityTX(ctx, this.nodeId);
      this.ensureSequenceNumber(securityManager);
      this.payload = import_shared.Bytes.from([this.sequenceNumber]);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: {
          "sequence number": this.sequenceNumber ?? "(not set)"
        }
      };
    }
  };
  return Security2CCNonceGet2 = _classThis;
})();
let Security2CCKEXReport = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.KEXReport)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCKEXReport2 = class extends _classSuper {
    static {
      __name(this, "Security2CCKEXReport");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCKEXReport2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.requestCSA = options.requestCSA;
      this.echo = options.echo;
      this._reserved = options._reserved ?? 0;
      this.supportedKEXSchemes = options.supportedKEXSchemes;
      this.supportedECDHProfiles = options.supportedECDHProfiles;
      this.requestedKeys = options.requestedKeys;
    }
    static from(raw, ctx) {
      (0, import_core.validatePayload)(raw.payload.length >= 4);
      const requestCSA = !!(raw.payload[0] & 2);
      const echo = !!(raw.payload[0] & 1);
      const _reserved = raw.payload[0] & 252;
      const supportedKEXSchemes = (0, import_core.parseBitMask)(raw.payload.subarray(1, 2), 0).filter((s) => s !== 0);
      const supportedECDHProfiles = (0, import_core.parseBitMask)(raw.payload.subarray(2, 3), import_shared2.ECDHProfiles.Curve25519);
      const requestedKeys = (0, import_core.parseBitMask)(raw.payload.subarray(3, 4), import_core.SecurityClass.S2_Unauthenticated);
      return new this({
        nodeId: ctx.sourceNodeId,
        requestCSA,
        echo,
        _reserved,
        supportedKEXSchemes,
        supportedECDHProfiles,
        requestedKeys
      });
    }
    _reserved;
    requestCSA;
    echo;
    supportedKEXSchemes;
    supportedECDHProfiles;
    requestedKeys;
    serialize(ctx) {
      this.payload = import_shared.Bytes.concat([
        [
          this._reserved + (this.requestCSA ? 2 : 0) + (this.echo ? 1 : 0)
        ],
        // The bit mask starts at 0, but bit 0 is not used
        (0, import_core.encodeBitMask)(this.supportedKEXSchemes, 7, 0),
        (0, import_core.encodeBitMask)(this.supportedECDHProfiles, 7, import_shared2.ECDHProfiles.Curve25519),
        (0, import_core.encodeBitMask)(this.requestedKeys, import_core.SecurityClass.S0_Legacy, import_core.SecurityClass.S2_Unauthenticated)
      ]);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: {
          echo: this.echo,
          "supported schemes": this.supportedKEXSchemes.map((s) => `
\xB7 ${(0, import_shared.getEnumMemberName)(import_shared2.KEXSchemes, s)}`).join(""),
          "supported ECDH profiles": this.supportedECDHProfiles.map((s) => `
\xB7 ${(0, import_shared.getEnumMemberName)(import_shared2.ECDHProfiles, s)}`).join(""),
          "CSA requested": this.requestCSA,
          "requested security classes": this.requestedKeys.map((s) => `
\xB7 ${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, s)}`).join("")
        }
      };
    }
  };
  return Security2CCKEXReport2 = _classThis;
})();
let Security2CCKEXGet = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.KEXGet), (0, import_CommandClassDecorators.expectedCCResponse)(Security2CCKEXReport)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCKEXGet2 = class extends _classSuper {
    static {
      __name(this, "Security2CCKEXGet");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCKEXGet2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
  };
  return Security2CCKEXGet2 = _classThis;
})();
function getExpectedResponseForKEXSet(ctx, sent) {
  if (sent.echo) {
    return [Security2CCKEXReport, Security2CCKEXFail];
  } else {
    return void 0;
  }
}
__name(getExpectedResponseForKEXSet, "getExpectedResponseForKEXSet");
function testExpectedResponseForKEXSet(sent, received) {
  if (sent.echo) {
    if (received instanceof Security2CCKEXReport) {
      return received.echo;
    } else if (received instanceof Security2CCKEXFail) {
      return true;
    }
  }
  return false;
}
__name(testExpectedResponseForKEXSet, "testExpectedResponseForKEXSet");
let Security2CCKEXSet = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.KEXSet), (0, import_CommandClassDecorators.expectedCCResponse)(getExpectedResponseForKEXSet, testExpectedResponseForKEXSet)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCKEXSet2 = class extends _classSuper {
    static {
      __name(this, "Security2CCKEXSet");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCKEXSet2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.permitCSA = options.permitCSA;
      this.echo = options.echo;
      this._reserved = options._reserved ?? 0;
      this.selectedKEXScheme = options.selectedKEXScheme;
      this.selectedECDHProfile = options.selectedECDHProfile;
      this.grantedKeys = options.grantedKeys;
    }
    static from(raw, ctx) {
      (0, import_core.validatePayload)(raw.payload.length >= 4);
      const _reserved = raw.payload[0] & 252;
      const permitCSA = !!(raw.payload[0] & 2);
      const echo = !!(raw.payload[0] & 1);
      const selectedKEXSchemes = (0, import_core.parseBitMask)(raw.payload.subarray(1, 2), 0).filter((s) => s !== 0);
      (0, import_core.validatePayload)(selectedKEXSchemes.length === 1);
      const selectedKEXScheme = selectedKEXSchemes[0];
      const selectedECDHProfiles = (0, import_core.parseBitMask)(raw.payload.subarray(2, 3), import_shared2.ECDHProfiles.Curve25519);
      (0, import_core.validatePayload)(selectedECDHProfiles.length === 1);
      const selectedECDHProfile = selectedECDHProfiles[0];
      const grantedKeys = (0, import_core.parseBitMask)(raw.payload.subarray(3, 4), import_core.SecurityClass.S2_Unauthenticated);
      return new this({
        nodeId: ctx.sourceNodeId,
        _reserved,
        permitCSA,
        echo,
        selectedKEXScheme,
        selectedECDHProfile,
        grantedKeys
      });
    }
    _reserved;
    permitCSA;
    echo;
    selectedKEXScheme;
    selectedECDHProfile;
    grantedKeys;
    serialize(ctx) {
      this.payload = import_shared.Bytes.concat([
        [
          this._reserved + (this.permitCSA ? 2 : 0) + (this.echo ? 1 : 0)
        ],
        // The bit mask starts at 0, but bit 0 is not used
        (0, import_core.encodeBitMask)([this.selectedKEXScheme], 7, 0),
        (0, import_core.encodeBitMask)([this.selectedECDHProfile], 7, import_shared2.ECDHProfiles.Curve25519),
        (0, import_core.encodeBitMask)(this.grantedKeys, import_core.SecurityClass.S0_Legacy, import_core.SecurityClass.S2_Unauthenticated)
      ]);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: {
          echo: this.echo,
          "selected scheme": (0, import_shared.getEnumMemberName)(import_shared2.KEXSchemes, this.selectedKEXScheme),
          "selected ECDH profile": (0, import_shared.getEnumMemberName)(import_shared2.ECDHProfiles, this.selectedECDHProfile),
          "CSA permitted": this.permitCSA,
          "granted security classes": this.grantedKeys.map((s) => `
\xB7 ${(0, import_shared.getEnumMemberName)(import_core.SecurityClass, s)}`).join("")
        }
      };
    }
  };
  return Security2CCKEXSet2 = _classThis;
})();
let Security2CCKEXFail = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.KEXFail)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCKEXFail2 = class extends _classSuper {
    static {
      __name(this, "Security2CCKEXFail");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCKEXFail2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.failType = options.failType;
    }
    static from(raw, ctx) {
      (0, import_core.validatePayload)(raw.payload.length >= 1);
      const failType = raw.payload[0];
      return new this({
        nodeId: ctx.sourceNodeId,
        failType
      });
    }
    failType;
    serialize(ctx) {
      this.payload = import_shared.Bytes.from([this.failType]);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: { reason: (0, import_shared.getEnumMemberName)(import_shared2.KEXFailType, this.failType) }
      };
    }
  };
  return Security2CCKEXFail2 = _classThis;
})();
let Security2CCPublicKeyReport = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.PublicKeyReport)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCPublicKeyReport2 = class extends _classSuper {
    static {
      __name(this, "Security2CCPublicKeyReport");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCPublicKeyReport2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.includingNode = options.includingNode;
      this.publicKey = options.publicKey;
    }
    static from(raw, ctx) {
      (0, import_core.validatePayload)(raw.payload.length >= 17);
      const includingNode = !!(raw.payload[0] & 1);
      const publicKey = raw.payload.subarray(1);
      return new this({
        nodeId: ctx.sourceNodeId,
        includingNode,
        publicKey
      });
    }
    includingNode;
    publicKey;
    serialize(ctx) {
      this.payload = import_shared.Bytes.concat([
        [this.includingNode ? 1 : 0],
        this.publicKey
      ]);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: {
          "is including node": this.includingNode,
          "public key": (0, import_shared.buffer2hex)(this.publicKey)
        }
      };
    }
  };
  return Security2CCPublicKeyReport2 = _classThis;
})();
let Security2CCNetworkKeyReport = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.NetworkKeyReport)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCNetworkKeyReport2 = class extends _classSuper {
    static {
      __name(this, "Security2CCNetworkKeyReport");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCNetworkKeyReport2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.grantedKey = options.grantedKey;
      this.networkKey = options.networkKey;
    }
    static from(raw, ctx) {
      (0, import_core.validatePayload)(raw.payload.length >= 17);
      const grantedKey = bitMaskToSecurityClass(raw.payload, 0);
      const networkKey = raw.payload.subarray(1, 17);
      return new this({
        nodeId: ctx.sourceNodeId,
        grantedKey,
        networkKey
      });
    }
    grantedKey;
    networkKey;
    serialize(ctx) {
      this.payload = import_shared.Bytes.concat([
        securityClassToBitMask(this.grantedKey),
        this.networkKey
      ]);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: {
          "security class": (0, import_shared.getEnumMemberName)(import_core.SecurityClass, this.grantedKey)
          // This shouldn't be logged, so users can safely post their logs online
          // "network key": buffer2hex(this.networkKey),
        }
      };
    }
  };
  return Security2CCNetworkKeyReport2 = _classThis;
})();
let Security2CCNetworkKeyGet = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.NetworkKeyGet)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCNetworkKeyGet2 = class extends _classSuper {
    static {
      __name(this, "Security2CCNetworkKeyGet");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCNetworkKeyGet2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.requestedKey = options.requestedKey;
    }
    static from(raw, ctx) {
      (0, import_core.validatePayload)(raw.payload.length >= 1);
      const requestedKey = bitMaskToSecurityClass(raw.payload, 0);
      return new this({
        nodeId: ctx.sourceNodeId,
        requestedKey
      });
    }
    requestedKey;
    serialize(ctx) {
      this.payload = securityClassToBitMask(this.requestedKey);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: {
          "security class": (0, import_shared.getEnumMemberName)(import_core.SecurityClass, this.requestedKey)
        }
      };
    }
  };
  return Security2CCNetworkKeyGet2 = _classThis;
})();
let Security2CCNetworkKeyVerify = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.NetworkKeyVerify)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCNetworkKeyVerify2 = class extends _classSuper {
    static {
      __name(this, "Security2CCNetworkKeyVerify");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCNetworkKeyVerify2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
  };
  return Security2CCNetworkKeyVerify2 = _classThis;
})();
let Security2CCTransferEnd = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.TransferEnd)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCTransferEnd2 = class extends _classSuper {
    static {
      __name(this, "Security2CCTransferEnd");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCTransferEnd2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.keyVerified = options.keyVerified;
      this.keyRequestComplete = options.keyRequestComplete;
    }
    static from(raw, ctx) {
      (0, import_core.validatePayload)(raw.payload.length >= 1);
      const keyVerified = !!(raw.payload[0] & 2);
      const keyRequestComplete = !!(raw.payload[0] & 1);
      return new this({
        nodeId: ctx.sourceNodeId,
        keyVerified,
        keyRequestComplete
      });
    }
    keyVerified;
    keyRequestComplete;
    serialize(ctx) {
      this.payload = import_shared.Bytes.from([
        (this.keyVerified ? 2 : 0) + (this.keyRequestComplete ? 1 : 0)
      ]);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: {
          "key verified": this.keyVerified,
          "request complete": this.keyRequestComplete
        }
      };
    }
  };
  return Security2CCTransferEnd2 = _classThis;
})();
let Security2CCCommandsSupportedReport = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.CommandsSupportedReport)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCCommandsSupportedReport2 = class extends _classSuper {
    static {
      __name(this, "Security2CCCommandsSupportedReport");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCCommandsSupportedReport2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
    constructor(options) {
      super(options);
      this.supportedCCs = options.supportedCCs;
    }
    static from(raw, ctx) {
      const CCs = (0, import_core.parseCCList)(raw.payload);
      const supportedCCs = CCs.supportedCCs;
      return new this({
        nodeId: ctx.sourceNodeId,
        supportedCCs
      });
    }
    supportedCCs;
    serialize(ctx) {
      this.payload = (0, import_core.encodeCCList)(this.supportedCCs, []);
      return super.serialize(ctx);
    }
    toLogEntry(ctx) {
      return {
        ...super.toLogEntry(ctx),
        message: {
          "supported CCs": this.supportedCCs.map((cc) => (0, import_core.getCCName)(cc)).map((cc) => `
\xB7 ${cc}`).join("")
        }
      };
    }
  };
  return Security2CCCommandsSupportedReport2 = _classThis;
})();
let Security2CCCommandsSupportedGet = (() => {
  let _classDecorators = [(0, import_CommandClassDecorators.CCCommand)(import_Types.Security2Command.CommandsSupportedGet), (0, import_CommandClassDecorators.expectedCCResponse)(Security2CCCommandsSupportedReport)];
  let _classDescriptor;
  let _classExtraInitializers = [];
  let _classThis;
  let _classSuper = Security2CC;
  var Security2CCCommandsSupportedGet2 = class extends _classSuper {
    static {
      __name(this, "Security2CCCommandsSupportedGet");
    }
    static {
      _classThis = this;
    }
    static {
      const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
      (0, import_tslib.__esDecorate)(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
      Security2CCCommandsSupportedGet2 = _classThis = _classDescriptor.value;
      if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
      (0, import_tslib.__runInitializers)(_classThis, _classExtraInitializers);
    }
  };
  return Security2CCCommandsSupportedGet2 = _classThis;
})();
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  Security2CC,
  Security2CCAPI,
  Security2CCCommandsSupportedGet,
  Security2CCCommandsSupportedReport,
  Security2CCKEXFail,
  Security2CCKEXGet,
  Security2CCKEXReport,
  Security2CCKEXSet,
  Security2CCMessageEncapsulation,
  Security2CCNetworkKeyGet,
  Security2CCNetworkKeyReport,
  Security2CCNetworkKeyVerify,
  Security2CCNonceGet,
  Security2CCNonceReport,
  Security2CCPublicKeyReport,
  Security2CCTransferEnd
});
//# sourceMappingURL=Security2CC.js.map
