There’s a neat looking Xiaomi sensor with a display which is capable of showing temperature and humidity data.

It can trasmit this information over Bluetooth Low Energy (BLE), and if we want to get that in command line from a Raspberry Pi, this is what we need to do.

Hardware
Xiaomi Mijia Hygrothermo v2 sensor

Raspberry Pi model which has inbuilt Bluetooth module:
Raspberry Pi 3B / Raspberry Pi Zero W / Raspberry Pi 3B+

Software

It will use ratcashdev’s mitemp library, which in turn depends on ChristianKuehnel’s btlewrap library, for me it was kinda tricky where to put the btlewrap inside mitemp, but it works the way I’ll show below.

We’ll do this as the default user ‘pi’.

Installing pre-requisites

pi@hassbian:~ $ cd /home/pi/

pi@hassbian:~ $ sudo apt-get update -y
Hit:1 http://mirrordirector.raspbian.org/raspbian stretch InRelease
Hit:2 http://archive.raspberrypi.org/debian stretch InRelease
Hit:3 https://deb.nodesource.com/wnode_8.x stretch InRelease
Reading package lists... Done

pi@hassbian:~ $ sudo apt-get install git -y
Reading package lists... Done
Building dependency tree       
Reading state information... Done
git is already the newest version (1:2.11.0-3+deb9u3).
0 upgraded, 0 newly installed, 0 to remove and 65 not upgraded.

pi@hassbian:~ $ sudo apt-get install python3 -y
Reading package lists... Done
Building dependency tree       
Reading state information... Done
python3 is already the newest version (3.5.3-1).
0 upgraded, 0 newly installed, 0 to remove and 65 not upgraded.

The default Bluetooth Low Energy (BLE) backend on Raspbian is Gatttool, but I recommend to install a better BLE backend, specially designed work with Python, called bluepy. The bluepy package can be installed from pip3 or built from source, we’ll use pip3. The steps are from the official bluepy repo https://github.com/IanHarvey/bluepy

It’s important to use pip3 and not pip, as we’re utilizing python3 for this project.

pi@hassbian:~ $ sudo apt-get install python3-pip libglib2.0-dev
Reading package lists... Done
Building dependency tree       
Reading state information... Done
libglib2.0-dev is already the newest version (2.50.3-2).
python3-pip is already the newest version (9.0.1-2+rpt2).
0 upgraded, 0 newly installed, 0 to remove and 65 not upgraded.
 
pi@hassbian:~ $ sudo pip3 install bluepy
Collecting bluepy
  Downloading https://www.piwheels.org/simple/bluepy/bluepy-1.2.0-cp35-cp35m-linux_armv7l.whl (509kB)
    100% |████████████████████████████████| 512kB 505kB/s 
Installing collected packages: bluepy
Successfully installed bluepy-1.2.0

Cloning the necessary repositories

pi@hassbian:~ $ git clone https://github.com/ratcashdev/mitemp.git
Cloning into 'mitemp'...
remote: Enumerating objects: 69, done.
remote: Total 69 (delta 0), reused 0 (delta 0), pack-reused 69
Unpacking objects: 100% (69/69), done.

pi@hassbian:~ $ git clone https://github.com/ChristianKuehnel/btlewrap.git btlewrap-git
Cloning into 'btlewrap-git'...
remote: Counting objects: 145, done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 145 (delta 8), reused 10 (delta 2), pack-reused 121
Receiving objects: 100% (145/145), 36.99 KiB | 0 bytes/s, done.
Resolving deltas: 100% (64/64), done.

At this point you’ll have these 2 cloned git repositories in your home directory: btlewrap-git and mitemp

pi@hassbian:~ $ ls
btlewrap-git  mitemp

We have named the btlewrap repository as btlewrap-git for a reason, to avoid confusion. The reason is that we don’t actually need the full contents of the btlewrap-git repository, we only need 1 folder from inside that btlewrap-git repository, which is also called btlewrap, it’s here: /home/pi/btlewrap-git/btlewrap/

We’ll move this btlewrap folder to the mitemp folder.

pi@hassbian:~ $ mv /home/pi/btlewrap-git/btlewrap/ /home/pi/mitemp/

After that we can delete the btlewrap-git repo, as we moved out the necessary folder from it:

