[PYTHON] Benachrichtigen Sie LINE über die Körpertemperatur vom BLE-Thermometer mit Raspeltorte Nr. 2

Einführung

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.

Installation von 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

Probieren Sie verschiedene Dinge mit Bluepy aus

Sprechen Sie mit einem BLE-Gerät mit Bluepy.

Nach Werbepaketen suchen

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.

Verbinden Sie sich und erhalten Sie eine Liste der Dienste

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 

Holen Sie sich Daten von einem Thermometer

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.

Analysieren empfangener Daten

Perspektive der Messwerte

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.

Zeitstempelperspektive

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.

Per LINE benachrichtigen

Ü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.

IMG_6943.png

Produktion

Ab hier ist die Produktion. Es ist einfach, weil Sie nur das tun müssen, was Sie in der richtigen Reihenfolge nachgeschlagen haben.

memo_04.png

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.

IMG_6944.png

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! ** ** **

Danke für Ihre Unterstützung

Ich kann momentan kein Thermometer oder Raspeltorte kaufen ...

Recommended Posts

Benachrichtigen Sie LINE über die Körpertemperatur vom BLE-Thermometer mit Raspeltorte Nr. 1
Benachrichtigen Sie LINE über die Körpertemperatur vom BLE-Thermometer mit Raspeltorte Nr. 2
Messen Sie die CPU-Temperatur von Raspeye mit Python
Benachrichtigen Sie regelmäßig den Verarbeitungsstatus von Raspberry Pi mit Python → Google Spreadsheet → LINE
Herstellung eines Temperaturregelungssystems mit Himbeerkuchen und ESP32 (1)
Ausgabe von Raspberry Pi an Line
Herstellung eines Temperaturregelungssystems mit Himbeerkuchen und ESP32 (2) Herstellung eines Übertragungsgeräts
CSV-Ausgabe von Impulsdaten mit Raspberry Pi (CSV-Ausgabe)
Holen Sie sich CPU-Informationen von Raspberry Pi mit Python
Holen Sie sich Temperatur und Luftfeuchtigkeit mit DHT11 und Raspberry Pi
Notieren Sie Temperatur und Luftfeuchtigkeit mit systemd auf Raspberry Pi
GPGPU mit Raspberry Pi
Nehmen Sie den Wert des SwitchBot-Thermo-Hygrometers mit Raspberry Pi
Umschalten der Bot-Thermo-Hygrometer-Werte mit Raspberry Pi
DigitalSignage mit Raspberry Pi
Lassen Sie uns GPIO von Raspeye mit Python CGI betreiben
Simulieren Sie die Temperaturmessung mit Raspberry Pi + Flask + SQLite + Ajax
Erstellen Sie mit Raspberry Pi + DHT11 ganz einfach einen TweetBot, der Sie über Temperatur und Luftfeuchtigkeit informiert.
Spielen Sie, um Slack mithilfe von AWS PaaS über Raspberry Pi3 über Umgebungsdaten von SensorTag zu informieren
Ich habe versucht, Movidius NCS mit Python von Raspberry Pi3 auszuführen
[RaspberryPi] [Python] Informieren Sie LINE mit dem Temperatursensor + IFTTT über Raumtemperatur
Messen und vergleichen Sie Temperaturen mit Raspberry Pi und generieren Sie automatisch Diagramme
So erhalten Sie die Temperatur vom SwitchBot-Thermo-Hygrometer mit Himbeer-Pi
Machen Sie ein BLE-Thermometer und ermitteln Sie die Temperatur mit Pythonista3
Mutter pflanzt mit Raspberry Pi
Mit Skype benachrichtigen Sie mit Skype von Python!
Bilderkennung von Müll mit Edge (Raspberry Pi) aus null Wissen mit AutoML Vsion und TPU
Machen Sie ein Thermometer mit Raspberry Pi und machen Sie es im Browser Teil 4 sichtbar
Grafische Darstellung des Stromverbrauchs im Haushalt mit 3GPI und Raspeye
[Hinweis] Verwenden eines 16x2-stelligen LCD-Zeichens (1602A) von Python mit Raspeye
Protokollieren Sie die Omron-Umgebungssensorwerte regelmäßig mit Raspberry Pi
Verwenden Sie vl53l0x mit RaspberryPi (Python)
Servomotorsteuerung mit Raspberry Pi
Serielle Kommunikation mit Raspberry Pi + PySerial
Betriebssystem-Setup mit Raspberry Pi Imager
Probieren Sie L Chika mit Himbeerpi
Aufbau eines VPN-Servers mit Raspberry Pie
Benachrichtigen Sie LINE über Informationen zum Zugbetrieb
Versuchen Sie, 3 Servos mit Raspeye zu bewegen
Verwenden einer Webkamera mit Raspberry Pi
CSV-Ausgabe von Pulsdaten mit Raspberry Pi (Analogeingang mit Python prüfen)
Versuchen Sie, den RSS-Feed von arXiv mit Python von Raspeye auf Twitter zu twittern
[Python + PHP] Erstellen Sie mit Raspberry Pi einen Temperatur-, Feuchtigkeits- und Druckmonitor
Benachrichtigen Sie LINE über Standortinformationen (Google-Karte) mit der GPS-SORACOM Edition mit mehreren Einheiten
Protokollierung der Omron-Umgebungssensorwerte mit Raspberry Pi (USB-Typ)