Monitorando a saúde de nossas plantas com o Home Assistant
Neste capítulo vamos aprender a controlar a saúde das nossas plantas de uma forma simples e barata. Onde podemos saber parâmetros como a humidade que tem, Temperatura, A quantidade de luz, ou fertilizantes, entre outros.
Nada mau, penso que ya casi todos habéis ouvido alguma vez estes sensores, penso que os há de muchas marcas y suelen ser el mismo cacharro al final, yo lo conozco como Xiaomi Mi Plant, aunque te lo podrás encontrar com qualquer nome tipo Flower Care… em Banggood estão a pôr algum desconto e por aproximadamente 10€ lo tienes.
O uso habitual seria com la app de turno del fabricante de turno que por bluetooth reconheça cada dados vez que se vea com tu móvel. 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 falar com 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 quieres saltar la BD podrías enviar los dados por MQTT, pero soy legacy, de andar armazenando las cosas en BD tradicional 🙂 Depende um pouco a ideia que tengas estoy seguro este post te va a ayudar.
sudo hcitool lescan LE Scan ... 0Para:4D:49:BA:19:XX (desconhecido) 0Para:4D:49:BA:19:XX (desconhecido) 54:5F:A0:C4:A5:XX (desconhecido) 0Para:4D:49:BA:19:XX (desconhecido) C4:7C:8D:6B:25:XX (desconhecido) C4:7C:8D:6B:25:XX Flower care:4D:49:BA:19:XX (desconhecido) 54:5F:A0:C4:A5:XX (desconhecido) ...
Agora vamos a instalar em esa Raspberry Pi la librería de Xiaomi Mi plant sensor para Python, y ya de paso el cliente de mysql que lo precisaremos:
sudo pip3 install miflora sudo pip3 install mysqlclient
Y ahora listo, sólo queda que os descarguéis este script, que no recuerdo bien de donde lo saqué para agradecérselo eternamente. Si os fijáis bien en la línea 47 le añadí unas líneas para que los datos que recoja los almacene en dicho servidor de MySQL, poned vuestros datos, así como el nombre de la planta.
#!/usr/bin/env python3 """Demo file showing how to use the miflora library.""" 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}")): """Check for valid mac adresses.""" if not pat.match(mac.upper()): raise argparse.ArgumentTypeError('The MAC address "{}" seems to be in the wrong format'.format(Mac)) return mac def poll(args): """Poll data from the sensor.""" backend = _get_backend(args) poller = MiFloraPoller(args.mac, backend) #imprimir("Getting data from Mi Flora") #imprimir("FW: {}".format(poller.firmware_version())) imprimir("Nome: {}".format(poller.name())) imprimir("Temperature: {}".format(poller.parameter_value(MI_TEMPERATURE))) imprimir("Moisture: {}".format(poller.parameter_value(MI_MOISTURE))) imprimir("Light: {}".format(poller.parameter_value(MI_LIGHT))) imprimir("Conductivity: {}".format(poller.parameter_value(MI_CONDUCTIVITY))) imprimir("Battery: {}".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)) imprimir (Designação) imprimir (temperatura) imprimir (humidade) imprimir (luz) imprimir (conductividad) imprimir (bateria) nombre = "NOMBRE_DE_LA_PLANTA" db = MySQLdb.connect("DIRECCION_IP_SERVIDOR_MYSQL","USUARIO_BD","CONTRASEÑA_BD","NOMBRE_BD") cursor = db.cursor() cursor.execute("""INSERT INTO plantas (Designação,temperatura,humidade,luz,conductividad,bateria) VALORES (%s,%s,%s,%s,%s,%s) """,(Designação,temperatura,humidade,luz,conductividad,bateria)) db.commit() def scan(args): """Scan for sensors.""" backend = _get_backend(args) imprimir('Scanning for 10 seconds...') devices = miflora_scanner.scan(backend, 10) imprimir('Found {} Dispositivos:'.format(len(Dispositivos))) for device in devices: imprimir(' {}'.format(dispositivo)) 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()] imprimir('\n'.join(backends)) def history(args): """Read the history from the sensor.""" backend = _get_backend(args) imprimir('Getting history from sensor...') poller = MiFloraPoller(args.mac, backend) history_list = poller.fetch_history() imprimir('History returned {} entries.'.format(len(history_list))) for entry in history_list: imprimir('History from {}'.format(entry.wall_time)) imprimir(" Temperature: {}".format(entry.temperature)) imprimir(" Moisture: {}".format(entry.moisture)) imprimir(" Light: {}".format(entry.light)) imprimir(" Conductivity: {}".format(entry.conductivity)) def clear_history(args): """Clear the sensor history.""" backend = _get_backend(args) imprimir('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', tipo=valid_miflora_mac) parser_poll.set_defaults(func=poll) parser_scan = subparsers.add_parser('scan', help='procurar dispositivos') parser_scan.set_defaults(func=scan) parser_scan = subparsers.add_parser('backends', help='listar os backends disponíveis') parser_scan.set_defaults(func=list_backends) parser_history = subparsers.add_parser('history', help='obter histórico do dispositivo') parser_history.add_argument('mac', tipo=valid_miflora_mac) parser_history.set_defaults(func=history) parser_history = subparsers.add_parser('clear-history', help='limpar histórico do dispositivo') parser_history.add_argument('mac', tipo=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()
Se quiserem, deixo-vos o código que irão precisar no MySQL para criar esta tabela, que no final é muito simples, Tem 7 Campos, onde se armazena o nome da planta, Temperatura, a humidade, a luz em luxes, a condutividade, o que resta da bateria e a data em que fez a verificação.
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,
'date' TIMESTAMP NOT NULL PADRÃO CURRENT_TIMESTAMP NA ATUALIZAÇÃO CURRENT_TIMESTAMP
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
ROW_FORMAT=COMPACT
;
Total, o que faremos é programar na Raspberry Pi para executar este script com uma tarefa programada, por exemplo, para que recolha os dados a cada 1 hora serve-me, adicionamos no cron através de ‘crontab -e’, e no final o endereço MAC bluetooth do vosso 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
Agora temos de recolher estes dados com o Home Assistant, como? Muito simples, com consultas mysql! Então, no nosso configuration.yaml podemos adicionar de cada planta as seguintes consultas:
sensor:
...
- Plataforma: sql
db_url: Mysql://USUARIO_BD:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD
consultas:
- Nome: "Ciclamen - Temperatura"
consulta: "SELECIONAR a temperatura DE plantas ONDE o nombre = 'Ciclamen' ORDENAR POR fecha DESC LIMIT 1;"
coluna: 'temperatura'
unit_of_measurement: «ºC»
- Plataforma: sql
db_url: Mysql://USUARIO_BD:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD
consultas:
- Nome: "Ciclamen - Humedad"
consulta: "SELECIONAR humedad FROM plantas WHERE nombre = 'Ciclamen' ORDER BY fecha DESC LIMIT 1;"
coluna: 'humedad'
unit_of_measurement: '%'
- Plataforma: sql
db_url: Mysql://USUARIO_BD:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD
consultas:
- Nome: "Ciclamen - Luz"
consulta: "SELECT luz FROM plantas WHERE nombre = 'Ciclamen' ORDEM POR fecha DESC LIMIT 1;"
coluna: 'luz'
unit_of_measurement: 'lux'
- Plataforma: sql
db_url: Mysql://USUARIO_BD:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD
consultas:
- Nome: "Ciclamen - Conductividad"
consulta: "SELECIONE condutividade DE plantas ONDE o nombre = 'Ciclamen' ORDEM POR fecha DESC LIMIT 1;"
coluna: 'condutividad'
unit_of_measurement: 'Ω'
- Plataforma: sql
db_url: Mysql://USUARIO_BD:CONTRASEÑA_BD@DIRECCION_IP_SERVIDOR_MYSQL/NOMBRE_DE_BD
consultas:
- Nome: "Ciclamen - Bateria"
consulta: "SELECIONE bateria DE plantas ONDE o nombre = 'Ciclamen' ORDEM POR fecha DESC LIMIT 1;"
coluna: 'bateria'
unit_of_measurement: '%'
...
Y ahora sí llegó el momento de añadir el componente de Plant para integrar estes valores que estamos a reconhecer, e indicando a qué le corresponden, así que añadiríamos algo como lo siguiente en configuration.yaml:
plant:
# Cyclamen
ciclamen:
Sensores:
moisture: sensor.ciclamen_humedad
battery: sensor.ciclamen_bateria
temperatura: sensor.ciclamen_temperatura
condutividade: sensor.ciclamen_conductividad
brilho: sensor.ciclamen_luz
min_moisture: 15
max_moisture: 75
min_battery: 10
min_conductivity: 250
max_conductivity: 2000
min_temperature: 1
max_temperature: 35
min_brightness: 2000
max_brightness: 40000
check_days: 3
Nada mau, y qué valores correspondem con los de nuestra planta? Here os dejo una hoja de Google Spreadsheet donde podéis obter informação de alguma planta, si no aproximadamente podéis indicarlos seeking un poco en San Google.
Como de costume, depois de tocar no arquivo de configuração, reiniciamos nosso Home Assistant y desde a UI de Lovelace poderemos adicionar ya nuestras tarjetas con as nossas plantas o flores, o jardín o árbol o lo que queramos controlar. Escogemos una carta de 'Estado de la planta’ e indicamos a entidade da planta y ¡zas! trabalho realizado. Já podemos conhecer o estado em todo o momento das nossas plantas.
E agora nos queda a guinda do pastel, vaya que quando passa algo que nos alerta, Por exemplo, si a humedad é baixa, pues eso es que la planta se está secando, que é melhor que mandar um Telegrama ou uma alerta por nossas altas vozes de casa para indicárnoslo.
Como de costume, agradeceros si habéis chegado hasta el final y esperando haber podido ajudar, y gracias sobre todo por compartir en redes sociales y esos likes!












































