Не бывает плохой погоды, бывает только плохая одежда
(шведская пословица)

Эта статья посвящена Zabbix-мониторингу устройств IoT простой метеостанции, подключенных через порт GPIO к микрокомпьютеру отечественной сборки Repka Pi 3 производства НПО Рэйнбовсофт (Rainbowsoft). Здесь будут представлены скрипты мониторинга, измеряющие температуру, давление, влажность, освещенность, а также контролирующие наличие воды (затопление).

Метеостанция оборудована контроллером BME280, измерителем освещенности BH1750, а также сенсором наличия воды YL-38. Результаты измерений периодически отправляются в Zabbix с помощью агента zabbix-agent2 и шаблона, работающего в активном режиме.

Помимо этого, в статье будет описан скрипт Python, который можно запускать периодически через crontab. Этот скрипт выводит результаты измерений на OLED-монитор SSD1306. На время проведения измерений зажигается светодиод, подключенный к GPIO.

Мониторинг самого микрокомпьютера был описан ранее в статье Zabbix-мониторинг российского микрокомпьютера Repka Pi.

Краткое введение в GPIO

Как и во многих микрокомпьютерах, в Repka Pi имеются контакты интерфейса общего назначения GPIO (General Purpose Input/Output). К контактам GPIO можно подключать различные устройства, например, погодную станцию, сенсоры наличия воды, измерители освещенности, OLED-мониторы, драйверы управления двигателями и серводвигателями, ультразвуковые измерители расстояния и так далее.

Порт GPIO в Repka Pi 3 содержит 40 контактов. Из них 28 контактов GPIO, контакты UART, I2C, SPI, а также PWM (рис. 1.)

Рис. 1. Контакты GPIO на плате Repka Pi 3
Рис. 1. Контакты GPIO на плате Repka Pi 3

Ограничения порта GPIO в Repka Pi 3

Подключая внешние устройства к порту GPIO, учтите, что ни при каких условиях вы не должны подавать на выводы сигналы с напряжением, превышающим 3,6 В, иначе микроконтроллер может быть поврежден. 

Также ток потребления контактов GPIO не должен превышать 40 мА (на один контакт).

Рекомендуемое входное напряжение, подаваемое на входы GPIO, составляет 3,3 В, а рекомендуемый потребляемый ток — 20 мА.

Еще важный момент: если вы подключаете периферию большой мощности (моторы, например), используйте для нее отдельный источник питания. При этом большой ток не должен проходить через землю микрокомпьютера.

Электрическую спецификацию на GPIO можно уточнить в даташите на процессор Allwinner H5, который нетрудно найти в интернете по запросу «Allwinner H5 Datasheet».

Обозначение выводов GPIO 

На сайте Repka Pi в разделе «Подключение периферии» указано, что всего предусмотрено пять вариантов прошивки с различной распиновкой (pinout):

  1. GPIO-26, UART-1 (по умолчанию)

  2. GPIO-15, UART-1, SPI-2, I2C-1 

  3. GPIO-11, UART-3, SPI-2, I2C-1 

  4. GPIO-13, UART-1, SPI-2, I2C-2

  5. GPIO-14, UART-1, SPI-2, I2C-1, PWM-1

Обозначение контактов для этих вариантов я взял с сайта разработчика и привел на рис. 2.

Рис. 2. Обозначение контактов GPIO Repka Pi 3 для разных прошивок
Рис. 2. Обозначение контактов GPIO Repka Pi 3 для разных прошивок

Как видите, здесь предусмотрены контакты питания 5 В и 3,3 В, которые можно использовать для питания периферийных модулей, подключенных к GPIO, а также контакты земли GND. Также есть контакты ввода/вывода IO, контакты интерфейсов UART, SPI, I2C, а также PWM.

По умолчанию установлен первый вариант, в котором нет нужного для погодной станции интерфейса I2C. Давайте сконфигурируем GPIO, выбрав второй вариант прошивки.

Конфигурирование GPIO

Для конфигурирования запустите из командного приглашения Repka OS утилиту repka-config. В консоли будет показано текущее значение максимальной частоты процессора (рис. 3).

Рис. 3. Просмотр текущей максимальной частоты процессора
Рис. 3. Просмотр текущей максимальной частоты процессора

Нажмите клавишу Enter. На экране появится меню конфигурирования (рис. 4).

Рис. 4. Меню конфигурирования
Рис. 4. Меню конфигурирования

