JAVA实现GBT32960报文解析(三):0x01整车数据解析源码

**JAVA实现GBT32960报文解析系列文章链接:**
JAVA实现GBT32960报文解析(一):掌握协议中的各种数据类型和完整报文结构
JAVA实现GBT32960报文解析(二):数据包结构解析源码
JAVA实现GBT32960报文解析(三):0x01整车数据解析源码
JAVA实现GBT32960报文解析(四):0x02驱动电机数据解析源码
JAVA实现GBT32960报文解析(五):0x03燃料电池数据解析源码(待更…)
JAVA实现GBT32960报文解析(六):0x04发动机数据解析源码(待更…)
JAVA实现GBT32960报文解析(七):0x05车辆位置数据解析源码(待更…)
JAVA实现GBT32960报文解析(八):0x06极值数据解析源码(待更…)
JAVA实现GBT32960报文解析(九):0x07报警数据解析源码(待更…)
实战需求示例:车辆月度充电详情统计报表,含快充、慢充区分统计(待更…)



前言

这是本系列的第三篇文章,从本文开始也就正式进入“数据单元”部分的解析,关于其他部分报文的解析可通过上方系列文章的链接进入了解。

《GB/T 32960.3-2016 电动汽车远程服务与管理系统技术规范 第3部分:通讯协议及数据格式》中,关于数据单元类型为0x01的整车数据格式和定义如下:
在这里插入图片描述


本文将继续对国标报文的剩余部分进行解析,即:0x01 =>【整车数据】部分

提示:下方“删除线”划掉的部分,是从本系列第二篇文章开始已经通过代码示例解析过的报文。

剩余报文信息如下(示例):

232303FE584C32434546355030414C30303730323301012D15071C110B320102030100000000010E0C58271000021013510065020101014F4E204E2055001F271005000633555501D2D2CE0601220D00011F0B1501014B010B49070300000450000000000801010C58271000600001600CBD0CD90CD00CCF0CE00CF00CE00CCB0CE10CE00CDF0CC80CC50CD30CCF0CE70CE50CE30CD90CE90CF60CEF0CE10CDF0CEA0CED0CE80CD10CDA0CEE0B150CD30CED0D000CCA0CED0CD60CDA0CED0CDC0CE70CF00CED0CDF0CF40CF30CDC0CE50CE00CEF0CE10CD20CDD0CE80CD60CEA0CDD0CE90CD90CD60CC90CCB0CDE0CCC0CD30CD60CE60CF20CE20CCC0CE90CE40CF80CA00CE50CE10CE90CE80CE20CF70CF50CEA0CCD0CF80CE50CDD0CE00CE10CE90CDD0CEB0CEE0CF40CF60CFC0CE109010100104B4A4A4A4949494A4A49494A4A4A4A4A5F

一、车辆状态

在这里插入图片描述
关于状态类型的解析:我延续个人的习惯在构造函数中采用Map键值对的方式定义,使其在初始化时就存储定义好,等到解析调用时通过Map.get()方法去取出对应的value值。

车辆状态解析,代码如下(示例):

		// 构造函数中定义车辆状态
        vehicleStateMap = new HashMap<String, String>();
        vehicleStateMap.put("0x01", "车辆启动状态");
        vehicleStateMap.put("0x02", "熄火");
        vehicleStateMap.put("0x03", "其他状态");
        vehicleStateMap.put("0xFE", "异常");
        vehicleStateMap.put("0xFF", "无效");
		// 解析调用(下标0是数据单元类型的定义,在主方法中已经处理,所以这里从下标1开始)
        map.put("车辆状态", vehicleStateMap.get("0x" + bytes[1]));

二、充电状态

在这里插入图片描述

充电状态解析,代码如下(示例):

		// 构造函数中定义充电状态
        chargeModeMap = new HashMap<String, String>();
        chargeModeMap.put("0x01", "停车充电");
        chargeModeMap.put("0x02", "行驶充电");
        chargeModeMap.put("0x03", "未充电");
        chargeModeMap.put("0x04", "充电完成");
        chargeModeMap.put("0xFE", "异常");
        chargeModeMap.put("0xFF", "无效");
		// 解析调用
        map.put("充电状态", chargeModeMap.get("0x" + bytes[2]));

三、运行模式

在这里插入图片描述

