【问题标题】:Reading the longitude [28:0] from a 4 byte hexadecimal number从 4 字节十六进制数中读取经度 [28:0]
【发布时间】:2021-04-01 20:21:18
【问题描述】:

我收到一个 4 字节十六进制字符串的经度和精度:99054840 我正在尝试从此值中提取经度。

规格告诉我以下内容:

  • 位 [28:0]:有符号值 λ,小端格式,经度° = λ ÷ 1,000,000

  • 位 [31:29]:无符号值 α,范围 0-7,精度度量

我的设备实际位于经度 4.7199。所以我现在转换的结果应该是什么。

读取我当前所做的经度值(结果不正确):

def get_longitude(reading):
    # split in different bytes
    n=2
    all_bytes = [reading[i:i+n] for i in range(0, len(reading), n)]
    
    # convert to binary
    long_bytes_binary = list(map(hex_to_binary, all_bytes))
    
    # drop the accuracy bits
    long_bytes_binary[3] = long_bytes_binary[3][0:5]

    # little endian & concatenate bytes
    longitude_binary = ''.join(list(reversed(long_bytes_binary)))

    # get longitude
    lon = binary_to_decimal(int(longitude_binary))/1_000_000

达到 138.93。与4.7199完全不同(预期结果)

这里是辅助方法

def hex_to_binary(payload):
    scale = 16
    num_of_bits = 8
    binary_payload = bin(int(payload, scale))[2:].zfill(num_of_bits)
    return binary_payload   

def binary_to_decimal(binary): 
  binary1 = binary
  decimal, i, n = 0, 0, 0
  while(binary != 0):
    dec = binary % 10
    decimal = decimal + dec * pow(2, i)
    binary = binary//10
    i += 1
  return decimal 

我做错了什么?如何正确读取值? 还是我的设备坏了:)

【问题讨论】:

    标签: python iot


    【解决方案1】:

    我在这里使用struct 进行字节序交换有点作弊,但你明白了。

    import struct
    
    val = 0x99054840
    val = struct.unpack('<I',struct.pack('>I',val))[0]
    print(hex(val))
    accuracy = (val >> 29) & 7
    longitude = (val & 0x1ffffff) / 1000000
    print(accuracy,longitude)
    

    输出:

    C:\tmp>x.py
    0x40480599
    2 4.720025
    
    C:\tmp>                                               ```
    

    【讨论】:

      【解决方案2】:

      为了准确,OP 代码丢弃了最后 3 位而不是前 3 位。此更改修复了它:

      # drop the accuracy bits
      long_bytes_binary[3] = long_bytes_binary[3][3:]
      

      但计算可以简单得多:

      def hex_to_longitude(x):
          b = bytes.fromhex(x)             # convert hex string to bytes
          i = int.from_bytes(b,'little')   # treat bytes as little-endian integer
          return (i & 0x1FFFFFFF) / 1e6    # 29-bitwise AND mask divided by one million
      
      x = '99054840'
      print(hex_to_longitude(x))
      
      4.720025
      

      【讨论】:

        猜你喜欢
        • 2013-09-20
        • 1970-01-01
        • 2015-08-08
        • 2022-01-17
        • 1970-01-01
        • 1970-01-01
        • 2015-05-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多