Browse Source
- 新增 WebSocket 就绪状态标识,确保仅在连接完全建立后发送消息。 - 实现消息队列功能,用于处理 WebSocket 就绪前发送的消息。 - 升级 AdvancedSettings 组件,通过自定义钩子函数管理设备配置,涵盖配置的获取与保存功能。 - 新增完善的 WebSocket 指令处理逻辑,支持设备编号、数据帧率、告警配置、过滤规则及 MQTT 配置的相关指令。 - 优化用户反馈体验,添加加载状态指示器及连接状态告警提示。 - 编写高级设置中 WebSocket 协议的完整使用文档。 - 将 package.json 文件中的版本号更新至 1.1.0。master
8 changed files with 1083 additions and 133 deletions
@ -0,0 +1,479 @@ |
|||
/** |
|||
* useAdvancedSettings Hook |
|||
* |
|||
* 高级配置管理 Hook,用于管理设备的高级参数配置 |
|||
* |
|||
* 功能包括: |
|||
* - 设备编码读取与设置 (getId/setId) |
|||
* - 数据帧率读取与设置 (getDataFps/setDataFps) |
|||
* - 异常超时监控读取与设置 (getAlert/setAlert) |
|||
* - 滤波配置读取与设置 (getWin/setWin) |
|||
* - MQTT 上报配置读取与设置 (getMqtt/setMqtt) |
|||
* |
|||
* 使用示例: |
|||
* ```jsx
|
|||
* const { |
|||
* settings, |
|||
* loading, |
|||
* fetchAllSettings, |
|||
* updateDeviceId, |
|||
* updateDataFps, |
|||
* updateAlertConfig, |
|||
* updateFilterConfig, |
|||
* updateMqttConfig, |
|||
* } = useAdvancedSettings(); |
|||
* ``` |
|||
*/ |
|||
|
|||
import { useState, useEffect, useCallback } from 'react'; |
|||
import { message } from 'antd'; |
|||
import { useWebSocket, useWebSocketSubscription } from '../actions/websocket.jsx'; |
|||
|
|||
/** |
|||
* 高级配置默认值 |
|||
*/ |
|||
const DEFAULT_SETTINGS = { |
|||
// 设备编码
|
|||
deviceId: '', |
|||
|
|||
// 数据帧率
|
|||
dataFps: 10, |
|||
|
|||
// 异常监控配置
|
|||
alertConfig: { |
|||
enable: false, |
|||
intervalSec: 60 |
|||
}, |
|||
|
|||
// 滤波配置
|
|||
filterConfig: { |
|||
enable: true, |
|||
method: 'median', |
|||
size: 5, |
|||
threshold: -0.1, |
|||
imgThreshold: 10.0 |
|||
}, |
|||
|
|||
// MQTT 配置
|
|||
mqttConfig: { |
|||
enable: true, |
|||
mqtt: { |
|||
broker: '', |
|||
port: 1883, |
|||
topic: '', |
|||
username: '', |
|||
password: '', |
|||
client_id: '' |
|||
} |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* 高级配置管理 Hook |
|||
*/ |
|||
const useAdvancedSettings = () => { |
|||
const { isConnected, isReady, sendMessage } = useWebSocket(); |
|||
|
|||
// 配置状态
|
|||
const [settings, setSettings] = useState(DEFAULT_SETTINGS); |
|||
const [loading, setLoading] = useState(false); |
|||
const [fetchStatus, setFetchStatus] = useState({}); |
|||
|
|||
// WebSocket 订阅 - 监听所有来自设备的响应
|
|||
const { latest: getIdResponse } = useWebSocketSubscription('dev', 'getId'); |
|||
const { latest: setIdResponse } = useWebSocketSubscription('dev', 'setId'); |
|||
const { latest: getDataFpsResponse } = useWebSocketSubscription('dev', 'getDataFps'); |
|||
const { latest: setDataFpsResponse } = useWebSocketSubscription('dev', 'setDataFps'); |
|||
const { latest: getAlertResponse } = useWebSocketSubscription('dev', 'getAlert'); |
|||
const { latest: setAlertResponse } = useWebSocketSubscription('dev', 'setAlert'); |
|||
const { latest: getWinResponse } = useWebSocketSubscription('dev', 'getWin'); |
|||
const { latest: setWinResponse } = useWebSocketSubscription('dev', 'setWin'); |
|||
const { latest: getMqttResponse } = useWebSocketSubscription('dev', 'getMqtt'); |
|||
const { latest: setMqttResponse } = useWebSocketSubscription('dev', 'setMqtt'); |
|||
|
|||
/** |
|||
* 处理设备编码读取响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (getIdResponse?.values?.id !== undefined) { |
|||
console.log('📥 收到设备编码:', getIdResponse.values.id); |
|||
setSettings(prev => ({ |
|||
...prev, |
|||
deviceId: getIdResponse.values.id |
|||
})); |
|||
setFetchStatus(prev => ({ ...prev, deviceId: 'success' })); |
|||
} |
|||
}, [getIdResponse]); |
|||
|
|||
/** |
|||
* 处理设备编码设置响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (setIdResponse?.values?.operate !== undefined) { |
|||
if (setIdResponse.values.operate) { |
|||
message.success('设备编码设置成功'); |
|||
} else { |
|||
message.error('设备编码设置失败'); |
|||
} |
|||
} |
|||
}, [setIdResponse]); |
|||
|
|||
/** |
|||
* 处理数据帧率读取响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (getDataFpsResponse?.values?.dataFps !== undefined) { |
|||
console.log('📥 收到数据帧率:', getDataFpsResponse.values.dataFps); |
|||
setSettings(prev => ({ |
|||
...prev, |
|||
dataFps: getDataFpsResponse.values.dataFps |
|||
})); |
|||
setFetchStatus(prev => ({ ...prev, dataFps: 'success' })); |
|||
} |
|||
}, [getDataFpsResponse]); |
|||
|
|||
/** |
|||
* 处理数据帧率设置响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (setDataFpsResponse?.values?.operate !== undefined) { |
|||
if (setDataFpsResponse.values.operate) { |
|||
message.success('数据帧率设置成功'); |
|||
} else { |
|||
message.error('数据帧率设置失败'); |
|||
} |
|||
} |
|||
}, [setDataFpsResponse]); |
|||
|
|||
/** |
|||
* 处理异常监控配置读取响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (getAlertResponse?.values) { |
|||
console.log('📥 收到异常监控配置:', getAlertResponse.values); |
|||
setSettings(prev => ({ |
|||
...prev, |
|||
alertConfig: getAlertResponse.values |
|||
})); |
|||
setFetchStatus(prev => ({ ...prev, alert: 'success' })); |
|||
} |
|||
}, [getAlertResponse]); |
|||
|
|||
/** |
|||
* 处理异常监控设置响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (setAlertResponse?.values?.operate !== undefined) { |
|||
if (setAlertResponse.values.operate) { |
|||
message.success('异常监控配置设置成功'); |
|||
} else { |
|||
message.error('异常监控配置设置失败'); |
|||
} |
|||
} |
|||
}, [setAlertResponse]); |
|||
|
|||
/** |
|||
* 处理滤波配置读取响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (getWinResponse?.values) { |
|||
console.log('📥 收到滤波配置:', getWinResponse.values); |
|||
setSettings(prev => ({ |
|||
...prev, |
|||
filterConfig: getWinResponse.values |
|||
})); |
|||
setFetchStatus(prev => ({ ...prev, filter: 'success' })); |
|||
} |
|||
}, [getWinResponse]); |
|||
|
|||
/** |
|||
* 处理滤波配置设置响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (setWinResponse?.values?.operate !== undefined) { |
|||
if (setWinResponse.values.operate) { |
|||
message.success('滤波配置设置成功'); |
|||
} else { |
|||
message.error('滤波配置设置失败'); |
|||
} |
|||
} |
|||
}, [setWinResponse]); |
|||
|
|||
/** |
|||
* 处理 MQTT 配置读取响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (getMqttResponse?.values) { |
|||
console.log('📥 收到 MQTT 配置:', getMqttResponse.values); |
|||
setSettings(prev => ({ |
|||
...prev, |
|||
mqttConfig: getMqttResponse.values |
|||
})); |
|||
setFetchStatus(prev => ({ ...prev, mqtt: 'success' })); |
|||
} |
|||
}, [getMqttResponse]); |
|||
|
|||
/** |
|||
* 处理 MQTT 配置设置响应 |
|||
*/ |
|||
useEffect(() => { |
|||
if (setMqttResponse?.values?.operate !== undefined) { |
|||
if (setMqttResponse.values.operate) { |
|||
message.success('MQTT 配置设置成功'); |
|||
} else { |
|||
message.error('MQTT 配置设置失败'); |
|||
} |
|||
} |
|||
}, [setMqttResponse]); |
|||
|
|||
/** |
|||
* 发送 WebSocket 命令 |
|||
*/ |
|||
const sendCommand = useCallback((cmd, values = {}) => { |
|||
if (!isConnected) { |
|||
message.warning('WebSocket 未连接,请稍后重试'); |
|||
return false; |
|||
} |
|||
|
|||
const command = { |
|||
_from: 'setup', |
|||
cmd, |
|||
values |
|||
}; |
|||
|
|||
console.log('📤 发送命令:', command); |
|||
return sendMessage(JSON.stringify(command)); |
|||
}, [isConnected, sendMessage]); |
|||
|
|||
/** |
|||
* 获取设备编码 |
|||
*/ |
|||
const fetchDeviceId = useCallback(() => { |
|||
setFetchStatus(prev => ({ ...prev, deviceId: 'loading' })); |
|||
return sendCommand('getId', {}); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 更新设备编码 |
|||
*/ |
|||
const updateDeviceId = useCallback((id) => { |
|||
if (!id || !id.trim()) { |
|||
message.warning('请输入设备编码'); |
|||
return false; |
|||
} |
|||
return sendCommand('setId', { id }); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 获取数据帧率 |
|||
*/ |
|||
const fetchDataFps = useCallback(() => { |
|||
setFetchStatus(prev => ({ ...prev, dataFps: 'loading' })); |
|||
return sendCommand('getDataFps', {}); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 更新数据帧率 |
|||
*/ |
|||
const updateDataFps = useCallback((dataFps) => { |
|||
if (dataFps < 1 || dataFps > 30) { |
|||
message.warning('数据帧率范围为 1-30 Hz'); |
|||
return false; |
|||
} |
|||
return sendCommand('setDataFps', { dataFps }); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 获取异常监控配置 |
|||
*/ |
|||
const fetchAlertConfig = useCallback(() => { |
|||
setFetchStatus(prev => ({ ...prev, alert: 'loading' })); |
|||
return sendCommand('getAlert', {}); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 更新异常监控配置 |
|||
*/ |
|||
const updateAlertConfig = useCallback((alertConfig) => { |
|||
const { enable, intervalSec } = alertConfig; |
|||
return sendCommand('setAlert', { enable, intervalSec }); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 获取滤波配置 |
|||
*/ |
|||
const fetchFilterConfig = useCallback(() => { |
|||
setFetchStatus(prev => ({ ...prev, filter: 'loading' })); |
|||
return sendCommand('getWin', {}); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 更新滤波配置 |
|||
*/ |
|||
const updateFilterConfig = useCallback((filterConfig) => { |
|||
const { enable, method, size, threshold, imgThreshold } = filterConfig; |
|||
return sendCommand('setWin', { |
|||
enable, |
|||
method, |
|||
size, |
|||
threshold, |
|||
imgThreshold |
|||
}); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 获取 MQTT 配置 |
|||
*/ |
|||
const fetchMqttConfig = useCallback(() => { |
|||
setFetchStatus(prev => ({ ...prev, mqtt: 'loading' })); |
|||
return sendCommand('getMqtt', {}); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 更新 MQTT 配置 |
|||
*/ |
|||
const updateMqttConfig = useCallback((mqttConfig) => { |
|||
const { enable, mqtt } = mqttConfig; |
|||
|
|||
// 验证必填字段
|
|||
if (enable) { |
|||
if (!mqtt.broker || !mqtt.broker.trim()) { |
|||
message.warning('请输入 Broker 地址'); |
|||
return false; |
|||
} |
|||
if (!mqtt.port) { |
|||
message.warning('请输入端口号'); |
|||
return false; |
|||
} |
|||
if (!mqtt.topic || !mqtt.topic.trim()) { |
|||
message.warning('请输入 Topic'); |
|||
return false; |
|||
} |
|||
if (!mqtt.client_id || !mqtt.client_id.trim()) { |
|||
message.warning('请输入 Client ID'); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return sendCommand('setMqtt', { enable, mqtt }); |
|||
}, [sendCommand]); |
|||
|
|||
/** |
|||
* 获取所有配置 |
|||
*/ |
|||
const fetchAllSettings = useCallback(async () => { |
|||
if (!isConnected) { |
|||
message.warning('WebSocket 未连接,无法获取配置'); |
|||
return; |
|||
} |
|||
|
|||
if (!isReady) { |
|||
message.info('连接正在建立中,指令已加入队列...'); |
|||
} |
|||
|
|||
setLoading(true); |
|||
setFetchStatus({}); |
|||
|
|||
console.log('🔄 开始获取所有高级配置...'); |
|||
|
|||
// 依次发送所有读取命令
|
|||
fetchDeviceId(); |
|||
|
|||
// 添加延迟避免命令过快
|
|||
setTimeout(() => fetchDataFps(), 100); |
|||
setTimeout(() => fetchAlertConfig(), 200); |
|||
setTimeout(() => fetchFilterConfig(), 300); |
|||
setTimeout(() => fetchMqttConfig(), 400); |
|||
|
|||
// 等待所有响应
|
|||
setTimeout(() => { |
|||
setLoading(false); |
|||
console.log('✅ 配置获取完成'); |
|||
}, 2000); |
|||
}, [isConnected, isReady, fetchDeviceId, fetchDataFps, fetchAlertConfig, fetchFilterConfig, fetchMqttConfig]); |
|||
|
|||
/** |
|||
* 保存所有配置 |
|||
*/ |
|||
const saveAllSettings = useCallback(() => { |
|||
if (!isConnected) { |
|||
message.warning('WebSocket 未连接,无法保存配置'); |
|||
return false; |
|||
} |
|||
|
|||
if (!isReady) { |
|||
message.info('连接正在建立中,指令已加入队列...'); |
|||
} else { |
|||
message.info('正在保存配置...'); |
|||
} |
|||
|
|||
// 依次发送所有设置命令
|
|||
updateDeviceId(settings.deviceId); |
|||
setTimeout(() => updateDataFps(settings.dataFps), 100); |
|||
setTimeout(() => updateAlertConfig(settings.alertConfig), 200); |
|||
setTimeout(() => updateFilterConfig(settings.filterConfig), 300); |
|||
setTimeout(() => updateMqttConfig(settings.mqttConfig), 400); |
|||
|
|||
return true; |
|||
}, [isConnected, isReady, settings, updateDeviceId, updateDataFps, updateAlertConfig, updateFilterConfig, updateMqttConfig]); |
|||
|
|||
/** |
|||
* 重置配置到默认值 |
|||
*/ |
|||
const resetSettings = useCallback(() => { |
|||
setSettings(DEFAULT_SETTINGS); |
|||
message.info('配置已重置为默认值'); |
|||
}, []); |
|||
|
|||
/** |
|||
* 更新本地设置(不发送到设备) |
|||
*/ |
|||
const updateLocalSettings = useCallback((updates) => { |
|||
setSettings(prev => ({ |
|||
...prev, |
|||
...updates |
|||
})); |
|||
}, []); |
|||
|
|||
/** |
|||
* WebSocket 连接建立后自动获取配置 |
|||
*/ |
|||
useEffect(() => { |
|||
if (isConnected) { |
|||
console.log('🔌 WebSocket 已连接,自动获取高级配置'); |
|||
// 延迟获取,避免连接刚建立时发送命令
|
|||
setTimeout(() => { |
|||
fetchAllSettings(); |
|||
}, 500); |
|||
} |
|||
}, [isConnected, fetchAllSettings]); |
|||
|
|||
return { |
|||
// 状态
|
|||
settings, |
|||
loading, |
|||
fetchStatus, |
|||
isConnected, |
|||
isReady, |
|||
|
|||
// 操作方法
|
|||
fetchAllSettings, |
|||
saveAllSettings, |
|||
resetSettings, |
|||
updateLocalSettings, |
|||
|
|||
// 单项操作
|
|||
fetchDeviceId, |
|||
updateDeviceId, |
|||
fetchDataFps, |
|||
updateDataFps, |
|||
fetchAlertConfig, |
|||
updateAlertConfig, |
|||
fetchFilterConfig, |
|||
updateFilterConfig, |
|||
fetchMqttConfig, |
|||
updateMqttConfig, |
|||
}; |
|||
}; |
|||
|
|||
export default useAdvancedSettings; |
|||
@ -0,0 +1,246 @@ |
|||
# 高级配置 WebSocket 协议对接文档 |
|||
|
|||
1. 主机编码读取指令 |
|||
|
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd": "getId", |
|||
"values": {} |
|||
} |
|||
``` |
|||
|
|||
响应示例 |
|||
|
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "getId", |
|||
"values": { |
|||
"id": "uu1234" |
|||
} |
|||
} |
|||
``` |
|||
|
|||
2. 主机编码设置指令 |
|||
|
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd": "setId", |
|||
"values": { "id": "uu1234" } |
|||
} |
|||
``` |
|||
|
|||
响应示例 |
|||
|
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "setId", |
|||
"values": { "operate": true } |
|||
} |
|||
``` |
|||
|
|||
3. 帧率读取指令 |
|||
|
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd": "getDataFps", |
|||
"values": {} |
|||
} |
|||
``` |
|||
响应示例 |
|||
|
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "getDataFps", |
|||
"values": { "dataFps": 10 } |
|||
} |
|||
``` |
|||
|
|||
4. 帧率设置指令 |
|||
|
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd": "setDataFps", |
|||
"values": { "dataFps": 10 } |
|||
} |
|||
``` |
|||
响应示例 |
|||
|
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "setDataFps", |
|||
"values": { "operate": true } |
|||
} |
|||
``` |
|||
|
|||
5. 异常超时监控-读取指令 |
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd": "getAlert", |
|||
"values": {} |
|||
} |
|||
``` |
|||
响应示例 |
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "getAlert", |
|||
"values": { |
|||
"enable": false, |
|||
"intervalSec": 6 |
|||
} |
|||
} |
|||
``` |
|||
|
|||
6. 异常超时监控-设置指令 |
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd": "setAlert", |
|||
"values": { |
|||
"enable": false, |
|||
"intervalSec": 6 |
|||
} |
|||
} |
|||
``` |
|||
响应示例 |
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "setAlert", |
|||
"values": { |
|||
"operate": true |
|||
} |
|||
} |
|||
``` |
|||
|
|||
7. 滤波-读取 |
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd":"getWin", |
|||
"values": {} |
|||
} |
|||
``` |
|||
响应示例 |
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "getWin", |
|||
"values": { |
|||
"enable": true, |
|||
"method": "median", |
|||
"size": 5, |
|||
"threshold": -0.1, |
|||
"imgThreshold": 10.0 |
|||
} |
|||
} |
|||
``` |
|||
|
|||
8. 滤波-设置 |
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd":"setWin", |
|||
"values": { |
|||
"enable": true, |
|||
"method": "median", |
|||
"size": 5, |
|||
"threshold": -0.1, |
|||
"imgThreshold": 10.0 |
|||
} |
|||
} |
|||
``` |
|||
响应示例 |
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "setWin", |
|||
"values": { |
|||
"operate": true |
|||
} |
|||
} |
|||
``` |
|||
|
|||
9. mqtt 上报读取 |
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd":"getMqtt", |
|||
"values": {} |
|||
} |
|||
``` |
|||
响应示例 |
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "getMqtt", |
|||
"values": { |
|||
"mqtt": { |
|||
"broker": "218.3.126.49", |
|||
"port": 1883, |
|||
"topic": "wybb/zj/mqtt110_debug", |
|||
"username": "", |
|||
"password": "", |
|||
"client_id": "wybb_debug" |
|||
}, |
|||
"enable": true |
|||
} |
|||
} |
|||
``` |
|||
|
|||
10. mqtt上报设置 |
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd": "setMqtt", |
|||
"values": { |
|||
"mqtt": { |
|||
"broker": "218.3.126.49", |
|||
"port": 1883, |
|||
"topic": "wybb/zj/mqtt110_debug", |
|||
"username": "", |
|||
"password": "", |
|||
"client_id": "wybb_debug" |
|||
}, |
|||
"enable": true |
|||
} |
|||
} |
|||
``` |
|||
响应示例 |
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "setMqtt", |
|||
"values": { |
|||
"operate": true |
|||
} |
|||
} |
|||
``` |
|||
10. 异常超时监控-读取 |
|||
```json |
|||
{ |
|||
"_from": "setup", |
|||
"cmd":"getAlert", |
|||
"values": {} |
|||
} |
|||
``` |
|||
响应示例 |
|||
```json |
|||
{ |
|||
"_from": "dev", |
|||
"cmd": "getAlert", |
|||
"values": { |
|||
"enable": false, |
|||
"intervalSec": 6 |
|||
} |
|||
} |
|||
``` |
|||
Loading…
Reference in new issue