feat(mqtt): implement useMqttWebSocket hook
Was previously a dead stub (TODO: implement). This real implementation is the foundation for live heartbeats, ping RTT, and the device command ack flow that later commits build on. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,2 +1,61 @@
|
|||||||
// TODO: implement
|
// frontend/src/hooks/useMqttWebSocket.js
|
||||||
export function useMqttWebSocket() {}
|
// Subscribes to /api/mqtt/ws — broadcasts every inbound MQTT message
|
||||||
|
// (status/heartbeat, status/alerts, status/info, logs, data) as it arrives.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// useMqttWebSocket({ onMessage: (msg) => { ... } })
|
||||||
|
// msg shape: { type: 'data'|'status/heartbeat'|..., device_serial, payload, topic }
|
||||||
|
|
||||||
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
|
||||||
|
export function useMqttWebSocket({ enabled = true, onMessage } = {}) {
|
||||||
|
const [connected, setConnected] = useState(false)
|
||||||
|
const onMessageRef = useRef(onMessage)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onMessageRef.current = onMessage
|
||||||
|
}, [onMessage])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!enabled) return
|
||||||
|
|
||||||
|
let ws = null
|
||||||
|
let reconnectTimer = null
|
||||||
|
let stopped = false
|
||||||
|
|
||||||
|
const connect = () => {
|
||||||
|
const token = localStorage.getItem('access_token')
|
||||||
|
if (!token) return
|
||||||
|
|
||||||
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||||
|
ws = new WebSocket(`${protocol}//${window.location.host}/api/mqtt/ws?token=${token}`)
|
||||||
|
|
||||||
|
ws.onopen = () => setConnected(true)
|
||||||
|
ws.onclose = () => {
|
||||||
|
setConnected(false)
|
||||||
|
if (!stopped) reconnectTimer = setTimeout(connect, 5000)
|
||||||
|
}
|
||||||
|
ws.onerror = () => {}
|
||||||
|
ws.onmessage = (event) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(event.data)
|
||||||
|
onMessageRef.current?.(data)
|
||||||
|
} catch {
|
||||||
|
// ignore invalid JSON
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connect()
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
stopped = true
|
||||||
|
clearTimeout(reconnectTimer)
|
||||||
|
ws?.close()
|
||||||
|
}
|
||||||
|
}, [enabled])
|
||||||
|
|
||||||
|
return { connected }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMqttWebSocket
|
||||||
|
|||||||
Reference in New Issue
Block a user