Мониторинг влажности растений, комплексный подход (на самом деле, на коленке)

Что же делать с raspberry? С ее стороны же как-то нужно собирать ту инфу что отдает ардуина, да еще и через шину i2c.

Для этого в интернете был сворован пятистрочник на питоне, который потом оброс моим быдлокодом, с целью создания удобства использования его в шелле.

import smbus
import time
import sys,getopt
# ($) - gets from /dev/i2c-$"
bus = smbus.SMBus(1)

# Arduino i2c address

def main(argv):
        # Here goes parsing input arguments.
        try:
                opts, args = getopt.getopt(argv,"hiva:s:",["inverted","verbose","i2caddr=","sensor="])
        except getopt.GetoptError:
                print ('usage:getdata.py -a <hex i2c address> -s <sensor> [-v] [-i]')
                sys.exit(2)
        # default flags
        verbose = 0
        inverted = 0
        for opt, arg in opts:
                if opt == '-h':
                        print ('getopt.py -a <hex i2c address> -s <sensor> [-v] [-i]')
                        sys.exit()
                elif opt in ("-i", "--inverted"):
                        inverted = 1
                elif opt in ("-v", "--verbose"):
                        verbose = 1
                elif opt in ("-a", "--i2caddr"):
                        address = arg
                elif opt in ("-s", "--sensor"):
                        send_int = arg

        if verbose == 1:
                print ("Polling sensor ",send_int," on i2c address ",address)
        bus.write_byte(int(address), int(send_int))
        time.sleep(1)
        rcv_byte = bus.read_byte(int(address))
        if verbose == 1 :
                if inverted == 1 :
                        print ("Received data ", 255 - rcv_byte)
                else:
                        print ("Received data ",rcv_byte)
        else:
                if inverted == 1 :
                        print (255 - rcv_byte)
                else:
                        print (rcv_byte)

main(sys.argv[1:])

Собственно, при запуске с ключом -h он покажет вам свой хелп. С ключом нужно указывать i2c адрес устройства на шине (тот что прошивается в коде ардуины), ключом -s указывается номер сенсора, -v включает подробный режим (в обычном выводится только число), -i инвертирует вывод, т.е. чем выше выводимое число, тем более влажная почва (по дефолту наоборот).
Так, удобным образом получать инфу с датчиков стало возможным, но вопрос визуализации остается открытым.

Визуализация

Я начинал рассуждать так: для хранения данных нужно сообразить какую-то базу, в нее складировать данные по датчикам, хранить всяческие переменные. По этим данным строить графики и иметь возможность оповещать себя в случае опасности пересыхания. Черт возьми, да это же самый обычный заббикс! Который, как раз, вполне спокойно у меня уже трудился, занимаясь мониторингом сервера, бесперебойника и сетевых железок.

Ставим на малинку zabbix-agentd и добавляем в конфиг кастомные метрики:

UserParameter=house.plant[*],/usr/bin/python3 /etc/zabbix/scripts/getdata.py -a $1 -s $2 -i

где /etc/zabbix/scripts/getdata.py – наш питоновский скриптец.

Теперь на сервере нужно добавить сам хост, чтобы заббикс начал его опрашивать, а после этого – айтемы, в которых будут хранится метрики растений.

Ключ house.plant[4,0] означает созданный нами UserParameter в конфиге на агенте, и первая цифра подставляется вместо $1, а вторая вместо $2. Следовательно [4,0] подразумевает сбор данных с i2c адреса “4” и датчика под номером “0”.
Update interval – как часто опрашивать датчик в секундах (не имеет смысла делать меньше чем переменная period из кода ардуины).
Вместо plant1 можно написать более понятное название, типо “большой цветок на подоконнике” или какая-нибудь “пальма большая”. Лучше в названии также фиксировать полный адрес датчика, типо 4-0, чтобы иметь возможность однозначно определить нужное растение.

Примерно так выглядит график, видны периодические поливы.

В общем смысле задача оказалась решенной, но все равно как-то недоставало наглядности. Опыт подсказывал, что когда заббикс нужно сделать красивым, за дело берется grafana.

Ставим графану и подключаем к заббиксу (тут без подробностей, всё в документации имеется).

В графане удачным вариантом мне показались красивые gauge-шкалы, у которых можно индивидуально выставлять границы зон:

Для отслеживания высыхания почвы удобно наблюдать графики:

По значениям на графике видно, что одновременный полив для разных растений поднимает значение до разных высот. Причина тому – разные типы почв. При высокой плотности почвы, соответственно, влажность поднимается до высоких значений и, зачастую, медленнее опускается. Рыхлая почва не может удерживать в себе много влаги и требует более частых поливов (хотя и зависит от влаголюбивости растения).

На самом деле, собирая метрики можно наблюдать много интересных корреляций, вроде влияния окружающей температуры и влажности на скорость высыхания почвы, или “сглаживание” переливов горшка (если набуцкать много воды, то сначала почва сильно напитается, но влажность быстро нормализуется путем оседания влаги на дно), и всякое такое. Для увеличения этой интересности, нужно добавить больше различных цветов: попробовать разных размеров горшки, понаблюдать как будут выглядеть затухание графиков у растений находящихся на подоконниках в комнатах на разных сторонах дома – предполагаю будет что-то типо “противофазы”, когда солнце сначала на одной стороне, а потом на другой… В общем есть где побаловаться.

Вроде заключения

В принципе, сей маленький эксперимент мне понравился – очень приятное ощущение когда электроника совершает какие-то возложенные непосредственно на нее задачи без какой-либо ОС. Сделать что-то по гайдам в интернете – раз плюнуть. Но когда нужна специфическая работа, нужен и соответствующий подход. Официальной документации по ардуине начинает не хватать, как начинает ощутимо не хватать и знаний в области микроэлектроники и электротехники.

Тем не менее, мне осталось допилить алерты в заббиксе (ну или в самой графане) чтобы получать уведомления “пора поливать растение $plantname!”. По крайней мере, это будет работать с имеющимися двумя (смешно, конечно) датчиками. Большой вопрос что будет при полных 5 датчиках? Если добавить еще десяток i2c-slave устройств? Что ж, когда нибудь я созрею для большого заказа из китая и проверим это на практике.