运行模式解析,代码如下(示例):

		// 构造函数中定义运行模式
        runStateMap = new HashMap<String, String>();
        runStateMap.put("0x01", "纯电");
        runStateMap.put("0x02", "混动");
        runStateMap.put("0x03", "燃油");
        runStateMap.put("0xFE", "异常");
        runStateMap.put("0xFF", "无效");
		// 解析调用
        map.put("运行模式", runStateMap.get("0x" + bytes[3]));

四、车速

在这里插入图片描述
关于数值类型的解析:需要优先处理异常无效数据的,然后注意是否有最小计量单位偏移量的描述。这些都需要一一处理,否则数据值解析错误很难直观看出。

车速解析,代码如下(示例):

	/**
     * 车速
     * @param strByte
     * @return
     */
    private String byte2speed(String strByte)
    {
        if(strByte.equals("FFFE"))
        {
            return "异常";
        }
        else if(strByte.equals("FFFF"))
        {
            return "无效";
        }

        // 排除以上两种情况后,就可以直接当做数字处理
        BigDecimal BdByte = new BigDecimal(Integer.valueOf(strByte, 16));
        // 精确到0.1km,所以在这里除以10
        BdByte = BdByte.divide(new BigDecimal(10));

        return BdByte.toString();
    }

五、累计里程

在这里插入图片描述

累计里程解析,代码如下(示例):

	/**
     * 累计里程
     * @param strByte
     * @return
     */
    private String byte2odometer(String strByte)
    {
        if(strByte.equals("FFFFFFFE"))
        {
            return "异常";
        }
        else if(strByte.equals("FFFFFFFF"))
        {
            return "无效";
        }

        // 排除以上两种情况后,就可以直接当做数字处理
        BigDecimal BdByte = new BigDecimal(Integer.valueOf(strByte, 16));
        // 精确到0.1km,所以在这里除以10
        BdByte = BdByte.divide(new BigDecimal(10));

        return BdByte.toString();
    }

六、总电压

在这里插入图片描述

总电压解析,代码如下(示例):

	/**
     * 总电压
     * @param strByte
     * @return
     */
    private String byte2totalVoltage(String strByte)
    {
        if(strByte.equals("FFFE"))
        {
            return "异常";
        }
        else if(strByte.equals("FFFF"))
        {
            return "无效";
        }

        // 排除以上两种情况后,就可以直接当做数字处理
        BigDecimal BdByte = new BigDecimal(Integer.valueOf(strByte, 16));
        // 精确到0.1V,所以在这里除以10
        BdByte = BdByte.divide(new BigDecimal(10));

        return BdByte.toString();
    }

七、总电流

在这里插入图片描述

总电流解析,代码如下(示例):

    /**
     * 总电流
     * @param strByte
     * @return
     */
    private String byte2totalCurrent(String strByte)
    {
        if(strByte.equals("FFFE"))
        {
            return "异常";
        }
        else if(strByte.equals("FFFF"))
        {
            return "无效";
        }

        // 排除以上两种情况后,就可以直接当做数字处理
        BigDecimal BdByte = new BigDecimal(Integer.valueOf(strByte, 16));
        // 精确到0.1A,所以在这里除以10
        BdByte = BdByte.divide(new BigDecimal(10));
        // 偏移量1000A,有效范围值:-1000A~1000A
        BdByte = BdByte.subtract(new BigDecimal(1000));

        return BdByte.toString();
    }

八、SOC

在这里插入图片描述

SOC解析,代码如下(示例):

    /**
     * SOC
     * @param strByte
     * @return
     */
    private String byte2soc(String strByte)
    {
        if(strByte.equals("FE"))
        {
            return "异常";
        }
        else if(strByte.equals("FF"))
        {
            return "无效";
        }

        // 排除以上两种情况后,就可以直接当做数字处理
        BigDecimal BdByte = new BigDecimal(Integer.valueOf(strByte, 16));

        return BdByte.toString();
    }

九、DC-DC状态

在这里插入图片描述

DC-DC状态解析,代码如下(示例):

		// 构造函数中定义DC-DC状态
        dc_dcStateMap = new HashMap<String, String>();
        dc_dcStateMap.put("0x01", "工作");
        dc_dcStateMap.put("0x02", "断开");
        dc_dcStateMap.put("0xFE", "异常");
        dc_dcStateMap.put("0xFF", "无效");
		// 解析调用
        map.put("DC-DC状态", dc_dcStateMap.get("0x" + bytes[15]));

十、档位