С помощью клавиш перемещения курсора выберите здесь пункт 3 Frequency / Pinout Options, а затем нажмите клавишу Enter.

Далее вам будет предложено выбрать максимальную частоту процессора (рис. 5).

Рис. 5. Выбор максимальной частоты процессора
Рис. 5. Выбор максимальной частоты процессора

Для метеостанции не нужна высокая частота процессора, так что можете оставить значение по умолчанию или снизить частоту до 1 ГГц.

Снова нажмите клавишу Enter. Появится меню выбора варианта прошивки (рис. 6).

Рис. 6. Выбор варианта прошивки
Рис. 6. Выбор варианта прошивки

Здесь нам нужна строка 2 Вариант – GPIO-15, UART-1, SPI-2, I2C-1. Выберите ее и снова нажмите Enter.

Далее подтвердите перезагрузку ОС (рис. 7).

Рис. 7. Подтверждение перезагрузки ОС
Рис. 7. Подтверждение перезагрузки ОС

После перезагрузки будет установлен нужный вам вариант использования контактов GPIO. Если вы откажетесь от перезагрузки, то для завершения работы утилиты repka-config нужно будет закрыть консольное окно, а затем открыть его заново.

Тестирование линий GPIO

Для тестирования линий GPIO подключим через резистор 300 Ом светодиод к физическим линиям 11 (сигнал) и 14 (земля), как это показано на рис. 8.

Рис. 8. Подключение светодиода к порту GPIO
Рис. 8. Подключение светодиода к порту GPIO

При подключении соблюдайте полярность — плюс светодиода нужно подключить к физическому контакту 11, а минус – к земле, к контакту 14. В качестве земли можно также использовать контакты 6, 9, 14, 20, 25, 30, 34  и 39 (в соответствии с рис. 2).

Скрипт тестирования на Bash

Для работы с линиями GPIO можно использовать несколько интерфейсов. Один из вариантов — интерфейс sysfs. 

При использовании этого интерфейса нужно зарезервировать нужную вам линию GPIO и указать режим ее работы — ввод или вывод с помощью команды echo. Чтобы прочитать состояние линии, воспользуйтесь командой cat. Изменить состояние линии можно с помощью команды echo.

Напишем простейший скрипт на Bash, который зажигает светодиод, а потом через некоторое время гасит его (листинг 1).

Листинг 1. https://github.com/AlexandreFrolov/zabbix-repka-pi-iot/blob/main/led.sh

#!/bin/bash
echo "8" > /sys/class/gpio/export
sleep 0.1
echo "out" > /sys/class/gpio/gpio8/direction
sleep 0.1
echo "1" > /sys/class/gpio/gpio8/value
sleep 5
echo "0" > /sys/class/gpio/gpio8/value 
sleep 0.1
echo "8" > /sys/class/gpio/unexport   
sleep 0.1

Вначале скрипт создает новую линию GPIO с номером 8, записывая этот номер в системный файл sys/class/gpio/export. На рис. 2 этой линии соответствует обозначение PA8.

Далее скрипт ожидает выполнения операции в течение 0.1 секунды. Аналогичная задержка добавлена и после других команд.

Когда порт GPIO добавлен, скрипт переключает его в режим вывода, записывая строку «out» в системный файл /sys/class/gpio/gpio8/direction.

После этого скрипт переводит линию 8 порта GPIO в состояние 1, записывая значение 1 в системный файл /sys/class/gpio/gpio8/value. В результате на соответствующем физическом контакте с номером 11 появляется напряжение +3.3 В, и светодиод зажигается.

Далее скрипт гасит светодиод, записывая в вышеупомянутый системный файл значение 0.

И, наконец, перед завершением своей работы скрипт освобождает линию, записывая значение 8 в системный файл /sys/class/gpio/unexport.

Чтобы запустить скрипт, введите в консоли команду:

# bash led.sh

Светодиод загорится, а через пять секунд погаснет.

Интерфейс доступа chardev

Интерфейс доступа sysfs вполне пригоден и работает, однако отмечен как устаревший. Вместо него рекомендуется использовать интерфейс chardev, особенно для асинхронной работы.

Для обмена данными при этом нужно использовать специальные утилиты. Сначала нужно вызвать утилиту gpiodetect, которая покажет на консоли список доступных чипов и количество подключенных к ним линий gpio:

# gpiodetect
gpiochip0 [1f02c00.pinctrl] (32 lines)
gpiochip1 [1c20800.pinctrl] (224 lines)

