-
Notifications
You must be signed in to change notification settings - Fork 12
Worklog
or How I bricked a Flower Care (Mi Flora)
Well, sometimes playing around with gadgets brings more work fun with it than you hoped for...
I wanted to figure out how to let a Mi Flora device blink. In the Flower Care App you have the option to search a device which lets the LED of the device blink 5 times. A useful functionality when you have several devices and didn't write down their mac addresses to identify them. The names configured in the app are stored in the app only. I use Node-Red for monitoring the plants in my apartment. I never came around to assign names to the devices and over the last months they grew in numbers.
Adafruits Bluefruit LE Sniffer to the rescue (nope, I don't get paid for the product placement)!
This was actually the first time I used this puppy and it took some time to set everything up and it was not the most elegant solution, but it worked. And I have to admit, it is a pretty nice way to investigate what your or your neighbors BLE devices actually spit out the whole time.
Anyway, back to the case...
As you might already know, you have to write the magic bytes 0xa01f
to the characteristic 00001a0000001000800000805f9b34fb
in order to read data from the characteristic 00001a0100001000800000805f9b34fb
. If you don't know what I'm talking about, maybe you should check The Basics.
I turns out, writing another pair of magic bytes (0xfdff
) to the same char lets the device blink 5 times.
YAY!
Now a word of warning: do NOT accidentally mix up the byte order!
Because this will bring the device in another mode and it will change its behavior. I noticed several differences to its normal behavior, here are some of them:
- it will advertise itself as Dial Test instead of Flower Care
- it won't automatically disconnect connections after 10 seconds
- the data char (
00001a01
) is always in realtime mode without writing0xa01f
to the mode char00001a00
- its LED will light up permanently
Especially the LED state worried me in terms of energy consumption. And besides I was angry at myself for breaking yet another a gadget by playing around.
I figured, they have to have a way to reset the device (like factory restore). I mean... right? After playing around with some other values I realised that you can "brick" it even more. So, sometimes it would advertise itself as INNORMAL and the LED made some kind of disco light show. That seemed even worse somehow ...
I had the library in a state of "well, it kinda works... mostly", so I threw together a script to write all possible 16-bit values (= 65536) to the mode characteristic and check if the data characteristic looked normal again (it reads aabbccddeeff99887766000000000000
on a "unbricked" device). Sounds easy enough...
Well, not really. Some values reset the device so that the script could not read after writing. Sometimes it would read a value, get disconnected and the value was different after reconnecting. And every now and then, the device just took a 10+ seconds timeout (which prolonged the whole adventure QUITE a bit). So, the final version did it like this:
loop modeValue 0-65535
{
connect()
write(modeValue)
disconnect()
connect()
read(dataValue)
if (dataValue == expected)
{
stop_and_dance_like_an_idiot()
}
}
85 hours and 53418 tries later, the logfile read
timestamp: 1522365618441
value: 53418
hex: "d0aa"
valueBefore: "cf000064000000000000023c00fb349b"
valueAfter: "aabbccddeeff99887766000000000000"
and my sensor lived happily ever after (atleast until I find another interesting feature)
After all the excitement I implemented the findDevice() method to leverage the newly gained knowledge. Sadly, the result was quite disappointing. When writing the blink command with the library (which uses noble for BLE communication) the LED lights up but slowly fades out, sometimes even twice, but never 5 times.
I have to investigate ...
0xFDFF
= enable blink
0xD0AA
= reset device