Monitorizando la salud de nuestras plantas con Home Assistant
En este capítulo aprenderemos a cómo controlar la salud de nuestras plantas de una manera sencilla y barata. Donde podremos conocer parámetros como la humedad que tiene, la temperatura, la cantidad de luz, o fertilizante entre otros.
Ondo, creo que ya casi todos habéis escuchado alguna vez estos sensores, creo que los hay de muchas marcas y suelen ser el mismo cacharro al final, yo lo conozco como Xiaomi Mi Plant, aunque te lo podrás encontrar con cualquier nombre tipo Flower Care… en Banggood suelen poner algún descuento y por aproximadamente 10€ lo tienes.
El uso habitual sería con la app de turno del fabricante de turno que por bluetooth recoge los datos cada vez que se vea con tu móvil. En este caso al tener un Home Assistant que no tiene bluetooth, ya que en mi caso corre como una máquina virtual pues difícil tiene para hablarse con el sensor de marras. Así que al tener varias Raspberry Pi repartidas por casa, en cada Raspberry Pi que quede más cerca de la planta en cuestión, esa será la que conecte con el sensor, recoja los datos por bluetooth, y los almacene en una BD que tengo por ahí de MySQL/MariaDB; también es cierto que si te nahi saltar la BD bidaltzea posible da MQTT, pero soy legacy, BD tradizionalean 🙂 gauzak gordetzen badituzu Depende un poco la idea que tengas estoy seguru hau post te va a ayudar.
sudo hcitool lescan LE Scan ... 0A:4D:49:BA:19:XX (ezezaguna) 0A:4D:49:BA:19:XX (ezezaguna) 54:5F:A0:C4:A5:XX (ezezaguna) 0A:4D:49:BA:19:XX (ezezaguna) C4:7C:8D:6B:25:XX (ezezaguna) C4:7C:8D:6B:25:XX Flower care:4D:49:BA:19:XX (ezezaguna) 54:5F:A0:C4:A5:XX (ezezaguna) ...
Orain vamos a instalatu en esa Raspberry Pi la librería Xiaomi Mi plant sensor para Python, eta ya de pasatzen du bezero de mysql que lo necesitaremos:
sudo pip3 install miflora sudo pip3 install mysqlclient
Y orain listo, sólo queda que os descarguéis este script, ez dakit ondo nondik atera nuen etengabe eskertzeko. lerroan ondo begiratuz gero 47 lerro batzuk gehitu nituen jasoko dituen datuak MySQL zerbitzari horretan gordetzeko, jarri zure datuak, hala nola landarearen izena.
#!/usr/bin/env python3
"""Demonstro fitxategia miflora liburutegia nola erabili erakusten duena."""
import argparse
import re
import logging
import sys
import MySQLdb
from btlewrap import available_backends, BluepyBackend, GatttoolBackend, PygattBackend
from miflora.miflora_poller import MiFloraPoller, \
MI_CONDUCTIVITY, MI_MOISTURE, MI_LIGHT, MI_TEMPERATURE, MI_BATTERY
from miflora import miflora_scanner
def valid_miflora_mac(mac, pat=re.compile(r"80:EA:CA:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}")):
"""Baliozko mac helbideak egiaztatu."""
if not pat.match(mac.upper()):
raise argparse.ArgumentTypeError('MAC helbidea "{}" formato okerrean dagoela dirudi'.format(mac))
return mac
def poll(args):
"""Poll data from the sensor."""
backend = _get_backend(args)
poller = MiFloraPoller(args.mac, backend)
#inprimatu("Getting data from Mi Flora")
#inprimatu("FW: {}".format(poller.firmware_version()))
inprimatu("Izena: {}".format(poller.name()))
inprimatu("Temperature: {}".format(poller.parameter_value(MI_TEMPERATURE)))
inprimatu("Moisture: {}".format(poller.parameter_value(MI_MOISTURE)))
inprimatu("Light: {}".format(poller.parameter_value(MI_LIGHT)))
inprimatu("Conductivity: {}".format(poller.parameter_value(MI_CONDUCTIVITY)))
inprimatu("Bateria: {}".format(poller.parameter_value(MI_BATTERY)))
nombre = (poller.name())
temperatura = (poller.parameter_value(MI_TEMPERATURE))
humedad = (poller.parameter_value(MI_MOISTURE))
luz = (poller.parameter_value(MI_LIGHT))
conductividad = (poller.parameter_value(MI_CONDUCTIVITY))
bateria = (poller.parameter_value(MI_BATTERY))
inprimatu (nombre)
inprimatu (temperatura)
inprimatu (humedad)
inprimatu (luz)
inprimatu (conductividad)
inprimatu (bateria)
nombre = "NOMBRE_DE_LA_PLANTA"
db = MySQLdb.connect("DIRECCION_IP_SERVIDOR_MYSQL","DB_ERABILTZAILEA","CONTRASEÑA_BD","NOMBRE_BD")
cursor = db.cursor()
cursor.execute("""INSERT INTO plantas (nombre,temperatura,humedad,luz,conductividad,bateria) BALIOAK (%s,%s,%s,%s,%s,%s) """,(nombre,temperatura,humedad,luz,conductividad,bateria))
db.commit()
def scan(args):
"""Scan for sensors."""
backend = _get_backend(args)
inprimatu('Scanning for 10 seconds...')
devices = miflora_scanner.scan(backend, 10)
inprimatu('Found {} gailuak:'.format(luzeera(gailuak)))
for device in devices:
inprimatu(' {}'.format(gailu))
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('unknown backend: {}'.format(args.backend))
return backend
def list_backends(_):
"""List all available backends."""
backends = [b.__name__ for b in available_backends()]
inprimatu('\n'.join(backends))
def history(args):
"""Read the history from the sensor."""
backend = _get_backend(args)
inprimatu('Getting history from sensor...')
poller = MiFloraPoller(args.mac, backend)
history_list = poller.fetch_history()
inprimatu('History returned {} entries.'.format(luzeera(history_list)))
for entry in history_list:
inprimatu('History from {}'.format(entry.wall_time))
inprimatu(" Temperature: {}".format(entry.temperature))
inprimatu(" Moisture: {}".format(entry.moisture))
inprimatu(" Light: {}".format(entry.light))
inprimatu(" Conductivity: {}".format(entry.conductivity))
def clear_history(args):
"""Clear the sensor history."""
backend = _get_backend(args)
inprimatu('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()
Si queréis, os dejo el código que necesitaréis en MySQL para crear esta tabla, que al final es muy sencilla, tiene 7 campos, donde se almacena el nombre de la planta, la temperatura, la humedad, la luz en luxes, la conductividad, lo que le queda de batería y la fecha de cuando hizo el chequeo.
CREATE TABLE `plantas` ( `nombre` CHAR(20) NULL COLLATE 'utf8mb4_general_ci', `temperatura` FLOAT NULL, `humedad` FLOAT NULL, `luz` FLOAT NULL, `conductividad` FLOAT NULL, `bateria` FLOAT NULL, 'fecha' TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) COLLATE='utf8mb4_general_ci' ENGINE=InnoDB ROW_FORMAT=COMPACT ;
Guztira, que lo que haremos es programar en la Raspberry Pi que ejecute este script con una tarea programada, por ejemplo con que recoja los datos cada 1 hora a mí me vale, añadimos en cron mediante ‘crontab -e’, y al final la dirección MAC bluetooth de vuestro sensor:
0 * * * * python3 /home/pi/miflora_jardin.py -v poll C4:7C:8D:6B:1E:XX 0 * * * * python3 /home/pi/miflora_portulaca.py -v poll 80:EA:CA:88:E4:XX
Ahora tenemos que recoger estos datos con Home Assistant, nola? Muy sencillo, ¡con consultas mysql! Así que en nuestro configuration.yaml podemos añadir de cada planta las siguientes consultas:
sensor: ... - platform: sql db_url: mysql://DB_ERABILTZAILEA:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD kontsultak: - name: "Ziklamen - Temperatura" query: "HAUTATU TENPERATURA PLANTETATIK NON nombre = 'Ziklamen' ORDENA FECHA DESC MUGA 1;" zutabea: 'temperatura' unit_of_measurement: 'ºC' - platform: sql db_url: mysql://DB_ERABILTZAILEA:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD kontsultak: - name: "Ziklamen - Humedad" query: "HAUTATU humedad PLANTETATIK NON nombre = 'Ziklamen' ORDENA FECHA DESC MUGA 1;" zutabea: 'humedad' unit_of_measurement: '%' - platform: sql db_url: mysql://DB_ERABILTZAILEA:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD kontsultak: - name: "Ziklamen - Luz" query: "HAUTATU luz PLANTETATIK NON nombre = 'Ziklamen' ORDENA FECHA DESC MUGAREN arabera 1;" zutabea: 'luz' unit_of_measurement: 'lux' - platform: sql db_url: mysql://DB_ERABILTZAILEA:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD kontsultak: - name: "Ziklamen - Conductividad" query: "HAUTATU eroankortasuna PLANTETATIK NON nombre = 'Ziklamen' ORDENA FECHA DESC MUG 1;" zutabea: 'eroankortasuna' unit_of_measurement: 'Ω' - platform: sql db_url: mysql://DB_ERABILTZAILEA:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD kontsultak: - name: "Ziklamen - Bateria" query: "HAUTATU bateria PLANTETATIK NON nombre = 'Ziklamen' ORDENA FECHA DESC MUG 1;" zutabea: 'bateria' unit_of_measurement: '%' ...
Eta orain bai, iritsi da momentua Plant osagaia gehitzeko, bildu nahi ditugun balio hauek integratzeko, eta zehazteko zeinari dagokion, beraz configuration.yaml-en honako hau gehi genezake:
landare:
# Cyclamen
ziklamena:
sensors:
hezetasuna: sentsorea.ciclamen_hezetasuna
bateria: sentsorea.ciclamen_bateria
tenperatura: sentsorea.ciclamen_tenperatura
eroankortasuna: sentsorea.ciclamen_eroankortasuna
distira: sentsorea.ciclamen_argia
min_hezetasuna: 15
max_hezetasuna: 75
min_bateria: 10
min_eroankortasuna: 250
max_eroankortasuna: 2000
min_tenperatura: 1
max_tenperatura: 35
min_distira: 2000
max_distira: 40000
kontrol_egunak: 3
Ondo, eta zeintzuk balio gure landarearekin bat datozen? Hemen uzten dizuet Google Spreadsheet fitxa bat non lor dezakezuen informazioa landare baten inguruan, si no aproximadamente podéis indicarlos buscando un poco en San Google.
Betiko moduan, tras tocar fichero de configuración, reiniciamos nuestro Home Assistant y desde la UI de Lovelace podremos añadir ya nuestras tarjetas con nuestras plantas o flores, o jardín o árbol o lo que queramos controlar. Escogemos una tarjeta de ‘Estado de la planta’ e indicamos la entidad de la planta y ¡zas! trabajo realizado. Ya podremos conocer el estado en todo momento de nuestras plantas.
Y ahora nos queda la guinda del pastel, vaya que cuando pase algo que nos alerte, adibidez, si la humedad es baja, pues eso es que la planta se está secando, que mejor que mandar un Telegram o una alerta por nuestros altavoces de casa para indicárnoslo.
Betiko moduan, eskerrak ematen dizkizu azken sareetan eta espero dut lagundu, eta eskerrik asko sare sozialetan eta bestelako gustukoak partekatzeko!












