Вызвав утилиту gpioinfo, можно получить детальную информацию по каждой линии.

Для того чтобы установить значение 1 на линии PA8, используйте следующую команду:

# gpioset 1c20800.pinctrl 8=1

Вернуть нулевое состояние линии можно так:

# gpioset 1c20800.pinctrl 8=0

Подробнее об этом можно почитать в упомянутой выше статье.

Также есть интерфейс, основанный на работе со специальным устройством /dev/mem. Однако проще работать с этим интерфейсом не напрямую, а с использованием библиотек.

Скрипт тестирования на Python

Хотя Repka Pi 3 создана для замены Raspberry Pi 3, полной совместимости нет, так как применяется другой процессор. Как результат, в скриптах Python вместо RPi.GPIO нужно подключать библиотеку RepkaPi.GPIO, доступную на GitHub.

Установка библиотеки выполняется следующим образом:

$ sudo apt-get update
$ sudo apt-get install python3-dev git
$ git clone https://github.com/DikShv/RepkaPi3.GPIO.git
$ cd RepkaPi3.GPIO
$ sudo python3 setup.py install

В листинге 2 вы найдете скрипт, который мигает светодиодом, подключенном к физическому выводу с номером 11. Этот скрипт сделан на базе примеров, которые есть в упомянутом выше репозитории.

Листинг 2. https://github.com/AlexandreFrolov/zabbix-repka-pi-iot/blob/main/blink_led.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import RepkaPi.GPIO as GPIO
from time import sleep

GPIO.setboard(GPIO.REPKAPI3)

#GPIO.setmode(GPIO.BOARD)
#pin = 11

#GPIO.setmode(GPIO.BCM)
#pin = 17

GPIO.setmode(GPIO.SUNXI)
pin = "PA8"

GPIO.setup(pin, GPIO.OUT)

try:
    print ("Press CTRL+C to exit")
    while True:
        GPIO.output(pin, 1)
        sleep(0.1)
        GPIO.output(pin, 0)
        sleep(1)
except KeyboardInterrupt:
    GPIO.output(pin, 0)
    GPIO.cleanup()
    print ("Bye.")

Программа импортирует библиотеки RepkaPi.GPIO и time. Первая из них нужна для работы с GPIO Repka Pi, а вторая — для задержки выполнения скрипта на заданное время.

Перед началом работы устанавливается тип платы микрокомпьютера:

GPIO.setboard(GPIO.REPKAPI3)

В данном случае это Repka Pi 3.

Вслед за этим программа устанавливает режим GPIO как SUNXI, после чего задает номер контакта с подключенным светодиодом:

GPIO.setmode(GPIO.SUNXI)
pin = "PA8"

В режиме SUNXI используется обозначение контактов GPIO в соответствии с рис. 2, поэтому физический контакт 11 указан как PA8. Этот режим используется на платформах, основанных на системе с чипом (SoC) Allwinner SoC.

В программе предусмотрено использование двух других режимов — GPIO.BOARD и GPIO.BCM:

#GPIO.setmode(GPIO.BOARD)
#pin = 11

#GPIO.setmode(GPIO.BCM)
#pin = 17

В режиме GPIO.BOARD нужно указать физический номер контакта на плате микрокомпьютера. В нашем случае это контакт 11 (рис. 8).

Если нужно адаптировать программу Python, созданную для Raspberry Pi, вам пригодится режим GPIO.BCM. В этом режиме линии GPIO нумеруются в соответствии с схемой Broadcom SOC channel (BCM). При этом нужно указывать такие же номера линий, как и для Raspberry Pi . Описание GPIO Raspberry Pi можно найти здесь.

Конечно, вы можете использовать только один из перечисленных выше режимов.

На следующем этапе программа переключает линию в режим вывода:

GPIO.setup(pin, GPIO.OUT)

После этого с помощью вызова GPIO.output в цикле выполняется попеременный вывод значений 1 и 0 с задержкой в 1 секунду:

while True:
    GPIO.output(pin, 1)
    sleep(0.1)
    GPIO.output(pin, 0)
    sleep(1)

Обратите внимание, что в программе также предусмотрена задержка на 0,1 секунду после операции вывода. Она нужна для ожидания завершения операции.

Подключение сенсора наличия воды YL-38

Наша погодная станция оснащена сенсором наличия воды на базе контроллера YL-38 (рис. 9).

