接受不定长协议:
程序员文章站
2022-03-07 09:33:31
...
协议头+数据长度+命令码+数据+校验码
协议头(2字节) | 数据长度(1字节) | 命令码(1字节) | 数据(N-2字节) | 校验码(1) |
---|---|---|---|---|
0x55,0xaa | 除协议头和数据长度以外的数据,N字节 | 从0x01开始 | 可以为空 | 除校验码以外的所有数据和,取低8位 |
0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
55 | aa | N | cmd | date | add |
1.命令码输液报警器->上位机
命令码 | 说明 | 数据 |
---|---|---|
0x00 | 收到上位机消息应答 | 1字节,返回收到消息的命令号 |
0x01 | 上传输液报警器的ID | 6字节, |
0x02 | 上传输液报设置号码 | 1字节 |
0x03 | 上传输液报警器设定滴速 | 1字节 |
0x04 | 上传输液报警器当前状态 | 1字节 |
0x05 | 上传输液报警器当前滴速与总滴数 | 1字节+4字节 |
0x01 ID 0代表没有ID
0x02 号码 0代表还没设号
0x03 滴速 0代表没有设置
0x04 输液报警状态
00正常 01过块 02过慢 03阻塞 04暂停 05完成 06移动 07报警08空闲
2.上位机->输液报警器
命令码 | 说明 | 数据1字节 |
---|---|---|
0x80 | 收到输液报警器消息应答 | 返回收到消息的命令号 |
0x81 | 查询输液报警器ID | |
0x82 | 查询输液报警器号码 | |
0x83 | 查询输液报警器设定滴速 | |
0x84 | 查询输液报警器当前状态 | |
0x85 | 查询输液报警器当前滴速与总滴数 | |
0x86 | 查询 |
uint8_t S_buff[255];
uint8_t len_s=0,len_temp=0;//开始与结束位置
void MainWindow::serialPortReadyRead()
{
/* 接收缓冲区中读取数据 */
uint8_t *str_buf;
uint8_t sum,temp;
int i;
uint8_t b;
char float_str[80];
QString AA="输液报警器状态:";
QString strA ,strB;
QByteArray date = serialPort->readAll();
int len=date.size();
//1.将数据放到缓存空间,计算位置
//2.从缓存空间开始位置,查到一条命令并处理命令
//3.处理完成重新计算缓存空间.
for(i=0;i<len;i++)
{
S_buff[len_s+i]= date[i];
}
len_s=len_s+i;
if(len_s<5)//说明收半包数据
{
qDebug("*半包数据*");
return;
}
for(i=0;i<len_s;i++)
{
if(i+6>len_s)//说明后面 6个数据都是存在的
{
return;
}
if(S_buff[i]==0x55&&S_buff[i+1]==0xaa)//头存在
{
uint8_t k=i;//记录开始
uint8_t m;
//去掉之前错误的数据 数据左移i
if(k!=0)
{
for(m=k;m<len_s;m++)
{
S_buff[m-k]=S_buff[m];
}
//重新计算长度
len_s=len_s-k;
i=0;//归位
}
//55 aa移动到 0位置
if((S_buff[2]+3)<=len_s)//通过数据长度判断是正包还是半包,
{//正包
sum=0;
for(uint8_t n=0; n<(S_buff[2]+2); n++)
{
sum=S_buff[n]+sum;
}
if(S_buff[S_buff[2]+2]!=sum)
{
qDebug("ble_del e -crc");//移除错误的数据
}else
{
switch(S_buff[3])
{
case 0:
break;
case 1:
for(temp=0;temp<6;temp++)
{
ID[temp]= S_buff[4+temp];
}
sprintf(float_str, "ID:%d",123456);
label2[0]->setText(float_str);
qDebug("收到ID");
break;
case 2://设置的号码
num=S_buff[4];
qDebug("设置号码");
sprintf(float_str, "输液号码:%d",num);
label2[1]->setText(float_str);
break;
case 3://设置的滴速 "ID:"<<"输液号码:"<<"设定的滴速:"<<"输液报警器状态:"<<"滴速: 总滴数:";
set_speed=S_buff[4];
qDebug("设置速度");
// receivedData_real(set_speed);
sprintf(float_str, "设定的滴速:%d",set_speed);
label2[2]->setText(float_str);
break;
case 4://读取的状态
stat=S_buff[4];
qDebug("读取状态");
switch(stat)
{
case 0:
label2[3]->setText(AA+"正常");
break;
case 1:
label2[3]->setText(AA+"过快");
break;
case 2:
label2[3]->setText(AA+"过慢");
break;
case 3:
label2[3]->setText(AA+"阻塞");
break;
case 4:
label2[3]->setText(AA+"暂停");
break;
case 5:
label2[3]->setText(AA+"完成");
break;
case 6:
label2[3]->setText(AA+"移动");
break;
}
break;
case 5://当前速度和滴数
speed=S_buff[4];
DOP_sum=S_buff[5]+(uint32_t)(S_buff[6]<<8)+(uint32_t)(S_buff[7]<<16)+(uint32_t)(S_buff[8]<<24);//低位在前
receivedData_real(set_speed);
receivedData(speed);
qDebug("--滴速--");
// sprintf(float_str, "滴速:%d 总滴数%ld",speed,DOP_sum);
strA=QString::number(speed);
strB=QString::number((uint)DOP_sum,10);
label2[4]->setText("滴速:"+strA+" 总滴数:"+strB);
break;
}
len_s=len_s-(S_buff[2]+3);
b= S_buff[2]+3;
if(len_s>0)//说明还有数据
{
for(m=0;m<len_s;m++)
{
S_buff[m]=S_buff[b+m];
}
i=0;//归位
}
}
// len_s=len_s-k;
}else//半包
{
break;//跳出循环不再判断
}
}
}
//解析协议
}
推荐阅读
-
解决HTTP数据不更新问题——no-cache在HTTP通信协议中的应用
-
国标GB28181协议国标视频平台EasyGBS修改云端录像不起效是什么原因?
-
网易云音乐公告:承诺不签订网络音乐独家版权协议
-
Dubbo 序列化协议 5 连问,你接得住不?
-
国标GB28181协议IP摄像头/录像机接入视频平台EasyGBS出现告警信息,但是不上报是什么原因?
-
有没有自己写的加密解密方法?(固定长度,不超过32位)
-
有没有自各儿写的加密解密方法?(固定长度,不超过32位)
-
web还没学好,与此同时看点http协议可以不
-
有没有自各儿写的加密解密方法?(固定长度,不超过32位)
-
求好手,看这个功能能否通过php实现(php直接接受tcp协议的tcp格式数据)