Бюджетный мониторинг температуры: Arduino + Zabbix

У нас в организации развёрнут сервер Zabbix для мониторинга работоспособности серверов и АРМов. Из-за особенностей техпроцесса оборудование «размазано» по нескольким помещениям и разнесено по территории предприятия. Естественно, вместе с основными параметрами компьютеров (работает/не работает) хочется контролировать и микроклимат в серверных. При этом, как обычно, возможности весьма ограничены, и «выбить» значительные средства на сложные системы мониторинга температуры (к ним я отношу и платы управления с термодатчиками для стоечных ИБП APC) — это отдельный квест.

В основной серверной всё просто — установлена одна такая плата (закуплена давным-давно предшественником вместе с основным оборудованием), воткнут APC-шный термодатчик, заведён агент в Заббиксе, всё работает по SNMP. Скучно :) На мониторинг удалённой аппаратной оборудования нет, средств тоже — см. выше. Поэтому было решено проявить смекалку, сэкономить бюджет и заодно прокачать новый навык путём конструирования простого и дешёвого «наколенного» решения, вписывающегося, тем не менее, в существующую инфраструктуру мониторинга Zabbix.

Необходимые компоненты:


Общая стоимость компонентов — $10 с доставкой.

Сборка устройства не составляет труда. Сетевой модуль надевается на основную плату «бутербродом», термодатчик припаивается к его пинам. Подключение датчика: красный +5 В, чёрный — земля, жёлтый — данные; между +5V и Data припаиваем подтягивающий резистор 4,7 кОм.

Пин для данных выбирается с учётом пинов, используемых сетевым модулем (D10 – SS; D11 – MOSI; D12 – MISO; D13 – SCK; D2 – IRQ).

Грабли: в прототипе устройства столкнулся с конфликтом — данные о температуре выдавались случайным образом, «через два на третий». Причиной оказалось то, что я прицепил термодатчик на пин 2, который, как потом нашёл на просторах интернета, используется сетевым модулем для генерации прерывания при поступлении пакета. Переставил на 4-й — заработало как часы.

После сборки аппаратной части переходим к программной.

Устройство будет работать в сети и притворяться заббикс-агентом, для этого ему нужен MAC и IP-адрес. Решаем, как удобнее — жёстко зашить при программировании, генерировать MAC из адреса температурного датчика и получать IP по DHCP, и т.д. Я пошёл по простейшему пути и захардкодил оба параметра.

Протокол обмена с заббикс-сервером описан в документации. Наше устройство будет откликаться на две команды — agent.ping и env.temp (здесь оставлен простор для дальнейшего творчества, можно привязать любой из модулей расширения, доступных для ардуино — хоть датчик влажности, хоть освещённости — да что душе угодно). На все остальные команды оно будет ругаться отвечать стандартным ответом, понятным заббикс-серверу.

Для тех, кто начинает с нуля (как я) — программирование Arduino выполняется с помощью Arduino IDE, установка и настройка которой элементарны. Для работы компонентов необходимы библиотеки UIPEthernet и OneWire, которые устанавливаются и подключаются к проекту через меню Скетч — Подключить библиотеку — Управлять библиотеками…
Если у вас будут другие компоненты (например, сетевой модуль не на enc28j60, а на другом чипе) — понадобятся и другие библиотеки!

Код работы с сетевым модулем и с датчиком температуры — типовой, из интернета, с некоторыми допущениями и упрощениями.

После заливки кода в контроллер и подключения ethernet-кабеля проверяем из консоли:

$ zabbix_get -s 192.168.4.5 -k agent.ping
1
$ zabbix_get -s 192.168.4.5 -k env.temp
23.12
$ zabbix_get -s 192.168.4.5 -k bla-blah
ZBX_NOTSUPPORTED


Грабли: выложенная на zabbix.com скомпилированная версия zabbix_get для Windows устарела и использует другой протокол (с заголовком ZBXD\x01 в запросе сервера). Линуксовая версия актуальна и протокол соответствует приведенному коду.

Всё работает, как и задумано. В админке заббикса создаём новый хост с выбранным IP, в нём — два ключа, Numeric (unsigned) agent.ping и Numeric (float) env.temp, наслаждаемся работой. Графики, триггеры — всё как обычно.

Питание устройства — через родной USB. Корпус — по желанию: подходящая пластиковая коробочка, термоусадка, синяя изолента.

Разрешение датчика — примерно 0.06 (точнее, 1/16) °С, точность — при погружении в таящий снег показал 0.19 °С (может, опустился бы и ниже, но снега было мало и он весь быстро растаял). Считаю, для устройства стоимостью 10 долларов и описанных целей — более чем достаточно.

Скетч
#include <OneWire.h>
#include <UIPEthernet.h>

byte mac[] = { 0xDE, 0x05, 0xB6, 0x27, 0x39, 0x19 }; // random MAC
byte ip[] = { 192, 168, 4, 5 }; // IP address in local network
String readString = String(20);
byte addr[8];

OneWire ds(4); // DS18B20 at pin 4
EthernetServer server(10050); // Zabbix port

void setup() {
Ethernet.begin(mac, ip);
server.begin();
ds.search(addr);
}

void loop() {
byte data[2];
float celsius;

readString = "";
if (EthernetClient client = server.available())
{
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n') // end of query from zabbix server
{
client.print("ZBXD\x01"); // response header
if (readString == "agent.ping") {
byte responseBytes [] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '1'};
client.write(responseBytes, 9);
} else
if (readString == "env.temp") {
ds.reset();
ds.select(addr);
ds.write(0x44); // start conversion with regular (non-parasite!) power
delay(1000);
ds.reset();
ds.select(addr);
ds.write(0xBE); // read Scratchpad

data[0] = ds.read();
data[1] = ds.read();

int16_t raw = (data[1] << 8) | data[0];
celsius = (float)raw / 16.0;

byte responseBytes [] = {(byte) String(celsius).length(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
client.write(responseBytes, 8);
client.print(celsius);
}
else {
byte responseBytes [] = {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
client.write(responseBytes, 8);
client.print("ZBX_NOTSUPPORTED");
}
break;
}
else if (readString.length() < 20) {
readString = readString + c;
}
}
}
delay(10);
client.stop();
}
}



UPD: В связи с незначительными изменениями протокола Zabbix, данный скетч не работает. Исправленная версия на Google Drive (поддерживает новый протокол, получает IP-адрес по DHCP).

Додати коментар


Захисний код
Оновити

EcoMonitoring

ЛІЧІЛЬНИК ВІДВІДУВАННЬ

Сьогодні 66
Вчора223
Цього тижня 545
Минулого тижня 949
Цей місяць 2313
Минулий місяць 7482
За весь час 183112
Ваш IP: 216.73.216.121
Сегодня: 2025-06-18
Пользователей на сайте: 0
Гостей на сайте: 18