import React, { useState } from 'react'; import { Card, Form, Input, Button, Table, Tag, Space, Statistic, InputNumber, message, Modal, Checkbox } from 'antd'; import { ThunderboltOutlined, PlusOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'; interface DeviceConfig { id: string; name: string; deviceNo: string; ipAddress: string; port: number; gatewayBaudRate: number; address: number; baudRate: number; dataBits: number; stopBits: number; parity: 'none' | 'even' | 'odd'; timeout: number; unitId: number; verificationCode?: string; // 报警阈值配置 tempThreshold: { min: number; max: number; }; humidityThreshold: { min: number; max: number; }; alertMethods: { push: boolean; sms: boolean; }; } interface SensorData { temperature: number; humidity: number; timestamp: string; } // 临时模拟ModbusRTU功能 const ModbusRTU = { connect: async (device: Omit): Promise => { console.log('模拟连接设备:', device); return true; }, readHoldingRegisters: async (addr: number, count: number): Promise => { console.log('模拟读取寄存器:', addr, count); return [255, 652]; // 模拟温度25.5°C和湿度65.2% } }; const GreenhouseProtocolPage: React.FC = () => { const [editingDevice, setEditingDevice] = useState(null); const [modalVisible, setModalVisible] = useState(false); const [form] = Form.useForm(); const [devices, setDevices] = useState([]); const [currentData, setCurrentData] = useState(null); const [loading, setLoading] = useState(false); const [connected, setConnected] = useState(false); const generateVerificationCode = () => { const code = Math.floor(Math.random() * 65536).toString(16).toUpperCase(); return code.length === 1 ? `0${code}` : code.padStart(2, '0'); }; const handleAddDevice = () => { const values = form.getFieldsValue(); setDevices([...devices, { id: `device-${Date.now()}`, deviceNo: values.deviceNo, verificationCode: generateVerificationCode(), tempThreshold: { min: 10, max: 30 }, humidityThreshold: { min: 30, max: 80 }, alertMethods: { push: true, sms: false }, ...values }]); form.resetFields(); }; const handleSendCommand = (device: DeviceConfig) => { if (!device.verificationCode) { message.error('请先生成校验码'); return; } const deviceNoHex = parseInt(device.deviceNo).toString(16).padStart(2, '0').toUpperCase(); const command = `[${deviceNoHex} 04 00 00 00 02 ${device.verificationCode}]`; // 模拟返回数据 (温度18-25℃, 湿度40-70%) const temp = (18 + Math.random() * 7).toFixed(1); const humidity = (40 + Math.random() * 30).toFixed(1); const tempInt = parseInt(temp); const tempDec = parseInt((temp.split('.')[1] || '0')); const humInt = parseInt(humidity); const humDec = parseInt((humidity.split('.')[1] || '0')); const response = `[${deviceNoHex} 04 04 ${tempInt.toString(16).padStart(2,'0')} ${tempDec.toString(16).padStart(2,'0')} ${humInt.toString(16).padStart(2,'0')} ${humDec.toString(16).padStart(2,'0')} 9B 1E]`; console.log('发送指令:', command); message.success(<>
指令已发送:
{command}
返回数据:
{response}
解析结果: 温度 {temp}℃, 湿度 {humidity}%
); }; const handleConnect = async (device: DeviceConfig) => { setLoading(true); try { await ModbusRTU.connect(device); setConnected(true); } catch (err) { console.error('连接失败:', err); } finally { setLoading(false); } }; const handleReadData = async () => { if (!connected) return; setLoading(true); try { const data = await ModbusRTU.readHoldingRegisters(0, 2); setCurrentData({ temperature: data[0] / 10, humidity: data[1] / 10, timestamp: new Date().toISOString() }); } catch (err) { console.error('读取数据失败:', err); } finally { setLoading(false); } }; const columns = [ { title: '报警状态', key: 'alertStatus', render: (_: unknown, record: DeviceConfig) => { const tempAlert = currentData && ( currentData.temperature < record.tempThreshold.min || currentData.temperature > record.tempThreshold.max ); const humidityAlert = currentData && ( currentData.humidity < record.humidityThreshold.min || currentData.humidity > record.humidityThreshold.max ); return ( {tempAlert && 温度异常} {humidityAlert && 湿度异常} {!tempAlert && !humidityAlert && 正常} ); }, }, { title: '设备ID', dataIndex: 'id', key: 'id', }, { title: '设备编号', dataIndex: 'deviceNo', key: 'deviceNo', }, { title: '设备名称', dataIndex: 'name', key: 'name', }, { title: 'Modbus地址', dataIndex: 'address', key: 'address', }, { title: '状态', key: 'status', render: () => ( {connected ? '已连接' : '未连接'} ), }, { title: '操作', key: 'action', render: (_: unknown, record: DeviceConfig) => ( ), }, ]; return (
setModalVisible(false)} footer={null} >
~ ~ 消息推送 短信通知
{currentData && (
最后更新: {new Date(currentData.timestamp).toLocaleString()}
)} ); }; export { GreenhouseProtocolPage };