Рис. 9. Контроллер сенсора наличия воды YL-38
Рис. 9. Контроллер сенсора наличия воды YL-38

Этот контроллер, созданный на базе компаратора LM393, поставляется вместе с сенсором MH-RD  (рис. 10).

Рис. 10. Сенсор наличия воды MH-RD
Рис. 10. Сенсор наличия воды MH-RD

Сенсор нужно разместить в контролируемой зоне, где возможны затопления.

На плате контроллера YL-38 есть регулятор для калибровки, два контакта для подключения датчика, а также четыре контакта для подключения питания и микрокомпьютера.

Назначение контактов:

  • Vcc – питание датчика от 3.3 до 5 В;

  • GND – земля;

  • D0 – цифровое значение наличия влажности (1 или 0)

  • A0 – переключение режима (аналоговый или цифровой);

Подключите вывод Vcc контроллера к контакту с физическим номером 17, где выведено напряжение 3,3 В. Также для питания YL-38 можно использовать и контакт с физическим номером 1.

Вывод GND нужно подключить к земле микрокомпьютера, например, к физическому контакту 9 или другому контакту земли, согласно рис. 2.

Вывод D0 подключите к контакту 13 (PA9), а вывод A0 оставьте свободным.

И, наконец, подключите сенсор наличия воды MH-RD к двум контактам на плате YL-38 (рис. 11).

Рис. 11. Подключен сенсор наличия воды MH-RD
Рис. 11. Подключен сенсор наличия воды MH-RD

Чтобы не повредить микрокомпьютер и контроллер, дважды проверьте все соединения перед включением питания.

Далее запустите программу, представленную в листинге 3.

Листинг 3. https://github.com/AlexandreFrolov/zabbix-repka-pi-iot/blob/main/yl38.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import RepkaPi.GPIO as GPIO
from time import sleep

GPIO.setboard(GPIO.REPKAPI3)
GPIO.setmode(GPIO.SUNXI)
pin = "PA9"

GPIO.setup(pin, GPIO.IN) 
sleep(0.1)
print(GPIO.input(pin))

GPIO.cleanup()

Эта программа использует режим GPIO.SUNXI и контакт PA9. Контакт переводится в режим чтения, а затем программа читает полученные данные и выводит их на консоль.

Если сенсор сухой, программа выводит значение единицы, а если влажный — нулевое значение. Если это необходимо, откалибруйте порог срабатывания при помощи регулятора.

Тестирование I2C

Если к микрокомпьютеру нужно подключить много устройств, удобен последовательный ассиметричный интерфейс I2C, разработанный в начале 80-х годов компанией Philips. На шине I2C может использоваться одно или несколько ведущих устройств и до 127 ведомых. При этом ведущие устройства управляют процессом передачи данных ведомых устройств.

Для передачи данных по шине I2C используются линии SLC и SDA. Линия SLC служит для передачи сигналов синхронизации, а линия SDA —для передачи данных. 

Для метеостанции в качестве ведущего устройства будет использован микрокомпьютер Repka Pi 3, а в качестве ведомых — измеритель освещенности BH1750, погодная станция BME280, а также дисплей OLED SSD1306.

Подключение измерителя освещенности BH1750

Для измерения освещенности в люксах установим контроллер BH1750 (рис. 12).

Рис. 12. Измеритель освещенности BH1750
Рис. 12. Измеритель освещенности BH1750

Выводы GND и VCC контроллера нужно подключить к земле и выводам питания +3,3 В. Используйте для питания контакт Repka Pi 3 с физическим номером 17.

Контакт ADD оставьте свободным. Он задает адрес люксметра на шине I2C. Если подключить этот контакт к земле, адрес будет 0x23, а если оставить свободным — 0x5C. Задавая разные адреса, вы можете подключить к шине I2C два измерителя освещенности.

Что касается выводов SDA и SLC, то их нужно подключить к контактам 3 и 5 (рис. 2). Напомним, что мы установили второй вариант прошивки (распиновки), где эти контакты используются для I2C.

Остановите ОС и выключите питание микрокомпьютера. Затем подключите BH1750 и проверьте, что его видно на шине I2C.

Для этого обновите ОС и установите пакет i2c-tools:

# apt update
# apt upgrade
# apt install i2c-tools

Затем посмотрите список шин I2C:

# i2cdetect -l
i2c-1   i2c   mv64xxx_i2c adapter  I2C adapter
i2c-2   i2c   mv64xxx_i2c adapter  I2C adapter
i2c-0   i2c   DesignWare HDMI      I2C adapter

Наше устройство подключено к шине с номером 1, в чем можно убедиться, выполнив следующую команду:

# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --

Как видите, здесь присутствует устройство с адресом 0x23, а это как раз наш измеритель освещенности BH1750. К шине I2C также подключена погодная станция BME280 с адресом 0x76, а еще дисплей OLED SSD1306 с адресом 0x3c.

В листинге 4 приведена несложная программа, которая получает данные от измерителя освещенности, преобразует их в значение, выраженное в люксах, а затем выводит на консоль.

Листинг 4. https://github.com/AlexandreFrolov/zabbix-repka-pi-iot/blob/main/bh1750.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import smbus2
import time

bus = smbus2.SMBus(1)
address = 0x23
command = 0x10

bus.write_byte(address, command)
time.sleep(0.5)
data = bus.read_i2c_block_data(address, command, 2)
illuminance = round((data[1] + (256 * data[0])) / 1.2)
print(illuminance)

Программа импортирует библиотеку smbus2 для работы с шиной I2C, а также библиотеку time для реализации функции задержки.

Первым делом программа создает объект bus для обращения к шине I2C с номером 1.

Далее команда выводит на шину по адресу 0x23 команду 0x10 для измерения освещенности в непрерывном режиме с разрешением в 1 люкс. 

После задержки на 0,5 секунды программа читает два байта данных с результатами измерений и преобразует их в люксы с округлением до целого числа. Далее значение освещенности выводится на консоль.

Подробную информацию об измерителе освещенности BH1750 можно найти здесь.

Подключение погодной станции BME280

Займемся подключением погодных станций BME280 и BMP280 (рис. 13). Первая из них измеряет температуру, давление и влажность, вторая — только температуру и давление. 

Рис. 13. Погодная станция BME280
Рис. 13. Погодная станция BME280

При подключении погодной станции к микрокомпьютеру Repka Pi 3 контакты VIN и GND нужно подключить к источнику питания 3,3 В и к земле соответственно. Используйте для питания контакт Repka Pi 3 с физическим номером 17.

Выводы SDA и SLC нужно подключить к контактам 3 и 5 микрокомпьютера Repka Pi 3 (рис. 2). Во втором варианте прошивки эти контакты используются для I2C.

Хотя погодная станция BME280 представляет собой сложное устройство, программа получения данных измерений достаточно проста (листинг 5) благодаря использованию библиотеки bme280.

Листинг 5. https://github.com/AlexandreFrolov/zabbix-repka-pi-iot/blob/main/bme380.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import smbus2
import bme280
import json

port = 1
address = 0x76
bus = smbus2.SMBus(port)

calibration_params = bme280.load_calibration_params(bus, address)
data = bme280.sample(bus, address, calibration_params)
data_json = {
"temperature": data.temperature,
"pressure": data.pressure,
"humidity": data.humidity
}
print(json.dumps(data_json))

Помимо bme280, в программе подключаются библиотеки smbus2 и json. Первая из них нужна для работы с шиной I2C, а вторая — для вывода на консоль результатов измерений в формате JSON. Этот формат удобен для мониторинга при помощи Zabbix.

После создания объекта bus для работы с портом 1 шины I2C программа загружает параметры калибровки для BME280.

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

И, наконец, параметры преобразуются в формат JSON и выводятся на консоль:

# python3 bme380.py
{"temperature": 25.057424980401994, "pressure": 994.2263284324112, "humidity": 22.976936524510958}

Техническое описание BME280 можно найти тут.

Просмотр результатов измерений на дисплее OLED SSD1306

Итак, теперь нам осталось только подключить к Repka Pi 3 дисплей OLED SSD1306 и написать программу, которая будет показывать на нем результаты измерений погоды, а также выводить предупреждение о протечке воды.

На рис. 14 показан собранный макет погодной станции со всеми упомянутыми ранее модулями. Чашка с водой нужна для проверки обнаружения протечки.

Рис. 14. Собранный макет погодной станции
Рис. 14. Собранный макет погодной станции

Дисплей OLED SSD1306 показан на рис. 15.

Рис. 15. Дисплей OLED SSD1306
Рис. 15. Дисплей OLED SSD1306

Как видите, здесь есть все те же контакты VCC, GND, SCL и SDA. Теперь вы уже знаете, куда их подключать.