pi@hassbian:~ $ rm -rf /home/pi/btlewrap-git/

Just for double checking, let’s list out the contents of the mitemp folder, as you can see, the btlewrap folder is inside the mitemp folder:

pi@hassbian:~ $ ls -lh /home/pi/mitemp
total 56K
drwxr-xr-x 2 pi pi 4,0K szept 27 14:05 btlewrap
-rwxr-xr-x 1 pi pi  100 szept 27 14:05 build.sh
-rw-r--r-- 1 pi pi  994 szept 27 14:05 CONTRIBUTING.md
-rwxr-xr-x 1 pi pi 3,0K szept 27 14:05 demo.py
-rw-r--r-- 1 pi pi 1,1K szept 27 14:05 LICENSE
drwxr-xr-x 2 pi pi 4,0K szept 27 14:05 mitemp_bt
-rw-r--r-- 1 pi pi  124 szept 27 14:05 pylintrc
-rw-r--r-- 1 pi pi 2,2K szept 27 14:05 README.md
-rw-r--r-- 1 pi pi   46 szept 27 14:05 requirements-test.txt
-rw-r--r-- 1 pi pi  108 szept 27 14:05 requirements.txt
-rwxr-xr-x 1 pi pi  513 szept 27 14:05 run_integration_tests
-rw-r--r-- 1 pi pi  958 szept 27 14:05 setup.py
drwxr-xr-x 4 pi pi 4,0K szept 27 14:05 test
-rw-r--r-- 1 pi pi  969 szept 27 14:05 tox.ini

We installed python3 earlier because the code which will fetch the data of the Mijia sensor is a python3 script called demo.py, we know that it’s a python3 script because the first line of the script, the “shebang” tells so:

pi@hassbian:~ $ head -n 1 /home/pi/mitemp/demo.py
#!/usr/bin/env python3

We also make sure the demo.py script is executable.

pi@hassbian:~ $ chmod +x /home/pi/mitemp/demo.py 

Running the script

First we’ll enter the folder of the script, and run the “-h” parameter to get the “help” function which will tell us how to use the script.

pi@hassbian:~ $ cd /home/pi/mitemp/

pi@hassbian:~/mitemp $ ./demo.py -h
usage: demo.py [-h] [--backend {gatttool,bluepy,pygatt}] [-v]
               {poll,backends} ...

positional arguments:
  {poll,backends}       sub-command help
    poll                poll data from a sensor
    backends            list the available backends

optional arguments:
  -h, --help            show this help message and exit
  --backend {gatttool,bluepy,pygatt}
  -v, --verbose

We’ll list out the available BLE backends, hopefully we’ll see BluepyBackend there too, as we installed it earlier.

pi@hassbian:~/mitemp $ ./demo.py backends
BluepyBackend
GatttoolBackend

Great!

Now we’ll need to know the MAC address of the sensor from which we want to fetch the data. I have 2 of them so we’ll see 2 MAC addresses in the output, one is 4c:65:a8:d4:f3:db, the other is 4c:65:a8:d4:a3:86

pi@hassbian:~/mitemp $ sudo blescan
Scanning for devices...
    Device (new): 4c:65:a8:d4:f3:db (public), -81 dBm 
	Flags: <06>
	Complete 16b Services: <0000180f-0000-1000-8000-00805f9b34fb>
	16b Service Data: 
	Complete Local Name: 'MJ_HT_V1'
    Device (new): 4c:65:a8:d4:a3:86 (public), -88 dBm 
	Flags: <06>
	Complete 16b Services: <0000180f-0000-1000-8000-00805f9b34fb>
	16b Service Data: 
	Complete Local Name: 'MJ_HT_V1'

So just to bring it all together, we’ll be using the parameters for the polling:
–backend bluepy (to tell the script we want to use the bluepy backend)
poll 4c:65:a8:d4:f3:db (to tell the script to poll this MAC address)

Now we’ll poll the sensor with these parameters:

pi@hassbian:~ $ python3 /home/pi/mitemp/demo.py --backend bluepy poll 4c:65:a8:d4:f3:db
Getting data from Mi Temperature and Humidity Sensor
FW: 00.00.66
Name: MJ_HT_V1
Battery: 85
Temperature: 21.8
Humidity: 44.1

You can use these data whereever you need to.

Thanks for checking out my tutorial!