Dies ist eine Fortsetzung von # 1, das die LINE über die Körpertemperatur vom BLE-Thermometer mit Raspeltorte informiert. Dieses Mal werden wir es mit Python implementieren. GATT mit Python. Die BLE-Bibliothek verwendet Bluepy.
Die BLE-Bibliothek verwendet bluepy. Installieren Sie bluepy.
$ sudo apt-get update
$ sudo apt-get -y upgrade
$ sudo apt-get -y install python3-pip libglib2.0-dev
$ sudo pip3 install bluepy
>Successfully installed bluepy-1.3.0
$ reboot
Sprechen Sie mit einem BLE-Gerät mit Bluepy.
Scannen Sie zunächst das Werbepaket.
from bluepy import btle
scanner = btle.Scanner(0)
devices = scanner.scan(3.0)
for device in devices:
print(f'BLE Address:{device.addr}')
for (adTypeCode, description, valueText) in device.getScanData():
print(f'- {description}:{valueText}')
Der Code ist einfach, hat aber Traps und erfordert ** sudo-Berechtigungen **, um einen Scan mit bluepy auszuführen. Wenn Sie nicht über genügend Berechtigungen verfügen, wird eine Fehlermeldung mit "scanner.scan ()" angezeigt.
Versetzen Sie das Thermometer in den ** Pairing-Modus ** und lassen Sie dann py laufen.
$ sudo python3 bluepyadv.py
BLE Address:18:93:d7:76:c9:b8
- Flags:05
- Incomplete 16b Services:00001809-0000-1000-8000-00805f9b34fb
- 0x12:5000a000
- Tx Power:00
- Complete Local Name:A&D_UT201BLE_76C9B8
BLE Address:6f:1a:a5:25:58:55
- Flags:06
- Manufacturer:4c001005571cf70bed
BLE-Adresse: 18: 93: d7: 76: c9: b8
ist die Information des Thermometergeräts. Es wurde ordnungsgemäß gescannt.
Holen Sie sich eine Liste der Dienstleistungen, indem Sie an ein Thermometer anschließen. Die BLE-Adresse entspricht einer MAC-Adresse und hängt daher vom Gerät ab. Bitte geben Sie die BLE-Adresse Ihres Geräts an. Die BLE-Adresse meines Thermometers lautet "18: 93: D7: 76: C9: B8".
from bluepy import btle
BLE_ADDRESS="18:93:D7:76:C9:B8"
peripheral = btle.Peripheral()
peripheral.connect(BLE_ADDRESS)
for service in peripheral.getServices():
print(f'Service UUID:{service.uuid}')
for characteristic in service.getCharacteristics():
print(f'- Characteristic UUID:{characteristic.uuid} , Handle:{hex(characteristic.getHandle())} , Property:{characteristic.propertiesToString()}')
Messen Sie mit einem Thermometer und führen Sie py aus, wenn es sich im ** Übertragungsmodus ** befindet. Da es eine Verbindung herstellt, befindet es sich im Übertragungsmodus und nicht im Pairing-Modus. Sie müssen nicht wie zuvor über Sudo-Berechtigungen verfügen.
$ python3 bluepyconnect.py
Service UUID:00001800-0000-1000-8000-00805f9b34fb
- Characteristic UUID:00002a00-0000-1000-8000-00805f9b34fb , Handle:0x3 , Property:READ
- Characteristic UUID:00002a01-0000-1000-8000-00805f9b34fb , Handle:0x5 , Property:READ
- Characteristic UUID:00002a02-0000-1000-8000-00805f9b34fb , Handle:0x7 , Property:READ WRITE
- Characteristic UUID:00002a03-0000-1000-8000-00805f9b34fb , Handle:0x9 , Property:WRITE
- Characteristic UUID:00002a04-0000-1000-8000-00805f9b34fb , Handle:0xb , Property:READ
Service UUID:00001801-0000-1000-8000-00805f9b34fb
- Characteristic UUID:00002a05-0000-1000-8000-00805f9b34fb , Handle:0xe , Property:INDICATE
Service UUID:00001809-0000-1000-8000-00805f9b34fb
- Characteristic UUID:00002a1c-0000-1000-8000-00805f9b34fb , Handle:0x12 , Property:INDICATE
- Characteristic UUID:00002a1d-0000-1000-8000-00805f9b34fb , Handle:0x15 , Property:READ
- Characteristic UUID:00002a08-0000-1000-8000-00805f9b34fb , Handle:0x17 , Property:READ WRITE
Service UUID:0000180a-0000-1000-8000-00805f9b34fb
- Characteristic UUID:00002a29-0000-1000-8000-00805f9b34fb , Handle:0x1a , Property:READ
- Characteristic UUID:00002a24-0000-1000-8000-00805f9b34fb , Handle:0x1c , Property:READ
- Characteristic UUID:00002a25-0000-1000-8000-00805f9b34fb , Handle:0x1e , Property:READ
- Characteristic UUID:00002a27-0000-1000-8000-00805f9b34fb , Handle:0x20 , Property:READ
- Characteristic UUID:00002a26-0000-1000-8000-00805f9b34fb , Handle:0x22 , Property:READ
- Characteristic UUID:00002a28-0000-1000-8000-00805f9b34fb , Handle:0x24 , Property:READ
- Characteristic UUID:00002a23-0000-1000-8000-00805f9b34fb , Handle:0x26 , Property:READ
- Characteristic UUID:00002a2a-0000-1000-8000-00805f9b34fb , Handle:0x28 , Property:READ
Service UUID:0000180f-0000-1000-8000-00805f9b34fb
- Characteristic UUID:00002a19-0000-1000-8000-00805f9b34fb , Handle:0x2b , Property:READ
Service UUID:233bf000-5a34-1b6d-975c-000d5690abe4
- Characteristic UUID:233bf001-5a34-1b6d-975c-000d5690abe4 , Handle:0x2e , Property:READ WRITE
Versuchen Sie, die gemessenen Daten zu empfangen.
import sys
from bluepy import btle
BLE_ADDRESS="18:93:D7:76:C9:B8"
SERVICE_UUID="00001809-0000-1000-8000-00805f9b34fb"
class MyDelegate(btle.DefaultDelegate):
def __init__(self):
btle.DefaultDelegate.__init__(self)
def handleNotification(self, cHandle, data):
print("Handle = " + hex(cHandle))
print("- Flags = " + hex(data[0]))
print("- C1:Temperature Measurement Value(Celsius) = " + hex(data[1])+":"+hex(data[2])+":"+hex(data[3])+":"+hex(data[4]))
print("- C3:Time Stamp = " + hex(data[5])+":"+hex(data[6])+":"+hex(data[7])+":"+hex(data[8])+":"+hex(data[9])+":"+hex(data[10])+":"+hex(data[11]))
if __name__ == '__main__':
print("Start")
print("Connecting Wait...")
try:
peripheral = btle.Peripheral()
peripheral.connect(BLE_ADDRESS)
except:
print("connect Error!")
sys.exit(0)
print("Connected!")
peripheral.withDelegate(MyDelegate())
# Enable Indicate
peripheral.writeCharacteristic(0x13, b'\x02\x00', True)
#Warten Sie auf die Benachrichtigung
print("Indicate Wait...")
try:
TIMEOUT = 3.0
while True:
if peripheral.waitForNotifications(TIMEOUT):
# handleNotification()Hieß
continue
# handleNotification()Wurde auch nach dem Warten auf TIME OUT Sekunden nicht aufgerufen
print("wait...")
except:
#Komm her, wenn die Verbindung getrennt ist
print("except!")
print("end")
Der Punkt ist, dass der Ereignishandler bei "peripher.withDelegate (MyDelegate ())" registriert ist und "peripher.writeCharacteristic (0x13, b" \ x02 \ x00 ", True) ausgeführt wird.
** Geben Sie an, dass der Start beginnt, wenn Sie 0200 auf das Merkmal des Handles 0x13 setzen. ** Wie in Vorherige Beschreibung angegeben. Das Ereignis "handleNotification ()" wird ausgelöst, wenn Daten empfangen werden. Die empfangenen Daten sind in Daten gestaut.
Hinweis Der Handle-Wert von 0x13 kann je nach Gerät unterschiedlich sein (nicht bestätigt). Überprüfen Sie daher den Handle-Wert mit gatttool und geben Sie den Wert Ihres Geräts an.
pi@raspberrypi:~/work/git/BLEThermometer/src $ python3 bluepygatt.py
Start
Connecting Wait...
Connected!
Indicate Wait...
Handle = 0x12
- Flags = 0x6
- C1:Temperature Measurement Value(Celsius) = 0x73:0x1:0x0:0xff
- C3:Time Stamp = 0xe4:0x7:0x5:0x4:0xa:0x7:0x2f
wait...
wait...
except!
end
In diesem Ausführungsprotokoll
Sie können sehen, dass es entfernt wurde.
Ich habe früher herausgefunden, dass "Körpertemperatur = 0x73: 0x1: 0x0: 0xff", aber diese 4-Byte-Daten sind binär im ** IEEE 11073 32-Bit-Float-Format **. Ich konnte keine einfache Möglichkeit finden, eine IEEE 11073 32-Bit-Float-Binärdatei in eine Float-Variable in Python zu konvertieren. Ich konnte nicht anders, also habe ich es selbst gemacht.
import numpy as np
def to_float_from_11073_32bit_float(data):
tmp = int.from_bytes(data,'little')
uint32val = np.array([tmp],dtype=np.uint32)
#Finden Sie das falsche Teil(0-24bit)
tmp = bin(uint32val[0] & 0xffffff)
mantissa = int(tmp,0)
#Suchen Sie den Indexteil(25-32bit)
tmp = int(data[3])
tmp2 = np.array([tmp],dtype=np.byte)
exponent = int(tmp2[0])
#Berechnen Sie reelle Zahlen
ret = round(mantissa * pow(10,exponent),1)
return ret
# 37.1
temp = to_float_from_11073_32bit_float(b'\x73\x01\x00\xff')
print("temp = " + str(temp) + " C")
Ich werde das machen.
$ python3 to_float_from_11073_32bit_float.py
temp = 37.1 C
0x73: 0x1: 0x0: 0xff
ist jetzt ** 37.1 **. Sehr gut.
Der Zeitstempel beträgt 7 Bytes. C3-Format für Temperaturmessung.
def to_date_time(data):
tmp = data[0:2]
yyyy = int.from_bytes(tmp,'little')
mm = int(data[2])
dd = int(data[3])
hh = int(data[4])
min = int(data[5])
ss = int(data[6])
strdate_time=str(yyyy)+"/"+str(mm)+"/"+str(dd)+" "+str(hh)+":"+str(min)+":"+str(ss)
return strdate_time
# 2020/5/4 10:07:47
date_time = to_date_time(b'\xe4\x07\x05\x04\x0a\x07\x2f')
print("date_time = " + date_time)
Ich werde das machen.
$ python3 to_date_time.py
date_time = 2020/5/4 10:7:47
Bisher können Sie mit Bulepy dasselbe tun wie mit Gatttool beim letzten Mal.
Übrigens musste ich das Messergebnis auf LINE benachrichtigen. LINE-Benachrichtigungen sind mit LINE Notify einfach.
Implementieren Sie die LINE-Benachrichtigung anhand des folgenden Artikels.
Das in dieser Quelle geschriebene Token ist ungültig. Stellen Sie es daher aus und verwenden Sie ein gültiges.
import requests
#LINE-Benachrichtigung
def send_notify(access_token,comment):
if( len(access_token) <= 0 ):
return
url = "https://notify-api.line.me/api/notify"
headers = {'Authorization': 'Bearer ' + access_token}
message = comment
payload = {'message': message}
print(message)
requests.post(url, headers=headers, params=payload,)
send_notify("token xxx","comment")
Ich werde das machen.
$ python3 sendline.py
comment
Kita.
Ab hier ist die Produktion. Es ist einfach, weil Sie nur das tun müssen, was Sie in der richtigen Reihenfolge nachgeschlagen haben.
Der Python-Quellcode ist etwas lang.
#Sie benötigen die Sudo-Berechtigung, um diesen Py auszuführen.
#Wenn Sie keine Erlaubnis haben, Scanner.scan()Wird zu einem Fehler führen.
from bluepy import btle
import sys
import time
import to_float_from_11073_32bit_float as tofl
import to_date_time as todt
import sendline as line
# define
SERVICE_UUID="00001809-0000-1000-8000-00805f9b34fb"
# global
BLE_ADDRESS="xx:xx:xx:xx:xx:xx"
TOKEN = "this is token"
def scan():
try:
scanner = btle.Scanner(0)
devices = scanner.scan(3.0)
for device in devices:
print(f'SCAN BLE_ADDR:{device.addr}')
if(device.addr.lower()==BLE_ADDRESS.lower()):
print("Find!")
return True
except:
print("scan Error!")
return False
print("---")
return False
class MyDelegate(btle.DefaultDelegate):
def __init__(self):
btle.DefaultDelegate.__init__(self)
def handleNotification(self, cHandle, data):
print("Indicate Handle = " + hex(cHandle))
print("Flags = " + hex(data[0]))
print("C1:Temperature Measurement Value(Celsius) = " + hex(data[1])+":"+hex(data[2])+":"+hex(data[3])+":"+hex(data[4]))
print("C3:Time Stamp = " + hex(data[5])+":"+hex(data[6])+":"+hex(data[7])+":"+hex(data[8])+":"+hex(data[9])+":"+hex(data[10])+":"+hex(data[11]))
temp = tofl.to_float_from_11073_32bit_float(data[1:5])
print("temp = " + str(temp))
timestamp = todt.to_date_time(data[5:12])
print("timestamp = " + timestamp)
line.send_notify(TOKEN,str(temp)+" C "+timestamp)
def main():
#
# Scan
#
print("<Scan Start>")
while True:
scanresult = scan()
if( scanresult==True):
break
time.sleep(3)
print("Scan End")
#
# Connect
#
print("Connect Start")
try:
peripheral = btle.Peripheral()
peripheral.connect(BLE_ADDRESS)
except:
print("connect Error!")
sys.exit(0)
print("Connected!")
service = peripheral.getServiceByUUID(SERVICE_UUID)
peripheral.withDelegate(MyDelegate())
# Enable Indicate
peripheral.writeCharacteristic(0x0013, b'\x02\x00', True)
#Warten Sie auf die Benachrichtigung
print("Indicate Wait...")
try:
TIMEOUT = 3.0
while True:
if peripheral.waitForNotifications(TIMEOUT):
# handleNotification()Hieß
continue
# handleNotification()Wurde auch nach dem Warten auf TIME OUT Sekunden nicht aufgerufen
print("wait...")
except:
print("except!")
print("<end>")
if __name__ == '__main__':
print(sys.argv[0])
#global TOKEN
TOKEN = sys.argv[1]
print("token = " + TOKEN)
#gloval BLE_ADDRESS
BLE_ADDRESS = sys.argv[2]
print("BLE device = " + BLE_ADDRESS)
while True:
main()
time.sleep(3)
Wenn Sie py ausführen, wird der Scan gestartet und Sie messen Ihre Körpertemperatur. Wenn die Messung abgeschlossen ist, wird sie automatisch empfangen und der Körpertemperatur- und Zeitstempel (Datum und Uhrzeit der Messung) wird LINE mitgeteilt.
$ sudo python3 bluepythermo.py [token] 18:93:D7:76:C9:B8
bluepythermo.py
token = [token]
BLE device = 18:93:D7:76:C9:B8
<Scan Start>
SCAN BLE_ADDR:18:93:d7:76:c9:b8
Find!
Scan End
Connect Start
Connected!
Indicate Wait...
Indicate Handle = 0x12
Flags = 0x6
C1:Temperature Measurement Value(Celsius) = 0x72:0x1:0x0:0xff
C3:Time Stamp = 0xe4:0x7:0x5:0x4:0xa:0x16:0x1c
temp = 37.0
timestamp = 2020/5/4 10:22:28
37.0 C 2020/5/4 10:22:28
wait...
wait...
except!
<end>
Ich habe eine Benachrichtigung an LINE erhalten.
Wenn Sie eine Raspeltorte in den Raum legen und py ausführen, verhält sie sich wie erwartet, indem Sie die Benachrichtigung Scan → LINE wiederholen. Wenn Sie ein Thermometer und eine Raspeltorte installieren, können Sie auch die Körpertemperatur einer weit entfernten Person anzeigen, um Ihr Überleben zu überprüfen.
** Es besteht kein Zweifel über die Erfassung der Körpertemperatur! ** ** **
Ich kann momentan kein Thermometer oder Raspeltorte kaufen ...
Recommended Posts