SXXXXXXX_PyBusMonitor1553/cpp/GrifoScope/GrifoXLruMonitor/portbridge.cpp
2025-12-17 07:59:30 +01:00

441 lines
10 KiB
C++

#include "portbridge.h"
#include <QVector>
#include <QDebug>
#include <QNetworkDatagram>
#include "xlru_serial_over_udp.h"
#include <QLinkedList>
#include <QTimer>
class MyFifo: public QLinkedList<char>
{
public:
bool pending() const
{
return size()>0;
}
char pop()
{
char c=this->first();
this->pop_front();
return c;
}
void push(const char* d, unsigned int len)
{
for(unsigned int i=0; i<len; ++i)
{
this->push_back(d[i]);
}
}
};
class PortBridge::Implementation
{
public:
QVector<PortBridgeForwarder*> forwarder;
unsigned long forwardIn;
unsigned long forwardOut;
LruSerialFilter* masterFilter;
QVector<LruSerialPort*> udpForward;
QVector<bool> udpSlow;
xlru::xlru_udp_slave_t slave_pkt;
QHostAddress slave_address;
unsigned short slave_port;
unsigned int udpIn;
unsigned int udpOut;
XlruLogClass* XlruLog;
};
PortBridge::PortBridge(QObject *parent):
QObject(parent),
forwardDisabled(false),
p_(*new Implementation),
s(0)
{
p_.forwardOut=0;
p_.forwardIn=0;
p_.udpIn=0;
p_.udpOut=0;
p_.masterFilter=0;
udpEnabled=true;
p_.XlruLog = new XlruLogClass();
p_.XlruLog->generateNewFile("SERIAL");
}
void PortBridge::close()
{
foreach(PortBridgeForwarder* f, p_.forwarder)
{
f->disconnect();
delete f;
}
this->disconnect();
}
void PortBridge::setMasterFilter(LruSerialFilter* f)
{
p_.masterFilter=f;
}
void PortBridge::setSocket(QUdpSocket * sk, unsigned int port)
{
s=sk;
connect(s, &QUdpSocket::readyRead, this, &PortBridge::udpReadyRead);
if (port==0)
{
port=51010;
}
p_.slave_port=port;
unsigned long broadcast=s->localAddress().toIPv4Address();
broadcast|=0x00FF;
p_.slave_address=QHostAddress(broadcast);
}
void PortBridge::udpEnable(bool enable)
{
udpEnabled=enable;
}
void PortBridge::addUdpBridge(LruSerialPort *s0, bool slaveSlow)
{
p_.udpSlow.append(slaveSlow);
p_.udpForward.append(s0);
//connect(&s0->realPort, &QSerialPort::readyRead, this, &PortBridge::serialUdpReadyRead);
//connect(s0, &LruSerialPort::readyRead, this, &PortBridge::serialUdpReadyRead);
}
void PortBridge::udpReadyRead()
{
uint32_t dst=0;
QHostAddress srcHost;
//int srcPort=0;
while(s->hasPendingDatagrams())
{
QNetworkDatagram d=s->receiveDatagram();
if (!udpEnabled)
continue;
//unsigned int size=d.data().size();
const xlru::xlru_udp_master_t& pkt=*reinterpret_cast<const xlru::xlru_udp_master_t*>(d.data().constData());
if (pkt.marker==xlru::xlru_udp_master_t::k_marker)
{
srcHost=d.senderAddress();
dst=d.destinationAddress().toIPv4Address();
//srcPort=d.destinationPort();
//unsigned int total_size=pkt.payload_size;
p_.udpIn+=pkt.payload_size;
QByteArray data((const char*)pkt.payload, pkt.payload_size);
qDebug()<<"UDPIN"<<dst<<data;
p_.XlruLog->saveString(QString(data));
if (p_.masterFilter)
p_.masterFilter->processMessages(data, 0);
}
}
#if 0
qDebug()<<"UDPIN"<<dst<<srcHost;
if (dst==0)
{
static xlru::xlru_udp_slave_t reply;
reply.marker=xlru::xlru_udp_slave_t::k_marker;
reply.override_enable_mask=0;
reply.payload_size=0;
s->writeDatagram((const char*)&reply, sizeof reply, srcHost, srcPort);
}
#endif
}
unsigned int PortBridge::udpCharOut()
{
return p_.udpOut;
}
unsigned int PortBridge::udpCharIn()
{
return p_.udpIn;
}
void PortBridge::serialUdpReadyRead()
{
xlru::xlru_udp_slave_t& pkt=p_.slave_pkt;
pkt.marker=xlru::xlru_udp_slave_t::k_marker;
pkt.override_enable_mask=0;
xlru::xlru_udp_data_t* d=reinterpret_cast<xlru::xlru_udp_data_t*>(pkt.payload);
LruSerialPort* s0=qobject_cast<LruSerialPort*>(sender());
if (!s0)
return;
for(;;)
{
QByteArray data=s0->readData();
int size=data.size();
p_.forwardIn+=size;
if (size)// && !fDisable)
{
qDebug()<<"MASTER IN:"<<s0->portName()<<data;
p_.XlruLog->saveString(QString(data));
unsigned int current_size=d->len;
if ((current_size+size)<900)
{
d->source=1;
memcpy(&d->data[d->len], data.constData(), size);
d->len+=size;
}
}
else
break;
}
if (d->len)
s->writeDatagram(reinterpret_cast<const char*>(&pkt), sizeof pkt, p_.slave_address, p_.slave_port);
}
void PortBridge::addBridge(LruSerialPort* s0, LruSerialPort* s1, bool slaveSlow)
{
PortBridgeForwarder* fw=0;
foreach (PortBridgeForwarder* i, p_.forwarder)
{
if (i->masterPort==s1)
{
fw=i;
break;
}
}
if (fw==0)
{
qDebug()<<"New Forwarder:"<<s0->portName()<<"z->"<<s1->portName();
fw=new PortBridgeForwarder;
fw->portBridge=this;
fw->setMaster(s1);
fw->addSlave(s0, slaveSlow);
p_.forwarder.append(fw);
return; //fw->controlWidget();
}
else
{
qDebug()<<"Add Slave:"<<s0->portName()<<"<->"<<fw->masterPort->portName();
fw->portBridge=this;
fw->addSlave(s0, slaveSlow);
return;
}
}
void PortBridge::forwardCount(int inbytes, int outbytes)
{
p_.forwardIn+=inbytes;
p_.forwardOut+=outbytes;
}
void PortBridge::getForwardCounter(int& in, int& out)
{
in=p_.forwardIn;
out=p_.forwardOut;
}
class PortBridgeForwarder::Implementation
{
public:
QVector<MyFifo> slowFifo;
QTimer slowTimer;
QByteArray masterMsg;
QVector<QByteArray> slavesMsg;
XlruLogClass* XlruLog;
};
PortBridgeForwarder::PortBridgeForwarder(QObject *parent):
QObject(parent),
p_(*new Implementation)
{
connect(&p_.slowTimer, &QTimer::timeout, this, &PortBridgeForwarder::slowTimeout);
p_.slowTimer.setSingleShot(true);
p_.masterMsg.reserve(256);
p_.XlruLog = new XlruLogClass();
p_.XlruLog->generateNewFile("SERIAL");
}
void PortBridgeForwarder::setMaster(LruSerialPort* master)
{
masterPort=master;
//connect(&master->realPort, &QSerialPort::readyRead, this, &PortBridgeForwarder::serialForwardToSlaves);
connect(master, &LruSerialPort::readyRead, this, &PortBridgeForwarder::serialForwardToSlaves);
}
void PortBridgeForwarder::addSlave(LruSerialPort* slave, bool slaveSlow)
{
slavePort.append(slave);
slaveSlowFlags.append(slaveSlow);
p_.slowFifo.append(MyFifo());
p_.slavesMsg.append(QByteArray());
//connect(&slave->realPort, &QSerialPort::readyRead, this, &PortBridgeForwarder::serialForwardToMaster);
connect(slave, &LruSerialPort::readyRead, this, &PortBridgeForwarder::serialForwardToMaster);
}
void PortBridgeForwarder::slowTimeout()
{
bool pending=false;
for(int i=0; i<p_.slowFifo.size(); ++i)
{
MyFifo& fifo=p_.slowFifo[i];
if (fifo.size())
{
pending=true;
char c=fifo.first();
fifo.pop_front();
if (c)
slavePort[i]->writeChar(c); //write(&c, 1);
}
}
if (pending)
p_.slowTimer.start(10);
}
void PortBridgeForwarder::serialForwardToSlaves()
{
int total_in=0;
int total_out=0;
LruSerialPort* s0=masterPort;
if (!s0)
return;
int n=slavePort.size();
bool fDisable=portBridge->forwardDisabled;
bool slowPushed=false;
for(;;)
{
QByteArray data=s0->readData();
int size=data.size();
total_in+=size;
if (size && !fDisable)
{
//qDebug()<<"MASTER IN:"<<s0->portName()<<data;
p_.masterMsg.append(data);
if ((p_.masterMsg.size()>80) || data.contains('\r'))
{
qDebug()<<"MASTER IN:"<<masterPort->portName()<<p_.masterMsg;
p_.XlruLog->saveString(QString(p_.masterMsg));
p_.masterMsg.resize(0);
}
for(int i=0; i<n; ++i)
{
LruSerialPort* slave=slavePort[i];
qint64 written=0;
qDebug()<<"Slave forward:"<<slave->portName();
//scrive su tutte le com in slave la stringa ricevuta
if (slaveSlowFlags[i])
{
//qDebug()<<"slow send";
const char* d=data.constData();
p_.slowFifo[i].push(d, size);
slowPushed=true;
#if 0
for(int n=0; n<size; ++n)
{
slave->write(&d[n], 1);
slave->flush();
}
#endif
}
else
written=slave->write(data);
if (written>=0)
total_out+=written;
}
}
else
break;
}
for(int i=0; i<n; ++i)
{
LruSerialPort* slave=slavePort[i];
slave->flush();
}
if (slowPushed)
{
if (!p_.slowTimer.isActive())
p_.slowTimer.start(10);
}
portBridge->forwardCount(total_in, total_out);
}
void PortBridgeForwarder::serialForwardToMaster()
{
int total_in=0;
int total_out=0;
bool fDisale=portBridge->forwardDisabled;
LruSerialPort* s0=qobject_cast<LruSerialPort*>(sender());
if (!s0)
return;
for(;;)
{
QByteArray data=s0->readAll();
int size=data.size();
total_in+=size;
if (size && !fDisale)
{
#if 0
qDebug()<<"SLAVE IN:"<<s0->portName()<<data;
#else
//qDebug()<<"SLAVE IN:"<<s0->portName()<<data;
s0->tempBuffer.append(data);
if ((s0->tempBuffer.size()>80) || s0->tempBuffer.contains('\r'))
{
qDebug()<<"SLAVE IN:"<<s0->portName()<<s0->tempBuffer;
p_.XlruLog->saveString(QString(s0->tempBuffer));
//masterPort->inFilter->processMessages(msg);
s0->tempBuffer.clear();
}
#endif
masterPort->inFilter->processMessages(data, s0->unitMonitor);
qint64 written=masterPort->write(data);
if (written>=0)
{
total_out+=written;
//qDebug()<<"SLAVE OUT:"<<written<<data;
}
}
else
break;
}
masterPort->flush();
portBridge->forwardCount(total_in, total_out);
}