通过拆卸制造库从蓝牙电子秤获取体重数据

问题描述

一个朋友拥有蓝牙Le的体重计。要保存体重,他必须在手机上打开Manufactures App。因此,我们尝试使用他的树莓派做作业。我们发现,规模是通过广告发送数据的。秤永远无法连接,您可以同时使用不同的电话来接收数据。在测量过程中,应用显示的值与秤的显示值相同。您知道,如果您站在秤上,则该值将上下波动,直到测量完成。在手机上,或者在您同时使用多个手机的情况下,此“向上和向下”也可见。因此,我认为事实是,数据是通过BLe广告传输的。它们只能出现在制造商数据中,例如:

starts always with:
0f ff ac a0 db 58 e2 53 91 a0

and then:

88,30kg
20 c9 f8 42 0d b0
20 c9 f8 78 0d a6

88,35kg
20 c9 f9 b4 0d a3
20 c9 f9 88 0d b7

88,40kg
20 c9 f9 e6 0d b5
20 c9 f9 e6 0d b5

2,15kg
a0 c8 ab 40 0d a0

0,00kg
a0 c8 a0 a0 0d b5

但是无论我如何尝试,我都无法按照给定的权重计算此数据。我用大尾数法,小尾数法,磅,盎司或什至石头之类的其他单位尝试过。我找不到公式来计算每个已知重量的数据。有趣的是,零是“ a0 c8 a0 a0 0d b5”。在测量过程中,第一个字节为20,完成后,秤会发送许多广告包装,第一个字节为a0。我认为这将是“最终价值”。无论如何,第五个字节始终为0d。第二个字节在权重较高时从c8更改为c9。我认为是50或60公斤。 因为我找不到解决方案,所以尝试了其他方法。我反编译了android应用程序的外观,其中解析了advertisment-package。不幸的是,该应用程序加载了本机库来执行此操作。看起来该制造厂真的想保守它的秘密。我试图将它们的库用于我的一个目的。但是看来我需要一个头文件才能在我自己的Java应用程序中使用该库。所以我最后的机会是拆卸图书馆,我已经做了。我用objdump。我从Java代码知道,我需要的功能是

private native List<Map<String,Object>> decode(byte[] bArr,int i,int i2,Object obj);

我可以在转储文件中找到此函数/子例程。但是我不明白如何使用它。我看了一个汇编程序的视频教程系列,这虽然很有趣,但是并不能帮助我。我假设您可以以某种方式查看数据的来源(用于解码的参数),如何处理和返回数据(例如保存到内存中)。我还找到了“ BleBroadcastScaleProtocol16decodeWeightData”功能,但仍然存在相同的问题。我现在的问题是:真的有机会这样做吗?转储文件具有10MB的文本。有人知道该怎么做,还是以前做过类似的事情?我已经为此工作了几个月,而且向前迈出了两步。

我将转储文件放在我的Cloud驱动器上,也许有人会看看。

Dump File

