/**
 * @license
 * Copyright 2025-2026 Open Home Foundation
 * SPDX-License-Identifier: Apache-2.0
 */
import { getCssVar } from "../../util/shared-styles.js";
const WIFI_FEATURE = 1 << 0;
const THREAD_FEATURE = 1 << 1;
const ETHERNET_FEATURE = 1 << 2;
const SIGNAL_STRONG_THRESHOLD = -70;
const SIGNAL_MEDIUM_THRESHOLD = -85;
const LQI_STRONG_THRESHOLD = 2;
const LQI_MEDIUM_THRESHOLD = 1;
function getSignalColorStrong() {
  return getCssVar("--signal-color-strong", "#4caf50");
}
function getSignalColorMedium() {
  return getCssVar("--signal-color-medium", "#ff9800");
}
function getSignalColorWeak() {
  return getCssVar("--signal-color-weak", "#f44336");
}
function getSignalColorNone() {
  return getCssVar("--signal-color-none", "#9e9e9e");
}
function base64ToBigInt(base64) {
  try {
    const binary = atob(base64);
    let result = 0n;
    const start = binary.length > 8 ? binary.length - 8 : 0;
    for (let i = start; i < binary.length; i++) {
      result = result << 8n | BigInt(binary.charCodeAt(i));
    }
    return result;
  } catch {
    return 0n;
  }
}
function normalizeExtAddress(value) {
  if (typeof value === "bigint") {
    return value;
  }
  if (typeof value === "string") {
    return base64ToBigInt(value);
  }
  if (typeof value === "number") {
    return BigInt(value);
  }
  return 0n;
}
function getNetworkType(node) {
  const featureMap = node.attributes["0/49/65532"];
  if (featureMap === void 0) {
    return "unknown";
  }
  if (featureMap & THREAD_FEATURE) {
    return "thread";
  }
  if (featureMap & WIFI_FEATURE) {
    return "wifi";
  }
  if (featureMap & ETHERNET_FEATURE) {
    return "ethernet";
  }
  return "unknown";
}
const THREAD_VERSION_NAMES = {
  1: "1.0",
  2: "1.1",
  3: "1.2",
  4: "1.3",
  5: "1.4"
};
function getThreadVersion(node) {
  const v = node.attributes["0/49/10"];
  return typeof v === "number" ? v : void 0;
}
function formatThreadVersion(tlv) {
  const name = THREAD_VERSION_NAMES[tlv];
  return name !== void 0 ? `Thread ${name}` : `Thread unknown (${tlv})`;
}
function categorizeDevices(nodes) {
  const result = {
    thread: [],
    wifi: [],
    ethernet: [],
    unknown: []
  };
  for (const node of Object.values(nodes)) {
    const nodeId = String(node.node_id);
    const networkType = getNetworkType(node);
    result[networkType].push(nodeId);
  }
  return result;
}
function getThreadRole(node) {
  const v = node.attributes["0/53/1"];
  return typeof v === "number" ? v : void 0;
}
function getThreadChannel(node) {
  const v = node.attributes["0/53/0"];
  return typeof v === "number" ? v : void 0;
}
function getThreadExtendedPanId(node) {
  const v = node.attributes["0/53/4"];
  if (typeof v === "bigint") return v;
  if (typeof v === "number" && Number.isInteger(v)) return BigInt(v);
  return void 0;
}
function getThreadExtendedAddress(node) {
  const networkInterfaces = node.attributes["0/51/0"];
  if (!Array.isArray(networkInterfaces) || networkInterfaces.length === 0) {
    return void 0;
  }
  const threadIface = networkInterfaces.find((i) => i["7"] === 4) || networkInterfaces[0];
  if (!threadIface) {
    return void 0;
  }
  const hwAddrB64 = threadIface["4"];
  if (typeof hwAddrB64 !== "string" || !hwAddrB64) {
    return void 0;
  }
  const extAddr = base64ToBigInt(hwAddrB64);
  return extAddr !== 0n ? extAddr : void 0;
}
function getThreadExtendedAddressHex(node) {
  const extAddr = getThreadExtendedAddress(node);
  if (extAddr !== void 0) {
    return extAddr.toString(16).padStart(16, "0").toUpperCase();
  }
  return void 0;
}
function getNeighborTableLength(node) {
  const neighborTable = node.attributes["0/53/7"];
  return Array.isArray(neighborTable) ? neighborTable.length : 0;
}
function parseNeighborTable(node) {
  const neighborTable = node.attributes["0/53/7"];
  if (!Array.isArray(neighborTable)) {
    return [];
  }
  return neighborTable.map((entry) => {
    const rawExtAddr = entry["0"] ?? entry.extAddress;
    const extAddress = normalizeExtAddress(rawExtAddr);
    return {
      extAddress,
      // Field 1: age
      age: entry["1"] ?? entry.age ?? 0,
      // Field 2: rloc16
      rloc16: entry["2"] ?? entry.rloc16 ?? 0,
      // Field 3: linkFrameCounter
      linkFrameCounter: entry["3"] ?? entry.linkFrameCounter ?? 0,
      // Field 4: mleFrameCounter
      mleFrameCounter: entry["4"] ?? entry.mleFrameCounter ?? 0,
      // Field 5: lqi
      lqi: entry["5"] ?? entry.lqi ?? 0,
      // Field 6: averageRssi (nullable)
      avgRssi: entry["6"] ?? entry.averageRssi ?? null,
      // Field 7: lastRssi (nullable)
      lastRssi: entry["7"] ?? entry.lastRssi ?? null,
      // Field 8: frameErrorRate
      frameErrorRate: entry["8"] ?? entry.frameErrorRate ?? 0,
      // Field 9: messageErrorRate
      messageErrorRate: entry["9"] ?? entry.messageErrorRate ?? 0,
      // Field 10: rxOnWhenIdle
      rxOnWhenIdle: entry["10"] ?? entry.rxOnWhenIdle ?? false,
      // Field 11: fullThreadDevice
      fullThreadDevice: entry["11"] ?? entry.fullThreadDevice ?? false,
      // Field 12: fullNetworkData
      fullNetworkData: entry["12"] ?? entry.fullNetworkData ?? false,
      // Field 13: isChild
      isChild: entry["13"] ?? entry.isChild ?? false
    };
  });
}
function parseRouteTable(node) {
  const routeTable = node.attributes["0/53/8"];
  if (!Array.isArray(routeTable)) {
    return [];
  }
  return routeTable.map((entry) => {
    const rawExtAddr = entry["0"] ?? entry.extAddress;
    const extAddress = normalizeExtAddress(rawExtAddr);
    return {
      extAddress,
      // Field 1: rloc16
      rloc16: entry["1"] ?? entry.rloc16 ?? 0,
      // Field 2: routerId
      routerId: entry["2"] ?? entry.routerId ?? 0,
      // Field 3: nextHop
      nextHop: entry["3"] ?? entry.nextHop ?? 0,
      // Field 4: pathCost
      pathCost: entry["4"] ?? entry.pathCost ?? 0,
      // Field 5: lqiIn
      lqiIn: entry["5"] ?? entry.lqiIn ?? 0,
      // Field 6: lqiOut
      lqiOut: entry["6"] ?? entry.lqiOut ?? 0,
      // Field 7: age
      age: entry["7"] ?? entry.age ?? 0,
      // Field 8: allocated
      allocated: entry["8"] ?? entry.allocated ?? false,
      // Field 9: linkEstablished
      linkEstablished: entry["9"] ?? entry.linkEstablished ?? false
    };
  });
}
function findRouteByExtAddress(node, targetExtAddr) {
  const routes = parseRouteTable(node);
  return routes.find((route) => route.extAddress === targetExtAddr && route.linkEstablished);
}
function getRoutableDestinationsCount(node) {
  const routes = parseRouteTable(node);
  return routes.filter((route) => route.allocated && route.linkEstablished).length;
}
function getRouteBidirectionalLqi(route) {
  if (route.lqiIn > 0 && route.lqiOut > 0) {
    return Math.round((route.lqiIn + route.lqiOut) / 2);
  }
  if (route.lqiIn > 0) return route.lqiIn;
  if (route.lqiOut > 0) return route.lqiOut;
  return void 0;
}
function getThreadRloc16(node) {
  const value = node.attributes["0/53/64"];
  if (typeof value === "number") {
    return value;
  }
  return void 0;
}
function buildExtAddrMap(nodes) {
  const extAddrMap = /* @__PURE__ */ new Map();
  for (const node of Object.values(nodes)) {
    const nodeId = String(node.node_id);
    const extAddr = getThreadExtendedAddress(node);
    if (extAddr !== void 0) {
      extAddrMap.set(extAddr, nodeId);
    }
  }
  return extAddrMap;
}
function buildRloc16Map(nodes) {
  const rloc16Map = /* @__PURE__ */ new Map();
  for (const node of Object.values(nodes)) {
    const nodeId = String(node.node_id);
    const rloc16 = getThreadRloc16(node);
    if (rloc16 !== void 0) {
      rloc16Map.set(rloc16, nodeId);
    }
  }
  return rloc16Map;
}
function findUnknownDevices(nodes, extAddrMap, rloc16Map, borderRouters) {
  const aggregates = /* @__PURE__ */ new Map();
  for (const node of Object.values(nodes)) {
    const nodeId = String(node.node_id);
    const neighbors = parseNeighborTable(node);
    const observerXp = getThreadExtendedPanId(node);
    const observerXpHex = observerXp !== void 0 ? observerXp.toString(16).padStart(16, "0").toUpperCase() : void 0;
    for (const neighbor of neighbors) {
      if (extAddrMap.has(neighbor.extAddress)) {
        continue;
      }
      if (neighbor.rloc16 !== 0 && rloc16Map.has(neighbor.rloc16)) {
        continue;
      }
      const extAddressHex = neighbor.extAddress.toString(16).padStart(16, "0").toUpperCase();
      let agg = aggregates.get(extAddressHex);
      if (agg === void 0) {
        agg = {
          extAddressHex,
          extAddress: neighbor.extAddress,
          seenBy: [],
          isRouter: false,
          bestRssi: null,
          extendedPanIdHex: observerXpHex
        };
        aggregates.set(extAddressHex, agg);
      } else if (agg.extendedPanIdHex === void 0 && observerXpHex !== void 0) {
        agg.extendedPanIdHex = observerXpHex;
      }
      if (!agg.seenBy.includes(nodeId)) {
        agg.seenBy.push(nodeId);
      }
      if (neighbor.rxOnWhenIdle) {
        agg.isRouter = true;
      }
      const rssi = neighbor.avgRssi ?? neighbor.lastRssi;
      if (rssi !== null && (agg.bestRssi === null || rssi > agg.bestRssi)) {
        agg.bestRssi = rssi;
      }
    }
  }
  const networkNameByXp = /* @__PURE__ */ new Map();
  if (borderRouters !== void 0) {
    for (const br of borderRouters.values()) {
      if (br.extendedPanIdHex !== void 0 && br.networkName !== void 0) {
        networkNameByXp.set(br.extendedPanIdHex, br.networkName);
      }
    }
  }
  const out = new Array();
  for (const agg of aggregates.values()) {
    const br = borderRouters?.get(agg.extAddressHex);
    if (br !== void 0) {
      out.push({
        kind: "br",
        ...br,
        id: `br_${agg.extAddressHex}`,
        extAddressHex: agg.extAddressHex,
        extAddress: agg.extAddress,
        seenBy: agg.seenBy,
        isRouter: agg.isRouter,
        bestRssi: agg.bestRssi
      });
    } else {
      const networkName = agg.extendedPanIdHex !== void 0 ? networkNameByXp.get(agg.extendedPanIdHex) : void 0;
      out.push({
        kind: "unknown",
        id: `unknown_${agg.extAddressHex}`,
        extAddressHex: agg.extAddressHex,
        extAddress: agg.extAddress,
        seenBy: agg.seenBy,
        isRouter: agg.isRouter,
        bestRssi: agg.bestRssi,
        extendedPanIdHex: agg.extendedPanIdHex,
        networkName
      });
    }
  }
  return out;
}
const CONNECTION_MODE_LABELS = {
  0: "disabled",
  1: "PSKc / DTLS",
  2: "PSKd / DTLS",
  3: "vendor-defined",
  4: "X.509"
};
const THREAD_INTERFACE_STATUS_LABELS = {
  0: "not initialized",
  1: "initialized, inactive",
  2: "initialized, active"
};
const AVAILABILITY_LABELS = {
  0: "infrequent",
  1: "high"
};
const THREAD_ROLE_LABELS = {
  0: "detached",
  1: "child",
  2: "router",
  3: "leader"
};
const MULTI_AIL_STATE_LABELS = {
  0: "disabled",
  1: "not detected",
  2: "detected"
};
function decodeMeshcopStateBitmap(hex) {
  if (hex === void 0 || !/^[0-9a-fA-F]{1,8}$/.test(hex)) return void 0;
  const value = parseInt(hex, 16);
  if (!Number.isFinite(value)) return void 0;
  const connectionModeValue = value & 7;
  const threadInterfaceStatusValue = value >> 3 & 3;
  const availabilityValue = value >> 5 & 3;
  const bbr = (value >> 7 & 1) === 1;
  const bbrIsPrimary = (value >> 8 & 1) === 1;
  const threadRoleValue = value >> 9 & 3;
  const epskcSupported = (value >> 11 & 1) === 1;
  const multiAilStateValue = value >> 12 & 3;
  const reserved = value >>> 14 >>> 0;
  return {
    connectionModeValue,
    connectionMode: CONNECTION_MODE_LABELS[connectionModeValue],
    threadInterfaceStatusValue,
    threadInterfaceStatus: THREAD_INTERFACE_STATUS_LABELS[threadInterfaceStatusValue],
    availabilityValue,
    availability: AVAILABILITY_LABELS[availabilityValue],
    bbr,
    bbrFunction: bbr ? bbrIsPrimary ? "primary" : "secondary" : void 0,
    threadRoleValue,
    threadRole: THREAD_ROLE_LABELS[threadRoleValue],
    epskcSupported,
    multiAilStateValue,
    multiAilState: MULTI_AIL_STATE_LABELS[multiAilStateValue],
    reservedHex: reserved !== 0 ? reserved.toString(16).toUpperCase() : void 0
  };
}
function getSignalLevel(neighbor) {
  return getSignalLevelFromLqi(neighbor.lqi);
}
function getSignalLevelFromLqi(lqi) {
  if (lqi <= 0) return "none";
  if (lqi > LQI_STRONG_THRESHOLD) return "strong";
  if (lqi > LQI_MEDIUM_THRESHOLD) return "medium";
  return "weak";
}
function signalLevelToColor(level) {
  switch (level) {
    case "strong":
      return getSignalColorStrong();
    case "medium":
      return getSignalColorMedium();
    case "weak":
      return getSignalColorWeak();
    case "none":
      return getSignalColorNone();
  }
}
function getSignalColor(neighbor) {
  return getSignalColorFromLqi(neighbor.lqi);
}
function getSignalColorFromLqi(lqi) {
  return signalLevelToColor(getSignalLevelFromLqi(lqi));
}
function stripMdnsHostname(hostname) {
  return hostname.replace(/\.$/, "").replace(/\.local$/i, "");
}
import { getDeviceName } from "../../util/node-name.js";
function getThreadRoleName(role) {
  switch (role) {
    case 0:
      return "Unspecified";
    case 1:
      return "Unassigned";
    case 2:
      return "Sleepy End Device";
    case 3:
      return "End Device";
    case 4:
      return "REED";
    case 5:
      return "Router";
    case 6:
      return "Leader";
    default:
      return "Unknown";
  }
}
function getWiFiDiagnostics(node) {
  const bssidRaw = node.attributes["0/54/0"];
  let bssid = null;
  if (bssidRaw) {
    try {
      const binary = atob(bssidRaw);
      bssid = Array.from(binary).map((c) => c.charCodeAt(0).toString(16).padStart(2, "0").toUpperCase()).join(":");
    } catch {
      bssid = null;
    }
  }
  const rssi = node.attributes["0/54/4"];
  const channel = node.attributes["0/54/3"];
  const securityType = node.attributes["0/54/1"];
  const wifiVersion = node.attributes["0/54/2"];
  return {
    bssid,
    rssi: rssi ?? null,
    channel: channel ?? null,
    securityType: securityType ?? null,
    wifiVersion: wifiVersion ?? null
  };
}
function getSignalColorFromRssi(rssi) {
  if (rssi === null) {
    return getSignalColorMedium();
  }
  if (rssi > SIGNAL_STRONG_THRESHOLD) {
    return getSignalColorStrong();
  }
  if (rssi > SIGNAL_MEDIUM_THRESHOLD) {
    return getSignalColorMedium();
  }
  return getSignalColorWeak();
}
function getWiFiSecurityTypeName(securityType) {
  switch (securityType) {
    case 0:
      return "Unspecified";
    case 1:
      return "None";
    case 2:
      return "WEP";
    case 3:
      return "WPA Personal";
    case 4:
      return "WPA2 Personal";
    case 5:
      return "WPA3 Personal";
    default:
      return "Unknown";
  }
}
function getWiFiVersionName(version) {
  switch (version) {
    case 0:
      return "802.11a";
    case 1:
      return "802.11b";
    case 2:
      return "802.11g";
    case 3:
      return "802.11n";
    case 4:
      return "802.11ac";
    case 5:
      return "802.11ax";
    case 6:
      return "802.11ah";
    default:
      return "Unknown";
  }
}
function makePairKey(a, b) {
  return a < b ? `${a}|${b}` : `${b}|${a}`;
}
function getEdgeSignalScore(conn) {
  const levelScore = conn.signalLevel === "strong" ? 3e3 : conn.signalLevel === "medium" ? 2e3 : conn.signalLevel === "weak" ? 1e3 : 0;
  const detail = conn.rssi !== null ? conn.rssi + 200 : conn.lqi;
  return levelScore + detail;
}
function buildThreadEdgePairs(nodes, extAddrMap, rloc16Map, unknownDevices) {
  const pairs = /* @__PURE__ */ new Map();
  const unknownExtAddrMap = /* @__PURE__ */ new Map();
  for (const unknown of unknownDevices) {
    unknownExtAddrMap.set(unknown.extAddress, unknown.id);
  }
  for (const node of Object.values(nodes)) {
    const fromNodeId = String(node.node_id);
    const neighbors = parseNeighborTable(node);
    for (const neighbor of neighbors) {
      let toNodeId = extAddrMap.get(neighbor.extAddress);
      if (toNodeId === void 0 && neighbor.rloc16 !== 0) {
        toNodeId = rloc16Map.get(neighbor.rloc16);
      }
      if (toNodeId === void 0) {
        toNodeId = unknownExtAddrMap.get(neighbor.extAddress);
      }
      if (toNodeId === void 0 || fromNodeId === toNodeId) continue;
      const pairKey = makePairKey(fromNodeId, toNodeId);
      if (!pairs.has(pairKey)) {
        const [nodeA, nodeB] = fromNodeId < toNodeId ? [fromNodeId, toNodeId] : [toNodeId, fromNodeId];
        pairs.set(pairKey, { pairKey, nodeA, nodeB });
      }
      const pair = pairs.get(pairKey);
      const isFromA = fromNodeId === pair.nodeA;
      if (isFromA && pair.edgeAB) continue;
      if (!isFromA && pair.edgeBA) continue;
      const routeEntry = findRouteByExtAddress(node, neighbor.extAddress);
      const bidirectionalLqi = routeEntry ? getRouteBidirectionalLqi(routeEntry) : void 0;
      const edge = {
        fromNodeId,
        toNodeId,
        signalColor: getSignalColor(neighbor),
        signalLevel: getSignalLevel(neighbor),
        lqi: neighbor.lqi,
        rssi: neighbor.avgRssi ?? neighbor.lastRssi,
        pathCost: routeEntry?.pathCost,
        bidirectionalLqi
      };
      if (isFromA) {
        pair.edgeAB = edge;
      } else {
        pair.edgeBA = edge;
      }
    }
    const routes = parseRouteTable(node);
    for (const route of routes) {
      if (!route.linkEstablished || !route.allocated) continue;
      let toNodeId = extAddrMap.get(route.extAddress);
      if (toNodeId === void 0 && route.rloc16 !== 0) {
        toNodeId = rloc16Map.get(route.rloc16);
      }
      if (toNodeId === void 0) {
        toNodeId = unknownExtAddrMap.get(route.extAddress);
      }
      if (toNodeId === void 0 || toNodeId === fromNodeId) continue;
      const pairKey = makePairKey(fromNodeId, toNodeId);
      if (!pairs.has(pairKey)) {
        const [nodeA, nodeB] = fromNodeId < toNodeId ? [fromNodeId, toNodeId] : [toNodeId, fromNodeId];
        pairs.set(pairKey, { pairKey, nodeA, nodeB });
      }
      const pair = pairs.get(pairKey);
      const isFromA = fromNodeId === pair.nodeA;
      if (isFromA && pair.edgeAB) continue;
      if (!isFromA && pair.edgeBA) continue;
      const bidirectionalLqi = getRouteBidirectionalLqi(route);
      const signalLevel = bidirectionalLqi !== void 0 ? getSignalLevelFromLqi(bidirectionalLqi) : "none";
      const edge = {
        fromNodeId,
        toNodeId,
        signalColor: signalLevelToColor(signalLevel),
        signalLevel,
        lqi: bidirectionalLqi ?? 0,
        rssi: null,
        pathCost: route.pathCost,
        bidirectionalLqi,
        fromRouteTable: true
      };
      if (isFromA) {
        pair.edgeAB = edge;
      } else {
        pair.edgeBA = edge;
      }
    }
  }
  return pairs;
}
function getNodeConnectionsFromPairs(nodeId, edgePairs, nodes, filters) {
  const connections = [];
  const hiddenNodeIds = /* @__PURE__ */ new Set();
  if (filters?.hideOfflineNodes) {
    for (const node of Object.values(nodes)) {
      if (node.available === false) {
        hiddenNodeIds.add(String(node.node_id));
      }
    }
  }
  for (const pair of edgePairs.values()) {
    const isA = pair.nodeA === nodeId;
    const isB = pair.nodeB === nodeId;
    if (!isA && !isB) continue;
    const remoteId = isA ? pair.nodeB : pair.nodeA;
    const outgoing = isA ? pair.edgeAB : pair.edgeBA;
    const incoming = isA ? pair.edgeBA : pair.edgeAB;
    const survivors = [];
    for (const [conn, isOut] of [
      [outgoing, true],
      [incoming, false]
    ]) {
      if (!conn) continue;
      if (filters) {
        const fromId = String(conn.fromNodeId);
        const toId = String(conn.toNodeId);
        if (hiddenNodeIds.has(fromId) || hiddenNodeIds.has(toId)) continue;
        if (filters.hideWeakSignalEdges && conn.signalLevel === "weak") continue;
        if (filters.hideMediumSignalEdges && conn.signalLevel === "medium") continue;
        if (filters.hideStrongSignalEdges && conn.signalLevel === "strong") continue;
      }
      survivors.push({ conn, isOutgoing: isOut });
    }
    if (survivors.length === 0) continue;
    const liveSurvivors = survivors.filter((s) => s.conn.signalLevel !== "none");
    const usable = liveSurvivors.length > 0 ? liveSurvivors : survivors;
    let winner;
    const outgoingSurvivor = usable.find((s) => s.isOutgoing);
    if (outgoingSurvivor) {
      winner = outgoingSurvivor;
    } else {
      usable.sort((a, b) => getEdgeSignalScore(a.conn) - getEdgeSignalScore(b.conn));
      winner = usable[0];
    }
    const remoteNode = nodes[remoteId];
    const isExternalUnknown = remoteId.startsWith("unknown_");
    const isExternalBr = remoteId.startsWith("br_");
    const isUnknown = isExternalUnknown || isExternalBr;
    let extAddressHex;
    if (isExternalUnknown) {
      extAddressHex = remoteId.slice("unknown_".length);
    } else if (isExternalBr) {
      extAddressHex = remoteId.slice("br_".length);
    } else if (remoteNode) {
      extAddressHex = getThreadExtendedAddressHex(remoteNode) ?? "Unknown";
    } else {
      extAddressHex = "Unknown";
    }
    connections.push({
      connectedNodeId: remoteId,
      connectedNode: remoteNode,
      extAddressHex,
      signalColor: winner.conn.signalColor,
      signalLevel: winner.conn.signalLevel,
      lqi: winner.conn.lqi,
      rssi: winner.conn.rssi,
      isOutgoing: winner.isOutgoing,
      isReverseOnly: !outgoing,
      isUnknown,
      pathCost: winner.conn.pathCost,
      bidirectionalLqi: winner.conn.bidirectionalLqi
    });
  }
  return connections;
}
export {
  buildExtAddrMap,
  buildRloc16Map,
  buildThreadEdgePairs,
  categorizeDevices,
  decodeMeshcopStateBitmap,
  findRouteByExtAddress,
  findUnknownDevices,
  formatThreadVersion,
  getDeviceName,
  getEdgeSignalScore,
  getNeighborTableLength,
  getNetworkType,
  getNodeConnectionsFromPairs,
  getRoutableDestinationsCount,
  getRouteBidirectionalLqi,
  getSignalColor,
  getSignalColorFromLqi,
  getSignalColorFromRssi,
  getSignalLevel,
  getSignalLevelFromLqi,
  getThreadChannel,
  getThreadExtendedAddress,
  getThreadExtendedAddressHex,
  getThreadExtendedPanId,
  getThreadRloc16,
  getThreadRole,
  getThreadRoleName,
  getThreadVersion,
  getWiFiDiagnostics,
  getWiFiSecurityTypeName,
  getWiFiVersionName,
  makePairKey,
  parseNeighborTable,
  parseRouteTable,
  signalLevelToColor,
  stripMdnsHostname
};
//# sourceMappingURL=network-utils.js.map
