如何用PHP解码GT06协议GPS追踪器的十六进制值?
GT06协议GPS位置解码修正方案
问题分析
你的代码存在三个核心问题导致位置解析错误:
- 未校验消息类型:GT06协议中只有
0x22(十六进制22)是位置上报消息,你的代码未判断消息ID,可能误处理其他类型消息(比如第一个payload是0x13心跳/状态消息)。 - 经纬度截取位置错误:位置字段的起始偏移计算错误,导致取到了错误的字节数据。
- 未处理小端字节序:GT06协议的多字节字段(如经纬度)采用小端序存储(低字节在前),原代码直接按字符串顺序解析,数值完全错误。
修正后的解码代码
protected function processLocationUpdate($hexData) { // 校验消息合法性 if (strlen($hexData) < 8) { $this->error("Invalid GT06 message format."); return; } // 提取消息ID,仅处理位置上报消息(0x22) $msgId = substr($hexData, 4, 2); if ($msgId !== '22') { $this->info("Skipping non-location message (ID: $msgId)."); return; } // 校验位置消息最小长度 if (strlen($hexData) < 76) { $this->error("Insufficient data for location update."); return; } // 解析纬度(3字节,小端序) $latitudeHex = substr($hexData, 14, 6); $reversedLatHex = implode('', array_reverse(str_split($latitudeHex, 2))); $latValue = hexdec($reversedLatHex); if ($latValue >= 0x800000) { $latValue -= 0x1000000; } $latitude = $latValue / 1000000; // 解析经度(4字节,小端序) $longitudeHex = substr($hexData, 20, 8); $reversedLonHex = implode('', array_reverse(str_split($longitudeHex, 2))); $lonValue = hexdec($reversedLonHex); if ($lonValue >= 0x80000000) { $lonValue -= 0x100000000; } $longitude = $lonValue / 1000000; $this->info("GPS Location - Latitude: " . number_format($latitude, 6) . ", Longitude: " . number_format($longitude, 6)); $this->info("Raw location hex: " . $latitudeHex . " | " . $longitudeHex); $this->info("Reversed hex for decoding: " . $reversedLatHex . " | " . $reversedLonHex); }
针对你的测试数据的解析结果
对于第二个位置上报payload:
Raw payload: 7878222204010101121dc000a39db508a59d9c000400019d01f956003bda00000002c6b3280d0a
解析后得到:
- 纬度:
-4.191982°(南纬) - 经度:
-125.150848°(西经)
该位置位于南美洲智利附近,符合GPS坐标逻辑。
第一个payload是0x13类型消息,代码会自动跳过位置解析,符合预期。
补充说明
GT06协议的核心规则:
- 帧头固定为
7878,帧尾固定为0d0a - 多字节数值字段(经纬度、速度、方向等)均为小端序存储,需反转字节后再解析
- 经纬度以度×10^6的整数形式存储,用补码表示正负(北纬/东经为正,南纬/西经为负)
内容的提问来源于stack exchange,提问作者tsn games
相关产品推荐
相关产品推荐

