Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test and add support for Xiaomi Mi Flora Monitor #19

Closed
vkolotov opened this issue Jan 16, 2018 · 10 comments
Closed

Test and add support for Xiaomi Mi Flora Monitor #19

vkolotov opened this issue Jan 16, 2018 · 10 comments
Assignees

Comments

@vkolotov
Copy link
Contributor

Check if the device conform to standard GATT specifications and works out of the box.

@vkolotov vkolotov self-assigned this Jan 16, 2018
@jerano
Copy link

jerano commented Jan 26, 2018

Let me know if you need any help testing this, I've got three Mi Floras.

Successfully installed the Bluetooth Binding and the TinyB Binding yesterday, and they were discovered and added to my test-system. The following channels were detected/added:
Online
Connected
Connection Control
Connected Adapter
RSSI
Estimated Distance
Nearest Adapter
Location

Would be awesome getting them supported, so I don't have to bother with external scripts and stuff for getting the data.

@vkolotov
Copy link
Contributor Author

hi @jerano, I'm working on this at the moment. It will be supported in the next release. I've got one sensor, so it is easier for me now.

@jerano
Copy link

jerano commented Jan 27, 2018

awesome! then I can hold off on using some alternative way to get the sensors into my OH system.

keep up the good work!

@vkolotov
Copy link
Contributor Author

vkolotov commented Jan 29, 2018

Unfortunately MiFlora sensor (and probably other Mi sensors) uses a proprietary authentication mechanism that involves a handshake, security token generation/exchange.
Here are some steps that have been captured by a bluetooth sniffer while a MiFlora sensor was getting connected:

Step 1. Authentication process begins
write 	0x0013 01 00 				- enable notification for 0x0012
Step 2. Session opens (a magic number {00 BC 43 CD} is written to 0x001B)
write 	0x001B 00 BC 43 CD          - 00000010-0000-1000-8000-00805f9b34fb
notify 	0x0012 CD 9B 00 FA			- 00000001-0000-1000-8000-00805f9b34fb
Step 3. Security tokens is generated and written
write 	0x0012 10 A1 FB D5			- 00000001-0000-1000-8000-00805f9b34fb
some kind of response after sending an auth token
notify 	0x0012 D0 55 DE 70			- 00000001-0000-1000-8000-00805f9b34fb
notify 	0x0012 D0 55 DE 70			- 00000001-0000-1000-8000-00805f9b34fb
write 	0x0013 00 00                - disable notification for 0x0012
authentication complete
 -----
read 	0x0038 -> 63 27 33 2E 31 2E 38         - 00001a02-0000-1000-8000-00805f9b34fb
write 	0x0036 01 00                - enable notif for data char 0x0035 (00001a01-0000-1000-8000-00805f9b34fb)
write	0x003F 01 00                - enable notif for 0x003E (00001a10-0000-1000-8000-00805f9b34fb)
write	0x0033 A0 1F  				- set the magic number (00001a00-0000-1000-8000-00805f9b34fb) to be able to read the data char (00001a01-0000-1000-8000-00805f9b34fb))
notify   0x0035 0E 01 00 4E 01 00 00 00 00 00 02 3C 00 FB 34 9B - data char
read	    0x0041 -> 1C 04 08 00       - (00001a12-0000-1000-8000-00805f9b34fb)
write  	0x003E A0 00 00             - 00001a10-0000-1000-8000-00805f9b34fb
notify   0x003E A0 00 00             - 00001a10-0000-1000-8000-00805f9b34fb
read	    0x003C -> 00 00 00 00 C6 13 08 00 C8 15 08 00 00 00 00 00 (00001a11-0000-1000-8000-00805f9b34fb)
write    0x003E A2 00 00
write    0x003F 00 00 				- disable for 0x003e
notify   0x0021 00 					- 00001001-0000-1000-8000-00805f9b34fb
notify 	0x0035 0D 01 00 97 01 00 00 00 00 00 02 3C 00 FB 34 9B - data
write    0x0036 00 00 				- disable for 0x0035
write	0x0033 C0 1F 				- set the magic number - different to previous one
read	    0x0038 -> 63 27 33 2E 31 2E 38         00001a02-0000-1000-8000-00805f9b34fb
write	0x0036 -> 01 00 			- enable notif for data
write	0x0033 -> A0 1F 			- magic number again
notify   0x0035 -> 0C 01 00 2B 01 00 00 00 00 00 02 3C 00 FB 34 9B - data
notify   0x0021 00 					- ??? 00001001-0000-1000-8000-00805f9b34fb
notify   0x0035 ...
notify   0x0035 ...