在这里插入图片描述
档位的报文信息,其实包含三个部分(抛出前面的两个预留字符过后):驱动状态、制动状态、档位。这里仅为了阅读便捷不在构建函数中单独做map定义,整体放在一个方法中去编写。

档位解析,代码如下(示例):

    /**
     * 档位
     * @param strByte
     * @return
     */
    private String byte2gearshift(String strByte)
    {
        String str = null;
        strByte = ParseUtils.hexStr2Byte(strByte);
        
        // 驱动状态解析
        if(strByte.substring(2, 3).equals("1"))
            str = "有驱动力";
        else
            str = "无驱动力";
        
        // 制动状态解析    
        if(strByte.substring(3, 4).equals("1"))
            str += ",有制动力";
        else
            str += ",无制动力";
        
        // 档位解析  
        switch (strByte.substring(4, 8)) {
            case "0000":
                str +=  ",空挡";
                break;
            case "0001":
                str +=  ",1挡";
                break;
            case "0010":
                str +=  ",2挡";
                break;
            case "0011":
                str +=  ",3挡";
                break;
            case "0100":
                str +=  ",4挡";
                break;
            case "0101":
                str +=  ",5挡";
                break;
            case "0110":
                str +=  ",6挡";
                break;
            case "1101":
                str +=  ",倒挡";
                break;
            case "1110":
                str +=  ",自动D挡";
                break;
            case "1111":
                str +=  ",停车P挡";
                break;
            default:
                System.out.println("not match !!!");
        }
        return str;
    }

提示:ParseUtils类是在第一篇文章中实现的代码类

十一、绝缘电阻

在这里插入图片描述

绝缘电阻解析,代码如下(示例):

		// 绝缘电阻
        map.put("绝缘电阻", Integer.valueOf(bytes[17] + bytes[18], 16).toString());

十二、加速踏板行程值

在这里插入图片描述

加速踏板行程值解析,代码如下(示例):

    /**
     * 加速踏板行程值
     * @param strByte
     * @return
     */
    private String byte2accPedalVal(String strByte)
    {
        if(strByte.equals("FE"))
        {
            return "异常";
        }
        else if(strByte.equals("FF"))
        {
            return "无效";
        }

        // 排除以上两种情况后,就可以直接当做数字处理
        BigDecimal BdByte = new BigDecimal(Integer.valueOf(strByte, 16));

        return BdByte.toString();
    }

十三、制动踏板状态

在这里插入图片描述

制动踏板状态解析,代码如下(示例):

    /**
     * 制动踏板状态
     * @param strByte
     * @return
     */
    private String byte2brakePedalState(String strByte)
    {
        if(strByte.equals("65"))
        {
            return "有效,但暂无具体值";
        }
        else if(strByte.equals("FE"))
        {
            return "异常";
        }
        else if(strByte.equals("FF"))
        {
            return "无效";
        }

        // 排除以上两种情况后,就可以直接当做数字处理
        BigDecimal BdByte = new BigDecimal(Integer.valueOf(strByte, 16));

        return BdByte.toString();
    }

总结

根据文章结尾可下载的完整代码示例,最终通过System.out.println("CompleteVehicle Map => " + map);打印到控制台。

控制台输出结果如下:

CompleteVehicle Map => {运行模式=纯电, 总电压=316, SOC=0, 档位=无驱动力,有制动力,空挡, 车速=0, 充电状态=未充电, 总电流=0, 车辆状态=熄火, 绝缘电阻=4945, 累计里程=27, 制动踏板状态=有效,但暂无具体值, 加速踏板行程值=0, DC-DC状态=断开}

从下一篇文章,继续解析:数据单元信息标识为0x02的驱动电机数据源码


