#include "stdio.h" #include "rtthread.h" #include "board.h" #include "mystdlib.h" #include "list.h" #include "mystring.h" #include "signal.h" #include "prot_uc.h" #include "buff.h" #include "bytearray.h" #include "debug.h" #include "crc.h" #include "dev_flash.h" #include "codec.h" #include "elec_det.h" /*rc{ 协议编解码器,用于适配各种协议 }*/ // 二代批检仪协议解码 array_def *protu_decode(protu_def *p,array_def *data) { array_def *r=arr_creat(); param_check(r); DBG_LOG("decode for checker"); str_set(p->str_err,"ok"); if(arr_length(data)<9) { // 主机一帧数据至少9字节 DBG_WARN("recv data len too less."); str_set(p->str_err,"recv data len too less."); return r; } if((arr_get(data,0)!=0x59)||(arr_get(data,1)!=0x6d)) { // 帧头不对 DBG_WARN("frame head not 0x59 0x6d."); str_set(p->str_err,"frame head not 0x59 0x6d."); return r; } int len=arr_get(data,2)|(arr_get(data,3)<<8); if(len==65535) { // 重新设置数据长度 len=arr_get(data,7)|(arr_get(data,8)<<8)|(arr_get(data,9)<<16)|(arr_get(data,10)<<24); p->is_big_data=1; }else{ p->is_big_data=0; } if(len+6!=arr_length(data)) { // 如果长度不相等则产生了数据丢失 DBG_WARN("recv data have lossed."); str_set(p->str_err,"recv data have lossed."); return r; } uint8_t chk_a,chk_b; crc_crc16(arr_data(data)+2,len+2,&chk_a,&chk_b); if(chk_a!=arr_get(data,-2)||chk_b!=arr_get(data,-1)) { // crc校验不对 DBG_WARN("recv data check error.h_crc=%02x %02x,crc=%02x %02x",chk_a,chk_b,arr_get(data,-2),arr_get(data,-1)); str_set(p->str_err,"recv data check error."); } int cmd_no=arr_get(data,5)|(arr_get(data,6)<<8); // if(p->cmd_no==cmd_no) // { // // 重复的cmd_no // DBG_WARN("duplicate sequence number."); // str_set(p->str_err,"duplicate sequence number."); // } p->cmd_no=cmd_no; p->cmd=arr_get(data,4); p->silent=0; // 数据负载 arr_delete(r); if(p->is_big_data==0) { return arr_mid(data,7,len-3); }else{ return arr_mid(data,11,len-7); } } // 二代批检仪协议编码 array_def *protu_encode(protu_def *p,array_def *data) { array_def *t=arr_creat(); param_check(t); uint16_t len=arr_length(data)+3; arr_append(t,0x59); arr_append(t,0x6d); arr_append(t,0x43); arr_append(t,len&0xff); arr_append(t,len>>8); arr_append(t,p->cmd); arr_append(t,p->cmd_no&0xff); arr_append(t,p->cmd_no>>8); arr_appends_from(t,data); uint8_t chk_a,chk_b; crc_crc16(arr_data(t)+3,len+2,&chk_a,&chk_b); arr_append(t,chk_a); arr_append(t,chk_b); return t; } protuc_codec_export(ym_checker,protu_decode,protu_encode); // 注码仪和批检仪协议相同 //protuc_codec_export(ym_coder2,protu_decode,protu_encode); // 赋码仪协议解码 array_def *protu_decode2(protu_def *p,array_def *data) { array_def *r=arr_creat(); param_check(r); DBG_LOG("decode for coder"); str_set(p->str_err,"ok"); if(arr_length(data)<6) { // 主机一帧数据至少9字节 DBG_WARN("recv data len too less."); str_set(p->str_err,"recv data len too less."); return r; } if((arr_get(data,0)!='Y')||(arr_get(data,1)!='m')) { // 帧头不对 DBG_WARN("frame head not 'Y' 'm'."); str_set(p->str_err,"frame head not 'Y' 'm'."); return r; } int len=arr_get(data,2)|(arr_get(data,3)<<8); p->is_big_data=0; if(len+6!=arr_length(data)) { // 如果长度不相等则产生了数据丢失 DBG_WARN("recv data have lossed."); str_set(p->str_err,"recv data have lossed."); return r; } uint8_t chk_a,chk_b; crc_sumcheck(arr_data(data)+4,len,&chk_a,&chk_b); if(chk_a!=arr_get(data,-2)||chk_b!=arr_get(data,-1)) { // crc校验不对 DBG_WARN("recv data check error.h_crc=%02x %02x,crc=%02x %02x",chk_a,chk_b,arr_get(data,-2),arr_get(data,-1)); str_set(p->str_err,"recv data check error."); } p->cmd_no=arr_get(data,5)|(arr_get(data,6)<<8); p->cmd=arr_get(data,4); p->silent=0; // 数据负载 arr_delete(r); if(p->is_big_data==0) { return arr_mid(data,7,len-3); }else{ return arr_mid(data,11,len-7); } } // 赋码仪协议编码 array_def *protu_encode2(protu_def *p,array_def *data) { array_def *t=arr_creat(); param_check(t); uint16_t len=arr_length(data)+3; arr_append(t,0x59); arr_append(t,0x6d); arr_append(t,0x43); arr_append(t,len&0xff); arr_append(t,len>>8); arr_append(t,p->cmd); arr_append(t,p->cmd_no&0xff); arr_append(t,p->cmd_no>>8); arr_appends_from(t,data); uint8_t chk_a,chk_b; crc_sumcheck(arr_data(t)+5,len,&chk_a,&chk_b); arr_append(t,chk_a); arr_append(t,chk_b); return t; } //protuc_codec_export(ym_coder,protu_decode2,protu_encode2); // 计算在第n为之前,bit为1的个数 static int calc_bit_num(int bits,int n) { int num=0; for(int i=0;istr_err,"ok"); if(arr_length(data)<10) { DBG_WARN("recv data len too less."); DBG_WARN("data=%s",str_temp(arr_string(data))); str_set(p->str_err,"recv data len too less."); return r; } uint8_t src=arr_get(data,4); uint8_t dst=arr_get(data,5); if((src!=0)||((dst!=elec_local_addr())&&(dst!=0x1f))){ DBG_WARN("src_addr/dst_addr not allowed."); DBG_WARN("data=%s",str_temp(arr_string(data))); str_set(p->str_err,"src_addr/dst_addr not allowed."); return r; } uint16_t len=arr_get(data,2)|(arr_get(data,3)<<8); uint8_t crc=crc_crc8(arr_data(data),arr_length(data)-1); if(len!=arr_length(data)) { // 如果长度不相等则产生了数据丢失 DBG_WARN("recv data have lossed."); str_set(p->str_err,"recv data have lossed."); return r; } uint16_t no=arr_get(data,7)|(arr_get(data,8)<<8); uint16_t h_no=p->cmd_no; if(no!=h_no) { // 发送一条指令等待其返回,此时流水号应相同 //DBG_WARN("slave_addr=%d cmd_no error:h_no=%d,no=%d.",src,h_no,no); //str_set(p->str_err,"cmd no err."); //return r; } if(crc!=arr_get(data,-1)) { DBG_WARN("recv data crc check error:%02x,%02x.",crc,arr_get(data,-1)); str_set(p->str_err,"crc check err."); } p->cmd=arr_get(data,6); arr_delete(r); r=arr_mid(data,9,len-10); if(dst==0x1f){ // 广播命令需判断额外字节 int self_addr=elec_local_addr(); int dst_addrs=arr_get(r,0)|(arr_get(r,1)<<8)|(arr_get(r,2)<<16); if((dst_addrs&(1<<(self_addr-1)))!=0){ p->silent=1; p->timer->write(p->timer,0); p->rank=calc_bit_num(dst_addrs,self_addr-1); p->num=calc_bit_num(dst_addrs,32); arr_remove(r,0,3); }else{ arr_delete(r); r=arr_creat(); str_set(p->str_err,"bordcast without this."); } }else{ p->rank=dst-1; p->num=20;// 最多支持20个设备 p->silent=0; } return r; } // 编码 array_def *protm_encode(protu_def *p,array_def *data) { array_def *t=arr_creat(); param_check(t); // if(p->silent==0){ uint16_t len=arr_length(data)+10; arr_append(t,'Y'); arr_append(t,'e'); arr_append(t,len&0xff); arr_append(t,len>>8); arr_append(t,elec_local_addr());// 源地址 arr_append(t,0);// 目标地址 arr_append(t,p->cmd);// 命令码 arr_append(t,p->cmd_no&0xff); arr_append(t,p->cmd_no>>8); arr_appends_from(t,data); arr_append(t,crc_crc8(arr_data(t),arr_length(t))); // }else{ // // 广播命令只需回复本机地址 // arr_append(t,elec_local_addr()); // } return t; } protuc_codec_export(ym_slave,protm_decode,protm_encode); // 小板ew协议解码 array_def *protew_decode(protu_def *p,array_def *data) { } array_def *protew_encode(protu_def *p,array_def *data) { } // protuc_codec_export(ew_slave,protm_decode,protm_encode);