【问题标题】:How to convert my binary (hex) data to latitude and longitude?如何将我的二进制(十六进制)数据转换为纬度和经度?
【发布时间】:2011-07-04 14:09:21
【问题描述】:

我有一些传递地理位置坐标的二进制数据流 - 纬度和经度。我需要找到它们的编码方法。

4adac812 = 74°26.2851' = 74.438085
2b6059f9 = 43°0.2763'  = 43.004605

4adaee12 = 74°26.3003' = 74.438338
2a3c8df9 = 42°56.3177' = 42.938628

4ae86d11 = 74°40.1463' = 74.669105
2afd0efb = 42°59.6263' = 42.993772

第一个值是十六进制值。第 2 和第 3 是我在输出中得到的值(不确定在转换中使用了哪一个)。

我发现第一个字节代表值的整数部分(0x4a = 74)。但我找不到小数部分是如何编码的。

非常感谢任何帮助!

谢谢。

--

Upd:这个流通过 tcp 协议来自一些“中国”gps 服务器软件。我没有 clent 软件的资源或文档。我想它是用 VC++6 编写的,并使用了一些标准实现。

--

更新:这是我收到的数据包:

Hex data:
41 00 00 00  13 bd b2 2c
4a e8 6d 11  2a 3c 8d f9
f6 0c ee 13

Log data in client soft:
[Lng] 74°40.1463', direction:1
[Lat] 42°56.3177', direction:1
[Head] direction:1006, speed:3318, AVA:1
[Time] 2011-02-25 19:52:19

Result data in client (UI):
74.669105
42.938628
Head 100 // floor(1006/10)
Speed 61.1 // floor(3318/54.3)


41 00 00 00  b1 bc b2 2c
4a da ee 12  2b 60 59 f9
00 00 bc 11
[Lng] 74°26.3003', direction:1
[Lat] 43°0.2763', direction:1
[Head] direction:444, speed:0, AVA:1
[Time] 2011-02-25 19:50:49
74.438338
43.004605


00 00 00 00  21 bd b2 2c
4a da c8 12  aa fd 0e fb
0d 0b e1 1d
[Lng] 74°26.2851', direction:1
[Lat] 42°59.6263', direction:1
[Head] direction:3553, speed:2829, AVA:1
[Time] 2011-02-25 19:52:33
74.438085
42.993772

我不知道前 4 个字节是什么意思。

我发现第 5 个字节的低 7 位代表秒数。 (也许 5-8 位是时间?) 字节 9 表示 Lat 的整数。

字节 13 是 Lng 的整数。

字节 17-18 反转(字字节)是速度。

字节 19-20 反转为 ava(?) 和方向(4 + 12 位)。 (顺便说一句,有人知道 ava 是什么吗?)

还有一个音符。在第 3 个数据包的第 13 个字节中,您可以看到仅使用了低 7 位。我猜第 1 位并不意味着什么(我一开始就删除了,如果我错了,请见谅)。

【问题讨论】:

  • 流来自什么设备?
  • 这是一个非常甜蜜的谜题。
  • 是的,请发布二进制数据包。即使它是一个中国随机数生成器,我们也应该能够想出一些疯狂的公式来推导出它。 :)
  • 你说:“我想它是用 VC++6 编写的” 你有 VC 项目吗?源代码将是解决这个问题的理想选择,呵呵。如果没有,但您可以给我们一份客户端程序的副本:这样我们就可以在调试器中查看它。
  • 是的,能够分析二进制文件可能是获取此信息的最直接方式。

标签: binary hex coordinates


【解决方案1】:

在这里进行头脑风暴。

如果我们查看第二个字节的低 6 位(data[1]&0x3f),我们会得到大多数示例的“分钟”值。

0xda & 0x3f = 0x1a = 26; // ok
0x60 & 0x3f = 0; // ok
0xe8 & 0x3f = 0x28 = 40; // ok
0x3c & 0x3f = 0x3c = 60; // should be 56
0xfd & 0x3f = 0x3d = 61; // should be 59

也许这是正确的方向?

【讨论】:

  • 0x60 & 0x3f = 01100000 && 00111111 = 32 // 不行。
【解决方案2】:

我已对您的数据进行了重新排序,因此我们首先有 3 个经度,然后是 3 个纬度:

74.438085、74.438338、74.669105、43.004605、42.938628、42.993772

这是我能想到的最适合的十六进制数:

74.437368、74.439881、74.668392、42.993224、42.961388、42.982391

区别是:-0.000717、0.001543、-0.000713、-0.011381、0.022760、-0.011381

从完整的十六进制(4 个而不是 3 个字节)生成这些值的程序是:

int main(int argc, char** argv) {
    int a[] = { 0x4adac812, 0x4adaee12, 0x4ae86d11, 0x2b6059f9, 0x2a3c8df9, 0x2afd0efb };
    int i = 0;
    while(i<3) {
        double b = (double)a[i] / (2<<(3*8)) * 8.668993 -250.0197;
        printf("%f\n",b);
        i++;
    }
    while(i<6) {
        double b = (double)a[i] / (2<<(3*8)) *  0.05586007 +41.78172;
        printf("%f\n",b);
    i++;
    }
    printf("press key");
    getch();
}

【讨论】:

  • 不错!我会试一试。但我对这些 8.668993、250.0197 等感到困惑。它可以在其他位置(不同于 74x43 和附近)工作吗?虽然我无法在其他位置验证它,但我会使用你的方法。 ;)
  • 这 4 个常量来自您的第一个数据包,并且对第二个数据包工作得相当好。我无法验证它们是否适用于完全不同的经度+纬度,因为我没有一些疯狂的中国 gps 东西可以给我更多数据:)
  • @AKE 如果您的 GPS 设备与 DarkSerg 的 GPS 设备具有相同的编码,这可能只会对您有所帮助。问题是他的 GPS 设备提供了一些字节,他需要知道是哪种格式。他给了我们他真实的 GPS 坐标,所以我可以重新排序,然后将 0...2^32 缩放到纬度/经度刻度浮动 0.0...360.0。
  • @eznme:是的,我推断的差不多。但这里有用的是您采用的方法,可以在其他情况下复制。聪明的!谢谢回复。 (顺便说一句——你知道 DarkSerg 的最后评论是什么意思吗——他为什么认为还有其他方法?是因为他不明白你在使用比例匹配吗?
  • @AKE 谢谢。我想他预计结果会在 1 米以内。例如 0.000717 度是 80 米。这可能是因为他在之后才添加了 5-6 位数字,这可能会给出比 80 米更近的距离(尽管非移动手持设备的分辨率 > 5m)。
【解决方案3】:

我已经试过你的新数据包了:

74+40.1463/60 74+26.3003/60 74+26.2851/60 42+56.3177/60 43+0.2763/60 42+59.6263/60

74.66910, 74.43834, 74.43809, 42.93863, 43.00460, 42.99377

我的程序给出:

74.668392, 74.439881, 74.437368, 42.961388, 42.993224, 39.407346

区别在于:

-0.000708,  0.001541,  -0.000722,  0.022758, -0.011376, -3.586424

我重新使用了从您的第一个数据包中派生的 4 个常量,因为它们可能存储在您的客户端某处。细微的差异可能是客户端为了防止您获得确切值或对其协议进行逆向工程而进行的一些随机化的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 2021-12-26
    • 2010-11-11
    • 2019-08-04
    • 2013-11-27
    • 1970-01-01
    相关资源
    最近更新 更多