Browse Source

feat: 增加相机流地址配置功能

master 1.1.5
liujiangyong 18 hours ago
parent
commit
5b241d4d06
  1. 38
      client/src/sections/wuyuanbiaoba/components/AdvancedSettings.jsx
  2. 77
      client/src/sections/wuyuanbiaoba/hooks/useAdvancedSettings.js
  3. 69
      client/src/sections/wuyuanbiaoba/hooks/高级配置说明.md
  4. 2
      package.json

38
client/src/sections/wuyuanbiaoba/components/AdvancedSettings.jsx

@ -14,6 +14,7 @@ import {
Typography, Typography,
Spin, Spin,
Alert, Alert,
Tooltip
} from "antd"; } from "antd";
import { import {
SettingOutlined, SettingOutlined,
@ -24,6 +25,7 @@ import {
FilterOutlined, FilterOutlined,
CloudUploadOutlined, CloudUploadOutlined,
SyncOutlined, SyncOutlined,
InfoCircleOutlined
} from "@ant-design/icons"; } from "@ant-design/icons";
import useAdvancedSettings from "../hooks/useAdvancedSettings"; import useAdvancedSettings from "../hooks/useAdvancedSettings";
@ -75,6 +77,7 @@ const AdvancedSettings = ({ onLogout }) => {
// settings // settings
const deviceId = settings.deviceId; const deviceId = settings.deviceId;
const captureAddress = settings.capture ?? '';
const fps = settings.dataFps; const fps = settings.dataFps;
const enableOfflineAlert = settings.alertConfig?.enable ?? false; const enableOfflineAlert = settings.alertConfig?.enable ?? false;
const offlineThreshold = settings.alertConfig?.intervalSec ?? 60; const offlineThreshold = settings.alertConfig?.intervalSec ?? 60;
@ -93,6 +96,7 @@ const AdvancedSettings = ({ onLogout }) => {
// //
const setDeviceId = (value) => updateLocalSettings({ deviceId: value }); const setDeviceId = (value) => updateLocalSettings({ deviceId: value });
const setCaptureAddress = (value) => updateLocalSettings({ capture: value });
const setFps = (value) => updateLocalSettings({ dataFps: value }); const setFps = (value) => updateLocalSettings({ dataFps: value });
const setEnableOfflineAlert = (value) => const setEnableOfflineAlert = (value) =>
updateLocalSettings({ updateLocalSettings({
@ -204,6 +208,7 @@ const AdvancedSettings = ({ onLogout }) => {
}); });
const [saving, setSaving] = React.useState(false); const [saving, setSaving] = React.useState(false);
const [captureEditable, setCaptureEditable] = React.useState(false);
const handleSave = async () => { const handleSave = async () => {
if (enableMqtt) { if (enableMqtt) {
@ -356,6 +361,39 @@ const AdvancedSettings = ({ onLogout }) => {
size="large" size="large"
style={{ borderRadius: 8 }} style={{ borderRadius: 8 }}
/> />
<Row
justify="space-between"
align="middle"
style={{ marginTop: 16, marginBottom: 4 }}
>
<Col>
<div style={{ fontWeight: 500 }}>
相机流地址&nbsp;
<Tooltip title="请确保输入有效的相机流地址">
<InfoCircleOutlined />
</Tooltip>
</div>
</Col>
<Col>
<Space size={8}>
<Text type="secondary" style={{ fontSize: 12 }}>
允许修改
</Text>
<Switch
checked={captureEditable}
onChange={setCaptureEditable}
/>
</Space>
</Col>
</Row>
<Input
value={captureAddress}
onChange={(e) => setCaptureAddress(e.target.value)}
placeholder="例如: rtsp://admin:admin@192.168.1.10/live0"
size="large"
disabled={!captureEditable}
style={{ borderRadius: 8 }}
/>
</Card> </Card>
<Card <Card

77
client/src/sections/wuyuanbiaoba/hooks/useAdvancedSettings.js

@ -5,6 +5,7 @@
* *
* 功能包括 * 功能包括
* - 设备编码读取与设置 (getId/setId) * - 设备编码读取与设置 (getId/setId)
* - 相机流地址读取与设置 (getCapture/setCapture)
* - 数据帧率读取与设置 (getDataFps/setDataFps) * - 数据帧率读取与设置 (getDataFps/setDataFps)
* - 异常超时监控读取与设置 (getAlert/setAlert) * - 异常超时监控读取与设置 (getAlert/setAlert)
* - 滤波配置读取与设置 (getWin/setWin) * - 滤波配置读取与设置 (getWin/setWin)
@ -36,6 +37,9 @@ const DEFAULT_SETTINGS = {
// 设备编码 // 设备编码
deviceId: '', deviceId: '',
// 相机流地址
capture: '',
// 数据帧率 // 数据帧率
dataFps: 10, dataFps: 10,
@ -72,6 +76,7 @@ const SAVE_RESPONSE_TIMEOUT = 10 * 1000;
const SAVE_ITEMS = { const SAVE_ITEMS = {
setId: '设备编码', setId: '设备编码',
setCapture: '相机流地址',
setDataFps: '数据帧率', setDataFps: '数据帧率',
setAlert: '异常监控配置', setAlert: '异常监控配置',
setWin: '滤波配置', setWin: '滤波配置',
@ -94,6 +99,8 @@ const useAdvancedSettings = () => {
// WebSocket 订阅 - 监听所有来自设备的响应 // WebSocket 订阅 - 监听所有来自设备的响应
const { latest: getIdResponse } = useWebSocketSubscription('dev', 'getId'); const { latest: getIdResponse } = useWebSocketSubscription('dev', 'getId');
const { latest: setIdResponse } = useWebSocketSubscription('dev', 'setId'); const { latest: setIdResponse } = useWebSocketSubscription('dev', 'setId');
const { latest: getCaptureResponse } = useWebSocketSubscription('dev', 'getCapture');
const { latest: setCaptureResponse } = useWebSocketSubscription('dev', 'setCapture');
const { latest: getDataFpsResponse } = useWebSocketSubscription('dev', 'getDataFps'); const { latest: getDataFpsResponse } = useWebSocketSubscription('dev', 'getDataFps');
const { latest: setDataFpsResponse } = useWebSocketSubscription('dev', 'setDataFps'); const { latest: setDataFpsResponse } = useWebSocketSubscription('dev', 'setDataFps');
const { latest: getAlertResponse } = useWebSocketSubscription('dev', 'getAlert'); const { latest: getAlertResponse } = useWebSocketSubscription('dev', 'getAlert');
@ -130,6 +137,33 @@ const useAdvancedSettings = () => {
} }
}, [setIdResponse]); }, [setIdResponse]);
/**
* 处理相机流地址读取响应
*/
useEffect(() => {
if (getCaptureResponse?.values?.capture !== undefined) {
console.log('📥 收到相机流地址:', getCaptureResponse.values.capture);
setSettings(prev => ({
...prev,
capture: getCaptureResponse.values.capture
}));
setFetchStatus(prev => ({ ...prev, capture: 'success' }));
}
}, [getCaptureResponse]);
/**
* 处理相机流地址设置响应
*/
useEffect(() => {
if (setCaptureResponse?.values?.operate !== undefined) {
if (setCaptureResponse.values.operate) {
} else {
message.error('相机流地址设置失败');
}
}
}, [setCaptureResponse]);
/** /**
* 处理数据帧率读取响应 * 处理数据帧率读取响应
*/ */
@ -276,6 +310,27 @@ const useAdvancedSettings = () => {
return sendCommand('setId', { id }); return sendCommand('setId', { id });
}, [sendCommand]); }, [sendCommand]);
/**
* 获取相机流地址
*/
const fetchCaptureConfig = useCallback(() => {
setFetchStatus(prev => ({ ...prev, capture: 'loading' }));
return sendCommand('getCapture', {});
}, [sendCommand]);
/**
* 更新相机流地址
*/
const updateCaptureConfig = useCallback((capture) => {
const captureValue = typeof capture === 'string' ? capture.trim() : '';
if (!captureValue) {
message.warning('请输入相机流地址');
return false;
}
return sendCommand('setCapture', { capture: captureValue });
}, [sendCommand]);
/** /**
* 获取数据帧率 * 获取数据帧率
*/ */
@ -424,6 +479,11 @@ const useAdvancedSettings = () => {
return false; return false;
} }
if (!settings.capture || !settings.capture.trim()) {
message.warning('请输入相机流地址');
return false;
}
if (settings.dataFps < 1 || settings.dataFps > 30) { if (settings.dataFps < 1 || settings.dataFps > 30) {
message.warning('数据帧率范围为 1-30 Hz'); message.warning('数据帧率范围为 1-30 Hz');
return false; return false;
@ -472,6 +532,10 @@ const useAdvancedSettings = () => {
cmd: 'setId', cmd: 'setId',
values: { id: settings.deviceId } values: { id: settings.deviceId }
}, },
{
cmd: 'setCapture',
values: { capture: settings.capture.trim() }
},
{ {
cmd: 'setDataFps', cmd: 'setDataFps',
values: { dataFps: settings.dataFps } values: { dataFps: settings.dataFps }
@ -525,17 +589,18 @@ const useAdvancedSettings = () => {
// 所有指令都用 setTimeout 包裹,首个指令也延迟,避免第一个指令丢包 // 所有指令都用 setTimeout 包裹,首个指令也延迟,避免第一个指令丢包
fetchDeviceId() fetchDeviceId()
setTimeout(() => fetchDeviceId(), 50); setTimeout(() => fetchDeviceId(), 50);
setTimeout(() => fetchDataFps(), 150); setTimeout(() => fetchCaptureConfig(), 150);
setTimeout(() => fetchAlertConfig(), 250); setTimeout(() => fetchDataFps(), 250);
setTimeout(() => fetchFilterConfig(), 350); setTimeout(() => fetchAlertConfig(), 350);
setTimeout(() => fetchMqttConfig(), 450); setTimeout(() => fetchFilterConfig(), 450);
setTimeout(() => fetchMqttConfig(), 550);
// 等待所有响应 // 等待所有响应
setTimeout(() => { setTimeout(() => {
setLoading(false); setLoading(false);
console.log('配置获取完成'); console.log('配置获取完成');
}, 2000); }, 2000);
}, [isConnected, isReady, fetchDeviceId, fetchDataFps, fetchAlertConfig, fetchFilterConfig, fetchMqttConfig]); }, [isConnected, isReady, fetchDeviceId, fetchCaptureConfig, fetchDataFps, fetchAlertConfig, fetchFilterConfig, fetchMqttConfig]);
/** /**
* 保存所有配置 * 保存所有配置
@ -613,6 +678,8 @@ const useAdvancedSettings = () => {
// 单项操作 // 单项操作
fetchDeviceId, fetchDeviceId,
updateDeviceId, updateDeviceId,
fetchCaptureConfig,
updateCaptureConfig,
fetchDataFps, fetchDataFps,
updateDataFps, updateDataFps,
fetchAlertConfig, fetchAlertConfig,

69
client/src/sections/wuyuanbiaoba/hooks/高级配置说明.md

@ -80,7 +80,45 @@
} }
``` ```
5. 异常超时监控-读取指令 5. 相机流地址读取指令
```json
{
"_from": "setup",
"cmd": "getCapture",
"values": {}
}
```
响应示例
```json
{
"_from": "dev",
"cmd": "getCapture",
"values": {
"capture": "rtsp://admin:admin@192.168.1.10/live0"
}
}
```
6. 相机流地址设置指令
```json
{
"_from": "setup",
"cmd": "setCapture",
"values": {
"capture": "rtsp://admin:admin@192.168.1.10/live0"
}
}
```
响应示例
```json
{
"_from": "dev",
"cmd": "setCapture",
"values": { "operate": true }
}
```
7. 异常超时监控-读取指令
```json ```json
{ {
"_from": "setup", "_from": "setup",
@ -100,7 +138,7 @@
} }
``` ```
6. 异常超时监控-设置指令 8. 异常超时监控-设置指令
```json ```json
{ {
"_from": "setup", "_from": "setup",
@ -122,7 +160,7 @@
} }
``` ```
7. 滤波-读取 9. 滤波-读取
```json ```json
{ {
"_from": "setup", "_from": "setup",
@ -145,7 +183,7 @@
} }
``` ```
8. 滤波-设置 10. 滤波-设置
```json ```json
{ {
"_from": "setup", "_from": "setup",
@ -170,7 +208,7 @@
} }
``` ```
9. mqtt 上报读取 11. mqtt 上报读取
```json ```json
{ {
"_from": "setup", "_from": "setup",
@ -197,7 +235,7 @@
} }
``` ```
10. mqtt上报设置 12. mqtt上报设置
```json ```json
{ {
"_from": "setup", "_from": "setup",
@ -225,22 +263,3 @@
} }
} }
``` ```
10. 异常超时监控-读取
```json
{
"_from": "setup",
"cmd":"getAlert",
"values": {}
}
```
响应示例
```json
{
"_from": "dev",
"cmd": "getAlert",
"values": {
"enable": false,
"intervalSec": 6
}
}
```

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "wuyuanbiaoba-web", "name": "wuyuanbiaoba-web",
"version": "1.1.4", "version": "1.1.5",
"main": "index.html", "main": "index.html",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",

Loading…
Cancel
Save