Для вывода данных на дисплей мы будем использовать библиотеку luma.oled. Чтобы ее установить, потребуется всего две команды:

# apt-get install python3 python3-pip python3-pil libjpeg-dev zlib1g-dev libfreetype6-dev liblcms2-dev libopenjp2-7 libtiff5 -y

# pip3 install luma.oled

Для изучения вы также можете установить другие программы, использующие эту библиотеку:

$ git clone https://github.com/rm-hull/luma.examples.git
$ cd luma.examples
$ sudo -H pip3 install -e .

В листинге 6 вы найдете программу, которая получает все данные от погодной станции и отображает их на дисплее. На время работы программы зажигается светодиод, подключенный к GPIO.

Листинг 6. https://github.com/AlexandreFrolov/zabbix-repka-pi-iot/blob/main/get_weather.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import smbus2
import bme280
import json
from luma.core.render import canvas
from luma.oled.device import ssd1306
from PIL import ImageFont
import time
from time import sleep
import RepkaPi.GPIO as GPIO
GPIO.setboard(GPIO.REPKAPI3)
GPIO.setmode(GPIO.BOARD)

pin = 11
GPIO.setup(pin, GPIO.OUT)
GPIO.output(pin, 1)
sleep(0.1)

pin2 = 13
GPIO.setup(pin2, GPIO.IN) 
sleep(0.1)
no_water = GPIO.input(pin2)    
sleep(0.1)

port = 1
address = 0x76
bus = smbus2.SMBus(port)
calibration_params = bme280.load_calibration_params(bus, address)
data = bme280.sample(bus, address, calibration_params)
temper=data.temperature
press= data.pressure
humi=data.humidity

address = 0x23
command = 0x10
bus.write_byte(address, command)
time.sleep(0.5)
data = bus.read_i2c_block_data(address, command, 2)
illuminance = round((data[1] + (256 * data[0])) / 1.2)

device = ssd1306(port=1, address=0x3C)
font = ImageFont.load_default()
with canvas(device) as draw:
    draw.text((0, 0), "temp: " + str(round(temper, 1)) + " C", font=font, fill="white")
    draw.text((0, 10), "press: "  + str(round(press, 1)) + " hPa", font=font, fill="white")
    draw.text((0, 20), "humi: "  + str(round(humi, 1)) + " %", font=font, fill="white")
    draw.text((0, 30), "luxur: "  + str(round(illuminance, 1)) + " Lux", font=font, fill="white")
    if no_water:
      draw.text((0, 40), "No water: "  + str(no_water), font=font, fill="white")
    else:
      draw.text((0, 40), "WATER DETECTED!", font=font, fill="white")
sleep(3)
device.command(0xAE)

sleep(1)
GPIO.output(pin, 0)
sleep(0.1)
GPIO.cleanup()

Мы рассмотрим только фрагменты кода, предназначенные для работы с дисплеем.

Прежде всего подключаются необходимые библиотеки:

from luma.core.render import canvas
from luma.oled.device import ssd1306
from PIL import ImageFont

Далее создается объект для работы с дисплеем, при этом указывается номер порта и адрес дисплея на шине I2C:

device = ssd1306(port=1, address=0x3C)

После этого загружаются шрифты:

font = ImageFont.load_default()

Создается объект draw, который предоставляет методы для рисования на дисплее. При этом canvas обеспечивает контекстное управление, что позволяет автоматически освобождать ресурсы после окончания работы с дисплеем:

with canvas(device) as draw:

После этого на экран дисплея выводятся четыре строки с данными о температуре, давлении, влажности и освещенности:

draw.text((0, 0), "temp: " + str(round(temper, 1)) + " C", font=font, fill="white")
draw.text((0, 10), "press: "  + str(round(press, 1)) + " hPa", font=font, fill="white")
draw.text((0, 20), "humi: "  + str(round(humi, 1)) + " %", font=font, fill="white")
draw.text((0, 30), "luxur: "  + str(round(illuminance, 1)) + " Lux", font=font, fill="white")

Вслед за этим, в зависимости от данных определения протечки, пятой строкой выводится сообщение об отсутствии или обнаружении воды (рис. 16):

if no_water:
  draw.text((0, 40), "No water: "  + str(no_water), font=font, fill="white")
else:
  draw.text((0, 40), "WATER DETECTED!", font=font, fill="white")
