最近项目对接一个电表硬件的电表,将电表传输报文数据解析后入库,电表协议为modbus。
电表提供了协议说明和数据字典,总的来说解析比较简单,整个报文数据都是由十六进制的数组合,协议定义了整个数据的格式,包括时间,数据起始位置,每个数据处于哪个位置,占用几个寄存器,按照说明拿出对应的字节转译成十进制即可。
再说下其中碰到的问题:
1.对于浮点型的十六进制转换十进制,我之前才用的方法是:
float value = Float.intBitsToFloat(Integer.valueOf("", 16));
这个方法一般情况下不会出现问题,但当这个十六进制数是一个有符号的负数时,这个方法就会报错
所以得改下转换方式:
float value = Float.intBitsToFloat(new BigInteger("str", 16).intValue());
2.第二个问题也是在转换数据类型为I16的时候也会遇到有符号的负数,这种正常解析情况下也不会报错,比如ff80,解析结果会是65408,但是这其实是一个负数,正确的结果应该为-128,我找了很多别人的解决方案,有说到反码原码补码的,说要先将这个十六进制转换成二进制,然后进行反码拿到它的正数,转成十进制后再加上符号的,看着都略麻烦,后面找到一个简单好用的,正负数都能正常转换:
int value = Integer.parseInt(str, 16);
value = ((value & 0x8000) > 0) ? (value - 0x10000) : (value );