首页 > 代码库 > 自制应用层协议的编写

自制应用层协议的编写

                                              



近日编写了一个手机的灯控系统:


                       

因为添加了许多以前不具备的功能,并且为了数据传输更加稳定,格式更加规范,并且为了以后再进行同类项目的格式统一,本次特地根据计算机网络,在已有的协议HipulseU基础上进一步改造,自制了一套应用层的协议。

首先本套协议的格式定义如下:



协议格式:


SOI 7EH 起始位标志 1字节   ASCII:  7EH


VER 10H            1字节    ASCII: 31H,30H


ADR 01H            1字节    ASCII:30H,31H


CID1 命令 41H  运行控制命令


           42H 配置文件读写命令


           43H 时钟控制命令


           44H EEPROM命令


           45H 写文件名


CID2 辅助命令       1字节


----------------------------------------------------------------------------------------------------------------------


           CID1=41H 运行命令


                CID2:


                 10H:参数配置信息n每条14字节HEX(28字节ASCII


                 13H:参数运行EEPROM中的配置信息开机缺省。


                 14H: 参数运行CID1=45H中指定的文件。


                 20H:停止命令


----------------------------------------------------------------------------------------------------------------------


           CID1=42H 写配置文件


                CID2:


                 00H:~FEH 写配置文件


                 FFH    写配置文件,续写配置文件结束


           CID1=43H:时钟 


                CID2:


                 00H:写时钟命令格式: ---星期--- (分别为两个字节ASCII)


                 01H:读时钟命令格式: ---星期---


                 02H:设置开机关机时间 


                                           


                      格式 开始:(年---参数---秒)


                            结束:(年---参数---秒) 


 


                     


 


 


                      参数:两字节ASCII                             


D7       D6       D5        D4        D3       D2        D1        D0


0         1         1         1          1        1         1          1  


    星期                                              


1         0         0        0         0         0         0         0


年月日十分秒


1         1         1


----------------------------------------------------------------------------------------------------------------------


           CID1=44HEEPROM写配置信息


                CID2:


                 00H:向EEPROM写配置信息


----------------------------------------------------------------------------------------------------------------------


           CID1=45H:文件名  


                CID2:


                 00H:文件名(写入或运行的文件名,1字节)


----------------------------------------------------------------------------------------------------------------------


           CID1=46H:预览设置


                CID2: 


                 00H: 1


                 01H: 10


                 02H:100


                 03H:1000


----------------------------------------------------------------------------------------------------------------------


 


 


      LENGTH  2字节长度 先传高字节再传低字节


      其中:校验码:LCHKSUM=D15~D12 


            长度标示码:LENID=D11~D0 表示INFO中传送的ASCII码字节数


            校验码计算:D11~D8+D7~D4+D3~D0,求和后模16余数取反加1


INFO数据格式


      COMMAND INFO


 


 


 


 


CHKSUM数据格式


    CHKSUM的计算是除SOI,EOICHKSUM外,其它字符按ASCII码值累加求和,所得结果模65536余数取反加1


      


EOI 0DH 结束码


 


 


响应信息


SOI 7EH 起始位标志 1字节   ASCII:  7EH


VER 10H            1字节    ASCII: 31H,30H


ADR 01H            1字节    ASCII:30H,31H


CID1 60H


CID2 RTN    


LENGTH 2字节长度 先传高字节再传低字节


      其中:校验码:LCHKSUM=D15~D12 


            长度标示码:LENID=D11~D0 表示INFO中传送的ASCII码字节数


            校验码计算:D11~D8+D7~D4+D3~D0,求和后模16余数取反加1


INFO数据格式


      DATA INFO


 


CHKSUM数据格式


    CHKSUM的计算是除SOI,EOICHKSUM外,其它字符按ASCII码值累加求和,所得结果模65536余数取反加1


 


EOI 0DH 结束码


 


RTN:


00:正常


 01VER


 02CHKSUM


 03LCHKSUM


 04: CID2无效


 05:命令格式错


 06:无效命令


 E0:地址错


 E1~EFH:其它错误


 12H:参数文件名 文件中存配置文件名每个配置文件名1字节(ASCII两字节)


 11H:参数文件名  每个1字节(两字节ASCII码)



协议中的所有内容都是把一字节的内容,用两字节的ascii码来替换,例如原本的内容是一字节0x2f,最终会被替换为

0x32 0x46(2的ascii码是0x32,f的ascii码是0x46)

由于本次使用的是Android编程所以最终协议被封装成java包,

首先定义数据格式类把要传输的数据定义为Data类:

public class Data {private byte[] sol;private byte[] eol;private byte[] ver;private byte[] adr;private byte[] cid1;private byte[] cid2;private byte[] lenid;private byte[] info;private byte[] chksum;
        //以下定义Data类的各个数据成员变量的getter和setter方法
}





再定义一个DataOperator类用对,Data类进行各种操作。

由于要进行十六进制代码与ascii码之间的转换所以,要创建一个静态数组来进行两者的对应:

public class Ascii {
public static byte[] ASCII = new byte[] { 0x30, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 };
}



下面主要介绍  LCHKSUM的计算方法和CHKSUN的计算方法:

下面是LCHKSUM的计算方法,该方法通过对相应的LENGTH内容进行构造LCHKSUM

public byte[] createLength_chksum(byte[] src) {
byte[] result = new byte[1];
// 用来记录计算len_chksum时的中间转换变量
int len_check = 0;
// 计算len_chksum先计算长度每个字节所代表的ascii码的字符的真值和
for (int i = 0; i < 3; i++) {
if (src[i] > 0x39) {
len_check = len_check + (src[i] & 0xff) - 0x37;
} else {
len_check = len_check + (src[i] & 0xff) - 0x30;
}
}
// System.out.println(len_check);
// 把相应的和模16
len_check %= 16;
// 再把结果取反
len_check = 16 - len_check;
// 得到结果的ascii码的真值
if (len_check == 16) {
result[0] = 0;
} else {
result[0] = Ascii.ASCII[len_check];
}
// System.out.println(result[0]);
return result;
}



下面是CHKSUM的计算方法,参数为整个数据(除了开始和结束位):

public byte[] createChksum(byte[] src) {
// 用来记录计算chksum时的中间转换变量
int check = 0;
// 用来存放chksum结果
byte[] result = new byte[4];
// 计算每一字节的和
for (int i = 1; i < src.length; i++) {
// System.out.println(src[i]);
int a = src[i] & 0xff;
check = check + a;
}
System.out.println(check);
// 把和对65535求余数
check = check % 65536;
// 再把求余之后的结果取反
check = 65536 - check;
// 把最后的结果分为四字节的ascii码
result[0] = Ascii.ASCII[((check >> 12) & 0x0000000f)];
result[1] = Ascii.ASCII[((check >> 8) & 0x0000000f)];
result[2] = Ascii.ASCII[((check >> 4) & 0x0000000f)];
result[3] = Ascii.ASCII[((check & 0x0000000f))];
System.out.println(result[0] + " " + result[1] + " " + result[2] + " "
+ result[3]);
return result;
}


















本文出自 “开发者” 博客,请务必保留此出处http://tang1513.blog.51cto.com/7678175/1566333

自制应用层协议的编写