revert: drop zigbee LQI edge coloring and path highlighting

Split out of this PR — will land separately with reworked zigbee edge
capture/storage. Keeps only the floor plan + generic media upload work.

- Remove getLqiColor + LQI-derived iot edge stroke (edges/index.tsx)
- Remove zigbee path highlight effect (DetailPanel.tsx)
- Remove highlightedPath/setHighlightedPath store state (canvasStore.ts)
- Delete utils/zigbeePathfinding.ts
- Revert associated test scaffolding and package-lock churn
This commit is contained in:
Pouzor
2026-07-02 17:16:51 +02:00
parent 1ed013bde2
commit 6160090919
7 changed files with 190 additions and 385 deletions
-89
View File
@@ -1,89 +0,0 @@
import type { Node, Edge } from '@xyflow/react'
import type { NodeData, EdgeData } from '@/types'
function getNodeLqi(node: Node<NodeData>): number {
const lqiProp = node.data.properties?.find((p) => p.key === 'LQI')
if (!lqiProp) return 255
const lqi = parseInt(lqiProp.value, 10)
return isNaN(lqi) ? 255 : lqi
}
/**
* Run Dijkstra on the Zigbee `iot` edge subgraph from `startNodeId` to
* `targetNodeId`. Returns the ordered list of edge IDs forming the optimal
* path, or an empty array if no path exists.
*
* Edge cost = 255 - LQI, where LQI is read from the edge's target node
* properties (higher LQI = lower cost). For reverse traversal, the same
* cost is used.
*/
export function findZigbeePath(
startNodeId: string,
targetNodeId: string,
nodes: Node<NodeData>[],
edges: Edge<EdgeData>[],
): string[] {
if (startNodeId === targetNodeId) return []
const iotEdges = edges.filter((e) => (e.data?.type ?? 'ethernet') === 'iot')
if (iotEdges.length === 0) return []
const nodeMap = new Map(nodes.map((n) => [n.id, n]))
const adjacency = new Map<string, { neighbor: string; edgeId: string; cost: number }[]>()
for (const e of iotEdges) {
const targetLqi = nodeMap.get(e.target) ? getNodeLqi(nodeMap.get(e.target)!) : 255
const sourceLqi = nodeMap.get(e.source) ? getNodeLqi(nodeMap.get(e.source)!) : 255
const cost = 255 - Math.min(targetLqi, sourceLqi)
if (!adjacency.has(e.source)) adjacency.set(e.source, [])
if (!adjacency.has(e.target)) adjacency.set(e.target, [])
adjacency.get(e.source)!.push({ neighbor: e.target, edgeId: e.id, cost })
adjacency.get(e.target)!.push({ neighbor: e.source, edgeId: e.id, cost })
}
if (!adjacency.has(startNodeId) || !adjacency.has(targetNodeId)) return []
const dist = new Map<string, number>()
const prev = new Map<string, { node: string; edgeId: string }>()
const unvisited = new Set(adjacency.keys())
for (const nodeId of unvisited) dist.set(nodeId, Infinity)
dist.set(startNodeId, 0)
while (unvisited.size > 0) {
let current: string | null = null
let minDist = Infinity
for (const nodeId of unvisited) {
const d = dist.get(nodeId)!
if (d < minDist) { minDist = d; current = nodeId }
}
if (current === null || minDist === Infinity) break
if (current === targetNodeId) break
unvisited.delete(current)
const neighbors = adjacency.get(current) ?? []
for (const { neighbor, edgeId, cost } of neighbors) {
if (!unvisited.has(neighbor)) continue
const alt = dist.get(current)! + cost
if (alt < (dist.get(neighbor) ?? Infinity)) {
dist.set(neighbor, alt)
prev.set(neighbor, { node: current, edgeId })
}
}
}
// Reconstruct path: walk from targetNodeId back to startNodeId
const pathEdges: string[] = []
let current = targetNodeId
while (current !== startNodeId) {
const p = prev.get(current)
if (!p) return []
pathEdges.unshift(p.edgeId)
current = p.node
}
return pathEdges
}