| |
| — | temp_mon [2023/09/20 12:05] (текущий) – создано - внешнее изменение 127.0.0.1 |
|---|
| | ====== Мониторинг температуры Raspberry Pi + zabbix ====== |
| |
| | ===== Введение ===== |
| | Задача: мониторинг температуры в серверной и на улице, а также сохранение статистики и рисование графиков. |
| | |
| | Для решения задачи нам понадобится: |
| | * [[http://amperka.ru/product/raspberry-pi-model-b|Raspberry pi]] |
| | * [[http://amperka.ru/product/temperature-sensor-ds18b20|Температурные датчики DS18B20]] (кол-во на одной шине ограничено 128 штуками, если не ошибаюсь) |
| | * [[http://amperka.ru/collection/display/product/text-lcd-20x4|Текстовый экран 20×4]] (опционально) |
| | * [[http://amperka.ru/collection/power-sources/product/usb-power-plug|Импульсный блок питания с USB-разъёмом (5 В, 1000 мА)]] |
| | * Резистор 4.7кОм |
| | * Развернутая система мониторинга [[https://www.zabbix.com|Zabbix]] |
| | * Какой-нибудь подходящий корпус для всего этого(я использовал обыкновенную пластиковую [[http://shop.avselectro.ru/catalog/__207RVOR/__1YJAVOR.html|электрическую распаячную коробку]]) |
| | |
| | |
| | ===== Подготовка Raspberry Pi ===== |
| | Для начала нужно установить ОС на флеш-карту, для этого используется [[https://downloads.raspberrypi.org/imager/imager_latest.exe|Raspberry Pi Imager]]. |
| | После того, как система установлена и загружается нужно ее подготовить для работы. Во-первых, настраивает локальную сеть, дату, время, часовой пояс и т.д. |
| | |
| | Во-вторых, нужно включить нужные интерфейсы, раньше это делалось добавлением модулей в файл /etc/modules, теперь это можно сделать утилитой raspi-config(встроена в систему) Interfacing Options -> 1-Wire и Interfacing Options -> I2C |
| | По сути дела эта утилита просто добавляет нужные параметры в файл /boot/config.txt нужные параметры, например для 1-wire она добавит в конец dtoverlay=w1-gpio, т.е. это можно сделать и вручную. |
| | ===== Подключение датчиков и дисплея ===== |
| | Для подключения температурных датчиков нам понадобится трехжильный кабель(или более), отлично подойдет четырехжильная витая пара. У датчика три пина: земля, пин по которому передаются данные и плюс питания: |
| | |
| | {{ :ds18b20-symbol.png?direct&100 |}} |
| | |
| | Датчики подключаются парралельно на один кабель. Протягиваем кабель от места установки Raspberry через те места, где мы хотим повесить датчики. После чего в конце линии вешаем датчик, подключив его к трем жилам кабеля(запоминаем цвета жил к каким подключили пины датчика) и соответственно по ходу линии делаем любое кол-во разрезов и врезаем туда датчики на те же цвета(не перепутать, а то можно спалить датчики). Также в любом месте между пином данных и пином +3,3в надо поставить один резистор 4.7кОм, я установил его в корпусе, но можно в любом месте на линии, где удобно. Наглядная сехма подключения датчика на макетной плате(для тестов) ниже: |
| | |
| | {{ :ds18b20-temperature-sensor_bb.png?direct&300 |}} |
| | |
| | Итак, датчик(и) подключен(ы), вышеуказанные модули ядра загружены, после этого в каталоге /sys/bus/w1/devices/ должен появиться список ваших датчиков, у каждого свой аппаратный номер: |
| | |
| | # ls -1 /sys/bus/w1/devices |
| | 28-0000045ef9b4 |
| | 28-0000045f1c62 |
| | 28-0000046022cb |
| | w1_bus_master1 |
| | |
| | В моем случае 3 датчика, пробуем теперь считать показания(заниает 1 секунду): |
| | |
| | # cat /sys/bus/w1/devices/28-0000045ef9b4/w1_slave |
| | a6 00 4b 46 7f ff 0a 10 cb : crc=cb YES |
| | a6 00 4b 46 7f ff 0a 10 cb t=10375 |
| | |
| | Вот в таком виде датчик дает показания, чтобы получить температуру в градусах нужно разделить на 1000: |
| | |
| | 10375 / 1000 = 10.375 С |
| | |
| | Также с датчиками можно работать с помощью библиотеки w1thermsensor для python, устанавливаем: |
| | |
| | pip3 install w1thermsensor |
| | |
| | Пример кода: |
| | |
| | from w1thermsensor import W1ThermSensor |
| | |
| | # Все сенсоры |
| | for sensor in W1ThermSensor.get_available_sensors(): |
| | print(f"Сенсон ID {sensor.id} температура {sensor.get_temperature():.2f}") |
| | |
| | # Определенный сенсор |
| | sensor = W1ThermSensor(sensor_id="0000046022cb") |
| | print(f"Температура {sensor.get_temperature():.2f}") |
| | |
| | Если все работает, переходим к подлючению дисплея. Схема подключения пинов дисплея к пинам GPIO показаны ниже(4х битный режим): |
| | |
| | {{ :gpio1.png?direct&300 |}} |
| | |
| | Если дисплей подключен правильно, то уже должна загореться подсветка. Далее нужно установить в системе библиотеку [[http://wiringpi.com/download-and-install/|Wiring Pi]] для Си, которая позволит нам работать с дисплеем. Установка очень простая, распаковываем архив и запускаем скрипт build: |
| | |
| | # tar xfz wiringPi-98bcb20.tar.gz |
| | # cd wiringPi-98bcb20 |
| | # ./build |
| | |
| | Установка завершена, проверим: |
| | |
| | # gpio -v |
| | # gpio readall |
| | |
| | Теперь проверим работоспособность дисплея, скомпилируем и запустим эту программу(источник указан в списке литературы), которая выведет сообщение на экран: |
| | |
| | #include <stdio.h> //стандартная библиотека ввода-вывода |
| | #include <wiringPi.h> //библиотека из пакета wiringPi |
| | #include <lcd.h> //библиотека из пакета wiringPi |
| | |
| | int main (void) |
| | { |
| | printf ("Raspberry Pi LCD test\n") ; |
| | //Инициализация порта GPIO |
| | if(wiringPiSetup ()==-1) |
| | { |
| | printf ("GPIO Setup failed!\n") ; |
| | } |
| | |
| | int fd; |
| | printf ("Start LCD initialization...\n") ; |
| | //Инициализация LCD |
| | fd = lcdInit (4,20,4, 11,10, 1,0,2,3,0,0,0,0); |
| | |
| | if(fd==-1) |
| | { |
| | printf ("Initialization failed\n") ; |
| | } |
| | else |
| | { |
| | printf ("GO!\n"); |
| | |
| | //Очистка дислпея |
| | lcdClear(fd); |
| | |
| | //Перевод каретки на первую позицию первой строки |
| | lcdPosition (fd,0,0); |
| | |
| | //Вывод форматированного текста |
| | lcdPrintf(fd, "Hello Pi"); |
| | |
| | //Перевод каретки на вторую строку и вывод текста |
| | lcdPosition (fd,0,1); |
| | lcdPrintf(fd, " World!"); |
| | |
| | //Перевод каретки на третью строку и вывод текста |
| | lcdPosition (fd,0,2); |
| | lcdPrintf(fd, "25-01-2014"); |
| | |
| | //Перевод каретки на четвертую строку и вывод текста |
| | lcdPosition (fd,0,3); |
| | lcdPrintf(fd, "Happy New Year))))"); |
| | } |
| | return 0; |
| | } |
| | |
| | Компилируем и запускаем: |
| | |
| | # gcc -Wall -o test test.c -lwiringPi -lwiringPiDev |
| | # ./test |
| | |
| | В результате чего на экране должна появится надпись. Если так и произошло, значит дисплей подключен верно и все необходимые библиотеки в системе присутствуют. |
| | |
| | |
| | ===== Снятие показаний ===== |
| | |
| | Если бы я использовал показания термодатчиков только для zabbix, то можно было бы снимать их непосредственно zabbix-агентом, но я еще захотел выводить эти показания на дисплей, соответственно, чтобы не было две программы, которые одновременно пытаются считать показания, я сделал скрипт, который через cron каждую минуту опрашивает датчики и сохраняет их показания, после чего эти данные также раз в минуту выводятся на дисплей и считываются zabbix-агентом. Так как в качестве устройства хранения данных используется флеш-карта, то было бы крайне не желательно писать на нее каждую минуту, пусть и небольшие кусочки данных, думаю, долго она не выдержала бы. Поэтому для этих целей в системе был создан ram-диск размером 10МБ и уже на него будут сохранятся показания датчиков. |
| | |
| | Итак, создаем каталог /mnt/tmpfs и в /etc/fstab прописываем стоку: |
| | |
| | tmpfs /mnt/tmpfs tmpfs nodev,nosuid,size=10M 0 0 |
| | |
| | Теперь после перезагрузки у нас появится небольшая файловая система в оперативной памяти. |
| | |
| | И наконец создадим скрипт /opt/scripts/gen_temp.sh(у меня три датчика): |
| | |
| | #!/bin/bash |
| | |
| | cat /sys/bus/w1/devices/28-0000045ef9b4/w1_slave | grep t= | head -1 | awk '{print substr($10,3)/1000; }' > /mnt/tmpfs/0000045ef9b4 |
| | |
| | cat /sys/bus/w1/devices/28-0000046022cb/w1_slave | grep t= | head -1 | awk '{print substr($10,3)/1000; }' > /mnt/tmpfs/0000046022cb |
| | |
| | cat /sys/bus/w1/devices/28-0000045f1c62/w1_slave | grep t= | head -1 | awk '{print substr($10,3)/1000; }' > /mnt/tmpfs/0000045f1c62 |
| | |
| | В результате выполнения которого в каталоге /mnt/tmpfs появятся файлы с показаниями датчиков в формате float. |
| | |
| | <note important>В скрипте нужно заменить ID моих датчиков на ваши (28-0000045ef9b4 и т.д.)</note> |
| | |
| | Осталось добавить строку в /etc/crontab и перезапустить cron: |
| | |
| | * * * * * root /opt/scripts/gen_temp.sh |
| | # /etc/init.d/cron restart |
| | |
| | На данном этапе у нас показания датчиков считываются каждую минуту и сохраняются в файл. Теперь надо написать программу, которая будет считывать эти файлы и выводить показания на экран. Вот пример моей программы с тремя датчиками display.c: |
| | |
| | #define _GNU_SOURCE |
| | #include <stdio.h> |
| | #include <stdlib.h> |
| | #include <wiringPi.h> |
| | #include <lcd.h> |
| | #include <unistd.h> |
| | |
| | int main (void) |
| | { |
| | FILE * fp; |
| | char * line = NULL; |
| | size_t len = 0; |
| | char display[81]; |
| | float temp_s1; |
| | float temp_s2; |
| | float temp_out; |
| | |
| | printf ("Raspberry Pi LCD test\n") ; |
| | //Инициализация порта GPIO |
| | if(wiringPiSetup ()==-1) |
| | { |
| | printf ("GPIO Setup failed!\n") ; |
| | } |
| | |
| | int fd; |
| | printf ("Start LCD initialization...\n") ; |
| | //Инициализация LCD |
| | fd = lcdInit (4,20,4, 11,10, 1,0,2,3,0,0,0,0); |
| | |
| | if(fd==-1) |
| | { |
| | printf ("Initialization failed\n") ; |
| | } |
| | else |
| | { |
| | printf ("GO!\n"); |
| | |
| | //Чтение температуры |
| | fp = fopen("/mnt/tmpfs/0000046022cb", "r"); |
| | if (fp == NULL) |
| | exit(EXIT_FAILURE); |
| | getline(&line, &len, fp); |
| | temp_s1 = strtof(line, NULL); |
| | close(fd); |
| | |
| | fp = fopen("/mnt/tmpfs/0000045ef9b4", "r"); |
| | if (fp == NULL) |
| | exit(EXIT_FAILURE); |
| | getline(&line, &len, fp); |
| | temp_s2 = strtof(line, NULL); |
| | close(fd); |
| | |
| | fp = fopen("/mnt/tmpfs/0000045f1c62", "r"); |
| | if (fp == NULL) |
| | exit(EXIT_FAILURE); |
| | getline(&line, &len, fp); |
| | temp_out = strtof(line, NULL); |
| | close(fd); |
| | |
| | //Очистка дислпея |
| | lcdClear(fd); |
| | |
| | //Перевод каретки на первую позицию первой строки |
| | lcdPosition (fd,0,0); |
| | |
| | //Формируем строку |
| | sprintf(display, "Pe\xBD\xE3""ep\xBD""a\xC7 \xE0""1: %06.2fPe\xBD\xE3""ep\xBD""a\xC7 \xE0""2: %06.2f\xA9\xBB\xB8\xE5""a : %06.2f ", temp_s1, temp_s2, temp_out); |
| | |
| | lcdPrintf(fd, display); |
| | } |
| | return 0; |
| | } |
| | |
| | Эта программа инициализирует дисплей, очищает его, считывает показания датчиков из файлов, формирует строку длиной 80 символов(дисплей выводит по 20 символов на строке) и выводит ее на дисплей. |
| | |
| | Скомпилируем ее и запустим: |
| | |
| | # gcc -Wall -o display display.c -lwiringPi -lwiringPiDev |
| | # ./display |
| | |
| | В результате чего на дисплее появятся показания с трех датчиков(в моем случае). |
| | |
| | <note>По поводу кирилицы: нельзя просто так взять и написать на русском языке, из-за кодировок дисплей выведет полную ерунду. Чтобы выводить русские символы нужно писать их в hex-формате, т.е. например \xFF. Таблицу самих же символов и их коды можно поглядеть в официальной [[http://files.amperka.ru/datasheets/MT-16S2H.pdf|документации]] к дисплею на странице 8 или на рисунке ниже. Если вы хотите смешивать латиницу и кирилицу(как сделал я), то после кода кирилического символа нужно добавить две кавычки "" и дальше любое кол-во латинских букв или цифр |
| | |
| | {{ :hex_codes_display.png?direct&300 |}} |
| | </note> |
| | |
| | |
| | |
| | Если все отработало корректно, то осталось добавить скомпилированную програму для автовыполнения в скрипт /opt/scripts/gen_temp.sh (в конец): |
| | |
| | /opt/scripts/display |
| | |
| | |
| | ===== Zabbix-агент ===== |
| | |
| | К этому моменту у нас уже показания с датчиков снимаются, на дисплей выводятся, осталось настроить zabbix. Подходящих бинарников для Raspberry Pi нет, поэтому придется собрать из исходников. Качаем [[http://sourceforge.net/projects/zabbix/files/ZABBIX%20Latest%20Stable/2.2.1/zabbix-2.2.1.tar.gz/download|сорцы]], распаковываем, компилируем и устанавливаем: |
| | |
| | # ./configure --prefix=/usr/local/zabbix_agent --enable-agent |
| | # make install |
| | # useradd zabbix |
| | # mkdir /var/run/zabbix |
| | # mkdir /var/log/zabbix |
| | # chown zabbix /var/run/zabbix |
| | # chown zabbix /var/log/zabbix |
| | |
| | Если все прошло успешно, редактируем конфигурационный файл /usr/local/zabbix_agent/etc/zabbix_agentd.conf и приводим его к такому виду: |
| | |
| | PidFile=/var/run/zabbix/zabbix_agentd.pid |
| | LogFile=/var/log/zabbix/zabbix_agentd.log |
| | LogFileSize=5 |
| | DebugLevel=0 |
| | Server=address.of.zabbix.server |
| | |
| | ListenIP=X.X.X.X |
| | Hostname=rfarm-raspberrypi |
| | |
| | ServerActive=address.of.zabbix.server |
| | HostnameItem=system.hostname |
| | |
| | Timeout=10 |
| | |
| | UserParameter=custom.temp.rfarm.sensor1,/bin/cat /mnt/tmpfs/0000046022cb |
| | UserParameter=custom.temp.rfarm.sensor2,/bin/cat /mnt/tmpfs/0000045ef9b4 |
| | UserParameter=custom.temp.outside.sensor1,/bin/cat /mnt/tmpfs/0000045f1c62 |
| | |
| | Тут главное указать адрес вашего zabbix-сервера в параметрах Server и ServerActive, IP-адрес на котором агент будет ждать подключения ListenIP и задать имя агента Hostname. И самое главное - задать параметры пользователя UserParameter с помощью которых агент будет считывать показания. |
| | |
| | Теперь протестируем наши параметры, что они корректно считываются: |
| | |
| | # /usr/local/zabbix_agent/sbin/zabbix_agentd -t custom.temp.rfarm.sensor1 |
| | custom.temp.rfarm.sensor1 [t|17.812] |
| | |
| | # /usr/local/zabbix_agent/sbin/zabbix_agentd -t custom.temp.rfarm.sensor2 |
| | custom.temp.rfarm.sensor2 [t|11.812] |
| | |
| | # /usr/local/zabbix_agent/sbin/zabbix_agentd -t custom.temp.outside.sensor1 |
| | custom.temp.outside.sensor1 [t|-5.125] |
| | |
| | Все нормально, осталось добавить агента в автозагрузку, проще всего добавить в /etc/rc.local такую строку: |
| | |
| | /usr/local/zabbix_agent/sbin/zabbix_agentd -c /usr/local/zabbix_agent/etc/zabbix_agentd.conf |
| | |
| | |
| | ===== Zabbix-сервер ===== |
| | |
| | Ну и осталось создать хост и прописать для него итемы и графики в веб-интерфейсе. |
| | |
| | Создаем хост(наш raspberry pi): |
| | {{ :create_host1.png?direct&300 |}} |
| | |
| | |
| | По желанию добавляем ему шаблон "zabbix-агент", чтобы отслеживать состояние хоста: |
| | {{ :create_host2.png?direct&300 |}} |
| | |
| | |
| | На каждый датчик создаем свой item(элемент, который будет коллекционировать данные), для каждого датчика у нас заранее на стороне zabbix-агента прописаны наши собственные параметры, ниже пример создания итема: |
| | {{ :create_item1.png?direct&300 |}} |
| | |
| | |
| | В итоге у меня получилось три итема, по одному на каждый датчик: |
| | {{ :items.png?direct&300 |}} |
| | |
| | |
| | И в конце создаем любое кол-во графиков, какое нужно, хоть по отельному на каждый итем, хоть один для всех сразу. На примере ниже создается один график, на котором будут рисоваться показания всех датчиков: |
| | {{ :graph.png?direct&300 |}} |
| | |
| | |
| | На этом все. |
| | |
| | |
| | ===== Заключение ===== |
| | |
| | В итоге получили прибор, который в режиме реального времени выводит информацию по температуре с датчиков на дисплей, а также коллекционируется статистика по температуре и строятся графики с помощью zabbix. Ниже можно поглядеть как это выглядит в жизне. |
| | |
| | {{:temp_mon1.jpg?direct&300|}} {{:temp_mon2.jpg?direct&300|}} {{:temp_mon3.jpg?direct&300|}} {{:temp_mon4.png?direct&300|}} |
| | |
| | |
| | ===== Список использованной литературы ===== |
| | |
| | - [[http://files.amperka.ru/datasheets/MT-16S2H.pdf|Даташит на дисплей]] |
| | - [[http://shabpoint.blogspot.ru/2013/09/lcd-raspberry-pi.html|Подключение LCD дисплея к Raspberry Pi]] |
| | - [[http://wiki.amperka.ru/схемы-подключения:подключение-текстового-экрана|Подключение текстового экрана к Arduino]] |
| | - [[http://wiringpi.com/download-and-install/|GPIO Interface library for the Raspberry Pi]] |
| | - [[http://www.raspberrypi-spy.co.uk/2013/03/raspberry-pi-1-wire-digital-thermometer-sensor/|Raspberry Pi 1- Wire Digital Thermometer Sensor]] |
| | - [[http://habrahabr.ru/post/204478/|Мониторинг температуры гермозоны с помощью 1-wire датчиков и Zabbix 2]] |
| | - [[https://www.zabbix.com/wiki/howto/install/ubuntu/ubuntuinstall|Installing Zabbix on Ubuntu from source files]] |
| | - [[http://forum.cxem.net/index.php?showtopic=114312&#entry1361054|Faq Raspberry Pi - Миникомпьютер С Linux За 25$/35$]] |