编辑: 我使用Raspberry Pi将广告发送到Manufactures App。我使用来自bluez的example-advertisement脚本。 如果我在制造商数据的前两个字节上发送带有Service-ID FFB0和“ aca0”的广告,则该应用会将pi识别为“智能”等级。 我还可以将体重数据发送到应用程序。如果我发送“((ac a0 db 58 e2 53 91 a0) a0 c8 a0 a0 0d b5“该应用显示0。 我玩了一下,发现最后四位是校验和,是通过将所有十六进制值相加而得出的,并取摘要的最后四位。 重量数据必须在2.至4.位(c8-秒a0)中。我编写了一个脚本,以从偏移量获取16位并打印出十六进制值。作为输入数据,我使用c8a0a0(= 0)。偏移量为1(从位2开始占用16位),它打印出“ 0x9141”。 在第二个脚本中,我可以输入一个十六进制值,它将与默认值“ c8a0a0”合并。因此,我可以输入9142并将其汇总为可以作为制造商数据发送的数据。 9142是c8a120,什么也没做,但9143是c8a1a0。该值为0.25kg。当我将第一个值(9143)增加2时,它将在应用程序中添加0.25kg。有时会增加0.3公斤。这适用于917f / c8bfa0 / 7,95kg。如果我转到9181 / c8c0a0,则跳至24,55kg。 i可以以0,25kg的步长继续前进到9195 / c8caa0 / 27,15kg。在9197 / c8cba0上,它更改单位并显示4:4.4st:lb。 如果我加1,则应用程序大多数时候都会崩溃,其他值(9144、9146、9148 ...) 有人认出其中的图案吗? 我也开始尝试不同的偏移量,但是看起来不太有前途。

Edit2: 4:4.4st:lb等于27.397kg。下一步是4:5.0st:lb,什么是27.67kg。因此,此时它是线性的。但是缺少8-24公斤的范围

Here are the scripts that i use

解决方法

更新: 根据您提供的数据,我认为您已经找到了可以找到权重值的模式。看起来可以将C8A0A0作为起始值(0kg)从2到4字节提取权重值。

要获取权重值,可以用C8A0A0减去第二至第四字节值。然后将答案除以1000。

以下示例基于您的数据。括号内的是您观察到的公斤值。

(0.25公斤) C8A1A0-C8A0A0 = 100HEX => 256DEC => 0.256kg

(7.95公斤) C8BFA0-C8A0A0 = 1F00HEX => 7936DEC => 7.936kg

(88.3公斤) C9F842-C8A0A0 = 157A2HEX => 87970DEC => 87.97千克 C9F878-C8A0A0 = 158D8HEX => 88280DEC => 88.28kg

(88.35公斤) C9F9B4-C8A0A0 = 15914HEX => 88340DEC => 88.34kg C9F988-C8A0A0 = 158E8HEX => 88296DEC => 88.296kg

(88.40公斤) C9F9E6-C8A0A0 = 15946HEX => 88390DEC => 88.39kg

(2.15公斤) C8AB40-C8A0A0 = AA0HEX => 2720DEC => 2.72kg

请尝试模拟发送C9B210的更多数据,看看是否能获得接近70kg的重量值。

上一个答案: 重量数据可能不在广告中。在您的描述中,我不清楚您是否尝试以标准方式连接到蓝牙电子秤。您可以使用nRF或Lightblue应用程序执行此操作。 这是常规过程:

  1. 打开应用。让它检测蓝牙规模。
  2. 连接到设备。确保体重秤未连接到其他应用程序(例如它自己的应用程序)。
  3. 您将看到有关服务和特征的UUID。
  4. 找到具有“通知”和“指示”特征的uuid,并订阅所有具有该特征的uuid。
  5. 在刻度值更改时查找这些特性的日志。您最有可能在其中看到体重数据。

根据体重秤的功能,可能需要在体重秤处于活动状态且尚未确定最终值时执行所有这些步骤,以便进行蓝牙通信。您可以通过在操作该应用程序时不断地跳入/跳出比例尺来做到这一点。

,

我们终于弄清楚了如何获取体重数据。正如我建议的那样,重量数据在第二到第四字节中,例如:c9 f8 42。 但是要获得正确的数据,您必须做一些奇怪的事情:必须像这样替换十六进制字符串的第三个和第五个“字符”:

0 1 2 3 4 5 6 7 8 9 a b c d e f Normal
a b 8 9 e f c d 2 3 0 1 6 7 4 5 Icomon

例如,c8a0a0(= 0,00kg)将变为0xC80000。 将其转换为整数并减去0xC80000,除以1000,就可以得到它。在此示例中,它仅为0,但我使用我们尝试的每个值。

我真的不知道这与Big / little Endian或MSB / LSB恶作剧有什么关系,还是只是一个非常简单的“加密”,但它完全可以工作。

感谢任何人的帮助,我们在这里有了一些新想法,这使我们找到了答案

这是我们用来解码数据的python文件:

#!/usr/bin/env python3
import sys
# 0 1 2 3 4 5 6 7 8 9 a b c d e f normal people
# a b 8 9 e f c d 2 3 0 1 6 7 4 5 Icomon
def main():
  hex_code = sys.argv[1]
  ic = ['a','b','8','9','e','f','c','d','2','3','0','1','6','7','4','5']

  i=0
  out=''
  for byte in hex_code:
    if i in [2,4]:
      index = int(f'0x{byte}',16)
      out = out+ic[index]
    else: out=out+byte  
    i=i+1
  value = round((int(f'0x{out}',16)-0xc80000)/1000,2)
  value=round05(value)
  print(value)

def round05(number):
  return (round(number * 20) / 20)

main()

编辑: 好吧,现在我知道'shenanigans'只是XOR。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...