部标808协议解析
部标808协议解析前言
HTTP协议大家应该都比较熟悉,不过我们使用HTTP协议的时候一般不会关心HTTP协议底层到底是怎么传输数据的。像ApacheTomcat等现成的第三方工具已经替我们做了协议的编码解码工作;HTTP协议的格式、编码、解码等问题就不用上层用户关心了。甚至都不用关心参数是怎么提取的,你只需要告诉框架你需要从请求中获取指定名称格式的参数就行了(比如SpringMVC会自动帮你从字节流中提取参数还能做简单的数据类型转换操作)。
类似地,部标808协议可以和HTTP协议类比:都是一堆字节的传输,而上层用户关心的仅仅是这个报文到底传输了什么数据,并不关心协议到底该怎么编码解码。
本文介绍的jtframework就是类似于ApacheTomcat或者SpringMVC一样的角色,只不过jtframework针对的是部标协议(目前仅仅支持JTT808)而不是HTTP协议。项目文档:https:hylexus。github。iojtframework源码地址:https:github。comhylexusjtframework解析部标协议
常见的自定义协议一般有如下三种类型:报文定长:每个报文的长度都是一样的,实际数据较少达不到报文的长度的会用特殊字符来填充(padding)。基于分隔符:每个报文之间使用固定的分隔符来分隔,以区分每个单独的报文。基于换行符:实际上就是上面提到的基于分隔符的特殊场景,分隔符就是换行符。
本文介绍的部标808协议就是属于基于分隔符(0x7E)的一种自定义协议。
jtframework屏蔽了具体的协议解析,你可以使用指令式编程的方式(类似于Java的Servlet)来处理请求,同时你也可以使用更简单的基于Java注解(类似于SpringMVC)的方式来处理请求。也提供了像SpringMVC一样的拦截器的机制。初始化项目
建立一个springboot项目,引入maven依赖:dependencies!fortestdependencygroupIdorg。springframework。bootgroupIdspringbootstarterwebfluxartifactIddependency!jt808服务端依赖dependencygroupIdio。github。hylexus。jtgroupIdjt808serverspringbootstaterartifactIdversion2。0。0RELEASEversiondependencydependencies
启动springboot项目:
启动之后可以看到,已经内置了一堆消息处理器(内置的这些消息处理器仅仅用于debug目的),每当我们自己实现一个对应组件(消息处理器或者其他内置的可替换组件时,会覆盖内置组件)。每个组件签名都有一个类型标记,比如B表示内置(Builtin)组件(绿色)、C表示客户自定义(custom)组件(蓝色)、D表示已废弃(Deprecated)的组件(红色)。
可以通过配置jt808。builtcomponents。requesthandlers。enabledfalse来禁用内置的请求处理器。
默认的TCP端口为6808,可以通过jt808。server。port6808来修改默认端口。
现在就可以用发包工具来测试808请求了。
现在使用下面这条终端注册报文来测试一下:7E010040560100000000013912344321007B000B0000313233353931323335393131323334353637383930313233343536373839303132333435363738393069643132333435363738393031323334353637383930313233343536373801B8CA4A2D3635343332313C7E
当请求发送到服务端之后,可以看到内置的用于处理终端注册消息的消息处理器已经接收到请求并打印出了解析后的请求数据,大致输出内容如下所示:INFO72031〔msgprocessor0〕。d。h。b。BuiltinTerminalRegisterMsgHandler:TerminalRegisterV2019:BuiltinMsg0100V2019(provinceId11,cityId0,manufacturerId12359123591,terminalType123456789012345678901234567890,terminalIdid1234567890123456789012345678,color1,carIdentifier甘J654321)
通过日志可以看到这条终端注册消息是被BuiltinTerminalRegisterMsgHandler处理器处理掉了。内置的这些消息处理器仅仅是解析请求、打印数据、正常响应数据给客户端。
我们可以参考内置的消息处理器(都在io。github。hylexus。jt。jt808。support。dispatcher。handler。builtin包里)来实现我们自己的消息处理器。下面就自定义终端注册的消息处理器。处理终端注册消息
要处理一条消息,大概分为下面几个步骤:1)。从请求中获取数据:一般是将请求数据映射到一个类似于DTO(DataTransferObject)的类中方便后续使用2)。进行业务逻辑处理3)。按实际业务场景回复客户端
先定义一个DTO来接受请求数据:将请求数据映射到一个DTO类,方便后续业务处理DataJt808RequestBodypublicclassClientRegisterDto{1。〔02)WORD省域IDWORD类型固定长度就是2字节所以无需指定lengthRequestField(order1,startIndex0,dataTypeWORD)privateintprovinceId;2。〔24)WORD省域IDRequestField(order2,startIndex2,dataTypeWORD)privateintcityId;3。〔415)BYTE〔11〕制造商IDRequestField(order3,startIndex4,dataTypeSTRING,length11)privateStringmanufacturerId;4。〔1545)BYTE〔30〕终端型号RequestField(order4,startIndex15,dataTypeSTRING,length30)privateStringterminalType;5。〔4575)BYTE〔30〕终端IDRequestField(order5,startIndex45,dataTypeSTRING,length30)privateStringterminalId;6。〔75〕BYTE车牌颜色RequestField(order6,startIndex75,dataTypeBYTE)privatebytecolor;7。〔76,n)String车辆标识使用SpEL计算消息长度(上下文中的消息体总长度减去前面消费掉的字节数)RequestField(order7,startIndex76,dataTypeSTRING,lengthExpressionctx。msgBodyLength()76)privateStringcarIdentifier;}
同时还需要定义个VO,用来回复数据给客户端:DataAccessors(chaintrue)这里指明回复给客户端的消息类型是0x8100Jt808ResponseBody(msgId0x8100)publicclassClientRegisterReplyVo{1。WORD对应的终端注册消息的流水号ResponseField(order0,dataTypeMsgDataType。WORD)privateintterminalFlowId;2。0:成功;1:车辆已被注册;2:数据库中无该车辆;3:终端已被注册;4:数据库中无该终端ResponseField(order1,dataTypeMsgDataType。BYTE)privatebyteresult;3。STRING鉴权码conditionalOn属性表示:只有在成功(result0)后才有该字段,否则输出给客户端的字节流中将不包含该字段ResponseField(order3,dataTypeMsgDataType。STRING,conditionalOnresult0)privateStringauthCode;}
接下来就是具体的请求处理流程了:Slf4jComponent该注解指明当前类是一个请求处理类Jt808RequestHandlerpublicclassMyJt808MsgHandler{处理2019版的终端注册消息这里类似于Spring的RequestMapping注解Jt808RequestHandlerMapping(msgType0x0100,versionsVERSION2019,desc2019版终端注册消息)publicClientRegisterReplyVoclientRegisterV2019(Jt808RequestEntityClientRegisterDtoentity){finalClientRegisterDtobodyentity。body();TODO这里处理具体的注册逻辑log。info(收到终端注册消息,终端手机号{},消息数据{},entity。terminalId(),body);returnnewClientRegisterReplyVo()。setTerminalFlowId(entity。flowId())。setResult((byte)0)。setAuthCode(SomeAuthCode。。。);}}
然后重启项目,注意观察日志:
你可以在启动日志中观察到我们自定义的消息处理器已经替换掉了内置的处理2019版本注册消息的消息处理器,而2011和2013的消息处理器任然是内置的。结语
至此,已经基于jtframework搭建起来了一个可以处理JTT808协议的TCP服务端。你可以像使用SpringMVC一样来基于注解处理808协议。该项目也支持指令式编程模型(类似于Servlet)。同时还有一下其他特性,比如分包支持、消息下发、SpEL(SpringExpressionLanguage)支持等特性。
具体的其他特性可以参考官网文档:https:hylexus。github。iojtframework。不过,官方文档只是介绍了该项目的设计原理和简单的使用方式,并不设计具体的业务处理。
本文只是一个helloworld级别的入门示例。如果有必要的话,后续会有文章继续介绍如何基于jtframework来处理具体的808业务处理。
7月出行清单国内这些景点,将迎来一年中最佳的旅行时间7月去哪里?本期为大家带来了一组适合7月去旅行的景点,这些地方有的夏季凉爽得就像是自带空调,有的将迎来一年中最佳的旅行时间,看看你去过几个!1。云南普者黑普者黑有云南小桂林之称,是
什么是免签落地签过境签申根签证?举例说明理解签证前,先弄明白护照,通俗点讲,护照就是国家发给本国公民证明其身份的证件,相当于国际身份证,但你要进入他国,必须获得他国的允许(包括进入时间),这个允许就是签证,然后持签证与护
光影行星宙斯双肩包装起梦想和行囊,来一场说走就走的旅行在出行背包的选择上,我喜欢大容量的双肩包,并且外观设计要兼顾商务和休闲,这样通勤或者出游,又或旅行时,既有足够的收纳空间,又不需要倒腾来倒腾去,方便省事儿。疫情开始之后,居家办公的
望仙谷民宿,无微的服务,可口的美食望仙谷仙宿,数百个院落多个客房,就散落在这片山谷里。望仙谷仙宿,外观是独具特色的传统民居,内部是现代简约的房间布置。望仙谷仙宿,无微不至的管家服务,精致可口的餐点饮食,让向往的生活
山西曾走红的景点,经过岁月洗礼随时可能倒塌,如今是这样的结果在山西省,以前有那样一个旅游景点,一夜爆红,当时由于这一塔的造型,遭受成千上万朋友的关心,由于造型与众不同,还被我们称之为是塔顽强,我们一起来看一下这一塔如今怎么样了吧。这一塔是文
内蒙古的4A级公园,耗资4亿打造,占地100万平米,门票免费内蒙古自治区是国内的一个管辖区范畴特别大的省区,这个地方不仅有着尤其辽阔的草原,本地也是有很多的少数民族,而这种少数民族的文化艺术在这儿都获得了很好的相融,产生了本地别具特色的文化
夏日雨后,公园美景清凉上新夏日雨后,高温得到暂时消减。在世纪公园,园区花草树木青翠欲滴,更加惹人陶醉。雨中的荷塘如诗如画,嫩粉色的新荷亭亭玉立,随风摇曳,更显清秀旖旎袅娜多姿。淅淅沥沥的雨点打在水面上,泛起
湖南哪里的米粉最好吃湖南哪里的米粉最好吃湖南省,简称湘,是中华人民共和国省级行政区,省会长沙,界于北纬24383008,东经1084711415之间,东临江西,西接重庆贵州,南毗广东广西,北连湖北米粉
养生说丨阿司匹林是否可以长期服用?编者按一年四季,春夏秋冬,周而复始。春生夏长秋收冬藏,人们该懂得如何来适应气候的变化,有效地保养身体,防御疾病的侵害。在现如今快节奏的生活环境中,很多中青年人只为生活奔波,而忽略了
注重养生能给男性带来这些好处门诊一个來自贵州的勃起功能障碍(ED)患者,35岁,病史五年,半年多没有一次成功的同房了。形体肥胖,患有脂肪肝高血压病高脂血症肝功能肾功能指标均不正常。我无法预计他的寿命,但我知道
老年高血压患者请注意,这9个时刻要小心对待高血压,是常见的慢性病之一老年人又是高血压的高发群体我国半数以上的老年人患有高血压而在80岁及以上的高龄人群中高血压的患病率接近90高血压又是罹患脑卒中心肌梗死甚至死亡的首要危险因