Unfortunately there is not any easy way to generate security tokens, the Flower Care android mobile app uses a JNI library to generate/encrypt tokens.
The authentication process is happening in BleRegisterConnector class (Flower Care app). There are three steps in total (see above). Security tokens are generated by BLECipher class which it turns uses a JNI library "blecipher". It is possible to extract that library from the mobile app (see BLECipher and generateToken), however it won't work in linux. Looks like android libs are not compatible with other distributions of linux.
The following error happens when you try to use it in ubuntu:
java.lang.UnsatisfiedLinkError: /home/user/projects/libblecipher.so: /usr/lib/x86_64-linux-gnu/libm.so: invalid ELF header
Furthermore, in order to read the data characteristic ("00001a01-0000-1000-8000-00805f9b34fb"), a special magic number ({0xA0, 0x1F}) must be set to a characteristic first ("00001a00-0000-1000-8000-00805f9b34fb").

If authentication token is not validated by device, device drops connection. However, fortunately it is still possible to quickly read data characteristic before it disconnects.

In other words, we won't be able to create a proper binding for Mi devices (unless someone figures out how to encrypt security tokens), however we still can create a binding that periodically connects to the device and fetches data while it is in authentication process (like other python scripts do).

@jerano
Copy link

jerano commented Jan 29, 2018

There's no checking of firmware version before that? I mean, it might be something they've implemented later, and us lucky ones with earlier versions (not using the app at all!) aren't affected by this!(?)

Just speculating though... I think I've noticed the sensor disconnecting after a while, when playing around with gatttool and other bluetooth tools.

Anyways, if it's possible to implement a small binding for them, I think lots of people would be happy, but if not... we'll just have to stick to scripts scraping the info and updating OH from outside.

Thanks for the work you put into this!!

@vkolotov
Copy link
Contributor Author

There's no checking of firmware version before that? I mean, it might be something they've implemented later, and us lucky ones with earlier versions (not using the app at all!) aren't affected by this!(?)

Indeed it might be like that. Unfortunately I have upgraded the device I have and I can't check now. Would you @jerano be able to double check this theory? E.g. use a gattool or bluetoothctrl to connect to the device and see if it disconnects after 5-10 secs?

@jerano
Copy link

jerano commented Jan 29, 2018

Hey @vkolotov !

With bluetoothctl, connection to a sensor seems to disconnect after 5-10secs, unfortunately.
Firmware on my sensors are v2.6.2.

Can read characteristics from sensor with gatttool, ie. like:
gatttool -i hci0 -b xx:xx:xx:xx:xx:xx --char-read --handle=0x0035
But sometimes it times out (I assume) with "connect error: Transport endpoint is not connected (107)"

Oh well, it seems there are some decent ways to get the sensor data into OH via ie. MQTT, so if no specific binding for these sensors are created, I guess we'll survice...

@vkolotov
Copy link
Contributor Author

I'm planning to create a bluetooth extension for this device anyway, it will allow us to use miflora with no issues, like if there was not that stupid auth mechanism, it just won't be efficient implementation-wise.

@vkolotov
Copy link
Contributor Author

Support for this device has been added in v1.1

@drndos
Copy link

drndos commented Feb 4, 2019

https://github.com/aprosvetova/xiaomi-kettle is getting really close to the solution to your problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants