Because of the corona sickness, I measure my body temperature every day. I tried to hack the thermometer because it was troublesome to take notes of body temperature one by one and GW was just free time.
: o: The following is written: o:
--How to use gatttool on Raspberry Pi --BLE with python with Raspberry Pi --GATT's Health Thermometer service
: x: I didn't write the following: x:
――In the first place, what is BLE, what is GATT, etc.
** Notify LINE when your body temperature is measured. ** **
** Thermometer-> BLE-> Raspberry Pi-> WebAPI-> LINE-> Smartphone and send measured values. ** **
** Notifications will be sent even if the thermometer and smartphone are physically separated, so I think it would be possible to remotely grasp the temperature of a person in another location or the grandmother at home. ** **
--Raspberry Pi: [Raspberry Pi 3 Model b +](https://www.amazon.co.jp/RS%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3 % 83% 8D% E3% 83% B3% E3% 83% 88Raspberry-Pi-3-B-% E3% 83% 9E% E3% 82% B6% E3% 83% BC% E3% 83% 9C% E3% 83% BC% E3% 83% 89 / dp / B07BFH96M3) --Raspberry Pi OS: Raspbian Buster with desktop 4.19
--Wifi connected --Google Japanese input "Mozc" installed --Reference: Enable Japanese input for Raspberry Pi 3
The thermometer is [A & D Bluetooth built-in thermometer UT-201BLE](https://www.amazon.co.jp/AD-Bluetooth%E5%86%85%E8%94%B5-%E4%BD%93%E6%B8 % A9% E8% A8% 88-UT-201BLE / dp / B00ZQMNV94) is used. This thermometer implements BLE's ** GATT (Generic attribute profile) **, a world standard interface specification. The interface is open to the public at the following sites.
The operating procedure is as follows.
--Pair the host with the thermometer. ――You only have to do it the first time. --When the body temperature is measured, the measured value is automatically sent to the host. --If you try to send for a certain period of time and cannot send, it will be sent together at the next transmission. --Since it has a built-in clock, it also sends the measurement time.
In this case, the host is Raspberry Pi.
Pair the thermometer and Raspberry Pi.
① First, insert blueman.
$ sudo apt-get install blueman
$ reboot
(2) When you restart, the number of icons will increase, so pair from here.
③ Pair with the wizard from "Set up a new device".
④ If pairing is successful, a key-like mark will be displayed on the upper left of the device. This is OK.
** This was a mystery after all, but the pairing fails. After doing so many times, I was finally able to pair. Maybe it's just my environment. Please note that if you do not pair and the key mark is not attached as shown in ④, a strange error will occur somewhere in the subsequent work. ** **
I will confirm it because it is not a program at once, but it can be done easily as a study.
hcitool
First, let's scan the advice packet sent by the thermometer. There is ** hcitool **, which can be used to scan advertisement packets for BLE devices.
Execute the following command.
$ sudo hcitool lescan
The command scans nearby BLE devices that are advertising.
If you put the thermometer in pairing mode in this state, you can check the advice packet.
The BLE address of my thermometer was 18: 93: D7: 76: C9: B8
.
$ sudo hcitool lescan
LE Scan ...
5A:60:E6:D4:EF:94 (unknown)
5F:C1:20:2B:BE:60 (unknown)
5F:C1:20:2B:BE:60 AQtGSk1xNFF0YQ
18:93:D7:76:C9:B8 A&D_UT201BLE_76C9B8 ← This!
gatttool
Next, try connecting to the thermometer with ** gatttool **. gatttool is a tool to talk to BLE devices with GATT. Specify the BLE address with -b and execute.
$ gatttool -b xx:xx:xx:xx:xx:xx -I
When executed with -I, it waits for command input in interactive mode.
Connect with the connect
command.
Quickly measure your body temperature and put the thermometer in transmit mode.
When connected to a thermometer, it becomes ** Connection successful **.
By the way, the transmission mode of the thermometer will be forcibly terminated in about 1 minute, so if it expires, measure the body temperature again and switch to the transmission mode. This is sober and annoying, but it can't be helped because it's a device specification ...
$ gatttool -b 18:93:D7:76:C9:B8 -I
[18:93:D7:76:C9:B8][LE]> connect
Attempting to connect to 18:93:D7:76:C9:B8
Connection successful
After connecting, use the primary
command to see the UUID of the service that the thermometer has.
[18:93:D7:76:C9:B8][LE]> primary
attr handle: 0x0001, end grp handle: 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x000c, end grp handle: 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0010, end grp handle: 0x0017 uuid: 00001809-0000-1000-8000-00805f9b34fb
attr handle: 0x0018, end grp handle: 0x0028 uuid: 0000180a-0000-1000-8000-00805f9b34fb
attr handle: 0x0029, end grp handle: 0x002b uuid: 0000180f-0000-1000-8000-00805f9b34fb
attr handle: 0x002c, end grp handle: 0xffff uuid: 233bf000-5a34-1b6d-975c-000d5690abe4
You can find out what these UUIDs are by looking at the GATT site.
handle | UUID | Name |
---|---|---|
0x0001 - 0x000b | 00001800-0000-1000-8000-00805f9b34fb | Generic Access |
0x000c - 0x000f | 00001801-0000-1000-8000-00805f9b34fb | Generic Attribute |
0x0010 - 0x0017 | 00001809-0000-1000-8000-00805f9b34fb | Health Thermometer |
0x0018 - 0x0028 | 0000180a-0000-1000-8000-00805f9b34fb | Device Information |
0x0029 - 0x002b | 0000180f-0000-1000-8000-00805f9b34fb | Battery Service |
0x002c - 0xffff | 233bf000-5a34-1b6d-975c-000d5690abe4 | unknown |
Important is the ** 1809 ** Health Thermometer Service **.
Use the char-desc
command to see the characteristics of the Health Thermometer service.
For char-desc
, specify the handle (attire handle and grp handle values) of the Health Thermometer service.
Also, the UUID will come out in a row.
[18:93:D7:76:C9:B8][LE]> char-desc 0x0010 0x0017
handle: 0x0010, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0011, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0012, uuid: 00002a1c-0000-1000-8000-00805f9b34fb
handle: 0x0013, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0014, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0015, uuid: 00002a1d-0000-1000-8000-00805f9b34fb
handle: 0x0016, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0017, uuid: 00002a08-0000-1000-8000-00805f9b34fb
Check the GATT site.
handle | UUID | Name |
---|---|---|
0x0010 | 00002800-0000-1000-8000-00805f9b34fb | Primary Service |
0x0011 | 00002803-0000-1000-8000-00805f9b34fb | Characteristic Declaration |
0x0012 | 00002a1c-0000-1000-8000-00805f9b34fb | Temperature Measurement |
0x0013 | 00002902-0000-1000-8000-00805f9b34fb | Descriptor |
0x0014 | 00002803-0000-1000-8000-00805f9b34fb | Characteristic Declaration |
0x0015 | 00002a1d-0000-1000-8000-00805f9b34fb | Temperature Type |
0x0016 | 00002803-0000-1000-8000-00805f9b34fb | Characteristic Declaration |
0x0017 | 00002a08-0000-1000-8000-00805f9b34fb | Date Time |
The following two are important here.
In short, ** If you set Descriptor to "Start sending", Temperature Measurement will send data **.
let's do it.
First, try reading the Descriptor settings. The char-read-hnd
command reads the characteristic value. Specify the Handle value of Descriptor in the argument.
[18:93:D7:76:C9:B8][LE]> char-read-hnd 0x0013
Characteristic value/descriptor: 00 00
The value is ** 00 00 **. This means that Indicate is OFF.
The value of Descriptor is
-** 0100 ** → Enable Notify -** 0200 ** → Enable Indicate
is what it means. Temperature Measurement is Indicate, which is determined by the GATT specifications, so you can set it to ** 0200 **.
To write the setting value, hit char-write-req
. Specify the Handle value of Descriptor and the setting value ** 0200 ** as arguments.
[18:93:D7:76:C9:B8][LE]> char-write-req 0x0013 0200
Characteristic value was written successfully
Indication handle = 0x0012 value: 06 73 01 00 ff e4 07 05 02 0a 28 13 02
If all goes well, Indicate will start and data will flow from handle = 0x0012.
handle = 0x0012 means ** 2a1c --Temperature Measurement **.
The story of gatttool has become long, so I will summarize it.
#Start gatttool
$ gatttool -b xx:xx:xx:xx:xx:xx -I
#Connect with device
> connect
#Get service UUID list
> primary
#Get a characteristic list
> char-desc start handle end handle
#Read the characteristic value
> char-read-hnd handle
#Write a characteristic value
> char-write-req handle data
After measuring the body temperature, you can get the measured value with the following command.
$ gatttool -b 18:93:D7:76:C9:B8 -I
> connect
> char-write-req 0x0013 0200
The thermometer gave me this kind of data, but what exactly is this?
06 73 01 00 ff e4 07 05 02 0a 28 13 02
The format of the data is written here.
It's really hard to understand, so I'll rewrite it.
Temperature Measurement
byte | name | |
---|---|---|
1 | Flags | Flags indicating the structure of the data bit 0 - Temperature Units Flag: 0 =C1 Yes C2 No, 1 =C1 None C2 Yes bit 1 - Time Stamp Flag : 0 =C3 none, 1 =With C3 bit 2 - Temperature Type Flag : 0 =C4 none, 1 =With C4 bit 3-7 :unused |
4 | C1 | Temperature Measurement Value (Celsius) -Measured value Celsius IEEE 11073 32bit float format |
4 | C2 | Temperature Measurement Value (Fahrenheit) -Measured value Fahrenheit IEEE 11073 32bit float format |
7 | C3 | Time Stamp Measurement date and time - yyyy 2byte ushort - mm 1byte - dd 1byte - hh 1byte - mm 1byte - ss 1byte |
1 | C4 | Temperature Type Temperature type reference |
Try to parse the received data.
byte | data | Perspective result |
---|---|---|
Flags | 06 | 0000-0110 bit 0 = 0 :C1 Yes C2 No bit 1 = 1 :With C3 bit 2 = 1 :With C4 |
C1 | 73 01 00 ff | 36.1 |
C3 | e4 07 05 02 0a 28 13 | 2020/5/2 10:40:19 |
C4 | 02 | Body (general) |
C1 is 4 bytes of data and is in ** IEEE 11073 32bit float ** format. For a detailed explanation of this format, refer to the following site.
-Handling binary data with JavaScript ~ IEEE-754 and IEEE-11073 floating point ~ (2/3) -[Communicate with thermometer and sphygmomanometer with BLE GATT with Windows desktop app]([https://qiita.com/gebo/items/41da7474936845d77d06#4temperature-measurement%E3%81%AE%E3%82%A4%] E3% 83% 99% E3% 83% B3% E3% 83% 88% E3% 81% A7% E4% BD% 93% E6% B8% A9% E6% B8% AC% E5% AE% 9A% E5% 80% A4% E3% 82% 92% E5% 8F% 96% E5% BE% 97](https://qiita.com/gebo/items/41da7474936845d77d06#4take thermometer measurement at temperature-measurement event))
result
--Body temperature = 36.1 ℃ --Measurement date and time = 2020/5/2 10:40:19
It turned out that it is the data. The body temperature and the measured date and time are properly taken. feel well.
This time it's up to here because it's sharp.
Continue to # 2 to notify LINE of body temperature from BLE thermometer with Raspberry Pi