首页 > 代码库 > 自制应用层协议的编写
自制应用层协议的编写
近日编写了一个手机的灯控系统:
因为添加了许多以前不具备的功能,并且为了数据传输更加稳定,格式更加规范,并且为了以后再进行同类项目的格式统一,本次特地根据计算机网络,在已有的协议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=44H时向EEPROM写配置信息
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,EOI和CHKSUM外,其它字符按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,EOI和CHKSUM外,其它字符按ASCII码值累加求和,所得结果模65536余数取反加1
EOI 0DH 结束码
RTN:
00:正常
01:VER错
02:CHKSUM错
03:LCHKSUM错
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
自制应用层协议的编写