XIAOMI Mijia Bluetooth Thermometer 2 integration

Hi,
i tested alot and also tried to connect a second sensor.
However a lot of times i am getting error messages reading the data from the sensors.
Currently i am reading the data via the “exec binding”.
This is how the script on the RPI3b+ looks like:

#!/bin/bash
sudo hciconfig hci0 down && sudo hciconfig hci0 up
bt=$(timeout 40 gatttool -b $1 --char-write-req --handle=‘0x0038’ --value=“0100” --listen)
if [ -z “$bt” ]
then
a = 0
else
temphexa=$(echo $bt | awk -F ’ ’ ‘{print $12$11}’| tr [:lower:] [:upper:] )
humhexa=$(echo $bt | awk -F ’ ’ ‘{print $13}’| tr [:lower:] [:upper:])
temperature100=$(echo “ibase=16; $temphexa” | bc)
humidity=$(echo “ibase=16; $humhexa” | bc)
if [ $2 = “temperature” ]
then
echo “scale=2;$temperature100/100”|bc
else
echo $humidity
fi
fi

I have created 2 things:

Thing exec:command:humidor_temperature “Humidor - Temperatur” @ “Buero” [command=“sudo bash /home/openhabian/xiaomi_sensor_uni.sh ‘A4:C1:38:E6:FF:3E’ ‘temperature’”, transform=“REGEX((.*?))”, interval=300, timeout=80, autorun=true]

Thing exec:command:humidor_humidity “Humidor - Luftfeuchtigkeit” @ “Buero” [command=“sudo bash /home/openhabian/xiaomi_sensor_uni.sh ‘A4:C1:38:E6:FF:3E’ ‘humidity’”, transform=“REGEX((.*?))”, interval=300, timeout=80, autorun=true]

And put the command into the exec.whitelist

However most of the time i am getting this in the log screen:

2020-09-17 10:52:50.277 [vent.ItemStateChangedEvent] - Humidor_Temperature changed from connect: No route to host (113)
/home/openhabian/xiaomi_sensor_uni.sh: line 7: a: command not found
connect: No route to host (113)
/home/openhabian/xiaomi_sensor_uni.sh: line 7: a: command not found to Can’t init device hci0: No such device (19)
connect: No route to host (113)
/home/openhabian/xiaomi_sensor_uni.sh: line 7: a: command not found
Can’t init device hci0: No such device (19)
connect: No route to host (113)
/home/openhabian/xiaomi_sensor_uni.sh: line 7: a: command not found

But sometimes its also working:

2020-09-17 10:31:04.635 [vent.ItemStateChangedEvent] - Humidor_Humidity changed from connect: Device or resource busy (16)
/home/openhabian/xiaomi_sensor_uni.sh: line 7: a: command not found
connect: Device or resource busy (16)
/home/openhabian/xiaomi_sensor_uni.sh: line 7: a: command not found to 60

The second sensor is even worse and i am not getting any value (openhab or RPI) even if it is located just next to the RPI. I also connected it to my Xiaomi smartphone app, there i do not have any trouble.

[10:57:16] openhabian@openhab:~$ sudo -u openhabian bash /home/openhabian/xiaomi_sensor_uni.sh ‘A4:C1:38:E6:FF:3E’ ‘humidity’
connect error: Function not implemented (38)
/home/openhabian/xiaomi_sensor_uni.sh: line 7: a: command not found

However via sudo blescan i am able to find it:

Device (new): a4:c1:38:e6:ff:3e (public), -69 dBm
Flags: <06>
16b Service Data: <95fe30585b05123effe638c1a408>

Also using sudo bluetoothctl i can find and connect the device:

