Files
testtools/dlink/dlink.cpp
T
2025-09-16 14:44:50 +08:00

697 lines
19 KiB
C++

#include "dlink.h"
#include <string.h>
#include "QDateTime"
#include "QThread"
DLink::DLink(QObject *parent) : QObject(parent)
{
QTimer *Timer = new QTimer(this);
Timer->setInterval(1000);
//定时刷新每个接口的通讯状态
connect(Timer,&QTimer::timeout,this,[=](){
static qint64 last = QDateTime::currentMSecsSinceEpoch();
qint64 time = QDateTime::currentMSecsSinceEpoch() - last;
if(time >= 1000)
{
foreach(clientNode node,sockets)
{
if(node.sock)
{
node.in.total += node.in.count;
node.out.total += node.out.count;
node.in.rate = (double)node.in.count / (time * 0.001);
node.out.rate = (double)node.out.count / (time * 0.001);
node.in.frequency = (double)node.in.frame / (time * 0.001);
node.out.frequency = (double)node.out.frame / (time * 0.001);
emit status(node.addr,node.port,node.in.total,node.in.rate,node.in.frequency,node.out.total,node.out.rate,node.out.frequency);
node.in.count = 0;
node.out.count = 0;
node.in.frame = 0;
node.out.frame = 0;
sockets.replace(sockets.indexOf(node),node);
//qDebug() << node.out.rate << node.out.frequency;
}
}
last = QDateTime::currentMSecsSinceEpoch();
}
});
connect(this,&DLink::destroyed,Timer,&QTimer::deleteLater);
Timer->start();
}
DLink::~DLink()
{
foreach (serialNode node, serials) {
if(node.port)
{
if(node.port->isOpen())
{
node.port->close();
}
delete node.port;
node.port = nullptr;
}
}
foreach(clientNode node,sockets)
{
if(node.sock)
{
node.sock->leaveMulticastGroup(node.addr);
node.sock->abort();
qWarning("leave multicast Group");
delete node.sock;
node.sock = nullptr;
}
}
disconnect(this, nullptr, nullptr, nullptr);
}
void DLink::transmit(QHostAddress ip,quint16 port,QByteArray data)
{
//qDebug() << "dlink transmit:" << QThread::currentThreadId();
QElapsedTimer time;
time.start();
foreach(clientNode node,sockets)
{
if((node.addr == ip) && (node.port == port))
{
qint64 flag = node.sock->writeDatagram(data,node.addr, node.port);
if(flag != -1)
{
node.out.count += flag;
node.out.frame += 1;
sockets.replace(sockets.indexOf(node),node);
}
else
{
qDebug() << "udp Send Msg failure";
}
}
}
//qDebug() << "dlink transmit time:" << time.nsecsElapsed() / 1000000.0 ;
}
void DLink::transmit(QString name,QByteArray data)
{
//qDebug() << "dlink transmit:" << QThread::currentThreadId();
QElapsedTimer time;
time.start();
foreach (serialNode node, serials) {
if((node.port)&&(node.name == name))
{
if(node.port->isOpen()||node.port->isWritable())
{
if(node.type == devtype::datalink)
{
qint64 flag = node.port->write(data);
if(flag != -1)
{
//qDebug() << data.toHex();
node.out.count += flag;
node.out.frame += 1;
serials.replace(serials.indexOf(node),node);
}
else
{
qDebug() << "serialPort Send Msg failure";
}
}
}
}
}
//qDebug() << "dlink transmit time:" << time.nsecsElapsed() / 1000000.0 ;
}
int DLink::SendMessageTo(quint8 ch, quint8 *msg, quint16 len)
{
//让这个函数在其他线程运行
outCount += len;
//qDebug() << "Send Msg";
//更加ch选择
foreach(clientNode node,sockets)
{
if(node.sock->isOpen()||node.sock->isWritable()||node.sock->isValid())
{
if(node.type == devtype::datalink)
{
qint64 flag = node.sock->writeDatagram((const char *)msg,len,node.addr, node.port);
if(flag != -1)
{
node.out.count += flag;
node.out.frame += 1;
sockets.replace(sockets.indexOf(node),node);
}
else
{
qDebug() << "udp Send Msg failure";
}
}
}
}
foreach (serialNode node, serials) {
if(node.port)
{
if(node.port->isOpen()||node.port->isWritable())
{
if(node.type == devtype::datalink)
{
qint64 flag = node.port->write((const char *)msg,len);
if(flag != -1)
{
node.out.count += flag;
node.out.frame += 1;
serials.replace(serials.indexOf(node),node);
}
else
{
qDebug() << "serialPort Send Msg failure";
}
}
}
}
}
return outCount;
}
/* 新想法
* dlink 当作一个线程一直循环,一旦某一个串口连接,就会把事件循环加入其中,得到事件驱动
* 指令按下会把数据存到缓存,等待发送出去,线程就会结束
* 发起任务读写,新建一个线程,航线读取发送结束,航线线程结束
* 发起参数读写,新建一个线程,参数读取发送结束,参数线程结束
*/
bool DLink::PortSetup(const QString &name, qint32 baudrate, QSerialPort::Parity parity)
{
bool isSuccess = false;
qDebug() << "Q_INVOKABLE" << baudrate << parity;
foreach (serialNode node, serials) {
if(node.port)
{
if(node.name == name)
{
if(node.port->isOpen())
{
node.port->close();
}
//断掉所有的连接
disconnect(node.port,nullptr,nullptr,nullptr);
delete node.port;
node.port = nullptr;
serials.removeAt(serials.indexOf(node));
}
}
}
QSerialPort *serialPort = new QSerialPort(name,this);
if (serialPort->open(QIODevice::ReadWrite))
{
serialPort->setBaudRate(baudrate);
serialPort->setParity(parity);
serialPort->setDataBits(QSerialPort::Data8);
serialPort->setStopBits(QSerialPort::OneStop);
connect(serialPort, SIGNAL(readyRead()), this, SLOT(readPendingDatagramsSerialPort()));//本线程内调用
isSuccess = true;
serialNode node;
node.port = serialPort;
node.baud = baudrate;
node.parity = parity;
node.name = name;
node.type = devtype::datalink;
serials.append(node);
emit showMessage(tr("Serial Port Open Success"),10000);
qWarning() << "Serial Port Open Success";
}
else
{
isSuccess = false;
emit showMessage(tr("Serial Port Open Fail"),10000);
qWarning() << "Serial Port Open Fail";
delete serialPort;
serialPort = nullptr;
}
return isSuccess;
}
bool DLink::PortState(const QString &name)
{
bool flag = false;
foreach (serialNode node, serials) {
if(node.port)
{
if(node.name == name)
{
flag = true;
break;
}
}
}
return flag;
}
bool DLink::PortStop(const QString &name)
{
bool flag = false;
foreach (serialNode node, serials) {
if(node.port)
{
if(node.name == name)
{
if(node.port->isOpen())
{
qDebug() << "close" << node.name;
emit showMessage(tr("%1 close").arg(node.name),10000);
node.port->close();
}
//断掉所有的连接
disconnect(node.port,nullptr,nullptr,nullptr);
delete node.port;
node.port = nullptr;
serials.removeOne(node);
flag = true;
}
}
}
return flag;
}
bool DLink::setupClient(const QHostAddress &local_addr,int local_port,const QHostAddress &remote_addr,int remote_port)
{
bool isSuccess = false;
foreach (clientNode node, sockets) {
if(node.sock)
{
if((node.addr == remote_addr)&&(node.port == remote_port))
{
if(node.sock->isOpen())
{
node.sock->leaveMulticastGroup(node.addr);
node.sock->close();
}
//断掉所有的连接
disconnect(node.sock,nullptr,nullptr,nullptr);
node.sock->deleteLater();
//node.sock = nullptr;
sockets.removeAt(sockets.indexOf(node));
}
}
}
QUdpSocket *clientsock = new QUdpSocket(this);
clientsock->setProxy(QNetworkProxy::DefaultProxy);//必须先设置不代理,否则连不上
int rst = clientsock->open(QIODevice::ReadWrite);
if(rst)
{
if(clientsock->bind(local_addr,local_port,QAbstractSocket::ShareAddress | QUdpSocket::ReuseAddressHint))
{
connect(clientsock, SIGNAL(readyRead()),
this, SLOT(readPendingDatagramsClient()));
clientNode node;
node.sock = clientsock;
node.addr = remote_addr;
node.port = remote_port;
node.type = devtype::datalink;
sockets.append(node);
qWarning() << "UdpSocket open:"
<< remote_addr
<< local_port
<< remote_port;
isSuccess = true;
emit showMessage(tr("UdpSocket open"),10000);
}
else
{
clientsock->close();
isSuccess = false;
qWarning() << "sock open failure" << clientsock->state();
delete clientsock;
clientsock = nullptr;
}
}
else
{
isSuccess = false;
clientsock->close();
qWarning("sock is not binded.");
delete clientsock;
clientsock = nullptr;
}
return isSuccess;
}
bool DLink::setup_multicast_recieve(const QHostAddress &ip, const quint16 &port, QHostAddress newip, quint16 newport)
{
bool isSuccess = false;
foreach (clientNode node, sockets) {
if(node.sock)
{
if((node.addr == QHostAddress(ip))&&(node.port == port))
{
if(node.sock->isOpen())
{
if(node.sock->state() != QAbstractSocket::UnconnectedState)
{
node.sock->leaveMulticastGroup(node.addr);
}
node.sock->disconnectFromHost();
node.sock->close();
}
//断掉所有的连接
disconnect(node.sock,nullptr,nullptr,nullptr);
node.sock->deleteLater();
sockets.removeAt(sockets.indexOf(node));
}
}
}
QHostAddress m_ip = ip;
quint16 m_port = port;
if((newip != QHostAddress("0,0,0,0")) &&
(newport != 0))
{
m_ip = newip;
m_port = newport;
}
QUdpSocket *clientsock = new QUdpSocket(this);
clientsock->setProxy(QNetworkProxy::DefaultProxy);//必须先设置不代理,否则连不上
//clientsock->open(QIODevice::ReadWrite);
if(clientsock->bind(QHostAddress::AnyIPv4,m_port,QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint))//
{
if (clientsock->joinMulticastGroup(QHostAddress(m_ip)))
{
// clientsock->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption,1024*1024*100);
clientsock->setSocketOption (QAbstractSocket::ReceiveBufferSizeSocketOption, 1024*1024*100);
clientsock->setSocketOption(QAbstractSocket::LowDelayOption, 1);
clientsock->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
//clientsock->setSocketOption(QAbstractSocket::MulticastTtlOption, 10);
//clientsock->setSocketOption(QAbstractSocket::MulticastLoopbackOption, 0);//禁止本机接收
clientNode node;
node.sock = clientsock;
node.addr = m_ip;
node.port = m_port;
node.type = devtype::datalink;
sockets.append(node);
qWarning() << "multicast open recieve:"
<< node.addr
<< node.port;
isSuccess = true;
connect(clientsock, SIGNAL(readyRead()),
this, SLOT(readPendingDatagramsClient()));
emit showMessage(tr("Bind and join the multicast group"),10000);
}
else
{
clientsock->close();
isSuccess = false;
qWarning() << "sock open failure" << clientsock->state();
delete clientsock;
clientsock = nullptr;
emit showMessage(tr("Fail to join multicast group."),10000);
}
}
else
{
isSuccess = false;
clientsock->close();
qWarning("sock is not binded.");
delete clientsock;
clientsock = nullptr;
emit showMessage(tr("Fail to bind multicast socket."),10000);
}
return isSuccess;
}
bool DLink::setup_multicast_transmit(const QHostAddress &ip,const quint16 &port, QHostAddress newip, quint16 newport)
{
bool isSuccess = false;
foreach (clientNode node, sockets) {
if(node.sock)
{
if((node.addr == QHostAddress(ip))&&(node.port == port))
{
if(node.sock->isOpen())
{
if(node.sock->state() != QAbstractSocket::UnconnectedState)
{
node.sock->leaveMulticastGroup(node.addr);
}
node.sock->disconnectFromHost();
node.sock->close();
}
//断掉所有的连接
disconnect(node.sock,nullptr,nullptr,nullptr);
node.sock->deleteLater();
sockets.removeAt(sockets.indexOf(node));
}
}
}
QHostAddress m_ip = ip;
quint16 m_port = port;
if((newip != QHostAddress("0,0,0,0")) &&
(newport != 0))
{
m_ip = newip;
m_port = newport;
}
QUdpSocket *clientsock = new QUdpSocket(this);
clientsock->setProxy(QNetworkProxy::DefaultProxy);//必须先设置不代理,否则连不上
clientsock->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption,1024);
//clientsock->setSocketOption (QAbstractSocket::ReceiveBufferSizeSocketOption, 1024*1024*100);
clientsock->setSocketOption(QAbstractSocket::LowDelayOption, 1);
clientsock->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
clientNode node;
node.sock = clientsock;
node.addr = m_ip;
node.port = m_port;
node.type = devtype::datalink;
sockets.append(node);
qWarning() << "multicast open transmit:"
<< node.addr
<< node.port;
isSuccess = true;
emit showMessage(tr("Bind and join the multicast group"),10000);
return isSuccess;
}
bool DLink::setup_multicast_close(const QHostAddress &ip,const quint16 &port)
{
bool isSuccess = false;
foreach (clientNode node, sockets) {
if(node.sock)
{
if((node.addr == QHostAddress(ip))&&(node.port == port))
{
if(node.sock->isOpen())
{
node.sock->close();//先关闭再退出
node.sock->leaveMulticastGroup(node.addr);
}
//断掉所有的连接
disconnect(node.sock,nullptr,nullptr,nullptr);
node.sock->deleteLater();
sockets.removeAt(sockets.indexOf(node));
qWarning() << "multicast delete:"
<< node.addr
<< node.port;
isSuccess = true;
}
}
}
return isSuccess;
}
void DLink::readPendingDatagramsSerialPort(void)
{
//QElapsedTimer time;
//time.start();
QObject *obj = sender();
if(obj)
{
QSerialPort *serialport = qobject_cast<QSerialPort *>(obj);
if(serialport)
{
QByteArray datagram = serialport->readAll();
//inCount += datagram.size();
foreach (serialNode node, serials) {
if(node.port)
{
if(node.port == serialport)
{
emit recieve(node.name,datagram);
node.in.count += datagram.size();
node.in.frame +=1;
serials.replace(serials.indexOf(node),node);
break;
}
}
}
}
}
//qDebug() << "dlink recieve time:" << time.nsecsElapsed() / 1000000.0 ;
}
void DLink::readPendingDatagramsClient(void)
{
//QElapsedTimer time;
//time.start();
QObject *obj = sender();
if(obj)
{
QUdpSocket *clientsock = qobject_cast<QUdpSocket *>(obj);
if(clientsock)
{
//QUdpSocket::readChannelFinished()
while (clientsock->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(clientsock->pendingDatagramSize());
QHostAddress address;//ip
quint16 port;//端口号
clientsock->readDatagram(datagram.data(), datagram.size(),&address,&port);
//emit recieve(address,port,datagram);
foreach (clientNode node, sockets) {
if(node.sock)
{
if(node.sock == clientsock)
{
emit recieve(node.addr,node.port,datagram);
//qDebug() << "dlink" << QThread::currentThread();
node.in.count += datagram.size();
node.in.frame +=1;
sockets.replace(sockets.indexOf(node),node);
break;
}
}
}
}
}
}
//qDebug() << "dlink recieve time:" << time.nsecsElapsed() / 1000000.0 ;
}