Hello all,
i am trying to integrate a XIAOMI Mijia Bluetooth Thermometer 2 device into my openhab 2 (runing on a RPI 3b+). I only have the sensors, no Xiaomi gateway.
I tried to use the bluetooth binding, however it is not detecting any device at all.
Using sudo bluetoothctl via SSH i can find and conncet the device to the RPI 3b+:
Hi Simon,
I have similar Mijia sensor (older version) and I am using python script to read temperature and humidity from it. The script uses bluepy library and sends the data using MQTT protocol.
To get the data into OH obviously you have to configure an MQTT thing.
I would, but the thing is these both versions use different format of the data, so my script will not read proper values from your sensor. Try find something on the internet.
Hi Simon,
I have similar Mijia sensor (older version) and I am using python script to read temperature and humidity from it. The script uses bluepy library and sends the data using MQTT protocol.
To get the data into OH obviously you have to configure an MQTT thing.
Till then everything seems fine but then i am getting this error:
[11:54:53] openhabian@openhab:~/mitemp$ sudo blescan
Scanning for devices…
Traceback (most recent call last):
File “/usr/local/bin/blescan”, line 10, in
sys.exit(main())
File “/usr/local/lib/python3.7/dist-packages/bluepy/blescan.py”, line 122, in main
devices = scanner.scan(arg.timeout)
File “/usr/local/lib/python3.7/dist-packages/bluepy/btle.py”, line 852, in scan
self.start(passive=passive)
File “/usr/local/lib/python3.7/dist-packages/bluepy/btle.py”, line 797, in start
self._mgmtCmd(self._cmd()+“end”)
File “/usr/local/lib/python3.7/dist-packages/bluepy/btle.py”, line 312, in _mgmtCmd
raise BTLEManagementError(“Failed to execute management command ‘%s’” % (cmd), rsp)
bluepy.btle.BTLEManagementError: Failed to execute management command ‘scanend’ (code: 11, error: Rejected)
sudo hciconfig hci0 down && sudo hciconfig hci0 up
Read carefully the whole article. You have to first find out HW address of your sensor using hcitool. Then put this address to this command in --device parameter. Also it seems you have wrong characteristic handle in your command line, it should be “0x0038”, “0x10” is for version 1, which I have.
Device (new): a4:c1:38:ad:3e:fa (public), -75 dBm
Flags: <06>
16b Service Data: <95fe30585b0559fa3ead38c1a408>
Complete Local Name: ‘LYWSD03MMC’
However again an error:
openhabian@openhab:~$ python3 mitemp/demo.py --backend bluepy poll a4:c1:38:ad:3e:fa
Getting data from Mi Temperature and Humidity Sensor
Traceback (most recent call last):
File “mitemp/demo.py”, line 96, in
main()
File “mitemp/demo.py”, line 92, in main
args.func(args)
File “mitemp/demo.py”, line 26, in poll
print(“FW: {}”.format(poller.firmware_version()))
File “/home/openhabian/mitemp/mitemp_bt/mitemp_bt_poller.py”, line 106, in firmware_version
self.battery = int(ord(res_battery))
TypeError: ord() expected a character, but string of length 15 found
Do you have an idea how to handle this?
Thank you!
I am glad I could help. If you prefer python, here is the script I use, but it is for version 1. I think it requires only few changes to work with version 2.
#!/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(0x10, 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):
if cHandle == 14:
m = re.search('T=([\d\.]*)\s+?H=([\d\.]*)', ''.join(map(chr, data)))
self.temperature = m.group(1)
self.humidity = m.group(2)
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()
For sure it requires changes after if full_read: and in handleNotification method. I hope you find it useful.
With this custom LYWSD03MMC firmware (supported by OpenMQTTGateway), the LYWSD03MMC advertises its data without encryption, so no need to connect to the sensor when using it. The data are read every BLEinterval, 55s per default, like all the other devices that advertise data.
Note that the device flashing process takes less than 5minutes and is done over the air (impressive :-)).