终端是指obd设备,既车载obd设备。php
平台是指上文中说到的经过短信设置的上报IP指向的机器所提供的网关服务。this
这两种消息一是终端设备发出的,一是平台发出的,都是通用应答的格式,所谓通用既是能够用于应答其余消息的一种消息格式。code
0x0001终端通用应答
起始字节
字段
数据类型
描述及要求
0
应答流水号
WORD
对应的平台消息的流水号
2
应答 ID
WORD
对应的平台消息的 ID
4
结果
BYTE
0:成功/确认;1:失败;2:消息有误;3:不支持
ps.上表省略消息头部分,默认全部的应答和发送都带有消息头字符串
在平台下发指令或者设置终端参数(0x8103)时设备将应答此消息。it
应答流水号:一个四位字符的16进制字符串,是平台消息的流水号,能够为 0000
应答ID: 四位字符16进制的消息id,如(8103,0001等)
应答结果:两位字符的16进制字符,如表中的结果应答为,00:成功,01:失败,02:消息有误等
0x8001平台通用应答
设备发送的消息,除注册应答(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;
}