[bluetooth]# info A4:C1:38:E6:FF:3E
Device A4:C1:38:E6:FF:3E (public)
Name: LYWSD03MMC
Alias: LYWSD03MMC
Paired: no
Trusted: no
Blocked: no
Connected: no
LegacyPairing: no
UUID: Vendor specific (00000100-0065-6c62-2e74-6f696d2e696d)
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: Device Information (0000180a-0000-1000-8000-00805f9b34fb)
UUID: Battery Service (0000180f-0000-1000-8000-00805f9b34fb)
UUID: Xiaomi Inc. (0000fe95-0000-1000-8000-00805f9b34fb)
UUID: Vendor specific (00010203-0405-0607-0809-0a0b0c0d1912)
UUID: Vendor specific (ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6)
ServiceData Key: 0000fe95-0000-1000-8000-00805f9b34fb
ServiceData Value:
30 58 5b 05 12 3e ff e6 38 c1 a4 08 0X[…>…8…
[bluetooth]# connect A4:C1:38:E6:FF:3E
Attempting to connect to A4:C1:38:E6:FF:3E
[CHG] Controller B8:27:EB:06:35:72 Powered: no
[CHG] Controller B8:27:EB:06:35:72 Discovering: no
Connection successful

Sorry for the extensive text but i am a little bit frustrated at the moment. Maybe someone can help :slight_smile:

Hi druciak,
thank you for the code but i have to admit i dont understand it :wink:
How to tell the script the MAC adress of the sensor?
Do you run it as a crontab?
Also i do not have a MQTT system runing. Would have to setup this first.

You put it as the first parameter in the command line. Have you tried to run this script already?

Yes

No didnt tried it because I have no Mqtt service running till now. Can it also be used for the exec binding? However I think mqtt is the better solution, what do you think?

You can, but you have to remove mqtt related code from the script. Anyway it should run even without mqtt server. You’ll an error, but it should print something, hopefully temperature and humidity from the sensor.

I think mqtt is better, but you can solve current issues first, without an mqtt server.

Hi, i tried your script and saved it into a *.py file. Also i commented “#from paho.mqtt import publish”.
Can you tell me what “location” means?
After running i am getting this message:

[18:31:03] openhabian@openhab:~$ sudo python xiaomi_sensor_test.py A4:C1:38:AD:3E:FA test
2020-09-18 18:31:27,230: Connected
2020-09-18 18:31:28,370: Got notification54
Traceback (most recent call last):
File “xiaomi_sensor_test.py”, line 73, in
if sensor.read_data(full_read):
File “xiaomi_sensor_test.py”, line 34, in read_data
while not self.p.waitForNotifications(15.0):
File “/usr/local/lib/python2.7/dist-packages/bluepy/btle.py”, line 560, in waitForNotifications
resp = self._getResp([‘ntfy’,‘ind’], timeout)
File “/usr/local/lib/python2.7/dist-packages/bluepy/btle.py”, line 416, in _getResp
self.delegate.handleNotification(hnd, data)
File “xiaomi_sensor_test.py”, line 57, in handleNotification
self.temperature = int.from_bytes(data[0:2],byteorder=‘little’,signed=True)/100
AttributeError: type object ‘int’ has no attribute ‘from_bytes’

Can you tell me where it is stuck?

Try to run this script using python3. It uses some python3 features and without changes will not run under python 2.7.

Hi guys. I have flashed custom firmware using OTA method - awesome!
I want to integrate these sensors into openhab2, I’m using RPI 3B+ embedded bluetooth and in Openhab using blueZ bridge discovering devices, but only RSSI channel is autodetected. Any thoughts why humidity, battery level and temperature is not detected?

Can i connect this mija ble temp sensors to my xiaomi hub 2 too or is the hub zigbee only?

Which temp sensor has better range? Zigbee xiaomi sensor or this ble sensor?

How long will last the battery in this ble sensor? Zigbee sensor is about 1 year.

You need a decoder to parse the data advertised by the LYWSD03MMC. I don’t know bluez but if you have an esp32 around you can flash it with OpenMQTTGateway.
https://docs.openmqttgateway.com/upload/binaries.html

Thanks, I have checked that solution too, but the thing is RPI 3B+ has embedded Bluetooth with BLE support, so why there should be any additional “xiaomi gateway” like device? By the way I have Xiaomi Gateway, but for some reason changing region to motherland china does not work now and I can’t hack into it to use it as gateway, any help would be appreciated.
I have posted my request in official openhab Bluetooth binding support here and got answer that this binding does not yet support GATT specs, there for all advertising data can’t be automatically discovered and added as separate channels only RSSI for now - as I understood. Feature is in development stage yet and going to be released soon.
However, I know that the devices supported and their channels are described in XML format somewhere in root files, so theoretically any device can be added to the binding, just need to describe the device in it. So there are 2 options now:

  1. wait till official Bluetooth binding finally support GATT specs
  2. Find and add device manually using custom xml file

It is used among others when you need to extend the range of your BLE setup. It’s more portable solution compared to a PI attached to an ethernet cable and an ssd.

If you have a solution that works with the PI and with a satisfying range you can go for it.
But from what I see it doesn’t seem to be available yet.

For anyone who is searching for this topic and still struggling with making it work:

After trying multiple solutions (manual, scripts mentioned here and some other found on internet) i found this:

This works like charm with not issues, has an example solution to publish to MQTT so easy to integrate with OpenHab and with custom firmware from (already mentioned here) atc1411 can work even better.

All I need to do is just make a systemd service out of it so it can run as daemon in background and start on boot (but there is no problem with just running on screen)

5 Likes

If you have an esp32, I would be interested by a test with OpenMQTTGateway and this v2. It would enable to verify the compatibility.

There is nothing really Home Assistant specific in it
Just the topic name but this can be anything really.

Wow this works great! Thanks to everyone!

I’m a beginner and I struggled with the corresponding mqtt-items etc.
Finally, I found out how it works, and I just wanted to share for others.

First add a generic-mqq-thing and then this:

The Channels Temperature

Channel Identifier: MiTemperature2_Living_Room_Channel_Temperature
Label: MiTemperature2
_Living_Room_Channel_Temperature
MQTT State Topic: MiTemperature2//temp

The Channels Humidity

Channel Identifier: MiTemperature2_Living_Room_Channel_Humidity
Label: MiTemperature2
_Living_Room_Channel_Humidity
MQTT State Topic: MiTemperature2//humidity

The Channels Batterylevel

Channel Identifier: MiTemperature2_Living_Room_Channel_Batterylevel
Label: MiTemperature2
_Living_Room_Channel_Batterylevel
MQTT State Topic: MiTemperature2//batterylevel

Add Equipment to Model

Name: MiTemperature2_Thing__Living_Room
Label: MiTemperature2 - Thing - - Living_Room
Category: temperature_hot
Semantic Class: Sensor

Item for the Channel for Batterylevel

Name: MiTemperature2__Item_Living_Room_Batterylevel
Labe: Battery Level: Living_Room
Type: dimmer
Category: batterylevel
Semantic Class: Status
Semantic Property: Energy

Item for the Channel for Humidity

Name: MiTemperature2__Item_Living_Room_Humidity
Label: Humidity: Living_Room
Type: dimmer
Category: humidity
Semantic Class: Measurement
Semantic Property: Humidity

Item for the Channel for Temperature

Name: MiTemperature2__Item_Living_Room_Temperature
Label: Temperature: Living_Room
Type: Number: number:temperature
Category: temperature
Semantic Class: Measurement
Semantic Property: Temperature

1 Like

Hello, I have been trying to get the whole thing to work on my Raspberry Pi 4 for a while now. I have currently installed the custom firmware on the sensors and can also address them via “sudo python3 LYWSD03MMC.py --atc” and also get values back. I have understood the instructions from DiViNe and I think I can do it that way. But where I fail is the intermediate step that the script calls itself regularly and the second is, how do I get the values I get back in the script then passed to an MQTT broker on the same Raspi? There is a script “sendToMqtt.sh” for this, but I don’t understand where to call it. :frowning:

A question on the side, since I also have the Bluetooth plant sensors from Xiaomi, which I already successfully read out with another script and pass to the broker (here it all runs foolproof in a file, so I probably managed it :smiley: ), the question is whether you know something where all this can be handled together. Now I have 2 scripts running in parallel.

Thank you in advance for your help.

Simply use cron to start the script.

crontab -e

paste this in:
@reboot /path_to_script/MySensor.sh

Script must be executable (might be allready):
chmod +x /path_to_script/MySensor.sh

Answer to question 2:
IMHO I would stick to one scripts, even though you could use one script for all. Having two is easier to debbug/change and so on…

Hey, thanks for quick replay!
wich option you use? This GitHub - JsBergbau/MiTemperature2: Read the values of the Xiaomi Mi Bluetooth Temperature sensor 2 including custom encrypted format.

#!/usr/bin/env python3

import re
import json
import logging
from bluepy.btle import *
from paho.mqtt import publish

logging.basicConfig(format='%(asctime)s: %(message)s', level=logging.DEBUG)

class XiaomiHygroThermoSensor:

    def __init__(self, mac):
        self._data = {}
        try:
            self.p = Peripheral(mac)
            self.p.setDelegate(XiaomiHygroThermoDelegate())
            logging.debug('Connected')

        except BTLEException:
            self.p = None
            raise

    def read_data(self, full_read = False):
        if self.p is None:
            return False

        try:
#            if full_read:
#                self.name = ''.join(map(chr, self.p.readCharacteristic(0x3)))
#                self.firmware = ''.join(map(chr, self.p.readCharacteristic(0x24)))
#                self.battery = self.p.readCharacteristic(0x18)[0]
            self.p.writeCharacteristic(0x0038, bytearray([1, 0]), True)
            while not self.p.waitForNotifications(15.0):
                continue
            self.temperature = self.p.delegate.temperature
            self.humidity = self.p.delegate.humidity
            return True

        except BTLEException as e:
            self.p.disconnect()
            raise

    def disconnect(self):
        self.p.disconnect()


class XiaomiHygroThermoDelegate:

    def __init__(self):
        self.temperature = None
        self.humidity = None
        self.received = False

    def handleNotification(self, cHandle, data):
		logging.debug('Got notification' + str(cHandle))
		self.temperature = int.from_bytes(data[0:2],byteorder='little',signed=True)/100
		self.humidity = int.from_bytes(data[2:3],byteorder='little')
		logging.debug('Temperature: ' + str(self.temperature))
		logging.debug('Humidity: ' + str(self.humidity))
		self.received = True

if __name__=="__main__":
    full_read = False
    if len(sys.argv) < 3:
        print('Provide sensor MAC and location')
        exit(0)
    if len(sys.argv) > 3:
        full_read = True

    sensor = XiaomiHygroThermoSensor(sys.argv[1])
    location = sys.argv[2]
    if sensor.read_data(full_read):
        mqtt_data = {"temperature": float(sensor.temperature), "humidity": float(sensor.humidity)}
        if full_read:
            mqtt_data.update({"battery": sensor.battery, "name": sensor.name, "version": sensor.firmware})
        logging.info(mqtt_data)
        msgs = [
            {"topic": "mijia/{}".format(location), "payload": json.dumps(mqtt_data)},
        ]
        publish.multiple(msgs, hostname="my.mqtt.server", auth={"username": "mqtt_user_name", "password": "mqtt_user_pass"})

    sensor.disconnect()

or the Code below?

i need one “MySensor” File for each Sensor?
sorry and thanks

I can no longer reach my sensors with the custom firmware with “–device AA:BB:CC:DD:EE:FF” (I replaced the Mac :slight_smile: ). I can only reach them with the ATC mode (–atc) is that right or have I done something wrong?