iot 终端上报数据进行大小端数据转换

Scroll Down

碰到问题是终端设备直接上报数据为 base64 加密的。

首先先把数据解析成16进制字符串。

然后按照协议进行位数截取可以得到对应的属性

这里拿比如截取后的属性是温度,十六进制字符串是 1D01

那个硬件师傅说这个数据其实是小端数据。

而java 是大端数据,那么就要进行数据的调换位置,就变成了011D

011D是16进制,需要转成10进制

image.png

就是285,协议里又说 这个数组要除以10,那么最终协议解析出来这个设备的温度字段值就是28.5

当然整个解决流程都是因为文档哈,不同的文档,肯定意思不同,但是大同小异,稍做调整,因为没问题

总结:还是仔细看文档,不理解及时沟通,不懂的方面很多,需要跟别人取经。

下面给出几个转换的方法

  /**
     * 解析数据方法
     */
    private static final char[] DIGITS
            = {'0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    public static final String toHex(byte[] data) {
        final StringBuffer sb = new StringBuffer(data.length * 2);
        for (int i = 0; i < data.length; i++) {
            sb.append(DIGITS[(data[i] >>> 4) & 0x0F]);
            sb.append(DIGITS[data[i] & 0x0F]);
        }
        return sb.toString();
    }

    /**
     * 小端转大端
     *
     * @param str
     * @return
     */
    public static byte[] string2Bytes(String str) {

        if (str == null || str.equals("")) {
            return null;
        }

        str = str.toUpperCase();
        int length = str.length() / 2;
        char[] strChar = str.toCharArray();
        byte[] bt = new byte[length];

        for (int i = 0; i < length; i++) {
            int index = i * 2;
            bt[i] = (byte) (char2Byte(strChar[index]) << 4 | char2Byte(strChar[index + 1]));
        }

        return bt;
    }

    private static byte char2Byte(char ch) {
        return (byte) "0123456789ABCDEF".indexOf(ch);
    }

    public final static long getLong(byte[] bt, boolean isAsc) {
        //BIG_ENDIAN
        if (bt == null) {
            throw new IllegalArgumentException("byte array is null.");
        }
        if (bt.length > 8) {
            throw new IllegalArgumentException("byte array size more than 8.");
        }
        long result = 0;
        if (isAsc) {
            for (int i = bt.length - 1; i >= 0; i--) {
                result <<= 8;
                result |= (bt[i] & 0x00000000000000ff);
            }
        } else {
            for (int i = 0; i < bt.length; i++) {
                result <<= 8;
                result |= (bt[i] & 0x00000000000000ff);
            }
        }
        return result;
    }

    /**
     * 16进制转10进制
     * 对方协议 大小写都是大写
     *
     * @param
     * @return
     */
    public static int hexToDecimal(String hex) {
        int outcome = 0;
        for (int i = 0; i < hex.length(); i++) {
            char hexChar = hex.charAt(i);
            outcome = outcome * 16 + charToDecimal(hexChar);
        }
        return outcome;
    }


    public static int charToDecimal(char c) {
        if (c >= 'A' && c <= 'F'){
            return 10 + c - 'A';
        } else{
            return c - '0';
        }
    }

    /**
     * 测试
     */
     public static void main(String[] args) {
        String temp = "1D01";
        byte[] tempBytes = string2Bytes(temp);
        String tempRecord = Long.toHexString(getLong(tempBytes, true));
        tempRecord = tempRecord.toUpperCase();
        int tempCovert = hexToDecimal(tempRecord);
        Double tempDouble = Double.valueOf(tempCovert) / 10;
        System.out.println(tempDouble);
    }