A142_Desktop/modbusoverudp.cpp

536 lines
13 KiB
C++
Raw Normal View History

2023-11-28 16:56:30 +03:00
#include "modbusoverudp.h"
ModbusOverUdp::ModbusOverUdp(QObject *parent) : QObject(parent)
2023-11-30 12:58:49 +03:00
{timer= new QTimer();
2023-12-19 15:15:10 +03:00
timer->setInterval(300);
2023-11-30 12:58:49 +03:00
connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));
timer->start();
}
void ModbusOverUdp::timeout()
2023-12-19 15:15:10 +03:00
{static int count;
if(!isConnected) count=0;
2023-11-30 12:58:49 +03:00
if(isConnected){//запросы по всем фронтам
2023-12-19 15:15:10 +03:00
/*
2023-11-30 12:58:49 +03:00
for(quint16 i=1; i<=4; i++){
req(i,SENS);
req(i,STATE);
2023-12-19 15:15:10 +03:00
}
*/
2023-11-30 12:58:49 +03:00
2023-12-19 15:15:10 +03:00
if(count<4)count++;
else count=1;
req(count,SENS);
req(count,STATE);
2023-11-30 12:58:49 +03:00
2023-12-19 15:15:10 +03:00
}
2023-11-30 12:58:49 +03:00
}
uint16_t ModbusOverUdp::Crc16(uint16_t len, uint16_t iobuf[]) //CRC для сообщения такой то длинны /Len - начало контрольной сумимы
{
uint16_t i;
uint16_t crc = 0xFFFF;
for(i = 0; i < len; i++) {
crc = (crc >> 8) ^ Crc16Table[(crc & 0xFF) ^ (iobuf[i]& 0xFF)];
}
return crc;
}
uint16_t ModbusOverUdp::Crc16(uint16_t len, QByteArray iobuf) //CRC для сообщения такой то длинны /Len - начало контрольной сумимы
2023-11-28 16:56:30 +03:00
{
2023-12-19 15:15:10 +03:00
if(iobuf.size()>len +2){qDebug()<<"немного великоват"; return 0;}
if(iobuf.size()==0){qDebug()<<"нулевой размер массива";}
if(len==0){qDebug()<<"нулевая длинна";}
2023-11-30 12:58:49 +03:00
uint16_t crc = 0xFFFF;
2023-12-19 15:15:10 +03:00
try{
2023-11-30 12:58:49 +03:00
2023-12-19 15:15:10 +03:00
for(uint16_t i = 0; i < len; i++) {
if(iobuf.size()<i){qDebug()<<"немного великоват"; return 0;};
crc = (crc >> 8) ^ Crc16Table[(crc & 0xFF) ^ (iobuf.at(i) & 0xFF)]; // ввел маску 0xFF, тк прилетает 0хFFFFFFxx
}
}
catch(const char* error_message){
qDebug()<<error_message;
2023-11-30 12:58:49 +03:00
}
2023-12-19 15:15:10 +03:00
2023-11-30 12:58:49 +03:00
return crc;
2023-12-19 15:15:10 +03:00
2023-11-30 12:58:49 +03:00
}
void ModbusOverUdp::readPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QNetworkDatagram datagram = udpSocket->receiveDatagram();
2023-12-19 15:15:10 +03:00
QByteArray recived = datagram.data(); // копируем датаграмку в аррэй для удобной работы
2023-12-19 15:15:10 +03:00
qDebug()<<"прибыл размером"<<recived.size();
if (recived.size()<5){
qDebug()<<"маленький пакет"; return;
};
if (!(recived.size()==recived[2]+5)){
qDebug()<<"не попал в размер"; return;
};
int indNachalaCrc = recived[2]+3;
2023-12-19 15:15:10 +03:00
uint16_t crcRecived = Crc16(indNachalaCrc, recived); // в функции используют больше или меньше
2023-12-19 15:15:10 +03:00
if((recived[indNachalaCrc]&0xFF)==LO(crcRecived)&&(recived[indNachalaCrc+1]&0xFF)==HI(crcRecived)){ //todo внимание костыль
2023-12-19 15:15:10 +03:00
// qDebug()<<"CRC Ок "; //это работает слишком часто
}else{
2023-12-19 15:15:10 +03:00
qDebug()<<"CRC не катит ожидалось"<<(recived[indNachalaCrc]&0xFF)<<(recived[indNachalaCrc+1]&0xFF)<<"пришло"<<HI(crcRecived)<<LO(crcRecived);
return;
}
2023-12-19 15:15:10 +03:00
processTheDatagram(datagram);
2023-11-30 12:58:49 +03:00
}
}
void ModbusOverUdp::processTheDatagram(QNetworkDatagram & datagram)
{
QByteArray recived = datagram.data(); // копируем датаграмку в аррэй для удобной работы
2023-11-30 12:58:49 +03:00
Set toSend; //структура для отправки в другой компонент
sfloat res; //флоат для сборки из пакета модбас
toSend.channel=(typeCHANNEL)(recived[0]-1); //Ch1 = 0 - в енаме
switch (recived.size()){ // пришла чувствительность
case 9: {
2023-11-30 12:58:49 +03:00
//посчитать контрольные суммы
// и добавить кучу проверок на хорошие значения
2023-11-30 12:58:49 +03:00
res.ch[3]=recived[3]; // Собираю флоат
res.ch[2]=recived[4];
res.ch[1]=recived[5];
res.ch[0]=recived[6];
//qDebug() <<"Чувствительность для модбас адреса"<<toSend.channel+1 <<res.fl;
toSend.SENS= res.fl;
emit sensRecive(toSend);
break;
}
2023-11-30 12:58:49 +03:00
case 25:
//qDebug() <<"Подвалило состояние для модбас адреса"<<toSend.channel+1;
//посчитать контрольные суммы
// и добавить кучу проверок на хорошие значения
if((int)recived[4]>2) return;
if((int)recived[6]>5) return;
if((int)recived[8]>7) return;
if((int)recived[10]>12) return;
2023-12-19 15:15:10 +03:00
if((int)recived[22]>7) return;
2023-11-28 16:56:30 +03:00
2023-11-30 12:58:49 +03:00
toSend.IIN=(typeIIN)(recived[4]-0);
toSend.IFV=(typeIFV)(recived[6]-0);
toSend.IFN=(typeIFN)(recived[8]-0);
toSend.IKU=(typeIKU)(recived[10]-0);
toSend.VALUE=(typeVALUE)(recived[22]-0);
2023-11-30 12:58:49 +03:00
emit stateRecive(toSend);
break;
default:
2023-11-30 12:58:49 +03:00
qDebug()<<recived;
2023-11-30 12:58:49 +03:00
break;
}
}
void ModbusOverUdp::connectTo(QString ipAdress, quint16 port)
{
udpSocket = new QUdpSocket(this);
targetIp =QHostAddress(ipAdress);
targetPort=port;
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
isConnected=1;
}
void ModbusOverUdp::disconnectFrom()
{
delete udpSocket;
2023-11-30 12:58:49 +03:00
isConnected=0;
disconnect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
}
void ModbusOverUdp::set(Set setWithState, typeREQ TYPEREQ)
{QByteArray data;
switch (TYPEREQ)
{
case SENS:{
data.resize(13);
data[0]=(uint16_t)setWithState.channel+1;
data[1]=0x10;
data[2]=0x1D;
data[3]=0x4E;
data[4]=0x00;
data[5]=0x1; //1- регистр 32 бит 7502
data[6]=0x4;
usfloat res;
res.fl=setWithState.SENS;
data[7]=res.ch[3]&0xFF; // Собираю флоат
data[8]=res.ch[2]&0xFF;
data[9]=res.ch[1]&0xFF;
data[10]=res.ch[0]&0xFF;
uint16_t crcToSend= Crc16((uint16_t)11, data);
data[11]=(LO(crcToSend)&0xFF);
data[12]=(HI(crcToSend)&0xFF);
break;
}
/*
* // c этими регистрами работает после перезагрузки
data[0]=(uint16_t)setWithState.channel+1;
data[1]=0x10;
data[2]=0x1B;
data[3]=0x5C;
data[4]=0x00;
data[5]=0x2;
data[6]=0x4;
usfloat res;
res.fl=setWithState.SENS;
data[7]=res.ch[3]&0xFF; // Собираю флоат
data[8]=res.ch[2]&0xFF;
data[9]=res.ch[1]&0xFF;
data[10]=res.ch[0]&0xFF;
*/
case STATE:{
qDebug()<<"Установка state";
data.resize(29);
data[0]=(uint16_t)setWithState.channel+1;
data[1]=0x10;
data[2]=0x13;
data[3]=0x89;
data[4]=0x00;
data[5]=0xa;// 10 регистров
data[6]=0x14;// фпропусил размер пакета
data[7]=0x00;
data[8]=(uint16_t)setWithState.IIN;// 5001
data[9]=0x00;
data[10]=(uint16_t)setWithState.IFV;// 5002
data[11]=0x00;
data[12]=(uint16_t)setWithState.IFN;// 5003
data[13]=0x00;
data[14]=(uint16_t)setWithState.IKU;;// 5004
data[15]=0x00;
data[16]=0x01;// 5005
data[17]=0x00;
data[18]=0x01;// 5006
data[19]=0x00;
data[20]=0x01;// 5007
data[21]=0x00;
data[22]=0x01;// 5008
data[23]=0x00;
data[24]=0x01;// 5009
data[25]=0x00;
data[26]=(uint16_t)setWithState.VALUE;// 5010
uint16_t crcToSend= Crc16((uint16_t)27, data);
data[27]=LO(crcToSend);
data[28]=HI(crcToSend);
break;
}
case IIN:{
qDebug()<<"Установка iin";
data.resize(11);
data[0]=(uint16_t)setWithState.channel+1;
data[1]=0x10;
data[2]=0x13; //5001
data[3]=0x89;
data[4]=0x00;
data[5]=0x1;// 1 регистров
data[6]=0x2;// байта
data[7]=0x00;
data[8]=(uint16_t)setWithState.IIN;// 5001
uint16_t crcToSend= Crc16((uint16_t)9, data);
data[9]=LO(crcToSend);
data[10]=HI(crcToSend);
break;
}
case IFV:{
qDebug()<<"Установка IVF";
data.resize(11);
data[0]=(uint16_t)setWithState.channel+1;
data[1]=0x10;
data[2]=0x13;
data[3]=0x8a;
data[4]=0x00;
data[5]=0x1;// 1 регистров
data[6]=0x2;// байта
data[7]=0x00;
data[8]=(uint16_t)setWithState.IFV;// 5002
uint16_t crcToSend= Crc16((uint16_t)9, data);
data[9]=LO(crcToSend);
data[10]=HI(crcToSend);
break;
}
case IFN:{
qDebug()<<"Установка IVN";
data.resize(11);
data[0]=(uint16_t)setWithState.channel+1;
data[1]=0x10;
data[2]=0x13;
data[3]=0x8b; //5003
data[4]=0x00;
data[5]=0x1;// 1 регистров
data[6]=0x2;// байта
data[7]=0x00;
data[8]=(uint16_t)setWithState.IFN;// 5003
uint16_t crcToSend= Crc16((uint16_t)9, data);
data[9]=LO(crcToSend);
data[10]=HI(crcToSend);
break;
}
case IKU:{
qDebug()<<"Установка IKU"<<(uint16_t)setWithState.IKU<<"в канал"<<(uint16_t)setWithState.channel+1;
data.resize(11);
data[0]=(uint16_t)setWithState.channel+1;
data[1]=0x10;
data[2]=0x13;
data[3]=0x8c; //5004
data[4]=0x00;
data[5]=0x1;// 1 регистров
data[6]=0x2;// байта
data[7]=0x00;
data[8]=(uint16_t)setWithState.IKU;// 5004
uint16_t crcToSend= Crc16((uint16_t)9, data);
data[9]=LO(crcToSend);
data[10]=HI(crcToSend);
break;
}
case VAL:{
qDebug()<<"Запрос Val";
data.resize(11);
data[0]=(uint16_t)setWithState.channel+1;
data[1]=0x10;
data[2]=0x13;//5010
data[3]=0x92;
data[4]=0x00;
data[5]=0x1;// 1 регистров
data[6]=0x2;// байта
data[7]=0x00;
data[8]=(uint16_t)setWithState.VALUE;// 5010
uint16_t crcToSend= Crc16((uint16_t)9, data);
data[9]=LO(crcToSend);
data[10]=HI(crcToSend);
break;
}
}//end switch
qDebug()<<"поясняю прибору"<<data.toHex();
sendPendingDatagrams(data);
2023-11-30 12:58:49 +03:00
}
2023-11-30 12:58:49 +03:00
void ModbusOverUdp::req(quint16 adr, typeREQ TYPEREQ)
{
QByteArray data;
switch (TYPEREQ)
{
case SENS:{
data.resize(8);
data[0]=adr;
data[1]=0x3;
data[2]=0x1b;
data[3]=0x5c;
data[4]=0x00;
data[5]=0x2;
uint16_t crcToSend= Crc16((uint16_t)6, data);
data[6]=LO(crcToSend);
data[7]=HI(crcToSend);
break;
}
case STATE:{
data.resize(8);
data[0]=adr;
data[1]=0x3;
data[2]=0x13;
data[3]=0x89;
data[4]=0x00;
data[5]=0xa;
uint16_t crcToSend= Crc16((uint16_t)6, data);
data[6]=LO(crcToSend);
data[7]=HI(crcToSend);
break;
}
}
sendPendingDatagrams(data);
}
void ModbusOverUdp::changeIp(QString oldIp, QString newIp)
{
qDebug()<<"НАчинаем смену Ip";
udpSocket = new QUdpSocket(this);
// udpSocket->bind(QHostAddress::LocalHost,8000,QAbstractSocket::DontShareAddress);
targetIp =QHostAddress(oldIp);
targetPort=7000;
// QUdpSocket *udpSocketForRecive= new QUdpSocket(this);
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
QStringList ip= newIp.split(".");
qDebug()<<ip;
uint16_t ip0= ip.at(0).toInt();
uint16_t ip1= ip.at(1).toInt();
uint16_t ip2= ip.at(2).toInt();
uint16_t ip3= ip.at(3).toInt();
qDebug()<<ip0;
qDebug()<<ip1;
qDebug()<<ip2;
qDebug()<<ip3;
QByteArray data;
data.resize(13);
data[0]=0x11; //наверное прокатит
data[1]=0x10;//команда на запись
data[2]=0x0f; //4001
data[3]=0xa1; //4001
data[4]=0x00;
data[5]=0x2; //2 колличество регистров
data[6]=0x4; //4 байта
data[7]=ip0;
data[8]=ip1;
data[9]=ip2;
data[10]=ip3;
uint16_t crcToSend= Crc16((uint16_t)11, data);
data[11]=(LO(crcToSend)&0xFF);
data[12]=(HI(crcToSend)&0xFF);
QNetworkDatagram datagram;
datagram.setDestination(targetIp,targetPort);
datagram.setData(data);
// qDebug()<<"sended"<<datagram.data();
udpSocket->writeDatagram(datagram);
udpSocket->waitForBytesWritten(50);
}
2023-11-30 12:58:49 +03:00
void ModbusOverUdp::testReq()
{
QByteArray data;
data.resize(8);
data[0]=0x1;
data[1]=0x3;
data[2]=0x13;
data[3]=0x89;
data[4]=0x00;
data[5]=0x4;
uint16_t crcToSend= Crc16((uint16_t)6, data);
data[6]=LO(crcToSend);
data[7]=HI(crcToSend);
sendPendingDatagrams(data);
}
void ModbusOverUdp::sendPendingDatagrams( QByteArray & data )
{
QNetworkDatagram datagram;
datagram.setDestination(targetIp,targetPort);
datagram.setData(data);
// qDebug()<<"sended"<<datagram.data();
udpSocket->writeDatagram(datagram);
}