A142_Desktop/modbusoverudp.cpp

536 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "modbusoverudp.h"
ModbusOverUdp::ModbusOverUdp(QObject *parent) : QObject(parent)
{timer= new QTimer();
timer->setInterval(300);
connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));
timer->start();
}
void ModbusOverUdp::timeout()
{static int count;
if(!isConnected) count=0;
if(isConnected){//запросы по всем фронтам
/*
for(quint16 i=1; i<=4; i++){
req(i,SENS);
req(i,STATE);
}
*/
if(count<4)count++;
else count=1;
req(count,SENS);
req(count,STATE);
}
}
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 - начало контрольной сумимы
{
if(iobuf.size()>len +2){qDebug()<<"немного великоват"; return 0;}
if(iobuf.size()==0){qDebug()<<"нулевой размер массива";}
if(len==0){qDebug()<<"нулевая длинна";}
uint16_t crc = 0xFFFF;
try{
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;
}
return crc;
}
void ModbusOverUdp::readPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QNetworkDatagram datagram = udpSocket->receiveDatagram();
QByteArray recived = datagram.data(); // копируем датаграмку в аррэй для удобной работы
qDebug()<<"прибыл размером"<<recived.size();
if (recived.size()<5){
qDebug()<<"маленький пакет"; return;
};
if (!(recived.size()==recived[2]+5)){
qDebug()<<"не попал в размер"; return;
};
int indNachalaCrc = recived[2]+3;
uint16_t crcRecived = Crc16(indNachalaCrc, recived); // в функции используют больше или меньше
if((recived[indNachalaCrc]&0xFF)==LO(crcRecived)&&(recived[indNachalaCrc+1]&0xFF)==HI(crcRecived)){ //todo внимание костыль
// qDebug()<<"CRC Ок "; //это работает слишком часто
}else{
qDebug()<<"CRC не катит ожидалось"<<(recived[indNachalaCrc]&0xFF)<<(recived[indNachalaCrc+1]&0xFF)<<"пришло"<<HI(crcRecived)<<LO(crcRecived);
return;
}
processTheDatagram(datagram);
}
}
void ModbusOverUdp::processTheDatagram(QNetworkDatagram & datagram)
{
QByteArray recived = datagram.data(); // копируем датаграмку в аррэй для удобной работы
Set toSend; //структура для отправки в другой компонент
sfloat res; //флоат для сборки из пакета модбас
toSend.channel=(typeCHANNEL)(recived[0]-1); //Ch1 = 0 - в енаме
switch (recived.size()){ // пришла чувствительность
case 9: {
//посчитать контрольные суммы
// и добавить кучу проверок на хорошие значения
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;
}
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;
if((int)recived[22]>7) return;
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);
emit stateRecive(toSend);
break;
default:
qDebug()<<recived;
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;
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);
}
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);
}
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);
}