Рис. 16. Вывод результатов измерений на дисплей OLED SSD1306
Рис. 16. Вывод результатов измерений на дисплей OLED SSD1306

И, наконец, после небольшой задержки экран дисплея выключается командой 0xAE:

sleep(10)
device.command(0xAE)

Даташит для дисплея OLED SSD1306 можно найти здесь. Также рекомендую полезную статью про работу с дисплеем.

Подключение метеостанции к Zabbix

Предполагаем, что вы уже настроили мониторинг Repka Pi по статье «Zabbix-мониторинг российского микрокомпьютера Repka Pi». В частности, вы уже установили агент Zabbix Agent2 в Repka OS, подключили шаблоны Linux by Zabbix agent active и zabbix-agent-on-repka-pi.

Теперь нужно добавить шаблон zabbix-repka-pi-iot, а также скрипты мониторинга данных для нашей метеостанции.

Шаблон zabbix-repka-pi-iot

Загрузите файл шаблона zabbix-repka-pi-iot и подключите его к узлу Repka Pi с помощью web-интерфейса вашего сервера Zabbix:

$ wget https://raw.githubusercontent.com/AlexandreFrolov/zabbix-repka-pi-iot/main/zabbix-repka-pi-iot-template.xml

Скрипты для шаблона zabbix-repka-pi-iot

Далее создайте на узле Repka Pi каталог /etc/zabbix/scripts (если такого каталога еще нет) и сделайте его текущим:

# mkdir /etc/zabbix/scripts/
# cd /etc/zabbix/scripts/

Загрузите скрипты для получения данных из репозитория Github:

# wget https://raw.githubusercontent.com/AlexandreFrolov/zabbix-repka-pi-iot/main/bme380.py

# wget https://raw.githubusercontent.com/AlexandreFrolov/zabbix-repka-pi-iot/main/bh1750.py

# wget https://raw.githubusercontent.com/AlexandreFrolov/zabbix-repka-pi-iot/main/yl38.py

# wget https://raw.githubusercontent.com/AlexandreFrolov/zabbix-repka-pi-iot/main/yl38_starter.sh

Разрешите выполнение загруженных скриптов:

# chmod 755 /etc/zabbix/scripts/bme380.py
# chmod 755 /etc/zabbix/scripts/bh1750.py
# chmod 755 /etc/zabbix/scripts/yl38.py
# chmod 755 /etc/zabbix/scripts/yl38_starter.sh

Скрипт yl38.py (листинг 3) для выполнения требует прав пользователя root, так как обращается к системным файлам, например, к файлу /sys/class/gpio/export. Чтобы этот скрипт мог запускаться агентом с правами пользователя zabbix, создадим скрипт yl38_starter.sh. Он будет запускать программу yl38.py через команду sudo (листинг 7).

Листинг 7. https://raw.githubusercontent.com/AlexandreFrolov/zabbix-repka-pi-iot/main/yl38_starter.sh

#!/bin/bash
sudo /etc/zabbix/scripts/yl38.py

Для того чтобы у агента Zabbix была возможность запуска программы yl38.py без указания пароля пользователя zabbix, отредактируем файл /etc/sudoers c помощью команды visudo:

# visudo

С помощью запущенного этой командой редактора вам нужно добавить следующую строку и сохранить изменения:

zabbix ALL=(ALL:ALL) NOPASSWD: /etc/zabbix/scripts/yl38.py

Очень важно указать здесь полный путь к программе /etc/zabbix/scripts/yl38.py, а не только ее имя. Иначе можно будет запустить с правами root любую программу с именем yl38.py, расположенную в любом каталоге.

Теперь проверьте, что скрипты работают при их запуске от имени пользователя zabbix и выводят на консоль данные для мониторинга:

# sudo -u zabbix /etc/zabbix/scripts/bh1750.py
# sudo -u zabbix /etc/zabbix/scripts/bme380.py
# sudo -u zabbix /etc/zabbix/scripts/yl38_starter.sh

Настройка конфигурации агента zabbix-agent2

Для настройки конфигурации агента zabbix-agent2 отредактируйте файл /etc/zabbix/zabbix_agent2.conf:

# vim /etc/zabbix/zabbix_agent2.conf

Добавьте в конец этого файла следующие строки:

UserParameter=bme280[*], /etc/zabbix/scripts/bme380.py
UserParameter=bh1750[*], /etc/zabbix/scripts/bh1750.py
UserParameter=yl38[*], /etc/zabbix/scripts/yl38_starter.sh

