Создавайте домашнюю температуру и влажность с помощью Raspberry Pi

Prometheus - это проект с открытым исходным кодом для мониторинга и оповещения метрик. Он опирается на базу данных временных рядов, которая хорошо подходит для целей Интернета вещей. В этой статье мы увидим, как измерять температуру и влажность с Raspberry Pi. Эти метрики собираются датчиком DHT22 / AM2302. Мы увидим, как подключить датчик к карте и подтвердить получение данных.

Следующим шагом является реализация экспортера Prometheus на Голанге. Экспортер предоставляет метрики через HTTP-сервер в хорошем формате. Сервер Prometheus вызывает экспортера для сбора и сохранения метрик. Prometheus сам написан на Golang, и наш экспортер будет использовать те же библиотеки.

После того, как метрики в Prometheus, мы настраиваем красивую панель управления Grafana.

Конфигурация датчика

Презентация

AM2302 - это проводная версия датчика DHT22. В даташите представлены следующие характеристики:

  • Бюджетный
  • Питание от 3 до 5 В и ввод / вывод
  • Максимальный ток 2,5 мА, используемый во время преобразования (при запросе данных)
  • Подходит для измерения влажности 0–100% с точностью 2–5%
  • Подходит для измерения температуры от -40 до 80 ° C с точностью ± 0,5 ° C
  • Частота дискретизации не более 0,5 Гц (один раз в 2 секунды)
  • Размер корпуса 15,1 мм x 25 мм x 7,7 мм
  • 4 контакта с шагом 0,1

Связь

Датчик работает по принципу Plug and Play и подключается к Raspberry Pi следующим образом:

  • DAT на выводе GPIO (GPIO3)
  • VCC на выводе питания между 3 В и 5 В (PIN1)
  • GCC на контакте заземления (PIN6)

Получение данных

Обновите список доступных пакетов и установите python3 и pip:

$ sudo apt-get update
$ sudo apt-get install python3 python3-pip
$ python3 -m pip install --upgrade pip

Установите пакет Adafruit-DHT pip:

$ python3 -m pip install Adafruit-DHT

Сделайте скрипт исполняемым и запустите его:

$ chmod +x am2302_tester.py
$ python3 am2302_tester.py
Temp=19.2*C  Humidity=55.0%

Датчик хорошо регистрирует показатели влажности и температуры.

Экспортер Прометея

Конфигурация

Конфигурация представляет собой файл YAML и находится в другом месте в соответствии с приоритетом:

  • /etc/dht-prometheus-exporter.yml
  • $HOME/dht-prometheus-exporter.yml
  • $PWD/dht-prometheus-exporter.yml

Пакет viper управляет файлом конфигурации и сохраняет значения в структуре. Периодическая информация доступна для других частей проекта.

логирование

Пакет logrus управляет регистрацией и повторно использует уровень, определенный в конфигурации:

Датчик

Интерфейс пакета go-dht с датчиком. В нем уже есть функция чтения данных с пина gpio. Структура содержит собранные метрики:

Коллекционер прометея

Пакет Prometheus предоставляет сборщик. В нем перечислены различные метрики, которые нужно собирать и раскрывать. Показатели влажности и температуры находятся в одном коллекторе. У метрик есть ярлыки, чтобы дать больше контекста:

  • dht_name: имя датчика, которое будет легко идентифицировать (в случае нескольких датчиков)
  • имя хоста
  • unit: единица измерения температуры в градусах Фаренгейта или Цельсия.

Функции Describe и Collector уже реализованы в пакете Prometheus. Нам нужно переопределить их, чтобы перегрузить функции нашими метриками:

Главный

Основной файл является связующим звеном между функциями предыдущего файла. Он создал клиента, которому поручено считывать данные с пина gpio. Затем он создает экземпляр сборщика с этим клиентом и регистрирует его. Наконец, он настраивает сервер promhttp с ведением журнала и запускает его. Метрики доступны по /metricspath:

После запуска двоичный файл по запросу показывает собранные метрики:

$ pi@raspberrypi:~/go/src/github.com/guivin/dht-prometheus-exporter $ ./dht-exporter
time="2021-02-17T20:19:20Z" level=info msg="Initializing the DHT22/AM2302 sensor on the host"
time="2021-02-17T20:19:20Z" level=info msg="Starting http server on TCP/8080 port"
time="2021-02-17T20:19:36Z" level=info msg="Retrieved humidity=62.70%, temperature=68.90°F from the sensor"

Запрос выполняется через порт TCP / 8080:

