如何将十六进制解释为无符号长整型(20 位整数、12 位分数、模 20 位)



我以UDP数据包的形式从传感器获取数据。手册提供了这些数据包的形式,但我无法理解如何解释时间戳。它被描述为长度为 4 个字节的无符号长整型(例如"a07245ba"),应该被解释为 20 位整数和 12 位分数。我也对包含的"模 20 位"信息感到困惑。

如何正确解释这些时间戳?

我尝试使用Python的"int('str', 16)"函数(例如int('a0724',16)和int('5ba',16))简单地将数字解释为两部分,然后将这两个部分与小数组合(例如'657188.1466秒')。 这似乎给了我时间戳(秒)的正确单位,因为我记录了 ~10 秒的数据,第一个和最后一个时间戳相隔 10 秒。但是,数字的小数部分似乎不正确。当我绘制数据时,时间戳会意外地向前和向后跳跃,这让我相信我错误地解释了时间戳。

此外,我解释的时间戳与任何预期值无关。手册说它应该以开机后的秒数或自 2010 年 1 月 1 日以来的秒数返回。检查时,这两种情况似乎都不是这样。

因此,时间戳意外跳升到 726162.71 秒,然后回落到 726126.125 秒。前四个字节是时间戳:

datasample = np.array(['b1491fda 00001017 00040a88 00000000 0a 02 00c24d18 0076dd10 fd13fe3c 0032d8ce 0222c71a 01f0f0fa',
'b1492010 00001018 00040a88 00000000 0a 02 00c249aa 0076dbee fd148e86 0032dc34 02235336 01f0f3c8',
'b1492047 00001019 00040a88 00000000 0a 02 00c2463c 0076dacc fd151ed0 0032df9a 0223df52 01f0f696',
'b149207d 0000101a 00040a88 00000000 0a 02 00c248d0 0076da0a fd13fff4 003265b8 02239a24 01f0f3e0',
'b14920b4 0000101b 00040a88 00000000 0a 02 00c248d0 0076da0a fd13fff4 003265b8 02239a24 01f0f3e0',
'b14920eb 0000101c 00040a88 00000000 0a 02 00c1eed0 0076a812 fd148d00 0032b896 022396fe 01f0b4ac'],
dtype='|S98')
timesample = np.array([726161.4058, 726162.16, 726162.71, 726162.125, 726162.18, 726162.235 ])

下面是相隔 ~10 秒的两个数据包的示例:

datasample10 = np.array(['b1a2f9ea 000012ea 00040a88 00000000 0a 02 00c230d4 007671a6 fd1c2538 002b512e 021b9f7c 01f14944',
'b1a39a8e 000015db 00040a88 00000000 0a 02 00c1d26c 0076b032 fd1c3554 002d51b2 021bd5a0 01f0cd92'],
dtype='|S98')
timesample10 = np.array([727599.2538, 727609.2702])

> 12 位可以表示2**12不同的数字。它可以表示从02**12 - 1的整数(即4095)。 如果我们采用该整数的十进制字符串表示形式并将其直接转换为秒的小数部分, 那么我们只能表示从00.4096的小数秒。这似乎不对。

为了在01之间均匀分布小数部分,我们希望除以4096

import numpy as np
datasample = np.array(['b1491fda 00001017 00040a88 00000000 0a 02 00c24d18 0076dd10 fd13fe3c 0032d8ce 0222c71a 01f0f0fa',
'b1492010 00001018 00040a88 00000000 0a 02 00c249aa 0076dbee fd148e86 0032dc34 02235336 01f0f3c8',
'b1492047 00001019 00040a88 00000000 0a 02 00c2463c 0076dacc fd151ed0 0032df9a 0223df52 01f0f696',
'b149207d 0000101a 00040a88 00000000 0a 02 00c248d0 0076da0a fd13fff4 003265b8 02239a24 01f0f3e0',
'b14920b4 0000101b 00040a88 00000000 0a 02 00c248d0 0076da0a fd13fff4 003265b8 02239a24 01f0f3e0',
'b14920eb 0000101c 00040a88 00000000 0a 02 00c1eed0 0076a812 fd148d00 0032b896 022396fe 01f0b4ac'],
dtype='|S98')
print(np.array([int(row[:8],16)  for row in datasample]) / 2**12)

收益 率

[726161.99072266 726162.00390625 726162.01733398 726162.03051758 726162.04394531 726162.05737305]

这有一个很好的属性,即时间戳都在增加:

result = (np.array([int(row[:8],16)  for row in datasample]) / 2**12)
print(np.diff(result))
# [0.01318359 0.01342773 0.01318359 0.01342773 0.01342773]

datasample10映射到相隔约 10 秒的时间戳:

datasample10 = np.array(['b1a2f9ea 000012ea 00040a88 00000000 0a 02 00c230d4 007671a6 fd1c2538 002b512e 021b9f7c 01f14944',
'b1a39a8e 000015db 00040a88 00000000 0a 02 00c1d26c 0076b032 fd1c3554 002d51b2 021bd5a0 01f0cd92'],
dtype='|S98')
result = (np.array([int(row[:8],16)  for row in datasample10]) / 2**12)
print(np.diff(result))
# [10.04003906]

我不确定这些十六进制字符串应该如何解释为秒 自电源打开或自 2010-1-1 以来。 如果它们旨在表示自打开电源以来的秒数,并且可能您发布的数据是在不久之后发布的, 那么使数字大小合理的一种方法是取整数模2**20- 即模20位:

result = (np.array([int(row[:8],16)  for row in datasample]) % 2**20 / 2**12) 
print(result)
# [145.99072266 146.00390625 146.01733398 146.03051758 146.04394531 146.05737305]

但如果这是正确的,那么在最初的 32 位中,只有最右边的 20 位 正在使用,小数部分为 12 位,整体为 8 位 秒。这意味着在值循环回 0 之前,最大时间戳仅为 256。 这似乎相当有限,所以我不相信这是解释"模 20 位"的正确方法。

另一方面,如果时间戳旨在表示自 2010-1-1 以来的秒数,那么我们应该期望整数在 301000000:

import datetime as DT
print((DT.datetime.now() - DT.datetime(2010,1,1)).total_seconds())
# 301151491.085063

我还没有设法猜测从日期样本到 3.01 亿范围内的时间戳的映射 它保留了单调性和已知的 10 秒间隔。

<块引用类>

好吧,我们可以在当前的公式中增加 3.01 亿,但这完全是人为的......

相关内容

最新更新