在系统设置中设置好网络转发参数后,可以在吸收的地方开启网络数据吸收,这样只须要吸收数据解析反应到界面就行,相称于数据源不是硬件设备而是网络转发过来的数据,不须要直接接硬件设备。
网络转发轫,单击同步数据会把本地的端口信息、掌握器信息、探测器信息发到远端。网络转发模块也可以作为无限级联利用,比如吸收端还可以开启转发,连续转发给须要的地方,一个客户端上设置的转发也支持多个,用英文分号 ; 隔开,一对多关系,采取的无连接udp协议,险些不占用系统资源。
五、干系代码
void UdpSend::sendData(const QString &portName, quint8 addr, const QByteArray &data){ if (!AppConfig::UseNetSend) { return; } //取出ip和端口 QList<QString> ips; QList<int> ports; QStringList list = AppConfig::NetSendInfo.split(";"); foreach (QString str, list) { if (str.contains(":")) { QStringList temp = str.split(":"); ips << temp.at(0); ports << temp.at(1).toInt(); } } //逐个发送 for (int i = 0; i < ips.count(); ++i) { if (data.size() > 0) { QString buffer; if (portName == "PortInfo" || portName == "DeviceInfo" || portName == "NodeInfo") { buffer = QString("%1|%2").arg(portName).arg(QString(data)); } else { buffer = QString("%1|%2").arg(portName).arg(QUIHelper::byteArrayToHexStr(data)); } udpSocket->writeDatagram(buffer.toUtf8(), QHostAddress(ips.at(i)), ports.at(i)); udpSocket->flush(); } }}//type: 0=端口信息 1=掌握器信息 2=探测器信息void UdpReceive::saveDataBase(const QString table, const QStringList &datas){ QString flag, sql; if (table == "PortInfo") { flag = "端口信息"; sql = "insert into PortInfo(PortID,PortName,PortType,ComName,BaudRate,TcpIP,TcpPort,ReadInterval,ReadTimeout,ReadMaxtime) values"; } else if (table == "DeviceInfo") { flag = "掌握器信息"; sql = "insert into DeviceInfo(DeviceID,PortName,DeviceName,DeviceAddr,DeviceType,NodeNumber) values"; } else if (table == "NodeInfo") { flag = "探测器信息"; sql = "insert into NodeInfo(NodeID,PositionID,DeviceName,NodeName,NodeAddr,NodeType,NodeClass,NodeSign,NodeUpper,NodeLimit,NodeMax," "NodeMin,NodeRange,NodeEnable,NodeSound,NodeImage,SaveInterval,DotCount,AlarmDelay,AlarmType,NodeX,NodeY) values"; } //清空原有数据 DbHelper::clearTable(table); //开启数据库事务 QSqlDatabase::database().transaction(); //组成sql语句挨个实行 foreach (QString data, datas) { QStringList list = data.split(","); QStringList values; int count = list.count(); for (int i = 0; i < count; ++i) { values << list.at(i); } QString sqlx = QString("%1('%2')").arg(sql).arg(values.join("','")); DbHelper::execSql(sqlx); } //提交数据库事务 if (QSqlDatabase::database().commit()) { QString msg = QString("批量插入%1成功").arg(flag); DbQuery::addUserLog(msg); emit receiveInfo(portName, 255, msg); } else { QSqlDatabase::database().rollback(); QString msg = QString("批量插入%1失落败").arg(flag); DbQuery::addUserLog(msg); emit receiveError(portName, 255, msg); }}void UdpReceive::checkData(const QString &data){ //取出端口名称+地址+数据 QStringList list = data.split("|"); if (list.count() != 2) { return; } //根据不同的端口处理数据,表信息也是端口号字段发过来的 QString portName = list.at(0); if (portName == "PortInfo" || portName == "DeviceInfo" || portName == "NodeInfo") { saveDataBase(portName, list.at(1).split(";")); if (portName == "NodeInfo") { //探测器表是末了发过来的,收到后延时重启运用新的数据 QTimer::singleShot(3000, this, SLOT(reboot())); } return; } //传过来的便是采集到的源数据 QByteArray buffer = QUIHelper::hexStrToByteArray(list.at(1)); //至少要多少个字节,担保下面取数据不出错 int size = buffer.size(); if (size < 5) { return; } //01 03 08 00 00 00 00 00 00 00 00 95 D7 //01 03 08 00 14 03 12 00 00 00 00 79 E6 //取出首字节,判断是否为当前地址凑集中的地址 quint8 addr = buffer.at(0); quint8 cmd = buffer.at(1); quint8 len = buffer.at(2); //如果是缺点码则直接解析缺点信息 QList<quint8> cmds; cmds << 0x03 << 0x04 << 0x06; if (!cmds.contains(cmd)) { emit receiveError(portName, addr, QString("数据出错: %1").arg(QUIHelper::byteArrayToHexStr(buffer))); buffer.clear(); return; } //后面的数据长度必须大于即是长度数据位表示的长度 if ((cmd == 0x03 || cmd == 0x04 || cmd == 0x06) && size < len + 5) { return; } //放在这里发出去数据是准确的完全的 emit receiveData(portName, addr, buffer); //来过的设备,立马更新末了的韶光,以及判断设备上线 int index = addrs.indexOf(addr); times[index] = QDateTime::currentDateTime(); if ((!lives.at(index) && onlines.at(index)) || !onlines.at(index)) { onlines[index] = true; lives[index] = true; emit receiveOnline(portName, addr, true); emit receiveInfo(portName, addr, "设备上线"); } //根据不同的cmd+不同的命令类型 取出对应的数据内容 if (cmd == 0x03) { QString info; if (currentType == "查询浓度值") { QList<quint16> values; for (int i = 3; i < size - 2; i = i + 2) { values << (float)QUIHelper::byteToUShort(buffer.mid(i, 2)); } QStringList list; foreach (quint16 value, values) { list << QString::number(value); } info = QString("%1返回: %2").arg(currentType).arg(list.join(" ")); emit receiveValue(portName, addr, values); } //发送对应的笔墨解析 if (!info.isEmpty()) { emit receiveInfo(portName, addr, info); } } else if (cmd == 0x04) { } else if (cmd == 0x06) { }}