# HELP dht_humidity_percent Humidity percent measured by the sensor
# TYPE dht_humidity_percent counter
dht_humidity_percent{dht_name="test",hostname="raspberrypi"} 62.8
# HELP dht_temperature_degree Temperature degree measured by the sensor
# TYPE dht_temperature_degree counter
dht_temperature_degree{dht_name="test",hostname="raspberrypi",unit="fahrenheit"} 68.9
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 12
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.11.6"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
go_memstats_alloc_bytes 1.798512e+06
# HELP go_memstats_alloc_bytes_total Total number of bytes allocated, even if freed.
# TYPE go_memstats_alloc_bytes_total counter
go_memstats_alloc_bytes_total 1.798512e+06
# HELP go_memstats_buck_hash_sys_bytes Number of bytes used by the profiling bucket hash table.
# TYPE go_memstats_buck_hash_sys_bytes gauge
go_memstats_buck_hash_sys_bytes 724468
# HELP go_memstats_frees_total Total number of frees.
# TYPE go_memstats_frees_total counter
go_memstats_frees_total 1026
# HELP go_memstats_gc_cpu_fraction The fraction of this program's available CPU time used by the GC since the program started.
# TYPE go_memstats_gc_cpu_fraction gauge
go_memstats_gc_cpu_fraction 0
# HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata.
# TYPE go_memstats_gc_sys_bytes gauge
go_memstats_gc_sys_bytes 334848
# HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use.
# TYPE go_memstats_heap_alloc_bytes gauge
go_memstats_heap_alloc_bytes 1.798512e+06
# HELP go_memstats_heap_idle_bytes Number of heap bytes waiting to be used.
# TYPE go_memstats_heap_idle_bytes gauge
go_memstats_heap_idle_bytes 589824
# HELP go_memstats_heap_inuse_bytes Number of heap bytes that are in use.
# TYPE go_memstats_heap_inuse_bytes gauge
go_memstats_heap_inuse_bytes 3.11296e+06
# HELP go_memstats_heap_objects Number of allocated objects.
# TYPE go_memstats_heap_objects gauge
go_memstats_heap_objects 6257
# HELP go_memstats_heap_released_bytes Number of heap bytes released to OS.
# TYPE go_memstats_heap_released_bytes gauge
go_memstats_heap_released_bytes 0
# HELP go_memstats_heap_sys_bytes Number of heap bytes obtained from system.
# TYPE go_memstats_heap_sys_bytes gauge
go_memstats_heap_sys_bytes 3.702784e+06
# HELP go_memstats_last_gc_time_seconds Number of seconds since 1970 of last garbage collection.
# TYPE go_memstats_last_gc_time_seconds gauge
go_memstats_last_gc_time_seconds 0
# HELP go_memstats_lookups_total Total number of pointer lookups.
# TYPE go_memstats_lookups_total counter
go_memstats_lookups_total 0
# HELP go_memstats_mallocs_total Total number of mallocs.
# TYPE go_memstats_mallocs_total counter
go_memstats_mallocs_total 7283
# HELP go_memstats_mcache_inuse_bytes Number of bytes in use by mcache structures.
# TYPE go_memstats_mcache_inuse_bytes gauge
go_memstats_mcache_inuse_bytes 3456
# HELP go_memstats_mcache_sys_bytes Number of bytes used for mcache structures obtained from system.
# TYPE go_memstats_mcache_sys_bytes gauge
go_memstats_mcache_sys_bytes 16384
# HELP go_memstats_mspan_inuse_bytes Number of bytes in use by mspan structures.
# TYPE go_memstats_mspan_inuse_bytes gauge
go_memstats_mspan_inuse_bytes 22080
# HELP go_memstats_mspan_sys_bytes Number of bytes used for mspan structures obtained from system.
# TYPE go_memstats_mspan_sys_bytes gauge
go_memstats_mspan_sys_bytes 32768
# HELP go_memstats_next_gc_bytes Number of heap bytes when next garbage collection will take place.
# TYPE go_memstats_next_gc_bytes gauge
go_memstats_next_gc_bytes 4.473924e+06
# HELP go_memstats_other_sys_bytes Number of bytes used for other system allocations.
# TYPE go_memstats_other_sys_bytes gauge
go_memstats_other_sys_bytes 1.315464e+06
# HELP go_memstats_stack_inuse_bytes Number of bytes in use by the stack allocator.
# TYPE go_memstats_stack_inuse_bytes gauge
go_memstats_stack_inuse_bytes 491520
# HELP go_memstats_stack_sys_bytes Number of bytes obtained from system for stack allocator.
# TYPE go_memstats_stack_sys_bytes gauge
go_memstats_stack_sys_bytes 491520
# HELP go_memstats_sys_bytes Number of bytes obtained from system.
# TYPE go_memstats_sys_bytes gauge
go_memstats_sys_bytes 6.618236e+06
# HELP go_threads Number of OS threads created.
# TYPE go_threads gauge
go_threads 9
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 0.16
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
process_max_fds 1024
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 101
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 1.0858496e+07
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.61359321311e+09
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 8.93046784e+08
# HELP process_virtual_memory_max_bytes Maximum amount of virtual memory available in bytes.
# TYPE process_virtual_memory_max_bytes gauge
process_virtual_memory_max_bytes 1.8446744073709552e+19

Установка Prometheus Exporter

Предпосылки

Установите golangи make, чтобы собрать исходный код:

$ sudo apt install golang make

Определяет переменные среды для Golang:

$ export GOPATH=$HOME/go
$ export GOBIN=$GOPATH/bin
$ export PATH=$PATH:$GOBIN

Скачать пакет dep:

go get -u github.com/golang/dep/cmd/dep

Строить

Клонируйте репозиторий git и соберите исходники:

$ go get -u github.com/guivin/dht-prometheus-exporter.git
$ cd $GOPATH/src/guivin/dht-prometheus-exporter
$ git checkout tags/v0.1
$ make all

Развертывание

Установите модуль systemdservice:

$ sudo cp dht-prometheus-exporter.service /etc/systemd/system

Разверните файл конфигурации:

$ sudo cp dht-prometheus-exporter.yml /etc
$ sudo chown dht-prometheus-exporter:dht-prometheus-exporter /etc/dht-prometheus-exporter.yml
$ sudo chmod 0640 /etc/dht-prometheus-exporter.yml

Создайте пользователя и группу dht-prometheus-exportersystem для экспортера. Этот системный пользователь также принадлежит gpio как вторичная группа для чтения пинов gpio:

$ sudo useradd --user-group --groups gpio --no-create-home --system --shell /usr/sbin/nologin dht-prometheus-exporter

Запустите systemdunit:

$ sudo systemctl daemon-reload
$ sudo systemctl start dht-prometheus-exporter

Проверьте журналы systemdunit:

$ sudo journalctl -u dht-prometheus-exporter -f
Feb 18 07:14:25 raspberrypi dht-prometheus-exporter[4031]: time="2021-02-18T07:14:25Z" level=info msg="Initializing the DHT22/AM2302 sensor on the host"
Feb 18 07:14:25 raspberrypi dht-prometheus-exporter[4031]: time="2021-02-18T07:14:25Z" level=info msg="Starting http server on TCP/8080 port"

Прометей

Установка и настройка

Создайте пользователя и группу prometheussystem:

$ useradd --home-dir /opt/prometheus --user-group --shell /usr/sbin/nologin --system prometheus

Загрузите двоичный файл prometheus и адаптируйте его под свою архитектуру Raspberry Pi (здесь мы используем armv7):

$ cd /tmp
$ wget https://github.com/prometheus/prometheus/releases/download/v2.25.0/prometheus-2.25.0.linux-armv7.tar.gz
$ tar xzf prometheus-2.25.0.linux-armv7.tar.gz

Создайте домашний каталог для prometheususer в /opt/prometheus:

$ sudo cp -r prometheus-2.25.0.linux-armv7 /opt/prometheus
$ sudo chown prometheus:prometheus /opt/prometheus
$ sudo chmod 0740 -R /opt/prometheus

Создайте каталог /var/lib/prometheus с хорошими разрешениями для хранения tsdb (база данных временных рядов):

$ sudo mkdir /var/lib/prometheus
$ sudo chown -R prometheus:prometheus /var/lib/prometheus
$ sudo chmod -R 0740 /var/lib/prometheus

Создайте символическую ссылку из конфигурации, представленной в /opt/prometheus, на /etc:

sudo ln -s /opt/prometheus/prometheus.yml /etc/prometheus.yml

Обновите /etc/prometheus.yml и добавьте новое задание в блок scrape_configs:

- job_name: 'dht-prometheus-exporter'
  static_configs:
    - targets: ['localhost:8080']

Создайте systemdunit для prometheus в /etc/systemd/system/prometheus.service следующим образом:

[Service]
Type=simple 
User=prometheus
Group=prometheus
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/opt/prometheus/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus \
  --storage.tsdb.retention.time=30d \
  --storage.tsdb.retention.size=0 \
  --web.console.libraries=/opt/prometheus/console_libraries \
  --web.console.templates=/opt/prometheus/consoles \
  --web.listen-address=0.0.0.0:9090 \
  --web.external-url=
SyslogIdentifier=prometheus
Restart=always
[Install]
WantedBy=multi-user.target

Запустите и включите prometheusservice:

$ sudo systemctl daemon-reload
$ sudo systemctl start prometheus
$ sudo systemctl enable prometheus

Убедитесь, что prometheus в порядке:

sudo systemctl status prometheus --no-pager
● prometheus.service
   Loaded: loaded (/etc/systemd/system/prometheus.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2021-02-18 07:37:18 GMT; 16min ago
 Main PID: 4348 (prometheus)
    Tasks: 9 (limit: 2062)
   CGroup: /system.slice/prometheus.service
           └─4348 /opt/prometheus/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/var/lib/prometheus --storage.tsdb.retention.time=30d --storage.tsdb.retention.size=0 --web.console.libraries=/opt/prometheus/console_libraries --web.console.templates=/opt/prometheus/consoles --web.listen-address=0.0.0.0:9090 --web.external-url=
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.614Z caller=head.go:682 component=tsdb msg="On-disk memory mappable chunks replay completed" duration=21.667µs
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.614Z caller=head.go:688 component=tsdb msg="Replaying WAL, this may take a while"
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.630Z caller=head.go:740 component=tsdb msg="WAL segment loaded" segment=0 maxSegment=1
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.632Z caller=head.go:740 component=tsdb msg="WAL segment loaded" segment=1 maxSegment=1
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.632Z caller=head.go:745 component=tsdb msg="WAL replay completed" checkpoint_replay_duration=372.29µs wal_replay_duration=17.413166ms total_replay_duration=18.029362ms
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.651Z caller=main.go:799 fs_type=EXT4_SUPER_MAGIC
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.652Z caller=main.go:802 msg="TSDB started"
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.652Z caller=main.go:928 msg="Loading configuration file" filename=/etc/prometheus/prometheus.yml
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.680Z caller=main.go:959 msg="Completed loading of configuration file" filename=/etc/prometheus/prometheus.yml totalDuration=27.748754ms remote_storage=11.666µs web_handler=3.281µs query_engine=5.104µs scrape=1.784837ms scrape_sd=278.332µs notify=7.552µs notify_sd=26.25µs rules=23.37…
Feb 18 07:37:18 raspberrypi prometheus[4348]: level=info ts=2021-02-18T07:37:18.682Z caller=main.go:751 msg="Server is ready to receive web requests."
Hint: Some lines were ellipsized, use -l to show in full.

веб интерфейс

Запишите свой частный IP-адрес Raspberry Pi с помощью ip acommand. Откройте браузер и подключитесь к нему через порт TCP / 8080 со схемой HTTP (например, http: // ‹RASPBERRY_IP›: 8080). Экспортер хорошо зарегистрирован в меню Цели:

На главной странице пользовательского интерфейса Prometheus мы вводим названия обеих метрик из экспортера. Они присутствуют и показывают свои ярлыки, которые мы определили ранее:

У нас также может быть график показателей экспортера:

Графана

Установка и настройка

Для Grafana вы можете следовать инструкциям по ссылке ниже:



Создание дашборда

Подключаемся к интерфейсу Grafana и создаем новую дашборд. На этой панели мы добавляем график для каждого показателя: температуры и влажности. Для обоих мы используем функцию avg_over_time с вектором в 1 минуту. Это сделано для того, чтобы избежать прекращения работы над графиками:

Вывод

С помощью этих различных шагов мы создали систему мониторинга с датчиком. Мы подключили сенсорную карту к Raspberry Pi и проверили получение данных. Мы смогли измерить температуру и влажность в комнате.

Чтобы предоставить Prometheus доступ к этим показателям, мы создали программу-экспортер. Он предоставляет метрики через HTTP-сервер по запросу. Мы также добавили несколько ярлыков к нашим показателям. Это полезно, если вы хотите отследить множество датчиков и идентифицировать их.

Затем мы установили и настроили Prometheus на Raspberry Pi. Он очищает экспортера и сохраняет показатели. Мы заметили, что в пользовательском интерфейсе Prometheus мы можем запрашивать и использовать показатели.

Используя пользовательский интерфейс Prometheus, мы смогли создавать графики из показателей. Но в дальнейшем мы устанавливаем Grafana, чтобы улучшить визуализацию. В Grafana мы создали информационную панель с графиками влажности и температуры.

Этот проект предлагает сквозной обзор того, что возможно с Raspberry Pi и Prometheus. Я надеюсь, что это вдохновило вас на следующие идеи для проектов домашней автоматизации. Спасибо за чтение и с нетерпением ждем ваших будущих достижений!

Чтобы поддержать мою работу и побудить меня писать лучшие статьи, вы можете подписаться на членство в Medium через мою реферальную ссылку. Кроме того, вы получите доступ к большому количеству контента и станете более осведомленными!

Ресурсы