A Python library for communicating with FlowerCare (Xiaomi MiFlora) Bluetooth plant sensors.
- Device Discovery: Scan and discover FlowerCare devices via Bluetooth Low Energy
- Real-time Sensor Data: Read temperature, brightness, soil moisture, and conductivity
- Historical Data: Access stored historical measurements from the device
- Device Management: Connect, disconnect, and manage multiple devices
- Async Support: Full asyncio support for non-blocking operations
- Error Handling: Comprehensive exception handling with meaningful error messages
pip install pyflowercare- Python 3.9+
- Bluetooth Low Energy support
- Linux/macOS/Windows with Bluetooth adapter
import asyncio
from pyflowercare import FlowerCareScanner
async def main():
scanner = FlowerCareScanner()
# Scan for devices
devices = await scanner.scan_for_devices(timeout=10.0)
if devices:
device = devices[0]
# Connect and read data
async with device:
sensor_data = await device.read_sensor_data()
print(f"Temperature: {sensor_data.temperature}°C")
print(f"Brightness: {sensor_data.brightness} lux")
print(f"Moisture: {sensor_data.moisture}%")
print(f"Conductivity: {sensor_data.conductivity} µS/cm")
asyncio.run(main())async with device:
info = await device.get_device_info()
print(f"Device: {info.name}")
print(f"MAC: {info.mac_address}")
print(f"Battery: {info.battery_level}%")
print(f"Firmware: {info.firmware_version}")async with device:
history = await device.get_historical_data()
for entry in history[-5:]: # Last 5 entries
print(f"{entry.timestamp}: {entry.sensor_data}")import asyncio
from datetime import datetime
from pyflowercare import FlowerCareScanner
async def monitor_device(device):
while True:
try:
async with device:
while True:
data = await device.read_sensor_data()
timestamp = datetime.now().strftime("%H:%M:%S")
print(f"[{timestamp}] {data}")
await asyncio.sleep(60) # Read every minute
except Exception as e:
print(f"Error: {e}")
await asyncio.sleep(5) # Retry after 5 seconds
async def main():
scanner = FlowerCareScanner()
devices = await scanner.scan_for_devices()
# Monitor all found devices
tasks = [monitor_device(device) for device in devices]
await asyncio.gather(*tasks)
asyncio.run(main())scan_for_devices(timeout=10.0): Scan for FlowerCare devicesfind_device_by_address(mac_address, timeout=10.0): Find specific device by MAC addressscan_continuously(callback, timeout=None): Continuous scanning with callbackscan_stream(timeout=None): Async generator for device discovery
connect(timeout=10.0): Connect to devicedisconnect(): Disconnect from deviceread_sensor_data(): Read current sensor measurementsget_device_info(): Get device information (name, MAC, battery, firmware)get_historical_data(): Get stored historical measurementsblink_led(): Make device LED blink
temperature: Temperature in Celsiusbrightness: Light intensity in luxmoisture: Soil moisture percentageconductivity: Soil conductivity in µS/cmtimestamp: Measurement timestamp
name: Device namemac_address: MAC addressfirmware_version: Firmware versionbattery_level: Battery level percentage
The library provides specific exception types:
from pyflowercare.exceptions import (
FlowerCareError, # Base exception
ConnectionError, # Connection failures
DeviceError, # Device operation errors
DataParsingError, # Data parsing errors
TimeoutError # Operation timeouts
)
try:
async with device:
data = await device.read_sensor_data()
except ConnectionError as e:
print(f"Failed to connect: {e}")
except DeviceError as e:
print(f"Device error: {e}")Enable logging to see detailed operation information:
from pyflowercare import setup_logging
setup_logging("DEBUG") # Enable debug loggingSee the examples/ directory for more comprehensive examples:
basic_usage.py: Simple device connection and data readingcontinuous_monitoring.py: Continuous monitoring of multiple deviceshistorical_data.py: Historical data retrieval and CSV export
sudo setcap cap_net_raw+eip $(eval readlink -f `which python`)Ensure your system has Bluetooth Low Energy support and the adapter is enabled.
- Ensure the FlowerCare device is nearby and not connected to another app
- Try increasing the scan timeout
- Check that the device battery is not depleted
This project is licensed under the MIT License.
Contributions are welcome! Please feel free to submit issues and enhancement requests.