This repo contains a Python script able to (passively) listen to Bluetooth LE (BLE) thermometers based on the Telink chipset and flashed with either the atc1441 or pvvx firmwares. There are a variety of sensors from Xiaomi, Qingping and Tuya compatible with such firmware, see the previous repositories.
The script supports both encrypted and un-encrypted BLE advertisements from the thermometers and reports the measurements to both MQTT (with customizable data formats) and Domoticz (using its native JSON API or via MQTT). Authentication and encryption are supported when sending data to these MQTT/Domoticz clients.
The script is daemonizable to be run as a service under a systemd
based Linux system. An example .service
file is provided.
The configuration of the script (sensors to listen to, clients where to publish measurements, encryption, authentication, etc.) are specified in a configuration file in the YAML human-readable data serialization language. Read the comments on it to learn how to write it.
The script is written in Python (v3) using asynchronous IO (async
/await
) to manage all BLE/http(s)/MQTT communications. Packages asyncio
, bleak
, aiohttp
and aiomqtt
are used for that. These asynchronous IO approach gives low CPU and memory usage even when managing many sensors and clients.
Previous work by jsBergbau served as an inspiration for this script that, in some parts, is a rewriting from scratch of jsBergbau's code. Such code offers more functionalities than this script, but this script does also work on Windows®, uses asyncio
(jsBergbau's code is based on blueply
, requests
and paho-mqtt
instead, which is fine, in any case) and, IMHO, it is easier to install and use.
You will need:
- Temperature/humidity sensors compatible and flashed with the atc1441 or pvvx firmwares
- A Bluetooth LE capable Windows® (≥ 10) or Linux box (supporting
BlueZ
≥ 5.43). Sorry, not tested on MacOS. A Raspberry Pi is enough (with its built-in Bluetooth or with an OS-supported BLE dongle)
You will need:
- Python (≥ 3.8)
- Python packages:
yaml
,bleak
,cryptodome
,aiohttp
andaiomqtt
.
Depending on the OS and its version, you may need to install them with the usual pip
(add the sudo
only in Linux and if you want all packages to be installed system-wide):
sudo pip install pyyaml bleak pycryptodomex aiohttp aiomqtt
or (in Debian Bookworm):
sudo apt install python3-yaml python3-bleak python3-pycryptodome python3-aiohttp
On Bookworm, aiomqtt
must be installed with:
sudo apt install python3-pip
sudo pip install aiomqtt --break-system-packages
so, maybe, you may prefer to install aiomqtt
inside a Python virtual environment.
Then, on Linux, file /usr/lib/systemd/system/bluetooth.service
must be edited:
sudo nano /usr/lib/systemd/system/bluetooth.service
in order to add option --experimental
to line:
ExecStart=/usr/libexec/bluetooth/bluetoothd --experimental
then:
sudo systemctl daemon-reload
sudo systemctl restart bluetooth
That's all, copy the supplied .py
file where you want and then atc_pvvx_monitor.py
can now be tested from the command line:
pi@rpiz2w:~ $ ./atc_pvvx_monitor.py -h
usage: atc_pvvx_monitor.py [-h] [-c CONFIG_FILE_NAME] [-a ADAPTER] [-s SCAN_TIME] [-p SCAN_PAUSE] [-l LOG_FILE_NAME] [-m] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-t] [-d]
Monitor atc1441/pvvx BLE thermometers.
options:
-h, --help show this help message and exit
-c CONFIG_FILE_NAME, --config-file CONFIG_FILE_NAME
file describing the thermometers to monitor and where to send (Domoticz/MQTT) their measurements. Defaults to "thermometers.yaml".
-a ADAPTER, --adapter ADAPTER
Bluetooth HCI adapter to use (hci0, hci1, ...). Used only in Linux/BlueZ. If not specified, uses system default.
-s SCAN_TIME, --scan_time SCAN_TIME
BLE scan time (in s). Defaults to 10. A <= 0 number is treated as "scan with no pauses".
-p SCAN_PAUSE, --scan-pause SCAN_PAUSE
pause time between scans (in s). Defaults to 50. Ignored if SCAN_TIME <= 0.
-l LOG_FILE_NAME, --log-file LOG_FILE_NAME
file where to write log messages. If not set, outputs messages to standard error.
-m, --measurements_as_info
log measurements as INFO, instead of as DEBUG.
--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
set log level. Defaults to "INFO".
-t, --timestamp include timestamps into log messages.
-d, --date include date into timestamps.
When invoked from the command line, atc_pvvx_monitor.py
supports options:
usage: atc_pvvx_monitor.py [-h] [-c CONFIG_FILE_NAME] [-a ADAPTER] [-s SCAN_TIME] [-p SCAN_PAUSE] [-l LOG_FILE_NAME] [-m] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-t] [-d]
options:
-h, --help show this help message and exit
-c CONFIG_FILE_NAME, --config-file CONFIG_FILE_NAME
file describing the thermometers to monitor and where to send (Domoticz/MQTT) their measurements. Defaults to "thermometers.yaml".
-a ADAPTER, --adapter ADAPTER
Bluetooth HCI adapter to use (hci0, hci1, ...). Used only in Linux/BlueZ. If not specified, uses system default.
-s SCAN_TIME, --scan_time SCAN_TIME
BLE scan time (in s). Defaults to 10. A <= 0 number is treated as "scan with no pauses".
-p SCAN_PAUSE, --scan-pause SCAN_PAUSE
pause time between scans (in s). Defaults to 50. Ignored if SCAN_TIME <= 0.
-l LOG_FILE_NAME, --log-file LOG_FILE_NAME
file where to write log messages. If not set, outputs messages to standard error.
-m, --measurements_as_info
log measurements as INFO, instead of as DEBUG.
--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
set log level. Defaults to "INFO".
-t, --timestamp include timestamps into log messages.
-d, --date include date into timestamps.
All these options seem self-explanatory. Only -s
and -p
may require a comment. When passively scanning for BLE advertisements, some backends (Linux with some chipsets) report each BLE device only once. Thus, in order to continuously report advertisements from the same devices, it is necessary to scan for a while and then stop the scanning in order to relaunch it later. Options -s
and -p
set the duration (in s) of these scan and pause between scans periods respectively. If option -s 0
is given, scanning never pauses. If your sensors have and advertisement period of, say, T seconds, a small multiple of T may be enough for -s
. Test your system for expected behaviour before setting option -s 0
.
By default, the log does not contain timestamps. This is because, when run as a daemon/service, the log messages are managed by journald
, that inserts them. Inserting timestamps in the log may be controlled with options -t
and -d
.
The configuration describing the sensors to listen to and the clients (Domoticz or MQTT) where to report the measurements is contained in a configuration file (whose name may be specified from the command line) in the YAML language. Please, read the provided thermometers.yaml
example configuration file to see how to write its contents.
In Linux this script can be run as a daemon. This is achieved creating a service that systemd
will start at boot. To accomplish this task an example atc_pvvx_monitor.service
file is provided. Its contents are:
[Unit]
Description=Monitor ambient temperature via BLE thermometers with ATC/pvvx firmware
Wants=multi-user.target bluetooth.service
After=bluetooth.service
[Service]
ExecStart=/usr/bin/python3 /home/pi/atc_pvvx_monitor.py -s10 -p50 -c /home/pi/thermometers.yaml
ExecReload=/usr/bin/kill -HUP $MAINPID
[Install]
WantedBy=default.target
You may want to edit line ExecStart=/usr/bin/python3 /home/pi/atc_pvvx_monitor.py -s10 -p50 -c /home/pi/thermometers.yaml
to better fit your needs. This file must be placed inside /usr/lib/systemd/system
, owned by root:root
with permission 640
, this is:
sudo cp atc_pvvx_monitor.service /usr/lib/systemd/system
sudo chown root:root /usr/lib/systemd/system/atc_pvvx_monitor.service
sudo chmod 640 /usr/lib/systemd/system/atc_pvvx_monitor.service
Then the service can be enabled and started:
sudo systemctl daemon-reload
sudo systemctl enable --now atc_pvvx_monitor
From now on, atc_pvvx_monitor
will be running in the system, automatically launched at boot. It can be stopped/started/restarted/reloaded (to re-read its YAML configuration file) with sudo systemctl stop/start/restart/reload atc_pvvx_monitor
. Its status can be viewed with sudo systemctl status atc_pvvx_monitor
.
When run as a service, its log is managed by the journald
service, and can be read with journalctl -u atc_pvvx_monitor
.