Wer von Außerhalb die Werte seiner Pflanzen beobachten möchte, kann dies entweder selber bauen, oder auf bestehende Lösungen zurückgreifen. Vom Hersteller Xiaomi gibt es u.a. für den Raspberry Pi Flower Care (ehemals MiFlora) – ein Alleskönner, was die Pflanzenüberwachung angeht. Dieses kleine Multitalent kann die Bodenfeuchtigkeit, Temperatur, Lichtintensität und Leitfähigkeit (Nährstoffhinweise) per Bluetooth verschicken, die zuhause oder im eigenen Gewächshaus sehr aufschlussreich sind. Mit Hilfe des Raspberry Pi’s bauen wir eine Digitalanzeige des Xiaomi Flower Care Pflanzensensors.
Des Weiteren können wir die ausgelesenen Werte in unser Smart Home System ein binden und lassen es auf dem OpenHAB Dashboard anzeigen.
Da der Sensor ebenfalls wasserdicht ist, können wir ihn auch außerhalb verwenden und so z.B. unsere Wetterstation erweitern.
Zubehör & Aufbau
Da der Pflanzensensor über Bluetooth kommuniziert, sollte der Raspberry Pi enweder eingebautes Bluetooth haben (ab Version 3), oder ein Dongle verfügbar sein. Hier die Liste des verwendeten Zubehörs:
- Raspberry Pi
- Xiaomi Flower Care Pflanzensensor (Mi Flora)
- ggf. Bluetooth Dongle (über USB)
- Knopfbatterie
- Micro-USB-Kabel als Stromversorgung des Pi’s
Weiteres Zubehör wie ein Bildschirm ist optional.
Öffne vorsichtig die Hinterseite des Flower Care / Mi Flora und setze die Batterie ein. Danach können wir bereits loslegen.
Raspberry Pi Flower Care / MiFlora Python Pakete installieren und Werte auslesen
Zunächst einmal möchten wir die reinen Werte des Sensors auslesen. Dazu müssen wir ein paar Bibliotheken installieren, bevor wir im nächsten Schritt das ganze in unsere Hausautomatisieren einbinden.
Verbinde dich mit deiner Konsole (per SSH) und gib folgendes ein (falls du den Raspberry Pi und den Xiaomi Flower Care Sensor in OpenHAB nutzen willst, sollte es bereits konfiguriert sein und als Betriebssystem zur Installation genutzt werden):
sudo pip3 install miflora
Nun müssen wir zunächst nach dem Sensor suchen. Rufe dazu folgenden Befehl über die Konsole auf:
sudo hcitool lescan
Hier ist ein beispielhaftes Ergebnis des Kommandos:
LE Scan ... C4:7C:8D:66:1A:C3 (unknown) C4:7C:8D:66:1A:C3 Flower care D4:36:39:C7:DB:BD (unknown)
Die Mac Adresse vor „Flower Care“ ist jene, die wir brauchen (hier: C4:7C:8D:66:1A:C3). Diese werden wir gleich noch brauchen.
Anschließend wollen wir den Sensor mittels Python auselesen. Somit starten wir die Python 3 Konsole (oder speichern es alternativ als Skript ab).
sudo python3
Zunächst müssen wir die benötigten Bibliotheken importieren und den Xiaomi Flower Care am Raspberry Pi initialisieren. Dabei ist es wichtig die MAC Adresse anzupassen. Natürlich kannst du auch mehr als einen Sensor verwenden.
from miflora.miflora_poller import MiFloraPoller
from miflora.backends.gatttool import GatttoolBackend
poller = MiFloraPoller('C4:7C:8D:66:1A:C3', GatttoolBackend)
Anschließend haben wir eine Reihe von Möglichkeiten. Da der Mi Flora Sensor verschiedene Werte misst (Bodenfeuchtigkeit, Temperatur, Lichtintensität und Leitfähigkeit), können wir diese auch alle einzeln auslesen.
Xiaomi Mi Flora Python Befehle
Folgende Befehle stehen über die Python Bibliothek des Xioami Mi Flora am Raspberry Pi zur Verfügung:
poller.battery_level()
– gibt den Batteristatus zurück.poller.firmware_version()
– liefert die aktuelle Firmware Version als Text.poller.parameter_value(parameter)
mit einem der folgenden Parametern:'temperature'
– liefert den Temperaturwert (in Grad Celsius)'light'
– gibt den Lichtwert zurück (umso größer – umso heller).'moisture'
– gibt die Feuchtigkeit an.'conductivity'
– gibt die Leitfähigkeit des Bodens an.'battery'
– gibt den Batteristatus an.
Daneben gibt es noch einige weitere Funktionen für den Cache, auf die in diesem Tutorial allerdings nicht näher eingegangen wird (siehe dazu Github).
Falls du also bspw. nur die Temperatur auslesen willst, so wäre folgender Python Code auszuführen:
temp = poller.parameter_value('temperature')
Hier gibt es außerdem noch ein etwas ausführlicheres Beispiel der Entwickler. Es werden die möglichen Szenarien gezeigt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
#!/usr/bin/env python3 """Demo file showing how to use the miflora library.""" import argparse import logging import re import sys from btlewrap import BluepyBackend, GatttoolBackend, PygattBackend, available_backends from miflora import miflora_scanner from miflora.miflora_poller import ( MI_BATTERY, MI_CONDUCTIVITY, MI_LIGHT, MI_MOISTURE, MI_TEMPERATURE, MiFloraPoller, ) def valid_miflora_mac( mac, pat=re.compile(r"(80:EA:CA)|(C4:7C:8D):[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}") ): """Check for valid mac adresses.""" if not pat.match(mac.upper()): raise argparse.ArgumentTypeError( f'The MAC address "{mac}" seems to be in the wrong format' ) return mac def poll(args): """Poll data from the sensor.""" backend = _get_backend(args) poller = MiFloraPoller(args.mac, backend) print("Getting data from Mi Flora") print(f"FW: {poller.firmware_version()}") print(f"Name: {poller.name()}") print("Temperature: {}".format(poller.parameter_value(MI_TEMPERATURE))) print("Moisture: {}".format(poller.parameter_value(MI_MOISTURE))) print("Light: {}".format(poller.parameter_value(MI_LIGHT))) print("Conductivity: {}".format(poller.parameter_value(MI_CONDUCTIVITY))) print("Battery: {}".format(poller.parameter_value(MI_BATTERY))) def scan(args): """Scan for sensors.""" backend = _get_backend(args) print("Scanning for 10 seconds...") devices = miflora_scanner.scan(backend, 10) print("Found {} devices:".format(len(devices))) for device in devices: print(f" {device}") def _get_backend(args): """Extract the backend class from the command line arguments.""" if args.backend == "gatttool": backend = GatttoolBackend elif args.backend == "bluepy": backend = BluepyBackend elif args.backend == "pygatt": backend = PygattBackend else: raise Exception(f"unknown backend: {args.backend}") return backend def list_backends(_): """List all available backends.""" backends = [b.__name__ for b in available_backends()] print("\n".join(backends)) def history(args): """Read the history from the sensor.""" backend = _get_backend(args) print("Getting history from sensor...") poller = MiFloraPoller(args.mac, backend) history_list = poller.fetch_history() print("History returned {} entries.".format(len(history_list))) for entry in history_list: print(f"History from {entry.wall_time}") print(f" Temperature: {entry.temperature}") print(f" Moisture: {entry.moisture}") print(f" Light: {entry.light}") print(f" Conductivity: {entry.conductivity}") def clear_history(args): """Clear the sensor history.""" backend = _get_backend(args) print("Deleting sensor history data...") poller = MiFloraPoller(args.mac, backend) poller.clear_history() def main(): """Main function. Mostly parsing the command line arguments. """ parser = argparse.ArgumentParser() parser.add_argument( "--backend", choices=["gatttool", "bluepy", "pygatt"], default="gatttool" ) parser.add_argument("-v", "--verbose", action="store_const", const=True) subparsers = parser.add_subparsers(help="sub-command help") parser_poll = subparsers.add_parser("poll", help="poll data from a sensor") parser_poll.add_argument("mac", type=valid_miflora_mac) parser_poll.set_defaults(func=poll) parser_scan = subparsers.add_parser("scan", help="scan for devices") parser_scan.set_defaults(func=scan) parser_scan = subparsers.add_parser("backends", help="list the available backends") parser_scan.set_defaults(func=list_backends) parser_history = subparsers.add_parser("history", help="get device history") parser_history.add_argument("mac", type=valid_miflora_mac) parser_history.set_defaults(func=history) parser_history = subparsers.add_parser("clear-history", help="clear device history") parser_history.add_argument("mac", type=valid_miflora_mac) parser_history.set_defaults(func=clear_history) args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.DEBUG) if not hasattr(args, "func"): parser.print_help() sys.exit(0) args.func(args) if __name__ == "__main__": main() |
Anwendungsfälle des Mi Flora Pflanzensensor mit dem Raspberry Pi
Wie bereits erwähnt ist eine verbreitete Anwendung des Sensors über ein Smart Home System wie OpenHAB. Hierbei kann ein entsprechendes Python Skript aufgerufen und dessen Werte angezeigt werden. Eine weitere Möglichkeit besteht direkt über MQTT. Auch hierfür gibt es verschiedene Bibliotheken.
Wer hingegen ein anderes Smart Home System nutzt, kann den Mehrzwecksensor auch nutzen. Für Lösungen wie Home Assistant gibt es ebenfalls bereits vorgefertigte Lösungen. Diese müssen lediglich installiert und die MAC Adresse angepasst werden.
Zu guter letzt kommt natürlich auch ein automatisches Gewächshaus in Frage. Der Sensor lässt sich mittels Python einfach auslesen und einbinden. Der Vorteil besteht darin, dass nun alles von einem Sensor kommt: Wofür vorher verschiedene, kabelgebunde Sensoren nötig waren, können wir nun einen kleinen Pflanzensensor nutzen.