做这个项目的时候从网上搜了很久没有相关的资料,目前数据显示没有问题,在此进行简单的分享。
首先需要了解:
数据包:总长度659字节,主要内容为645协议数据(长度211字节),其余为外部封装以及数据填充。
如何获取文件:MCU侧主动发起请求获取电能表数据,收到数据后通过232发送到Linux侧,Linux侧进行封装保存,3秒一次。以小时为单位保存到某一个文件中(2023072014.dat:7月20日14点的数据),此文件名保存到.txt文件中,(txt文件中的文件名只有一个即当前小时的文件名)。
实时数据:从文件的末尾截取最后一包进行分析
显示数据:定时器加lcd显示
展示
初始化并开始定时获取二进制数据
void Widget::initFile()
{
int a = 0;
QFile file("./indicate.txt");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug()<<"open failed";
return;
}
QTextStream txtInput(&file);
QString lineStr;
while(!txtInput.atEnd())
{
lineStr = txtInput.readLine();
QStringList filenameList = lineStr.split(" ");
filename = filenameList[0];
qDebug()<<filename;
}
file.close();
a = fileFunc(filename,659,659,PATH1);
if (a)
{
a = fileFunc(PATH1,211,659,PATH2);
if (a)
{
parseFunc();
}
}
}
void Widget::initTimer()
{
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(initFile()));
timer->start(3200);
}
文件获取函数:
int Widget::fileFunc(QString filename1, int size, int num, QString filename2)
{
char tmp[size];
memset(tmp,0,size*sizeof(char));
QString filename = filename1;
QFile useFile(filename);
if(!(useFile.open(QIODevice::ReadOnly)))
{
qDebug()<<"error!!!!!";
return -1;
}
QByteArray ewsArr = useFile.readAll();
int postion = useFile.pos();
useFile.seek(postion-num);
QDataStream in(&useFile);
in.readRawData(tmp,sizeof(char)*size);
QString outPath1 = filename2;
QFile outFile1(outPath1);
if(!outFile1.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
qDebug()<<"error one!!!";
return -1;
}
QDataStream out1(&outFile1);
out1.writeRawData(tmp,sizeof(char)*size);
outFile1.close();
useFile.close();
return 1;
}
数据解析:对645协议需要进行研究,目前只分析电流电压值
void Widget::parseFunc()
{
char tmp[195];
memset(tmp,0,195*sizeof(char));
QString filename = PATH2;
QFile useFile(filename);
if(!(useFile.open(QIODevice::ReadOnly)))
{
qDebug()<<"error!!!!!";
return;
}
useFile.seek(16);
QDataStream in(&useFile);
in.readRawData(tmp,sizeof(char)*195);
int a = 8;
for(int q = 0; q < 8; q++)
{
if ("91" == (QString().asprintf("%X",(unsigned char)tmp[a])))
{
a += 1;
if(("33" == (QString().asprintf("%X",(unsigned char)tmp[a+1]))) && ("32" == (QString().asprintf("%X",(unsigned char)tmp[a+2]))) && ("34" == (QString().asprintf("%X",(unsigned char)tmp[a+3])) && ("35" == (QString().asprintf("%X",(unsigned char)tmp[a+4])))))
{
while("16" != (QString().asprintf("%X",(unsigned char)tmp[a])))
{
a += 1;
}
a = a - 2;
U_data[0][0] = tmp[a];
U_data[0][1] = tmp[a-1];
U_data[1][0] = tmp[a-2];
U_data[1][1] = tmp[a-3];
U_data[2][0] = tmp[a-4];
U_data[2][1] = tmp[a-5];
a += 11;
}else if(("33" == (QString().asprintf("%X",(unsigned char)tmp[a+1]))) && ("32" == (QString().asprintf("%X",(unsigned char)tmp[a+2]))) && ("35" == (QString().asprintf("%X",(unsigned char)tmp[a+3])) && ("35" == (QString().asprintf("%X",(unsigned char)tmp[a+4])))))
{
while("16" != (QString().asprintf("%X",(unsigned char)tmp[a])))
{
a += 1;
}
a = a - 2;
I_data[0][0] = tmp[a];
I_data[0][1] = tmp[a-1];
I_data[0][2] = tmp[a-2];
I_data[1][0] = tmp[a-3];
I_data[1][1] = tmp[a-4];
I_data[1][2] = tmp[a-5];
I_data[2][0] = tmp[a-6];
I_data[2][1] = tmp[a-7];
I_data[2][2] = tmp[a-8];
a += 11; //Numbers before 16 and between 68 and 68
}
}
}
useFile.close();
displayFunc();
}
显示需要进行数据类型转换:
bool ok;
QString U_tmp[3][2];
QString I_tmp[3][3];
QString result_U[3];
QString result_I[3];
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 2; j++)
{
int num = QString().asprintf("%X",(unsigned char)U_data[i][j]).toInt(&ok, 16);
num = num - 51;
U_tmp[i][j] = QString().asprintf("%X",num);
}
int change_num =U_tmp[i][0].toInt(&ok, 16);
int change_num1 =U_tmp[i][1].toInt(&ok, 16);
if(change_num1 < 10)
{
change_num = change_num << 4;
U_tmp[i][0] = QString().asprintf("%X",change_num);
}
result_U[i].append(U_tmp[i][0]).append(U_tmp[i][1]);
int change_result = result_U[i].toInt(&ok, 16);
if(51 < change_result)
{
U[i] = result_U[i].toInt(nullptr,10);
}
else
{
U[i] = 1234;
}
}
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
int num = QString().asprintf("%X",(unsigned char)I_data[i][j]).toInt(&ok, 16);
num = num - 51;
I_tmp[i][j] = QString().asprintf("%X",num);
}
result_I[i].append(I_tmp[i][0]).append(I_tmp[i][1]).append(I_tmp[i][2]);
I[i] = result_I[i].toInt(nullptr,10);
}
real_time_display();
实时显示:
plcd_I1->display(I[2] * 0.001);
plcd_I2->display(I[1] * 0.001);
plcd_I3->display(I[0] * 0.001);
plcd_U1->display(U[2] * 0.1);
plcd_U2->display(U[1] * 0.1);
plcd_U3->display(U[0] * 0.1);
整包资源可直接下载执行。
需要在Ubuntu下打开,QStreamData在Windows下有增加数据字节的现象,有兴趣的可以自行查阅。