This PlatformIO project implements an ESP32 BLE client for Xiaomi Flora Plant sensors, pushing the measurements in json format to a MQTT broker.
Base on the great work of @sidddy and @jvyoralek (and all other contributors), this project adds:
- Support for multiple Miflora sensors with friendly named topics
- Payloads in json format
- Device (Wifi) status and lwt (last will and testament)
- Seperate configurable (sub) topics
- Measurement levels (configurable by min, max values)
- Battery low status and battery level (configurable by thresholds)
Note : tested with a maximum of 8 Miflora sensors configured, however the ESP32 for some unknown reason get's stuck sometimes. With 4 Miflora sensors configured the ESP32 looks stable and therefore it's advisable to configure a maximum of 4 Miflora sensors per ESP32.
Hardware:
- ESP32 device (ESP32 at AliExpress)
- Xiaomi Flora Plant Sensor (firmware revision >= 2.6.6) (Xiaomi flora at AliExpress)
Software:
- MQTT broker (e.g. Mosquitto)
Assumed you are familiar with Visual Studo Code and PlatformIO.
- Open the project in Visual Studio Code with PlatformIO installed
- Copy
example/config.h.example
toinclude/config.h
and update settings according to your environment:- MAC address(es), location(s), plant id(s) and min and max values of your Xiaomi Flora Plant sensor(s)
- Device id
- WLAN Settings
- MQTT Settings
- Modify platform.ini according to your environment:
- upload_port
- monitor_port
The ESP32 will perform a single connection attempt to the Xiaomi Mi Plant sensor, read the sensor data & push it to the MQTT server. The ESP32 will enter deep sleep mode after all sensors have been read and sleep for n minutes before repeating the exercise... Battery level is read every nth wakeup. Up to n attempst per sensor are performed when reading the data fails.
SLEEP_DURATION
- how long should the device sleep between sensor reads?EMERGENCY_HIBERNATE
- how long after wakeup should the device forcefully go to sleep (e.g. when something gets stuck)?BATTERY_INTERVAL
- how often should the battery status be read?BATTERY_THRESHOLD
- when is the battery on low power?SENSOR_RETRY
- how ofter should a single sensor be tried on each run?
The ESP32 will publish payload in json format on two base topics and are divided in two categories:
This topic is used to publish payload related to the esp32 device status and lwt (last will and testament).
When the ESP32 connects to the MQTT broker a online
message will be published to the /device/lwt
subtopic to indicate the ESP32 is online.
Topic format: <base_topic>/<device_id>/device/lwt
Example plain text payload:
online
When the ESP32 disconnects from the MQTT broker an offline
message is published to the /device/lwt
subtopic to indicate the ESP32 is offline and in sleep mode.
Example plain text payload:
offline
The subtopic /device/status
is used to publish payload related to ESP32 (WiFi) status.
Topic format: <base_topic>/<device_id>/device/status
Example json payload:
{
"id": "esp32-1",
"ipaddress": "10.40.1.1",
"mac": "24:62:AB:CA:F6:40",
"channel": 10,
"rssi": -51
}
id
- the id of the ESP32 as defined inconfig.h
ipaddress
- the ip address of the ESP32 given by the DHCP servermac
- the MAC address of the ESP32channel
- the channel of the WiFi networkrssi
- the WiFi Received Signal Strength Indicator
This topic is used to publish payload related to the Miflora sensor measurements. Each Miflora sensor has its own subtopic.
Topic format: <base_topic>/<device_id>/sensor/<location>/<plant_id>
Example json payload:
{
"id": "calathea-1",
"location": "livingroom",
"mac": "C4:7C:8D:67:57:07",
"retryCount": 1,
"rssi": -75,
"temperature": 21.2,
"temperatureLevel": 1,
"moisture": 4,
"moistureLevel": 0,
"light": 1203,
"lightLevel": 1,
"conductivity": 72,
"conductivityLevel": 0,
"battery": 98,
"batteryLow": false,
"batteryLevel": 2
}
id
- the id of the plantlocation
- the location where the Miflora is placedmac
- the MAC address of the MifloraretryCount
- number of retry attempts to retreive valid data from the Miflorarssi
- the BLE Received Signal Strength Indicatortemperature
- the measured temperature in degree CelsiustemperatureLevel
- indicates if the temperature is 0=low, 1=medium or 2=high, configurable by minTemperature and maxTemperaturemoisture
- the measured moisture in percentagemoistureLevel
- indicates if the moisture is 0=low, 1=medium or 2=high, configurable by minMoisture and maxMoisturelight
- the measured light in luxlightLevel
- indicates if the light is 0=low, 1=medium or 2=high, configurable by minLight and maxLightconductivity
- the measured conductivity in uS/cmconductivityLevel
- indicates if the conductivity is 0=low, 1=medium or 2=high, configurable by minConductivity and maxConductivitybattery
- the measured battery level in percentagebatteryLow
- indicates if the battery is low (true or false), based on the battery low thresholdbatteryLevel
- indicates if the battery is 0=low, 1=medium or 2=high, based on the battery low and mediun thresholds
Note: the min and max values for each measurement can be found in the Flower Care app for IOS or Android.
Some "nice to have" features are not yet implemented or cannot be implemented:
- OTA updates: I didn't manage to implement OTA update capabilities due to program size constraints: BLE and WLAN brings the sketch up to 90% of the size limit, so I decided to use the remaining 10% for something more useful than OTA...
The sketch does not fit into the default arduino parition size of around 1.3MB. You'll need to change your default parition table and increase maximum build size to at least 1.6MB.
On Arduino IDE this can be achieved using "Tools -> Partition Scheme -> No OTA".
For this platform.io project this is achieved using board_build.partitions = no_ota.csv
in platformio.ini
.
Many thanks go to @sidddy and @jvyoralek for most of the work of the project and improvements! Many thanks go to the guys at https://github.com/open-homeautomation/miflora for figuring out the sensor protocol.