После этого перезапустите сервис zabbix-agent2 и проверьте его статус:

# service zabbix-agent2 restart
# service zabbix-agent2 status

Метрики шаблона zabbix-repka-pi-iot

Откройте через web-интерфейс Zabbix раздел Latest Data для вашего узла Repka Pi. На экране появятся данные метрик шаблона zabbix-repka-pi-iot (рис. 17).

Рис. 17. Данные метрик шаблона zabbix-repka-pi-iot
Рис. 17. Данные метрик шаблона zabbix-repka-pi-iot

Метрики, полученные от контроллера BME280, возвращаются программой bme380.py в виде данных JSON:

{
  "temperature": 25.579528852575457, 
  "pressure": 991.6858111589619, 
  "humidity": 29.90541603887028
}

Для получения нужных значений в шаблоне zabbix-repka-pi-iot используется предварительная обработка JSON Path, аналогично тому, как это было описано в статье про мониторинг Repka Pi.

Триггеры шаблона zabbix-repka-pi-iot

В шаблоне zabbix-repka-pi-iot определен только один триггер, срабатывающий при обнаружении контроллером YL-38 протечки воды (рис. 18).

Рис. 18. Триггер в шаблоне zabbix-repka-pi-iot
Рис. 18. Триггер в шаблоне zabbix-repka-pi-iot

Когда YL38 находит воду, на его выходе устанавливается нулевое значение напряжения. Именно на эту ситуацию и настроен триггер. Я присвоил триггеру высокий (High) уровень серьезности, но вы можете изменить его на катастрофический (Disaster), если протечка может иметь очень серьезные последствия.

При необходимости добавьте триггеры, например, на слишком низкую и высокую температуру или на появление света там, где его не должно быть.

При срабатывании триггера сервер Zabbix может отправлять вам сообщения Email, SMS, писать в Телеграм и даже звонить голосом по телефону, если все это настроить.

Следим за погодой

Как известно, погода переменчива. Настроив мониторинг метеостанции с помощью Zabbix, вы сможете убедиться в этом лично.

На рис. 19 показан график изменения температуры в районе рабочего стола автора этой статьи при открытом окне.

Рис. 19. Контроль температуры
Рис. 19. Контроль температуры

Как видите, утром температура немного повысилась. В целом, для лета это неплохая температура.

Влажность тоже вполне приемлемая, и к утру она немного повысилась (рис. 20).

Рис. 20. Контроль влажности
Рис. 20. Контроль влажности

Давление изменялось не очень сильно. На рис. 21 показаны его значение в гПа.

Рис. 21. Контроль давления
Рис. 21. Контроль давления

Измеряя освещенность, можно заметить, что солнце зашло примерно в 9 часов вечера, а в 4:19 начался восход (рис. 22).

Рис. 22. Контроль освещенности
Рис. 22. Контроль освещенности

Сравнивая график освещенности с графиками температуры и влажности, можно обнаружить связь — с восходом солнца температура и влажность увеличились. Что логично.

Для имитации протечки мы использовали чашку с водой, опуская в нее сенсор MH-RD, подключенный к контроллеру YL-38. На рис. 23 виден график изменения значений, полученных от YL-38. По умолчанию Zabbix получает значение раз в минуту.

Рис. 23. Контроль протечек воды
Рис. 23. Контроль протечек воды

Пунктирной линией красного цвета на этом графике обозначено пороговое значение срабатывания триггера протечки.

Итоги

Итак, вы научились подключать устройства IoT к GPIO микрокомпьютера Repka Pi 3, обмениваться с ними данными, в том числе по шине I2C, а также отправлять эти данные в Zabbix для мониторинга и отображения в виде графиков. Также вы настроили триггер в Zabbix, срабатывающий при обнаружении протечки воды.

Полученные знания пригодятся, если вы, например, создаете свой умный дом или автоматизируете какое-либо оборудование, подключенное к GPIO, с помощью российского микрокомпьютера Repka Pi 3.

Использованы изображения с сайта https://commons.wikimedia.org с лицензией No restrictions:

Автор: Александр Фролов.


НЛО прилетело и оставило здесь промокод для читателей нашего блога:

-15% на заказ любого VDS (кроме тарифа Прогрев) — HABRFIRSTVDS

Комментарии (1)


  1. Jury_78
    30.06.2023 15:41

    Все красиво, но за свои деньги цена не гуманная...