Skip to content

The Basics

Christian Scheffler edited this page Apr 8, 2018 · 3 revisions

While tinkering with the device I learned alot about the underlying technology and protocols. This page is for sharing that information so that you can play around with the devices and its services yourself.

The Flower Care family includes two devices, which can be controlled and monitored with the Flower Care App (Android / iOS):

  • Mi Flora Plant Monitor
  • Mi Flora Smart Flower Pot

As far as I know, both use the same concept of communication and provide the same services to read data off of them.

The following information is solely based on experience with the Plant Monitor (the stick) as I don't own a smart pot. ...yet

Hardware & Software

My devices are on the latest (as of 04/2018) firmware version 3.1.8.

This is the hardware I use to fiddle around with:

On the software side I used:

BLE & GATT

The basic technologies behind the sensors communication are Bluetooth Low Energy (BLE) and GATT. They allow the devices and the app to share data in a defined manner and define the way you can discover the devices and their services.
In general you have to know about services and characteristics to talk to a BLE device.

Adafruits Kevin Townsend has published a really nice introduction on the subject and if you don't know about BLE and/or GATT you should definitely give it a look.

Services & Characteristics

We are interested in the followings service and characteristics.

Service UUID (id) Characteristic UUID (id) Read/Write Description
0000fe95-0000-1000-8000-00805f9b34fb (ROOT_SERVICE) - - used for discovery
00001204-0000-1000-8000-00805f9b34fb (DATA_SERVICE) 00001a00-0000-1000-8000-00805f9b34fb (CMD_CHAR) write send command
00001204-0000-1000-8000-00805f9b34fb (DATA_SERVICE) 00001a01-0000-1000-8000-00805f9b34fb (DATA_CHAR) read get actual sensor values
00001204-0000-1000-8000-00805f9b34fb (DATA_SERVICE) 00001a02-0000-1000-8000-00805f9b34fb (FIRM_CHAR) read get battery state and firmware version

Discover Devices

A BLE device periodically advertises its existence and provided services. The Flower Care sensors make no exception to this and advertise themselfs with the name Flower care and the root service (ROOT_SERVICE) fe95 (shortened version of 0000fe95-0000-1000-8000-00805f9b34fb). In order to discover them you need to scan for a while and filter the advertisements packets by either the name or the ROOT_SERVICE UUID.

In javascript with noble you could do something like the following example.

noble.on('discover', peripheral => {
    console.log('discovered a device by UUID', peripheral.address);
});
// let noble filter it for us
noble.startScanning(['fe95'], false);

Identify Devices

Besides the service UUID, an advertisement packet of the Flora Care devices also contains Service Data, for example 0x712098003c1dd6658d7cc40d0910024706. Bytes 2 and 3 (little endian) reveal the device model.

Value Device
0x0098 Mi Flora Plant Monitor
0x015d Mi Flora Smart Flower Pot

Read Data

Firmware & Battery

To figure out what features you can use on the device you should check the firmware version first. Thankfully we get the battery level at the same time. Both information can be read from the firmware characteristic (FIRM_CHAR) 00001a02-0000-1000-8000-00805f9b34fb within the data service (DATA_SERVICE) 00001204-0000-1000-8000-00805f9b34fb.

A read request will return 7 bytes of data, for example 0x6327332e312e38.

Position 0 1 2 3 4 5 6
Value 63 27 33 2e 31 2e 38
Byte Content Value Comment
0 battery level in % 0x63 = 99% byte
2-6 firmware version 3.1.8 ASCII text

The second byte (0x27) seems to be a separator. In older firmware versions it always read 0x13. Both are control characters in the ASCII table.

Sensor Values

In order to read the sensor values you need to change its mode. This can be done by writing 2 bytes to the command characteristic (CMD_CHAR) 00001a00-0000-1000-8000-00805f9b34fb within the data service (DATA_SERVICE) 00001204-0000-1000-8000-00805f9b34fb.

The magic bytes are 0xa01f.

After writing them you can read the actual sensor values from the data characteristic (DATA_CHAR) 00001a01-0000-1000-8000-00805f9b34fb within the data service (DATA_SERVICE) 00001204-0000-1000-8000-00805f9b34fb.

A read request will return 16 bytes of data, for example 0xc90000d2410100381906023c00fb349b.

Position 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
Value c9 00 00 d2 41 01 00 38 19 06 02 3c 00 fb 34 9b
Byte Content Value Comment
0-1 temperature in 0.1°C 0x00c9 = 201 (20.1°C) unsigned 16-bit int (little endian)
3-6 light in lux 0x000141d2 = 82386 lux unsigned 32-bit int (little endian)
7 moisture in % 0x38 = 56% byte
8-9 conductivity in µS/cm 0x0619 = 1561 µS/cm unsigned 16-bit int (little endian)

(the high lux value was being forced with a torch light in order to verify that the value is stored in 32-bit)

Serial Number

Just like when reading sensor values you have to write to the command characteristic (CMD_CHAR) 00001a00-0000-1000-8000-00805f9b34fb within the data service (DATA_SERVICE) 00001204-0000-1000-8000-00805f9b34fb first in order to read the serial number.

This time the magic bytes are 0xb0ff.

After writing the value you can read the data from the data characteristic (DATA_CHAR) 00001a01-0000-1000-8000-00805f9b34fb within the data service (DATA_SERVICE) 00001204-0000-1000-8000-00805f9b34fb.

It seems like the complete result is the serial number.