Инструменты пользователя

Инструменты сайта


temp_mon

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

temp_mon [2014/02/06 16:24]
metallic [Zabbix-сервер]
temp_mon [2022/03/25 17:00]
Строка 1: Строка 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]] (опционально) 
-  * Резистор 4.7кОм 
-  * Развернутая система мониторинга [[https://www.zabbix.com|Zabbix]] 
-  * Какой-нибудь подходящий корпус для всего этого(я использовал обыкновенную пластиковую [[http://shop.avselectro.ru/catalog/__207RVOR/__1YJAVOR.html|электрическую распаячную коробку]]) 
- 
- 
-===== Подготовка Raspberry Pi ===== 
-Для начала нужно установить ОС на флеш-карту, как это сделать подробно описано [[http://forum.cxem.net/index.php?showtopic=114312&#entry1326610|тут]]. После того, как система установлена и загружается нужно ее подготовить для работы. Во-первых, настраивает локальную сеть, дату, время, часовой пояс и т.д. Во-вторых в файл /etc/modules добавляем модули необходимые для работы температурных датчиков и дисплея: 
- 
-  i2c-dev 
-  w1-gpio 
-  w1-therm 
- 
-   
-===== Подключение датчиков и дисплея ===== 
-Для подключения температурных датчиков нам понадобится трехжильный кабель(или более), отлично подойдет четырехжильная витая пара. У датчика три пина: земля, пин по которому передаются данные и плюс питания: 
- 
-{{ :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 С 
-   
-Если все работает, переходим к подлючению дисплея. Схема подключения пинов дисплея к пинам 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""      : %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 |}} 
- 
- 
-На этом все. 
temp_mon.txt · Последнее изменение: 2022/03/25 17:00 (внешнее изменение)