使用 Python 从多个低功耗蓝牙 BLE 设备存储数据

像 Hexiwear 这样的 BLE(低功耗蓝牙)传感器设备非常棒,但是不能存储大量的数据。对于一个研究项目,我必须从许多 BLE 设备收集数据以供后续处理。我使用的是在 Raspberry Pi 上运行的 Python 脚本,它收集数据并将其存储在文件中。

从单一设备接收数据

以下脚本用于从单个设备获取传感器数据:

# Using Hexiwear with Python
# Script to get the device data and append it to a file
# Usage
# python GetData.py <device>
# e.g. python GetData.py "00:29:40:08:00:01"
import pexpect
import time
import sys
import os
# ---------------------------------------------------------------------
# function to transform hex string like "0a cd" into signed integer
# ---------------------------------------------------------------------
def hexStrToInt(hexstr):
    val = int(hexstr[0:2],16) + (int(hexstr[3:5],16)<<8)
    if ((val&0x8000)==0x8000): # treat signed 16bits
        val = -((val^0xffff)+1)
    return val
# ---------------------------------------------------------------------
DEVICE = "00:29:40:08:00:01"   # device #24
if len(sys.argv) == 2:
  DEVICE = str(sys.argv[1])
# Run gatttool interactively.
child = pexpect.spawn("gatttool -I")
# Connect to the device.
print("Connecting to:"),
print(DEVICE)
NOF_REMAINING_RETRY = 3
while True:
  try:
    child.sendline("connect {0}".format(DEVICE))
    child.expect("Connection successful", timeout=5)
  except pexpect.TIMEOUT:
    NOF_REMAINING_RETRY = NOF_REMAINING_RETRY-1
    if (NOF_REMAINING_RETRY>0):
      print "timeout, retry..."
      continue
    else:
      print "timeout, giving up."
      break
  else:
    print("Connected!")
    break
if NOF_REMAINING_RETRY>0:
  unixTime = int(time.time())
  unixTime += 60*60 # GMT+1
  unixTime += 60*60 # added daylight saving time of one hour
  # open file
  file = open("data.csv", "a")
  if (os.path.getsize("data.csv")==0):
    file.write("Device\ttime\tAppMode\tBattery\tAmbient\tTemperature\tHumidity\tPressure\tHeartRate\tSteps\tCalorie\tAccX\tAccY\tAccZ\tGyroX\tGyroY\tGyroZ\tMagX\tMagY\tMagZ\n")
  file.write(DEVICE)
  file.write("\t")
  file.write(str(unixTime)) # Unix timestamp in seconds 
  file.write("\t")
  # App mode
  child.sendline("char-read-hnd 0x6d")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("AppMode:  "),
  print(child.before),
  print(str(int(child.before[0:2],16)))
  file.write(str(int(child.before[0:2],16)))
  file.write("\t")
  # Battery
  child.sendline("char-read-hnd 0x28")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("Battery:  "),
  print(child.before),
  print(str(int(child.before[0:2],16)))
  file.write(str(int(child.before[0:2],16)))
  file.write("\t")
  # Ambient Light (0x2011)
  child.sendline("char-read-hnd 0x3f")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("Ambient:  "),
  print(child.before),
  print(str(int(child.before[0:2],16)))
  file.write(str(int(child.before[0:2],16)))
  file.write("\t")
  # Temperature (0x2012)
  child.sendline("char-read-hnd 0x43")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("Temperature:  "),
  print(child.before),
  print(float(hexStrToInt(child.before[0:5]))/100)
  file.write(str(float(hexStrToInt(child.before[0:5]))/100))
  file.write("\t")
  # Humidity (0x2013)
  child.sendline("char-read-hnd 0x47")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("Humidity:  "),
  print(child.before),
  print(float(hexStrToInt(child.before[0:5]))/100)
  file.write(str(float(hexStrToInt(child.before[0:5]))/100))
  file.write("\t")
  # Pressure (0x2014)
  child.sendline("char-read-hnd 0x4b")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("Pressure:  "),
  print(child.before),
  print(float(hexStrToInt(child.before[0:5]))/100)
  file.write(str(float(hexStrToInt(child.before[0:5]))/100))
  file.write("\t")
  # HeartRate (0x2021)
  child.sendline("char-read-hnd 0x52")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("HeartRate:  "),
  print(child.before),
  print(str(int(child.before[0:2],16)))
  file.write(str(int(child.before[0:2],16)))
  file.write("\t")
  # Steps (0x2022)
  child.sendline("char-read-hnd 0x56")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("Steps:  "),
  print(child.before),
  print(hexStrToInt(child.before[0:5]))
  file.write(str(hexStrToInt(child.before[0:5])))
  file.write("\t")
  # Calorie (0x2023)
  child.sendline("char-read-hnd 0x5a")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("Calorie:  "),
  print(child.before),
  print(hexStrToInt(child.before[0:5]))
  file.write(str(hexStrToInt(child.before[0:5])))
  file.write("\t")
  # Accelerometer
  child.sendline("char-read-hnd 0x30")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=5)
  print("Accel:  "),
  print(child.before),
  print(float(hexStrToInt(child.before[0:5]))/100),
  print(float(hexStrToInt(child.before[6:11]))/100),
  print(float(hexStrToInt(child.before[12:17]))/100)
  file.write(str(float(hexStrToInt(child.before[0:5]))/100))
  file.write("\t")
  file.write(str(float(hexStrToInt(child.before[6:11]))/100))
  file.write("\t")
  file.write(str(float(hexStrToInt(child.before[12:17]))/100))
  file.write("\t")
  # Gyro
  child.sendline("char-read-hnd 0x34")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=10)
  print("Gyro:   "),
  print(child.before),
  print(float(hexStrToInt(child.before[0:5]))/100),
  print(float(hexStrToInt(child.before[6:11]))/100),
  print(float(hexStrToInt(child.before[12:17]))/100)
  file.write(str(float(hexStrToInt(child.before[0:5]))/100))
  file.write("\t")
  file.write(str(float(hexStrToInt(child.before[6:11]))/100))
  file.write("\t")
  file.write(str(float(hexStrToInt(child.before[12:17]))/100))
  file.write("\t")
  # Magnetometer
  child.sendline("char-read-hnd 0x38")
  child.expect("Characteristic value/descriptor: ", timeout=5)
  child.expect("\r\n", timeout=10)
  print("Magneto:"),
  print(child.before),
  print(hexStrToInt(child.before[0:5])),
  print(hexStrToInt(child.before[6:11])),
  print(hexStrToInt(child.before[12:17]))
  file.write(str(float(hexStrToInt(child.before[0:5]))/100))
  file.write("\t")
  file.write(str(float(hexStrToInt(child.before[6:11]))/100))
  file.write("\t")
  file.write(str(float(hexStrToInt(child.before[12:17]))/100))
  file.write("\t")
  file.write("\n")
  file.close()
  print("done!")
  sys.exit(0)