** 相关下载:**
国标协议GBT32960文档 (包含《GB/T 32960-2016 电动汽车远程服务与管理系统技术规范》完整的1、2、3部分)
源码部分:
JAVA解析GBT32960协议 - 数据包结构源码(另含ParseUtils.java和BCCVerifyUtils.java两个工具类)
JAVA解析GBT32960协议 - 0x01整车数据源码
JAVA解析GBT32960协议 - 0x02驱动电机数据源码
JAVA解析GBT32960协议 - 0x03燃料电池数据源码(待更…)
JAVA解析GBT32960协议 - 0x04发动机数据源码(待更…)
JAVA解析GBT32960协议 - 0x05车辆位置数据源码(待更…)
JAVA解析GBT32960协议 - 0x06极值数据源码(待更…)
JAVA解析GBT32960协议 - 0x07报警数据源码(待更…)

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: GBT32960是中国国家标准委员会发布的一项关于电动汽车远程监控与服务管理系统的国家标准。该标准规定了电动汽车与远程监控平台之间的通信协议,包括了报文格式、数据解析等内容。 在Java中进行GBT32960通讯报文解析,首先需要通过网络连接获取到电动汽车发送的报文数据。接下来,需要按照GBT32960标准规定的报文格式进行解析,提取出报文中的各个字段信息。 通常,GBT32960报文的开头是固定的报文头,包含了报文的起始标志、协议版本等信息。接下来是报文的主体部分,其中包含多个数据项,如车辆状态数据、电池状态数据等。每个数据项都有自己的数据标识符、数据长度及数据内容。 在Java中,可以通过解析报文头和主体部分,按照标准规定的数据标识符提取出需要的数据项。然后,根据数据项的数据类型,进行相应的解析操作,如将字节转换为数值、日期转换、字符编码转换等。最后,将解析得到的数据存储或进行相应的业务逻辑处理。 解析GBT32960通讯报文需要熟悉GBT32960标准的相关规定,了解每个数据项的含义和使用方式。同时,还需要具备Java编程的基础知识,包括字节操作、数据类型转换等。 在实际应用中,GBT32960通讯报文解析往往会与其他功能结合,如数据存储、报表生成、远程控制等,以实现更多的业务需求。因此,在解析GBT32960通讯报文时,也需要考虑与其他模块的集成和数据交互的问题。 ### 回答2: GBT32960通讯报文是中国国家标准委员会发布的国家标准,用于规范电动汽车与后台监测平台之间的通信协议。通讯报文解析就是在接收到GBT32960协议格式的报文后,通过程序解析报文中的各个字段信息。 通讯报文解析主要使用Java编程语言进行实现。首先需要参考GBT32960标准文档,了解报文的结构和定义。然后,可以通过Java的IO流和网络通信库,接收到报文数据,并将其按照GBT32960协议进行解析解析GBT32960通讯报文的过程包括以下步骤: 1. 接收报文:使用Java的网络通信库,接收来自电动汽车或后台监测平台的GBT32960格式报文。 2. 报文解析:根据GBT32960标准文档,解析报文中的各个字段信息。可以使用Java的字符串处理函数和正则表达式来提取字段数据。 3. 数据处理:对解析出的字段数据进行二进制转换、数值转换等处理,将其转换成对应的数值或文本格式。 4. 数据存储:将解析出的各个字段数据存储到数据库或其他数据结构中,以便后续的数据分析和使用。 在实现GBT32960通讯报文解析时,需要提前确定报文协议版本和报文含义,确保解析过程的准确性。同时,还需对异常情况进行处理,如报文格式错误、字段缺失等情况的异常处理。 通过Java实现GBT32960通讯报文解析,可以方便地应用于电动汽车监测和管理系统中,提供对电动汽车相关数据的实时监测与控制功能。 ### 回答3: GBT32960是中国国家标准化管理委员会发布的一项关于电动汽车远程监控系统的标准,旨在规范电动汽车与监控平台之间的通信报文格式。 通讯报文解析是指将GBT32960标准规定的通信报文按照特定的解析规则解析成可读性高的数据。在Java语言中,可以使用各种方法和库来实现GBT32960通信报文解析。 首先,需要定义GBT32960通信报文的结构,包括报文头和报文体。报文头包括起始符、数据单元长度、数据单元标识等字段,而报文体包括车辆识别码、车辆状态等信息。 然后,可以使用Java的字符、字符串处理函数来逐个解析报文。通过读取报文头的数据单元长度字段,可以确定报文体的长度,从而按照GBT32960规定的报文格式解析出各个字段的值。 在实现过程中,可以使用正则表达式、字符串截取等方法来提取报文中的特定字段值。同时,需要注意数据类型的转换,如将字符串转换为整数、浮点数等。 最后,可以将解析得到的数据进行进一步处理,如存储到数据库、输出到日志文件等。此外,还可以根据实际需求,在解析过程中添加校验和验证逻辑,确保报文的完整性和正确性。 总之,GBT32960通讯报文解析Java实现需要遵循GBT32960标准规定的报文格式和解析规则,通过合理运用Java语言的字符串处理和数据类型转换等功能,将报文解析为可读性高的数据。这样可以为电动汽车远程监控系统提供有效的数据支持,以实现对电动汽车的远程监控和管理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值