697 lines
19 KiB
C++
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 ;
|
|
}
|
|
|
|
|