终端是指obd设备,既车载obd设备。php
平台是指上文中说到的经过短信设置的上报IP指向的机器所提供的网关服务。this
这两种消息一是终端设备发出的,一是平台发出的,都是通用应答的格式,所谓通用既是能够用于应答其余消息的一种消息格式。code
起始字节 | 字段 | 数据类型 | 描述及要求 |
---|---|---|---|
0 | 应答流水号 | WORD | 对应的平台消息的流水号 |
2 | 应答 ID | WORD | 对应的平台消息的 ID |
4 | 结果 | BYTE | 0:成功/确认;1:失败;2:消息有误;3:不支持 |
ps.上表省略消息头部分,默认全部的应答和发送都带有消息头字符串
在平台下发指令或者设置终端参数(0x8103)时设备将应答此消息。it
0000
设备发送的消息,除注册应答(0x8100)、校时应答(0x8f01)外其余数据数据发送均可使用此消息id应答。io
如消息:7E80010005013183700516000005D2020000817Etable
拆分编号 | 消息 | 说明 |
---|---|---|
1 | 7e | 消息标示 |
2 | 8100 | 消息ID |
3 | 000F | 消息体属性 |
4 | 013183700516 | 设备号 |
5 | 0000 | 消息流水号 |
6 | 05D2 | 对应的终端消息的流水号,既终端消息的流水号 |
7 | 0200 | 对应的终端消息的 ID |
8 | 00 | 0:成功/确认;1:失败;2:消息有误;3:不支持;4:报警确认处理 |
9 | 81 | 校验码 |
10 | 7e | 消息标示 |
消息头就不说了,这里须要注意的是 编号7 行的 0200是设备位置信息汇报的消息id,这说明这条信息是应答设备发出的位置信息汇报(0x0200)的结果, 回复不一样的消息,这里的数据是不一样的。function
上篇大概说了一下计算的方法,这里详细写下计算校验码和验证校验码的细节。class
将接收到的消息还原转义后除去消息标识和校验位,按位异或获得的结果就是这条消息的校验码,和校验位比对验证其的一致性。
将要发出的消息封装好后出去标示位外,按位异或,获得的校验码放在消息尾部,而后转义。终端
#按位伪代码 function bcc(array data) { xor = data[0]; for(i=1; i< data.length; i++) { xor ^= data[i] } return xor }
熟悉上面的过程且看下以下代码:
/** * Jt808协议解析 */ class Jt808 implements Protocol { public $hex; /** * 消息体内容 * @var |body */ public $body; /** * 转义与转义还原时使用 * @var array */ public $search = ['7d01', '7d02']; public $replace = ['7d', '7e']; ... ... /** * 转义消息内容 * 7d -> 7d01 * 7e -> 7d02 * @return mixed */ public function escape($msg = '') { if ($msg) { return '7e' . str_replace($this->replace, $this->search, $msg) . '7e'; } else { $this->hex = '7e' . str_replace($this->replace, $this->search, substr($this->hex, 2, -2)) . '7e'; } } /** * 还原转义 * 7d01 -> 7d * 7d02 -> 7e * @return mixed */ public function descape($msg = '') { if ($msg) { return str_replace($this->search, $this->replace, $msg); } else { $this->hex = '7e' . str_replace($this->search, $this->replace, substr($this->hex, 2, -2)) . '7e'; } } }
#@param check_code|校验码 为空是计算校验码,不为空为验证校验码 function bcc($msg, $check_code = '') { //按两位字符切割字符串 $check_str_array = str_split($msg, 2); $str_len = count($check_str_array); $xor = hexdec($check_str_array[0]); for ($i = 1; $i < $str_len; $i++) { $xor ^= hexdec($check_str_array[$i]); } $xor = dechex($xor); $xor = str_pad($xor, 2, 0, STR_PAD_LEFT); #不足两位前面填充0 if (!$check_code) { return $xor; } return $xor == $check_code; }