问题
- 项目为交通大数据相关,使用雷视一体机获取车辆实时信息,通过socket上报给平台
- 雷达会根据安装点的一个坐标为原点,构建自己的坐标系,记录车辆实时位置
- 雷达按照一定的通信协议,上报车辆编号、坐标、速度数据等给平台
- 查看上报数据,发现位置和速度数据异常,与实际情况不符,查看设备原始数据是正常的,应该是数据解析出了问题
- 重新查看了通信协议,没发现什么问题,咨询了相关同事了解到,为了处理负数,需要按照一定规则解析(文档里没有注明)
解决
- 我们约定按照字节传输数据,使用了netty,使用
io.netty.buffer.ByteBuf
接收数据 - 原有代码片段如下,全部以无符号数解析的:
realTimeDataPO.vehiclePositionX = (float) 0.1 * buf.readUnsignedShort();
realTimeDataPO.vehiclePositionY = (float) 0.1 * buf.readUnsignedShort();
realTimeDataPO.vehicleSpeedX = (float) 0.1 * buf.readUnsignedShort();
realTimeDataPO.vehicleSpeedY = (float) 0.1 * buf.readUnsignedShort();
- 实际规则如下:
1.取值范围>=0,按无符号数解析,<0,按有符号数解析
2.长度大于2个字节的,注意大小端字节顺序(否则解析出来的值也不对)
3.注意协议中的备注中说明的单位,如0.1米,那解析的值,再乘以0.1,就是实际的米单位
- 需要根据值是否为负数,分别使用无符号解析和有符号解析,具体代码如下:
realTimeDataPO.vehiclePositionX = (float) 0.1 * buf.readShort();
realTimeDataPO.vehiclePositionY = (float) 0.1 * buf.readShort();
realTimeDataPO.vehicleSpeedX = (float) 0.1 * buf.readShort();
realTimeDataPO.vehicleSpeedY = (float) 0.1 * buf.readShort();
- 这里的取值范围,就是指文档里的取值范围,带负数直接使用有符号数解析,而不是根据具体值是正是负来决定使用有符号或无符号数解析,所以下面的转换方法不需要了,实际使用中也发现下面的解析并不全符合实际数据
- 我们是按照顺序传输数字的,具体byte[]转short代码如下:
/**
* 获取short值
* @param low
* @param high
* @return
*/
public static int getShort(byte high, byte low) {
int result;
// 大于等于0,无符号数;小于0,有符号数(为了方便直接使用高位判断了)
if (high >= 0) {
result = byte2UnsignedShort(low, high);
} else {
result = byte2Short(low, high);
}
return result;
}
/**
* byte[2] 转 unsignedShort
*
* @param low
* @param high
* @return
*/
public static int byte2UnsignedShort(byte low, byte high) {
return (high << 8 | low);
}
/**
* byte[2] 转 short
*
* @param low
* @param high
* @return
*/
public static short byte2Short(byte low, byte high) {
return (short) ((low & 0xFF) | (high << 8));
}
- 这样取的数据,已经没问题了,与设备里的原始数据一致(实际上直接使用readShort就可以了,自己判断转化反而部分值不对),部分打印如下: