sputnikdev / eclipse-smarthome-bluetooth-binding

Eclipse SmartHome Bluetooth Binding
46 stars 10 forks source link

Test and add support for Xiaomi Mijia Bluetooth Temperature Smart Humidity Sensor #18

Closed vkolotov closed 6 years ago

vkolotov commented 6 years ago

Xiaomi bluetooth temperature and humidity sensor is widely available for a cheap rice. Hopefully it is using standard GATT specification so that it can work out of the box.

dtony commented 6 years ago

Hi am really interested by this feature. I own the device myself and I am able to read temperature and humidity using this command on a Linux computer with a Bleutooth 4.0 dongle : gatttool -b <MAC> --char-write-req --handle=0x0010 --value=0100 --listen There is 12 readings that follows and then it is blocked but I can do ctrl-c and restart the command.

the output is in this following form : Notification handle = 0x000e value: 54 3d 32 33 2e 36 20 48 3d 33 37 2e 33 00 It translates in ASCII to : T=23.6 H=37.3 which is a temperature of 23.6°C and a relative humidity of 37.3% I hope this is enough to implement this sensor. If you need my help to test it, do not hesitate to ask !

vkolotov commented 6 years ago

Hi @dtony, thanks for your input. It is planned to be implemented in the next release. It is already implemented in the GattParser, check this out: https://github.com/sputnikdev/bluetooth-gatt-parser/blob/12e2a73505232b1625ac3123fadf7043f6d0a9f0/src/test/java/org/sputnikdev/bluetooth/gattparser/GenericCharacteristicParserIntegrationTest.java#L220

It would be great if you could do the initial testing for this. Please stay tuned.

dtony commented 6 years ago

Unfortunately I realized that my openhab installation was in a LXD container and using a a bluetooth usb dongle is not going to be easy at all. It could work with the libusb bluetooth stack but not with BlueZ.

rliffredo commented 6 years ago

I have just got a couple of those sensors, so I can do the testing.

vkolotov commented 6 years ago

Good news here is that I have managed to decode device advertising data. In short, it is quite easy to extract Temp, Humidity and battery level from the device advertising service data. Here is the data structure: https://github.com/sputnikdev/bluetooth-gatt-parser/blob/master/src/main/resources/gatt/characteristic/com.xiaomi.bluetooth.characteristic.advertised_data.xml

rliffredo commented 6 years ago

Awesome :) Where should I put that definition? In the documentation there is some reference to the fact that you can add definitions, but I have no idea how...

vkolotov commented 6 years ago

Give me a couple of days, I'll be releasing a new version of the binding where it is included.

rliffredo commented 6 years ago

OK, thanks :)

RealLittleSherman commented 6 years ago

Hello to all, i had a new unit, im open to tests

Regards

RealLittleSherman commented 6 years ago

Do you have any idea how to "decrypt" the battery info? In my case, my Hygromter send the following hex chars:

0xfd 0x44 0xec 0x1f 0x31 0x6f

In this case the ASCII transformation does not making sense.

Thanks in advance

vkolotov commented 6 years ago

Hi @RealLittleSherman, thanks for your interested. This device is already supported in the upcoming version of the binding. I'm in the process of releasing it.

franckFleet commented 6 years ago

Hi, I very apreciate the content of your work about xiaomi data advertising. how have you find all of theses informations ? do you have access to sources or does theses informations opened ?

vkolotov commented 6 years ago

Hi @franckFleet,

do you have access to sources or does theses informations opened ?

I do not have access to Xiaomi sources. However it is still possible to decompile their official android apps.

how have you find all of theses informations ?

It was quite easy to fine out what each advertisement packet means by just looking at it (what's changing).

vkolotov commented 6 years ago

Support for this device has been added in v1.1

GerSant commented 6 years ago

@vkolotov i try to write a HomeBridge PlugIn in NodeJS for this device, can you helpme to understand and decode the Advertisement data with noble? My twittwer is @sdnpro

Thanks for advance

tuzzo77 commented 6 years ago

Please someone can help me: Where can i found temp/humidity from this bytes? Thanks.

54 3D 32 38 2E 39 20 48 3D 35 33 2E 35 00

GerSant commented 6 years ago

Hi Tuzzo, its perfectly explained in the README.md of @hannseman in the "Technical details" section of her plugin https://github.com/hannseman/homebridge-mi-hygrothermograph.

Regards

tuzzo77 commented 6 years ago

Thanks for the reply, but my packet length is 14 bytes and not 16 as explained in the README. Is it possible?

GerSant commented 6 years ago

Yes, you must discard that and wait for a 16-byte full packet

On Thu, May 31, 2018 at 11:23 AM Alessandro Mattiuzzi < notifications@github.com> wrote:

Thanks for the reply, but my packet length is 14 bytes and not 16 as explained in the README. Is it possible?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/sputnikdev/eclipse-smarthome-bluetooth-binding/issues/18#issuecomment-393470742, or mute the thread https://github.com/notifications/unsubscribe-auth/AjDvnxm1G3xhySACoj9ork6v6Cl0Jx0Qks5t37augaJpZM4RgX5R .

-- Germán Santillán Capristo

tuzzo77 commented 6 years ago

Thanks so much, but my device disconnected after few seconds: "Disconnected MJ_HT_V1"

tuzzo77 commented 6 years ago

My MJ_HT_V1 got disconnected after few seconds. I receive only 14 bytes packet.

GerSant commented 6 years ago

You don´t need to establish a connection with the Hygrometer, because you don't have the secret Token to maitain the connection up, you need only "hear" the advertisement messages ;)

vkolotov commented 6 years ago

Hi @GSanCap , @tuzzo77 , it is all (the format) explained here:

https://github.com/sputnikdev/bluetooth-gatt-parser/blob/master/src/main/resources/gatt/characteristic/com.xiaomi.bluetooth.characteristic.mi_service.xml

and here

https://github.com/sputnikdev/bluetooth-gatt-parser/blob/master/src/main/resources/gatt/characteristic/com.xiaomi.bluetooth.characteristic.events_data.xml

tuzzo77 commented 6 years ago

Maybe I'm reading the wrong UUID. First UUID: 226C0000-6476-4566-7562-66734470666D Second UUID: 226CAA55-6476-4566-7562-66734470666D.

What's inside UUID: FE95? Thanks

marcvandam2 commented 6 years ago

For those how are interested.

I was able to authenticate on the Xiaomi Temp sensor since yesterday. I have it working now on a rpi 3 with Android Things installed on it. With Android studio I was able to import project: https://github.com/MiEcosystem/XmPluginSDK/tree/master/BluetoothDemo/app with some minor changes this just works.

I can confirm that library found in https://github.com/MiEcosystem/XmPluginSDK/XmPluginSDK/BluetoothDemo/app/src/main/jniLibs/armeabi-v7a will work on rpi. But to get it working on a normal not "Android Things" environment some extra .so library files are needed I think. Don't know that yet.

From a high level view: Software generates a token. And sends that encrypted to sensor. Also using BLECipher.mixA method. This method needs mac of sensor and device type. Please note, device type of temp sensor is 426. Default in the project is 156. That is an other device..

        byte[] var1 = BLECipher.mixA("my mac", deviceid);
        byte[] var2 = BLECipher.encrypt(var1, this.f);

The token is then encrypted and send over the ble line. The "not encrypted token" is used together with the "answer" that is received from the sensor to give a "final answer".

        byte[] var4 = BLECipher.mixA(this.b, this.c);
        byte[] var5 = BLECipher.mixB(this.b, this.c);
        byte[] var6 = BLECipher.encrypt(var5, BLECipher.encrypt(var4, var3));

After this the device remained connected for me. No more disconnects after few seconds.

Regards, Marc van Dam

vkolotov commented 6 years ago

Nice one @marcvandam2! I'll have a look later if I can add a proper authentication. Just so you know, this might be not necessary to do authentication and keep connection always open for this type of sensor (temp and humidity). Especially if you are limited with available connections. Xiaomi sensors advertise enough data without establishing connection to them. Reading these advertisements have been implemented in this binding sometime ago (two releases back I believe).

marcvandam2 commented 6 years ago

yes. it is indeed true that tempurature is given even without authentication. By my opinion conecting to device is required. Normally after 5 seconds it throughs out the connection because no authentication took place. The fun part in that ~5 seconds it is possible to read 2 or 3 temp/hum values. But that could only be done in limited time. If a more continuation is needed authentication would be required.

In my use case these temp sensors will be used in thermostat setting. During morning hours I would like them to report to the software on an more event driven way. I want to know each temp change. Specially during morning hours.

vkolotov commented 6 years ago

It seems to me there is a confusion. That sensors (and some other Xiaomi sensors) constantly advertises temp and humidity readings without establishing any connections to them. It is a broadcasting mechanism in Bluetooth protocol, in other words it is 1 to many relationship, e.g. one sensor can be read/listened by many receivers (adapters) without establishing any connection to it.

emericg commented 6 years ago

Hey guys, does anyone know if it's possible to get battery level without advertisment datas? My bluetooth library doesn't support them (yet) unfortunately...

GerSant commented 6 years ago

If you do "gatttool -b BLE_MAC_ADDRESS --char-read --handle=0x0018" you will be obtain an Hexa value, yo need to convert it to uint8, thats the percent of battery life!! ;)

emericg commented 6 years ago

Thanks for the very quick answer! Using btgatt-client I can indeed read this value, thanks! With weird results, 70% for a fully charged ni-mh, 9x% for a new AA battery while all the screen indiator seems to be full in both case, but that is the device fault anyway...

I know why I didn't picked up this value while looking around though... the associated service, {0000180f-0000-1000-8000-00805f9b34fb} (I think) and the {00002a19-0000-1000-8000-00805f9b34fb} characteristic are just completely invisible from my bluetooth library, I'm not really sure why. I'm using Qt Bluetooth and... there is a few undocumented caveats :-(

vkolotov commented 6 years ago

Hi @emericg, Bluez 5.48+ makes it invisible unfortunately. And just in general newer Bluez are more unstable from my observation.

emericg commented 6 years ago

Humm maybe that's it, I am using bluez 5.50. But btgatt-client does report the service, and Qt Bluetooth (using the bluez D-Bus API now) doesn't? Why is this service special though, is it just a bug?

Thanks for all these infos!

vkolotov commented 6 years ago

Nope, it is not a bug, it is a new bloody feature... https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/battery-api.txt

emericg commented 6 years ago

Soo, I guess it will be hidden by Bluez on linux, available instead through a new API that will maybe implemented next year on Qt Bluetooth, but will still be available directly on other OSes... Yeah that's great...

I'll just mask the battery icon dynamically if no value is available then ^^ Thanks!

BikeAtor commented 5 years ago

Its just ASCII: 54 3D 32 38 2E 39 20 48 3D 35 33 2E 35 00 T = 2 8 . 9 H = 5 3 . 5 EOS

mahlich commented 5 years ago

Hi, i am using these sensors within openhab and the bluetooth BLE binding. I have placed one of my sensors outside and the moment the temperature is below 0°C the reading is not converted correctly. The sensors shows -0.3°C, the item reads 6553.3 °C. Do I have to adjust something for the item? Thanks! I just saw that there is already an open issue for that (#78), sorry for placing the question here...

tomascrespo commented 5 years ago

Hi! I see you know this Mi Temp Humidity sensor very well.

I'm trying to get the historical values of the sensor, but I don't know how to do it. I can sniff how the Mi Home app does it, because it doesn't do it. You need a BLE Gateway to obtain historical values of temp and humidity. Perhaps sniffing the communication between BLE Gateway and Mi Temp and Humidity sensor it could be achieved.

In another Xiaomi sensor, Mi Flower Care sensor, it is possible read historical values, playing with two handles, this way:

  1. Write the magic word 0xa00000 in handle 0x003e
  2. Read the historical entry count in handle 0x003c
  3. Write the address of the historical entry we want in 0x003e
  4. Read the values of the given address in 0x003c

If it were possible to know what are these two handles and the magic word for Mi Temp and Humidity sensor will be great.

Thanks!

Could it be that Mi Temp and Humidity sensor does not store historical values? Could it be that the values were stored in the BLE gateway? I don't think so.

matbra commented 1 year ago

Specifically regarding fetching of historic data: This Python library is able to do that for the lywsd03mmc sensor: https://github.com/uduncanu/lywsd03mmc.

Maybe this helps with investigating how it's done.