Browse Source

feat: mqtt双发配置;滤波窗口大小上限21改为31

master 1.1.9
liujiangyong 1 day ago
parent
commit
0011d569b7
  1. 388
      client/src/sections/wuyuanbiaoba/components/AdvancedSettings.jsx
  2. 133
      client/src/sections/wuyuanbiaoba/hooks/useAdvancedSettings.js
  3. 50
      client/src/sections/wuyuanbiaoba/hooks/高级配置说明.md

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

@ -15,7 +15,8 @@ import {
Spin,
Alert,
Tooltip,
Modal
Modal,
Tabs
} from "antd";
import {
SettingOutlined,
@ -87,15 +88,20 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
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 enableBatch = settings.mqttConfig?.batch ?? false;
const batchInterpolation = settings.mqttConfig?.interpolation ?? 'copy';
const MQTT_TEMPLATE = {
enable: false,
broker: '',
port: 1883,
topic: '',
username: '',
password: '',
client_id: ''
};
const mqtts = settings.mqttConfig?.mqtts ?? [MQTT_TEMPLATE, MQTT_TEMPLATE];
const brokers = [0, 1].map((i) => ({ ...MQTT_TEMPLATE, ...(mqtts[i] ?? {}) }));
const anyMqttEnabled = brokers.some((b) => b.enable);
// 更新本地状态的辅助函数
const setDeviceId = (value) => updateLocalSettings({ deviceId: value });
@ -135,78 +141,22 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
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) =>
const setMqttEnable = (index, value) =>
updateLocalSettings({
mqttConfig: {
...settings.mqttConfig,
mqtt: {
...(settings.mqttConfig?.mqtt ?? {}),
broker: value
},
mqtts: brokers.map((b, i) =>
i === index ? { ...b, enable: value } : b
),
},
});
const setMqttPort = (value) =>
const setMqttField = (index, field, 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
},
mqtts: brokers.map((b, i) =>
i === index ? { ...b, [field]: value } : b
),
},
});
const setEnableBatch = (value) =>
@ -303,21 +253,36 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
};
const handleSave = async () => {
if (enableMqtt) {
if (brokerAddress && !validateIP(brokerAddress)) {
message.error('Broker 地址格式不正确,请检查后重试');
for (let index = 0; index < brokers.length; index++) {
const broker = brokers[index];
if (!broker.enable) {
continue;
}
const brokerNo = index + 1;
if (broker.broker && !validateIP(broker.broker)) {
message.error(`Broker ${brokerNo} 地址格式不正确,请检查后重试`);
return;
}
if (mqttPort && !validatePort(mqttPort)) {
message.error('端口号格式不正确,请检查后重试');
if (broker.port && !validatePort(broker.port)) {
message.error(`Broker ${brokerNo} 端口号格式不正确,请检查后重试`);
return;
}
if (!brokerAddress) {
message.warning('启用 MQTT 时请填写 Broker 地址');
if (!broker.broker) {
message.warning(`启用了 Broker ${brokerNo},请填写 Broker 地址`);
return;
}
}
if (
brokers[0].enable &&
brokers[1].enable &&
brokers[0].broker.trim().toLowerCase() ===
brokers[1].broker.trim().toLowerCase()
) {
message.warning("Broker 1 与 Broker 2 的地址不能相同");
return;
}
try {
setSaving(true);
const success = await saveAllSettings();
@ -333,6 +298,145 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
}
};
// 渲染单个 Broker 配置面板(Tabs 内容)
const renderBrokerPane = (index) => {
const broker = brokers[index];
const brokerNo = index + 1;
return (
<div>
{/* 启用开关 */}
<div
style={{
background:
"linear-gradient(135deg, #f5f7fa 0%, #e8eef5 100%)",
padding: 20,
borderRadius: 12,
}}
>
<Row justify="space-between" align="middle">
<Col>
<Text strong>启用 Broker {brokerNo} 上报</Text>
<br />
<Text type="secondary" style={{ fontSize: 12 }}>
开启后,设备将按下方配置向该 Broker 上报数据。
</Text>
</Col>
<Col>
<Switch
checked={broker.enable}
onChange={(value) => setMqttEnable(index, value)}
checkedChildren="开启"
unCheckedChildren="关闭"
/>
</Col>
</Row>
</div>
{/* Broker 配置字段 */}
<Row gutter={[12, 12]} style={{ marginTop: 16 }}>
<Col span={12}>
<div style={{ marginBottom: 4, fontWeight: 500 }}>
Broker Address
<Text type="danger"> *</Text>
</div>
<Input
value={broker.broker}
onChange={(e) => setMqttField(index, 'broker', e.target.value)}
placeholder="例如: 218.3.126.49 或 mqtt.example.com"
size="large"
disabled={!broker.enable}
style={{
borderRadius: 8,
borderColor: broker.broker && !validateIP(broker.broker) ? '#ff4d4f' : undefined
}}
status={broker.broker && !validateIP(broker.broker) ? 'error' : undefined}
/>
{broker.broker && !validateIP(broker.broker) && (
<Text type="danger" style={{ fontSize: 12 }}>
请输入有效的 IPv4 地址
</Text>
)}
</Col>
<Col span={8}>
<div style={{ marginBottom: 4, fontWeight: 500 }}>
Port
<Text type="danger"> *</Text>
</div>
<Input
value={broker.port}
onChange={(e) => setMqttField(index, 'port', e.target.value)}
placeholder="1883"
size="large"
disabled={!broker.enable}
style={{
borderRadius: 8,
borderColor: broker.port && !validatePort(broker.port) ? '#ff4d4f' : undefined
}}
status={broker.port && !validatePort(broker.port) ? 'error' : undefined}
/>
{broker.port && !validatePort(broker.port) && (
<Text type="danger" style={{ fontSize: 12 }}>
端口范围: 1-65535
</Text>
)}
</Col>
<Col span={12}>
<div style={{ marginBottom: 4, fontWeight: 500 }}>
Topic
</div>
<Input
value={broker.topic}
onChange={(e) => setMqttField(index, 'topic', e.target.value)}
placeholder="例如: wybb/z/mqtt179"
size="large"
disabled={!broker.enable}
style={{ borderRadius: 8 }}
/>
</Col>
<Col span={8}>
<div style={{ marginBottom: 4, fontWeight: 500 }}>
Client ID
</div>
<Input
value={broker.client_id}
onChange={(e) => setMqttField(index, 'client_id', e.target.value)}
placeholder="wybb_z1_123"
size="large"
disabled={!broker.enable}
style={{ borderRadius: 8 }}
/>
</Col>
<Col span={8}>
<div style={{ marginBottom: 4, fontWeight: 500 }}>
Username
</div>
<Input
value={broker.username}
onChange={(e) => setMqttField(index, 'username', e.target.value)}
placeholder="用户名"
size="large"
disabled={!broker.enable}
style={{ borderRadius: 8 }}
/>
</Col>
<Col span={8}>
<div style={{ marginBottom: 4, fontWeight: 500 }}>
Password
</div>
<Input.Password
value={broker.password}
onChange={(e) => setMqttField(index, 'password', e.target.value)}
placeholder="密码"
size="large"
disabled={!broker.enable}
style={{ borderRadius: 8 }}
/>
</Col>
</Row>
</div>
);
};
const handleReset = () => {
fetchAllSettings();
};
@ -654,7 +758,7 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
</div>
<InputNumber
min={3}
max={21}
max={31}
step={2}
value={windowSize}
onChange={setWindowSize}
@ -697,24 +801,10 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
<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={{
@ -723,106 +813,14 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
paddingRight: 24,
}}
>
<Row gutter={[12, 12]}>
<Col span={12}>
<div style={{ marginBottom: 4, fontWeight: 500 }}>
Broker Address
<Text type="danger"> *</Text>
</div>
<Input
value={brokerAddress}
onChange={(e) => setBrokerAddress(e.target.value)}
placeholder="例如: 218.3.126.49 或 mqtt.example.com"
size="large"
disabled={!enableMqtt}
style={{
borderRadius: 8,
borderColor: brokerAddress && !validateIP(brokerAddress) ? '#ff4d4f' : undefined
}}
status={brokerAddress && !validateIP(brokerAddress) ? 'error' : undefined}
/>
{brokerAddress && !validateIP(brokerAddress) && (
<Text type="danger" style={{ fontSize: 12 }}>
请输入有效的 IPv4 地址
</Text>
)}
</Col>
<Col span={8}>
<div style={{ marginBottom: 4, fontWeight: 500 }}>
Port
<Text type="danger"> *</Text>
</div>
<Input
value={mqttPort}
onChange={(e) => setMqttPort(e.target.value)}
placeholder="1883"
size="large"
disabled={!enableMqtt}
style={{
borderRadius: 8,
borderColor: mqttPort && !validatePort(mqttPort) ? '#ff4d4f' : undefined
}}
status={mqttPort && !validatePort(mqttPort) ? 'error' : undefined}
/>
{mqttPort && !validatePort(mqttPort) && (
<Text type="danger" style={{ fontSize: 12 }}>
端口范围: 1-65535
</Text>
)}
</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 }}
<Tabs
defaultActiveKey="0"
items={[0, 1].map((index) => ({
key: String(index),
label: `Broker ${index + 1}`,
children: renderBrokerPane(index),
}))}
/>
</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>
{/* 每秒批量上报 */}
<div
@ -848,7 +846,7 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
onChange={setEnableBatch}
checkedChildren="开启"
unCheckedChildren="关闭"
disabled={!enableMqtt}
disabled={!anyMqttEnabled}
/>
</Col>
</Row>
@ -863,7 +861,7 @@ const AdvancedSettings = ({ onLogout, locationConfig }) => {
value={batchInterpolation}
onChange={setBatchInterpolation}
size="large"
disabled={!enableMqtt || !enableBatch}
disabled={!anyMqttEnabled || !enableBatch}
style={{ width: "50%", borderRadius: 8 }}
>
<Option value="copy">分段复制</Option>

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

@ -9,7 +9,7 @@
* - 数据帧率读取与设置 (getDataFps/setDataFps)
* - 异常超时监控读取与设置 (getAlert/setAlert)
* - 滤波配置读取与设置 (getWin/setWin)
* - MQTT 上报配置读取与设置 (getMqtt/setMqtt)
* - MQTT 上报配置读取与设置 (getMqtt2/setMqtt2,双 Broker)
*
* 使用示例:
* ```jsx
@ -58,12 +58,22 @@ const DEFAULT_SETTINGS = {
imgThreshold: 10.0
},
// MQTT 配置
// MQTT 配置(双 Broker)
mqttConfig: {
enable: true,
batch: false,
interpolation: 'copy',
mqtt: {
mqtts: [
{
enable: true,
broker: '',
port: 1883,
topic: '',
username: '',
password: '',
client_id: ''
},
{
enable: false,
broker: '',
port: 1883,
topic: '',
@ -71,6 +81,7 @@ const DEFAULT_SETTINGS = {
password: '',
client_id: ''
}
]
}
};
@ -82,7 +93,7 @@ const SAVE_ITEMS = {
setDataFps: '数据帧率',
setAlert: '异常监控配置',
setWin: '滤波配置',
setMqtt: 'MQTT 配置'
setMqtt2: 'MQTT 配置'
};
const MQTT_CONNECT_WARNING = '配置已保存,但 MQTT Broker 连接失败,请检查网络、Broker 地址和端口';
@ -109,8 +120,8 @@ const useAdvancedSettings = () => {
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');
const { latest: getMqtt2Response } = useWebSocketSubscription('dev', 'getMqtt2');
const { latest: setMqtt2Response } = useWebSocketSubscription('dev', 'setMqtt2');
/**
* 处理设备编码读取响应
@ -248,31 +259,31 @@ const useAdvancedSettings = () => {
}, [setWinResponse]);
/**
* 处理 MQTT 配置读取响应
* 处理 MQTT 配置读取响应(getMqtt2)
*/
useEffect(() => {
if (getMqttResponse?.values) {
console.log('📥 收到 MQTT 配置:', getMqttResponse.values);
if (getMqtt2Response?.values?.mqtts) {
console.log('📥 收到 MQTT 配置:', getMqtt2Response.values);
setSettings(prev => ({
...prev,
mqttConfig: getMqttResponse.values
mqttConfig: getMqtt2Response.values
}));
setFetchStatus(prev => ({ ...prev, mqtt: 'success' }));
}
}, [getMqttResponse]);
}, [getMqtt2Response]);
/**
* 处理 MQTT 配置设置响应
* 处理 MQTT 配置设置响应(setMqtt2)
*/
useEffect(() => {
if (setMqttResponse?.values?.operate !== undefined) {
if (setMqttResponse.values.operate) {
if (setMqtt2Response?.values?.operate !== undefined) {
if (setMqtt2Response.values.operate) {
} else {
console.warn('MQTT 配置已保存,但 Broker 连接失败:', setMqttResponse.values);
console.warn('MQTT 配置已保存,但 Broker 连接失败:', setMqtt2Response.values);
}
}
}, [setMqttResponse]);
}, [setMqtt2Response]);
/**
* 发送 WebSocket 命令
@ -395,38 +406,52 @@ const useAdvancedSettings = () => {
*/
const fetchMqttConfig = useCallback(() => {
setFetchStatus(prev => ({ ...prev, mqtt: 'loading' }));
return sendCommand('getMqtt', {});
return sendCommand('getMqtt2', {});
}, [sendCommand]);
/**
* 更新 MQTT 配置
* 更新 MQTT 配置(双 Broker)
*/
const updateMqttConfig = useCallback((mqttConfig) => {
const { enable, mqtt, batch, interpolation } = mqttConfig;
const { mqtts, batch, interpolation } = mqttConfig;
// 验证必填字段
if (enable) {
if (!mqtt.broker || !mqtt.broker.trim()) {
message.warning('请输入 Broker 地址');
// 验证每个启用 Broker 的必填字段
for (let index = 0; index < (mqtts || []).length; index++) {
const item = mqtts[index];
if (!item?.enable) {
continue;
}
const brokerNo = index + 1;
if (!item.broker || !item.broker.trim()) {
message.warning(`请输入 Broker ${brokerNo} 地址`);
return false;
}
if (!mqtt.port) {
message.warning('请输入端口号');
if (!item.port) {
message.warning(`请输入 Broker ${brokerNo} 端口号`);
return false;
}
if (!mqtt.topic || !mqtt.topic.trim()) {
message.warning('请输入 Topic');
if (!item.topic || !item.topic.trim()) {
message.warning(`请输入 Broker ${brokerNo} Topic`);
return false;
}
if (!mqtt.client_id || !mqtt.client_id.trim()) {
message.warning('请输入 Client ID');
if (!item.client_id || !item.client_id.trim()) {
message.warning(`请输入 Broker ${brokerNo} Client ID`);
return false;
}
}
return sendCommand('setMqtt', {
enable,
mqtt,
if (
mqtts?.[0]?.enable &&
mqtts?.[1]?.enable &&
(mqtts[0].broker || '').trim().toLowerCase() ===
(mqtts[1].broker || '').trim().toLowerCase()
) {
message.warning('Broker 1 与 Broker 2 的地址不能相同');
return false;
}
return sendCommand('setMqtt2', {
mqtts,
batch: batch ?? false,
interpolation: interpolation ?? 'copy'
});
@ -496,26 +521,41 @@ const useAdvancedSettings = () => {
return false;
}
const { enable, mqtt } = settings.mqttConfig || {};
if (enable) {
if (!mqtt?.broker || !mqtt.broker.trim()) {
message.warning('请输入 Broker 地址');
const mqtts = settings.mqttConfig?.mqtts || [];
for (let index = 0; index < mqtts.length; index++) {
const item = mqtts[index];
if (!item?.enable) {
continue;
}
const brokerNo = index + 1;
if (!item.broker || !item.broker.trim()) {
message.warning(`请输入 Broker ${brokerNo} 地址`);
return false;
}
if (!mqtt.port) {
message.warning('请输入端口号');
if (!item.port) {
message.warning(`请输入 Broker ${brokerNo} 端口号`);
return false;
}
if (!mqtt.topic || !mqtt.topic.trim()) {
message.warning('请输入 Topic');
if (!item.topic || !item.topic.trim()) {
message.warning(`请输入 Broker ${brokerNo} Topic`);
return false;
}
if (!mqtt.client_id || !mqtt.client_id.trim()) {
message.warning('请输入 Client ID');
if (!item.client_id || !item.client_id.trim()) {
message.warning(`请输入 Broker ${brokerNo} Client ID`);
return false;
}
}
if (
mqtts[0]?.enable &&
mqtts[1]?.enable &&
(mqtts[0].broker || '').trim().toLowerCase() ===
(mqtts[1].broker || '').trim().toLowerCase()
) {
message.warning('Broker 1 与 Broker 2 的地址不能相同');
return false;
}
return true;
}, [settings]);
@ -565,10 +605,9 @@ const useAdvancedSettings = () => {
}
},
{
cmd: 'setMqtt',
cmd: 'setMqtt2',
values: {
enable: settings.mqttConfig.enable,
mqtt: settings.mqttConfig.mqtt,
mqtts: settings.mqttConfig.mqtts,
batch: settings.mqttConfig.batch ?? false,
interpolation: settings.mqttConfig.interpolation ?? 'copy'
}
@ -633,7 +672,7 @@ const useAdvancedSettings = () => {
for (const command of commands) {
const result = await sendAndWaitOperate(command.cmd, command.values);
if (!result.success) {
if (result.cmd === 'setMqtt' && !result.timeout) {
if (result.cmd === 'setMqtt2' && !result.timeout) {
mqttConnectWarning = result;
continue;
}

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

@ -212,7 +212,7 @@
```json
{
"_from": "setup",
"cmd":"getMqtt",
"cmd":"getMqtt2",
"values": {}
}
```
@ -220,45 +220,67 @@
```json
{
"_from": "dev",
"cmd": "getMqtt",
"cmd": "getMqtt2",
"values": {
"mqtt": {
"mqtts": [
{
"enable": true,
"broker": "218.3.126.49",
"port": 1883,
"topic": "wybb/zj/mqtt110_debug",
"topic": "wybb/hg/mqtt179_debug1",
"username": "",
"password": "",
"client_id": "wybb_debug"
"client_id": "wybb_hg_1"
},
{
"enable": true,
"broker": "218.3.126.49",
"port": 1883,
"topic": "wybb/hg/mqtt179_debug2",
"username": "",
"password": "",
"client_id": "wybb_hg_2"
}
],
"batch": true,
"interpolation": "lowpass"
"interpolation": "copy"
}
}
```
字段说明:
- `enable`:MQTT 上报总开关
- `mqtts`:Broker 配置数组,支持 2 个 Broker,每项含 `enable`(该 Broker 上报开关)及 `broker`/`port`/`topic`/`username`/`password`/`client_id`
- `batch`:每秒批量上报开关。开启后,每秒将多条数据合并为一个数组发送;关闭时数据格式不变(一秒内上报多次)
- `interpolation`:批量补全算法,`copy`=分段复制(现有算法,数据缺失时仍复制该条),`lowpass`=低通滤波插值(3Hz FIR 滤波器插值补全缺失数据)
- `interpolation`:批量补全算法,`copy`=分段复制(数据缺失时仍复制该条),`lowpass`=低通滤波插值(3Hz FIR 滤波器插值补全缺失数据)
12. mqtt上报设置
```json
{
"_from": "setup",
"cmd": "setMqtt",
"cmd": "setMqtt2",
"values": {
"mqtt": {
"mqtts": [
{
"enable": true,
"broker": "218.3.126.49",
"port": 1883,
"topic": "wybb/zj/mqtt110_debug",
"topic": "wybb/hg/mqtt179_debug1",
"username": "",
"password": "",
"client_id": "wybb_debug"
"client_id": "wybb_hg_1"
},
{
"enable": true,
"broker": "218.3.126.49",
"port": 1883,
"topic": "wybb/hg/mqtt179_debug2",
"username": "",
"password": "",
"client_id": "wybb_hg_2"
}
],
"batch": true,
"interpolation": "lowpass"
"interpolation": "copy"
}
}
```
@ -266,7 +288,7 @@
```json
{
"_from": "dev",
"cmd": "setMqtt",
"cmd": "setMqtt2",
"values": {
"operate": true
}

Loading…
Cancel
Save