netty 自定义16进制 项目实战

来源:互联网 发布:社会心理学 知乎 编辑:程序博客网 时间:2024/04/30 17:19

有关netty基本知识就不在此做过多说明、大家可以baidu学习基本知识。本文给大家提供一个netty 项目实例供大家学习、也可在项目中使用。


项目说明:

用户使用手机app 下发消息给充电设备、从而达到自动给电动汽车充电、也就是现在流行的充电桩。


定义协议如下:

                                                   发送报文

   

域  名

字节数

说  明

起始域

1

起始字节,固定为0x68

版本

1

该版本文件固定为0x01

功能码

1

消息类型,下文做解析

充电设施ID

4

设备唯一编码

包号

1

针对需要多包传输的数据

包号起始位0x01

数据长度

2

单包数据域字节数,单包长度不超过500字节

数据

n

数据域,不同的功能码对应不同的数据定义

校验码

1

采用累积和校验,计算范围为数据域


                                                              接收报文

域  名

字节数

说  明

起始域

1

起始字节,固定为0x68

版本

1

该版本文件固定为0x01

功能码

1

消息类型,下文将详细解析 

充电设施ID

4

设备唯一编码

反馈标志码

1

反馈标志码下文做解析

包号

1

针对需要多包传输的数据

数据长度

2

单包数据域字节数,单包长度不超过500字节

数据

n

数据域,不同的功能码对应不同的数据定义

校验码

1

采用累积和校验,计算范围为数据域


心跳故障码(1字节):自定义


返回错误码(1字节):自定义


具体解码编码代码如下:

解码:

// 68开头
if (hex.startsWith("68")) {


ParamInfo result = new ParamInfo();


// 设置版本号
result.setVersion(DigitalUtils.hex2Algorism(hex.substring(2, 4)));


// 设置功能码
result.setServiceName(hex.substring(4, 6));


// 设置充电桩编号(16进制转10进制,前面补0)
result.setStubId(StringUtils.leftPad(String.valueOf(DigitalUtils.hex2Algorism(hex.substring(6, 14))), 8, "0"));


// 数据索引块(包号)
result.setDataIdx(DigitalUtils.hex2Algorism(hex.substring(14, 16)));


// 数据长度
result.setDataLength(DigitalUtils.hex2Algorism(hex.substring(16, 20)));


// 数据长度检查
if (hex.length() != 20 + result.getDataLength() * 2 + 2) {
result.setErrCode("F1");
return result;
}


// 数据拆分
String dataHex = hex.substring(20, 20 + result.getDataLength() * 2);


if (result.getDataLength() > 0) {
int startIdx = 0;


List<StructInfo> structureList = ConfigUtils.getDecodeStruct().get(result.getServiceName());


if (structureList != null) {


for (StructInfo structInfo : structureList) {


result.addRequestData(structInfo.getName(), structInfo.cover(dataHex, startIdx));
startIdx = startIdx + structInfo.getLength() * 2;
}


} else {
result.setErrCode("05");
return result;
}
}


// 校验运算
String verifyString = hex.substring(20 + result.getDataLength() * 2, 20 + result.getDataLength() * 2 + 2);
if (!verifyString.equals(DigitalUtils.ADD(dataHex))) {
result.setErrCode("07");
return result;
}


return result;
}


编码:

// 起始域+版本+功能码+充电桩编号+错误位
hexSb.append("68").append("01").append(param.getServiceName()).append(param.getStubId()).append(param.getErrCode()).append("01");


List<StructInfo> structList = ConfigUtils.getEncodeStruct().get(param.getServiceName());


// 生成数据
StringBuffer dataHex = new StringBuffer();


// 有返回数据结构且是正常返回
if (structList != null && "00".equals(param.getErrCode())) {


for (StructInfo structInfo : structList) {


Object value = param.getResponseDate().get(structInfo.getName());


// TODO 不在此范围内的转型报错
if (structInfo.getType() == 1) {


// 如果返回数据类型必须为ascii
if (value instanceof String) {
dataHex.append(DigitalUtils.StringToAscii((String) value));
}
} else if (structInfo.getType() == 0) {


// 如果返回数据类型必须为hex
if (value instanceof Integer) {
dataHex.append(DigitalUtils.algorism2Hex((Integer) value, structInfo.getLength() * 2));
} else if (value instanceof BigDecimal) {
dataHex.append(DigitalUtils.algorism2Hex(((BigDecimal) value).intValue(), structInfo.getLength() * 2));
} else if (value instanceof String) {
dataHex.append(value);
}
}


}

项目架构:

spring 注解、jdbc 连接池、membercache、netty4 。因项目比较大、如需要项目源码 可联系我 qq 451366323




1 0
原创粉丝点击