Compare commits
4 Commits
6543c526ca
...
37066e2184
| Author | SHA1 | Date |
|---|---|---|
|
|
37066e2184 | 3 weeks ago |
|
|
505aa3f199 | 3 weeks ago |
|
|
f542142645 | 1 month ago |
|
|
b7182c7066 | 1 month ago |
12 changed files with 1724 additions and 98 deletions
@ -0,0 +1,114 @@ |
|||||
|
import React, { useState } from 'react'; |
||||
|
import { Card, Input, Button, message } from 'antd'; |
||||
|
import { LockOutlined } from '@ant-design/icons'; |
||||
|
|
||||
|
/** |
||||
|
* 高级配置密码验证组件 |
||||
|
*/ |
||||
|
const AdvancedConfigAuth = ({ verifyPassword, onUnlock }) => { |
||||
|
const [password, setPassword] = useState(''); |
||||
|
const [loading, setLoading] = useState(false); |
||||
|
|
||||
|
const handleVerify = async () => { |
||||
|
if (!password) { |
||||
|
message.warning('请输入密码'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
setLoading(true); |
||||
|
try { |
||||
|
const isValid = await verifyPassword(password); |
||||
|
|
||||
|
if (isValid) { |
||||
|
message.success('密码正确,已解锁高级配置'); |
||||
|
onUnlock && onUnlock(); |
||||
|
} else { |
||||
|
message.error('密码错误,请重试'); |
||||
|
setPassword(''); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('密码验证失败:', error); |
||||
|
message.error('验证过程出错,请重试'); |
||||
|
} finally { |
||||
|
setLoading(false); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const handleKeyPress = (e) => { |
||||
|
if (e.key === 'Enter') { |
||||
|
handleVerify(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
return ( |
||||
|
<div |
||||
|
style={{ |
||||
|
display: 'flex', |
||||
|
alignItems: 'center', |
||||
|
justifyContent: 'center', |
||||
|
minHeight: 'calc(100vh - 92px)', |
||||
|
padding: '24px', |
||||
|
}} |
||||
|
> |
||||
|
<Card |
||||
|
style={{ |
||||
|
width: 400, |
||||
|
textAlign: 'center', |
||||
|
boxShadow: '0 2px 8px rgba(0,0,0,0.1)', |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: 64, |
||||
|
height: 64, |
||||
|
borderRadius: '50%', |
||||
|
backgroundColor: '#e6f4ff', |
||||
|
display: 'flex', |
||||
|
alignItems: 'center', |
||||
|
justifyContent: 'center', |
||||
|
margin: '0 auto 24px', |
||||
|
}} |
||||
|
> |
||||
|
<LockOutlined style={{ fontSize: 32, color: '#1890ff' }} /> |
||||
|
</div> |
||||
|
|
||||
|
<h2 style={{ marginBottom: 8 }}>内部高级配置</h2> |
||||
|
<p style={{ color: '#999', marginBottom: 24 }}> |
||||
|
请输入管理员访问密码以继续 |
||||
|
</p> |
||||
|
|
||||
|
<Input.Password |
||||
|
size="large" |
||||
|
placeholder="请输入密码" |
||||
|
value={password} |
||||
|
onChange={(e) => setPassword(e.target.value)} |
||||
|
onKeyPress={handleKeyPress} |
||||
|
prefix={<LockOutlined style={{ color: '#999' }} />} |
||||
|
style={{ marginBottom: 16 }} |
||||
|
/> |
||||
|
|
||||
|
<Button |
||||
|
type="primary" |
||||
|
size="large" |
||||
|
block |
||||
|
loading={loading} |
||||
|
onClick={handleVerify} |
||||
|
> |
||||
|
解锁配置 |
||||
|
</Button> |
||||
|
|
||||
|
<div |
||||
|
style={{ |
||||
|
marginTop: 24, |
||||
|
fontSize: 12, |
||||
|
color: '#999', |
||||
|
}} |
||||
|
> |
||||
|
视觉位移计配置工具 v{window.env?.FS_VERSION || ''} Build {new Date().getFullYear()} |
||||
|
</div> |
||||
|
</Card> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default AdvancedConfigAuth; |
||||
@ -0,0 +1,630 @@ |
|||||
|
import React, { useEffect } from "react"; |
||||
|
import { |
||||
|
Card, |
||||
|
Input, |
||||
|
Slider, |
||||
|
InputNumber, |
||||
|
Switch, |
||||
|
Select, |
||||
|
Row, |
||||
|
Col, |
||||
|
Button, |
||||
|
message, |
||||
|
Space, |
||||
|
Typography, |
||||
|
Spin, |
||||
|
Alert, |
||||
|
} from "antd"; |
||||
|
import { |
||||
|
SettingOutlined, |
||||
|
SaveOutlined, |
||||
|
DatabaseOutlined, |
||||
|
ClockCircleOutlined, |
||||
|
BellOutlined, |
||||
|
FilterOutlined, |
||||
|
CloudUploadOutlined, |
||||
|
SyncOutlined, |
||||
|
} from "@ant-design/icons"; |
||||
|
import useAdvancedSettings from "../hooks/useAdvancedSettings"; |
||||
|
|
||||
|
const { Option } = Select; |
||||
|
const { Title, Text } = Typography; |
||||
|
|
||||
|
const AdvancedSettings = ({ onLogout }) => { |
||||
|
// 使用高级配置 Hook |
||||
|
const { |
||||
|
settings, |
||||
|
loading, |
||||
|
isConnected, |
||||
|
isReady, |
||||
|
fetchAllSettings, |
||||
|
saveAllSettings, |
||||
|
resetSettings, |
||||
|
updateLocalSettings, |
||||
|
} = useAdvancedSettings(); |
||||
|
|
||||
|
// 只在首次 isReady 变为 true 时自动拉取配置 |
||||
|
const hasFetchedRef = React.useRef(false); |
||||
|
useEffect(() => { |
||||
|
if (isReady && !hasFetchedRef.current) { |
||||
|
fetchAllSettings(); |
||||
|
hasFetchedRef.current = true; |
||||
|
} |
||||
|
}, [isReady, fetchAllSettings]); |
||||
|
|
||||
|
// 从 settings 中提取配置 |
||||
|
const deviceId = settings.deviceId; |
||||
|
const fps = settings.dataFps; |
||||
|
const enableOfflineAlert = settings.alertConfig?.enable ?? false; |
||||
|
const offlineThreshold = settings.alertConfig?.intervalSec ?? 60; |
||||
|
const enableFiltering = settings.filterConfig?.enable ?? true; |
||||
|
const filterMethod = settings.filterConfig?.method ?? 'median'; |
||||
|
const windowSize = settings.filterConfig?.size ?? 5; |
||||
|
const filterThreshold = settings.filterConfig?.threshold ?? 0.1; |
||||
|
const flowThreshold = settings.filterConfig?.imgThreshold ?? 10.0; |
||||
|
const enableMqtt = settings.mqttConfig?.enable ?? true; |
||||
|
const brokerAddress = settings.mqttConfig?.mqtt?.broker ?? ''; |
||||
|
const mqttPort = settings.mqttConfig?.mqtt?.port ?? 1883; |
||||
|
const mqttTopic = settings.mqttConfig?.mqtt?.topic ?? ''; |
||||
|
const mqttClientId = settings.mqttConfig?.mqtt?.client_id ?? ''; |
||||
|
const mqttUsername = settings.mqttConfig?.mqtt?.username ?? ''; |
||||
|
const mqttPassword = settings.mqttConfig?.mqtt?.password ?? ''; |
||||
|
|
||||
|
// 更新本地状态的辅助函数 |
||||
|
const setDeviceId = (value) => updateLocalSettings({ deviceId: value }); |
||||
|
const setFps = (value) => updateLocalSettings({ dataFps: value }); |
||||
|
const setEnableOfflineAlert = (value) => |
||||
|
updateLocalSettings({ |
||||
|
alertConfig: { |
||||
|
enable: value, |
||||
|
intervalSec: settings.alertConfig?.intervalSec ?? 60 |
||||
|
}, |
||||
|
}); |
||||
|
const setOfflineThreshold = (value) => |
||||
|
updateLocalSettings({ |
||||
|
alertConfig: { |
||||
|
enable: settings.alertConfig?.enable ?? false, |
||||
|
intervalSec: value |
||||
|
}, |
||||
|
}); |
||||
|
const setEnableFiltering = (value) => |
||||
|
updateLocalSettings({ |
||||
|
filterConfig: { ...settings.filterConfig, enable: value }, |
||||
|
}); |
||||
|
const setFilterMethod = (value) => |
||||
|
updateLocalSettings({ |
||||
|
filterConfig: { ...settings.filterConfig, method: value }, |
||||
|
}); |
||||
|
const setWindowSize = (value) => |
||||
|
updateLocalSettings({ |
||||
|
filterConfig: { ...settings.filterConfig, size: value }, |
||||
|
}); |
||||
|
const setFilterThreshold = (value) => |
||||
|
updateLocalSettings({ |
||||
|
filterConfig: { ...settings.filterConfig, threshold: -Math.abs(value) }, |
||||
|
}); |
||||
|
const setFlowThreshold = (value) => |
||||
|
updateLocalSettings({ |
||||
|
filterConfig: { ...settings.filterConfig, imgThreshold: value }, |
||||
|
}); |
||||
|
const setEnableMqtt = (value) => |
||||
|
updateLocalSettings({ |
||||
|
mqttConfig: { |
||||
|
enable: value, |
||||
|
mqtt: settings.mqttConfig?.mqtt ?? { |
||||
|
broker: '', |
||||
|
port: 1883, |
||||
|
topic: '', |
||||
|
username: '', |
||||
|
password: '', |
||||
|
client_id: '' |
||||
|
} |
||||
|
}, |
||||
|
}); |
||||
|
const setBrokerAddress = (value) => |
||||
|
updateLocalSettings({ |
||||
|
mqttConfig: { |
||||
|
...settings.mqttConfig, |
||||
|
mqtt: { |
||||
|
...(settings.mqttConfig?.mqtt ?? {}), |
||||
|
broker: value |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
const setMqttPort = (value) => |
||||
|
updateLocalSettings({ |
||||
|
mqttConfig: { |
||||
|
...settings.mqttConfig, |
||||
|
mqtt: { |
||||
|
...(settings.mqttConfig?.mqtt ?? {}), |
||||
|
port: value |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
const setMqttTopic = (value) => |
||||
|
updateLocalSettings({ |
||||
|
mqttConfig: { |
||||
|
...settings.mqttConfig, |
||||
|
mqtt: { |
||||
|
...(settings.mqttConfig?.mqtt ?? {}), |
||||
|
topic: value |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
const setMqttClientId = (value) => |
||||
|
updateLocalSettings({ |
||||
|
mqttConfig: { |
||||
|
...settings.mqttConfig, |
||||
|
mqtt: { |
||||
|
...(settings.mqttConfig?.mqtt ?? {}), |
||||
|
client_id: value |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
const setMqttUsername = (value) => |
||||
|
updateLocalSettings({ |
||||
|
mqttConfig: { |
||||
|
...settings.mqttConfig, |
||||
|
mqtt: { |
||||
|
...(settings.mqttConfig?.mqtt ?? {}), |
||||
|
username: value |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
const setMqttPassword = (value) => |
||||
|
updateLocalSettings({ |
||||
|
mqttConfig: { |
||||
|
...settings.mqttConfig, |
||||
|
mqtt: { |
||||
|
...(settings.mqttConfig?.mqtt ?? {}), |
||||
|
password: value |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
const handleSave = () => { |
||||
|
saveAllSettings(); |
||||
|
}; |
||||
|
|
||||
|
const handleReset = () => { |
||||
|
fetchAllSettings(); |
||||
|
}; |
||||
|
|
||||
|
return ( |
||||
|
<Spin spinning={loading} tip="正在加载配置..."> |
||||
|
<div |
||||
|
style={{ |
||||
|
padding: "12px", |
||||
|
backgroundColor: "#f5f7fa", |
||||
|
minHeight: "calc(100vh - 92px)", |
||||
|
}} |
||||
|
> |
||||
|
{/* WebSocket 连接状态提示 */} |
||||
|
{!isConnected && ( |
||||
|
<Alert |
||||
|
message="WebSocket 未连接" |
||||
|
description="当前未连接到设备,无法读取或保存配置。请检查网络连接。" |
||||
|
type="warning" |
||||
|
showIcon |
||||
|
style={{ marginBottom: 12, borderRadius: 8 }} |
||||
|
/> |
||||
|
)} |
||||
|
|
||||
|
<Card |
||||
|
style={{ |
||||
|
marginBottom: 12, |
||||
|
background: |
||||
|
"linear-gradient(135deg, #01152cff 0%, #063b77ff 100%)", |
||||
|
borderRadius: 12, |
||||
|
}} |
||||
|
styles={{ padding: 12 }} |
||||
|
> |
||||
|
<Row justify="space-between" align="middle"> |
||||
|
<Col> |
||||
|
<Space direction="vertical" size={4}> |
||||
|
<Title |
||||
|
level={2} |
||||
|
style={{ |
||||
|
margin: 0, |
||||
|
color: "white", |
||||
|
display: "flex", |
||||
|
alignItems: "center", |
||||
|
gap: 12, |
||||
|
}} |
||||
|
> |
||||
|
<SettingOutlined /> |
||||
|
高级参数配置 |
||||
|
</Title> |
||||
|
<Text |
||||
|
style={{ |
||||
|
color: "rgba(255,255,255,0.85)", |
||||
|
fontSize: 14, |
||||
|
}} |
||||
|
> |
||||
|
针对下位机运行的参数配置,修改后请及时保存(慎用) |
||||
|
</Text> |
||||
|
|
||||
|
</Space> |
||||
|
</Col> |
||||
|
<Col> |
||||
|
<Space size="middle"> |
||||
|
<Button |
||||
|
icon={<SyncOutlined spin={loading} />} |
||||
|
onClick={handleReset} |
||||
|
size="large" |
||||
|
disabled={!isConnected || loading} |
||||
|
style={{ height: 42, borderRadius: 8 }} |
||||
|
> |
||||
|
刷新配置 |
||||
|
</Button> |
||||
|
<Button |
||||
|
type="primary" |
||||
|
icon={<SaveOutlined />} |
||||
|
onClick={handleSave} |
||||
|
size="large" |
||||
|
disabled={!isConnected || loading} |
||||
|
style={{ |
||||
|
height: 42, |
||||
|
borderRadius: 8, |
||||
|
background: "white", |
||||
|
color: "#667eea", |
||||
|
borderColor: "white", |
||||
|
}} |
||||
|
> |
||||
|
保存更改 |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</Card> |
||||
|
|
||||
|
<Row gutter={12}> |
||||
|
<Col xs={12} lg={12}> |
||||
|
<Card |
||||
|
title={ |
||||
|
<Space> |
||||
|
<DatabaseOutlined style={{ color: "#667eea" }} /> |
||||
|
<span>基础设备信息</span> |
||||
|
</Space> |
||||
|
} |
||||
|
|
||||
|
style={{ |
||||
|
marginBottom: 12, |
||||
|
borderRadius: 12, |
||||
|
paddingLeft: 24, |
||||
|
paddingRight: 24, |
||||
|
}} |
||||
|
> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
设备编码 |
||||
|
</div> |
||||
|
<Input |
||||
|
value={deviceId} |
||||
|
onChange={(e) => setDeviceId(e.target.value)} |
||||
|
placeholder="请输入设备编码" |
||||
|
size="large" |
||||
|
style={{ borderRadius: 8 }} |
||||
|
/> |
||||
|
</Card> |
||||
|
|
||||
|
<Card |
||||
|
title={ |
||||
|
<Space> |
||||
|
<ClockCircleOutlined style={{ color: "#667eea" }} /> |
||||
|
<span>数据帧率 (FPS)</span> |
||||
|
</Space> |
||||
|
} |
||||
|
|
||||
|
style={{ |
||||
|
marginBottom: 12, |
||||
|
borderRadius: 12, |
||||
|
paddingLeft: 24, |
||||
|
paddingRight: 24, |
||||
|
}} |
||||
|
> |
||||
|
<div style={{ marginBottom: 12, fontWeight: 500 }}> |
||||
|
数据帧率 |
||||
|
</div> |
||||
|
<Row gutter={12} align="middle"> |
||||
|
<Col span={18}> |
||||
|
<Slider |
||||
|
min={1} |
||||
|
max={30} |
||||
|
value={fps} |
||||
|
onChange={setFps} |
||||
|
marks={{ 1: "1 Hz", 30: "30 Hz" }} |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={6}> |
||||
|
<InputNumber |
||||
|
min={1} |
||||
|
max={30} |
||||
|
value={fps} |
||||
|
onChange={setFps} |
||||
|
style={{ width: "100%", borderRadius: 8 }} |
||||
|
size="large" |
||||
|
/> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
<Text type="secondary" style={{ fontSize: 12 }}> |
||||
|
有效范围 1~30 Hz |
||||
|
</Text> |
||||
|
</Card> |
||||
|
|
||||
|
<Card |
||||
|
title={ |
||||
|
<Space> |
||||
|
<BellOutlined style={{ color: "#667eea" }} /> |
||||
|
<span>异常监控与报警</span> |
||||
|
</Space> |
||||
|
} |
||||
|
|
||||
|
style={{ |
||||
|
marginBottom: 12, |
||||
|
borderRadius: 12, |
||||
|
paddingLeft: 24, |
||||
|
paddingRight: 24, |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
background: |
||||
|
"linear-gradient(135deg, #f5f7fa 0%, #e8eef5 100%)", |
||||
|
padding: 20, |
||||
|
borderRadius: 12, |
||||
|
marginBottom: 12, |
||||
|
}} |
||||
|
> |
||||
|
<Row justify="space-between" align="middle"> |
||||
|
<Col> |
||||
|
<Text strong>启用离线超时告警</Text> |
||||
|
<br /> |
||||
|
<Text type="secondary" style={{ fontSize: 12 }}> |
||||
|
超过此时长未接收到新数据则触发报警 |
||||
|
</Text> |
||||
|
</Col> |
||||
|
<Col> |
||||
|
<Switch |
||||
|
checked={enableOfflineAlert} |
||||
|
onChange={setEnableOfflineAlert} |
||||
|
/> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</div> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
超时阈值 |
||||
|
</div> |
||||
|
<InputNumber |
||||
|
min={10} |
||||
|
max={300} |
||||
|
value={offlineThreshold} |
||||
|
onChange={setOfflineThreshold} |
||||
|
size="large" |
||||
|
addonAfter="秒" |
||||
|
style={{ width: "100%", borderRadius: 8 }} |
||||
|
/> |
||||
|
</Card> |
||||
|
</Col> |
||||
|
|
||||
|
<Col xs={12} lg={12}> |
||||
|
<Card |
||||
|
title={ |
||||
|
<Space> |
||||
|
<FilterOutlined style={{ color: "#667eea" }} /> |
||||
|
<span>数据滤波与异常记录</span> |
||||
|
</Space> |
||||
|
} |
||||
|
|
||||
|
style={{ |
||||
|
marginBottom: 12, |
||||
|
borderRadius: 12, |
||||
|
paddingLeft: 24, |
||||
|
paddingRight: 24, |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
background: |
||||
|
"linear-gradient(135deg, #f5f7fa 0%, #e8eef5 100%)", |
||||
|
padding: 20, |
||||
|
borderRadius: 12, |
||||
|
marginBottom: 20, |
||||
|
}} |
||||
|
> |
||||
|
<Row justify="space-between" align="middle"> |
||||
|
<Col> |
||||
|
<Text strong>滤波配置</Text> |
||||
|
<br /> |
||||
|
<Text type="secondary" style={{ fontSize: 12 }}> |
||||
|
启用数据滤波算法 |
||||
|
</Text> |
||||
|
</Col> |
||||
|
<Col> |
||||
|
<Switch |
||||
|
checked={enableFiltering} |
||||
|
onChange={setEnableFiltering} |
||||
|
checkedChildren="已启用" |
||||
|
unCheckedChildren="已停用" |
||||
|
/> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</div> |
||||
|
<Row gutter={[12, 12]}> |
||||
|
<Col span={12}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
滤波方法 |
||||
|
</div> |
||||
|
<Select |
||||
|
value={filterMethod} |
||||
|
onChange={setFilterMethod} |
||||
|
size="large" |
||||
|
disabled={!enableFiltering} |
||||
|
style={{ width: "100%", borderRadius: 8 }} |
||||
|
> |
||||
|
<Option value="median">中值滤波</Option> |
||||
|
</Select> |
||||
|
</Col> |
||||
|
<Col span={12}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
窗口大小 |
||||
|
</div> |
||||
|
<InputNumber |
||||
|
min={3} |
||||
|
max={21} |
||||
|
step={2} |
||||
|
value={windowSize} |
||||
|
onChange={setWindowSize} |
||||
|
size="large" |
||||
|
disabled={!enableFiltering} |
||||
|
style={{ width: "100%", borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={12}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
滤波阈值 |
||||
|
</div> |
||||
|
<InputNumber |
||||
|
value={filterThreshold} |
||||
|
onChange={setFilterThreshold} |
||||
|
addonAfter="mm" |
||||
|
size="large" |
||||
|
disabled={!enableFiltering} |
||||
|
style={{ width: "100%", borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={12}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
波动阈值 |
||||
|
</div> |
||||
|
<InputNumber |
||||
|
min={0} |
||||
|
max={100} |
||||
|
step={0.1} |
||||
|
value={flowThreshold} |
||||
|
onChange={setFlowThreshold} |
||||
|
addonAfter="mm" |
||||
|
size="large" |
||||
|
disabled={!enableFiltering} |
||||
|
style={{ width: "100%", borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</Card> |
||||
|
|
||||
|
<Card |
||||
|
title={ |
||||
|
<div |
||||
|
style={{ |
||||
|
display: "flex", |
||||
|
justifyContent: "space-between", |
||||
|
alignItems: "center", |
||||
|
}} |
||||
|
> |
||||
|
<Space> |
||||
|
<CloudUploadOutlined style={{ color: "#667eea" }} /> |
||||
|
<span>数据上报 (MQTT)</span> |
||||
|
</Space> |
||||
|
<Switch |
||||
|
checked={enableMqtt} |
||||
|
onChange={setEnableMqtt} |
||||
|
checkedChildren="启用" |
||||
|
unCheckedChildren="禁用" |
||||
|
/> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
style={{ |
||||
|
borderRadius: 12, |
||||
|
paddingLeft: 24, |
||||
|
paddingRight: 24, |
||||
|
}} |
||||
|
> |
||||
|
<Row gutter={[12, 12]}> |
||||
|
<Col span={12}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
Broker Address |
||||
|
</div> |
||||
|
<Input |
||||
|
value={brokerAddress} |
||||
|
onChange={(e) => setBrokerAddress(e.target.value)} |
||||
|
placeholder="例如: 218.3.126.49" |
||||
|
size="large" |
||||
|
disabled={!enableMqtt} |
||||
|
style={{ borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={8}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
Port |
||||
|
</div> |
||||
|
<Input |
||||
|
value={mqttPort} |
||||
|
onChange={(e) => setMqttPort(e.target.value)} |
||||
|
placeholder="1883" |
||||
|
size="large" |
||||
|
disabled={!enableMqtt} |
||||
|
style={{ borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={12}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
Topic |
||||
|
</div> |
||||
|
<Input |
||||
|
value={mqttTopic} |
||||
|
onChange={(e) => setMqttTopic(e.target.value)} |
||||
|
placeholder="例如: wybb/z/mqtt179" |
||||
|
size="large" |
||||
|
disabled={!enableMqtt} |
||||
|
style={{ borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={8}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
Client ID |
||||
|
</div> |
||||
|
<Input |
||||
|
value={mqttClientId} |
||||
|
onChange={(e) => setMqttClientId(e.target.value)} |
||||
|
placeholder="wybb_z1_123" |
||||
|
size="large" |
||||
|
disabled={!enableMqtt} |
||||
|
style={{ borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={8}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
Username |
||||
|
</div> |
||||
|
<Input |
||||
|
value={mqttUsername} |
||||
|
onChange={(e) => setMqttUsername(e.target.value)} |
||||
|
placeholder="用户名" |
||||
|
size="large" |
||||
|
disabled={!enableMqtt} |
||||
|
style={{ borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={8}> |
||||
|
<div style={{ marginBottom: 4, fontWeight: 500 }}> |
||||
|
Password |
||||
|
</div> |
||||
|
<Input.Password |
||||
|
value={mqttPassword} |
||||
|
onChange={(e) => setMqttPassword(e.target.value)} |
||||
|
placeholder="密码" |
||||
|
size="large" |
||||
|
disabled={!enableMqtt} |
||||
|
style={{ borderRadius: 8 }} |
||||
|
/> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</Card> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</div> |
||||
|
</Spin> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default AdvancedSettings; |
||||
@ -0,0 +1,475 @@ |
|||||
|
/** |
||||
|
* 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) { |
||||
|
|
||||
|
} 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) { |
||||
|
|
||||
|
} 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) { |
||||
|
|
||||
|
} 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) { |
||||
|
|
||||
|
} 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) { |
||||
|
|
||||
|
} 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('🔄 开始获取所有高级配置...'); |
||||
|
|
||||
|
|
||||
|
// 所有指令都用 setTimeout 包裹,首个指令也延迟,避免第一个指令丢包
|
||||
|
fetchDeviceId() |
||||
|
setTimeout(() => fetchDeviceId(), 50); |
||||
|
setTimeout(() => fetchDataFps(), 150); |
||||
|
setTimeout(() => fetchAlertConfig(), 250); |
||||
|
setTimeout(() => fetchFilterConfig(), 350); |
||||
|
setTimeout(() => fetchMqttConfig(), 450); |
||||
|
|
||||
|
// 等待所有响应
|
||||
|
setTimeout(() => { |
||||
|
setLoading(false); |
||||
|
console.log('配置获取完成'); |
||||
|
}, 2000); |
||||
|
}, [isConnected, isReady, fetchDeviceId, fetchDataFps, fetchAlertConfig, fetchFilterConfig, fetchMqttConfig]); |
||||
|
|
||||
|
/** |
||||
|
* 保存所有配置 |
||||
|
*/ |
||||
|
const saveAllSettings = useCallback(async () => { |
||||
|
if (!isConnected) { |
||||
|
message.warning('WebSocket 未连接,无法保存配置'); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!isReady) { |
||||
|
message.info('连接正在建立中,指令已加入队列...'); |
||||
|
} |
||||
|
|
||||
|
// 依次发送所有设置命令,并收集每项的结果
|
||||
|
const results = []; |
||||
|
results.push(await updateDeviceId(settings.deviceId)); |
||||
|
results.push(await new Promise(resolve => setTimeout(() => resolve(updateDataFps(settings.dataFps)), 100))); |
||||
|
results.push(await new Promise(resolve => setTimeout(() => resolve(updateAlertConfig(settings.alertConfig)), 200))); |
||||
|
results.push(await new Promise(resolve => setTimeout(() => resolve(updateFilterConfig(settings.filterConfig)), 300))); |
||||
|
results.push(await new Promise(resolve => setTimeout(() => resolve(updateMqttConfig(settings.mqttConfig)), 400))); |
||||
|
|
||||
|
// 判断是否全部成功
|
||||
|
const allSuccess = results.every(r => r !== false); |
||||
|
if (allSuccess) { |
||||
|
message.success('保存成功'); |
||||
|
return true; |
||||
|
} else { |
||||
|
message.error('保存失败'); |
||||
|
return false; |
||||
|
} |
||||
|
}, [isConnected, isReady, settings, updateDeviceId, updateDataFps, updateAlertConfig, updateFilterConfig, updateMqttConfig]); |
||||
|
|
||||
|
/** |
||||
|
* 重置配置到默认值 |
||||
|
*/ |
||||
|
const resetSettings = useCallback(() => { |
||||
|
setSettings(DEFAULT_SETTINGS); |
||||
|
message.info('配置已重置为默认值'); |
||||
|
}, []); |
||||
|
|
||||
|
/** |
||||
|
* 更新本地设置(不发送到设备) |
||||
|
*/ |
||||
|
const updateLocalSettings = useCallback((updates) => { |
||||
|
setSettings(prev => ({ |
||||
|
...prev, |
||||
|
...updates |
||||
|
})); |
||||
|
}, []); |
||||
|
|
||||
|
// 组件应在需要时自行调用 fetchAllSettings,不再在 hook 内自动调用
|
||||
|
|
||||
|
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 @@ |
|||||
|
import { useState, useEffect, useCallback } from "react"; const CORRECT_PASSWORD_HASH = "77796ac7e66ecc44954287ed7de7096c4016dd6ffb2763091c4eb3bc4d28b6dc", AUTH_STATUS_KEY = "advanced_config_unlocked"; async function generatePasswordHash(e) { try { var t = (new TextEncoder).encode(e), c = await crypto.subtle.digest("SHA-256", t); return Array.from(new Uint8Array(c)).map(e => e.toString(16).padStart(2, "0")).join("") } catch (e) { throw console.error("密码哈希生成失败:", e), e } } function checkUnlockStatus() { return "true" === sessionStorage.getItem(AUTH_STATUS_KEY) } function setUnlockStatus(e) { e ? sessionStorage.setItem(AUTH_STATUS_KEY, "true") : sessionStorage.removeItem(AUTH_STATUS_KEY) } function useAuth() { let [e, t] = useState(checkUnlockStatus); return useEffect(() => { t(checkUnlockStatus()) }, []), { isUnlocked: e, verifyPassword: useCallback(async e => { try { return e ? await generatePasswordHash(e) === CORRECT_PASSWORD_HASH && (setUnlockStatus(!0), t(!0), !0) : !1 } catch (e) { return console.error("密码验证失败:", e), !1 } }, []), logout: useCallback(() => { setUnlockStatus(!1), t(!1) }, []) } } export { useAuth, generatePasswordHash, checkUnlockStatus }; |
||||
@ -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