else:
  print("FAILED!")
  sys.exit(-1)

使用设备 ID 调用它,它获取传感器节点数据,将其附加到文件,并在控制台上显示它:

pi@raspberrypi:~ $ python GetData.py "00:2A:40:0B:00:4E"
Connecting to: 00:2A:40:0B:00:4E
Connected!
AppMode: 02 2
Battery: 64 100
Ambient: 0b 11
Accel: 05 00 02 00 9b ff 0.05 0.02 -1.01
...
done!

数据被存储到 CSV 文本文件中。

从多个设备获取数据

以下脚本用于从多个设备获取数据:

# Python script to get data from multiple devices
# Usage:
# python GetDataAll.py
import subprocess
# list of devices
devices = [
  "00:32:40:08:00:12",  # device 01
  "00:2F:17:03:00:35",  # device 20
  "00:28:22:0C:00:15",  # device 21
  "00:15:77:03:10:01",  # device 22
  "00:2A:40:0B:00:4E",  # device 23
  "00:29:40:08:00:01",  # device 24
   ]
for x in range(0,len(devices)):
  cmd = "python GetData.py " + devices[x]
  subprocess.call(cmd, shell=True)
print("finished all devices!")

该脚本有一个 BLE 设备列表,用于轮询数据。

总结

通过使用 Raspberry Pi 和 Python 脚本,我可以从多个 BLE 设备收集数据,并将信息存储到文件中以供进一步处理。 因为我不需要保持 BLE 连接处于活动状态,所以我可以将其扩展到几乎不限数量的设备,而不会遇到大约八个设备的典型 BLE 连接限制。

我正在使用类似的方法来更新所有的设备(例如使用当前的时间/日期),另外我在每个 BLE 设备中都实现了一个远程shell:这样,我可以向每个节点发送命令,然后执行 BLE 设备。

使用的 Python 脚本可以在 GitHub 上找到。

英语原文链接:https://dzone.com/articles/using-python-to-store-data-from-many-ble-devices

尚未评分
您的评分将帮助我们做出更好的玩法

观光\评论区

Copyright © 2017 玩点什么. 闽ICP备17004100号-4 All Rights Reserved.