esp8266 & Zabbix

ratman
Offline
Зарегистрирован: 11.10.2015

В общем, добил я эту тему, правда пока всё в наколенном состоянии, просто, наверное, сообщить, что это работает. Действующие лица:

USB to ESP-01 adapter: https://ru.aliexpress.com/item/SMART-USB-ESP8266-ESP-01-Wi-Fi-Bluetooth-CH340G/32915870451.html

ESP8266-01: https://ru.aliexpress.com/item/ESP-01-ESP8266-wifi/32900849637.html

ESP-01S DHT11 module: https://ru.aliexpress.com/item/ESP8266-ESP-01-ESP-01S-DHT11-esp8266/32887522806.html

Как этим добром пользоваться: http://robotchip.ru/obzor-modulya-dht11-dlya-esp-01/

Zabbix server 4.0 (последний актуальный).

Берём библиотеку ESP8266ZabbixSender https://github.com/DTherHtun/ESP8266ZabbixSender Пример из нее замечательно работает с минимальными изменениями (я лишь добавил подъём статики).

Далее, имплантируем код опроса датчика DHT11 (знаю, что говно, но с чего-то начинать надо).

Получается что-то вроде:

#include <ESP8266ZabbixSender.h>
#include "DHT.h"                                        // Подключаем библиотеку DHT

#define DHTPIN 2                                        // Пин к которому подключен датчик
#define DHTTYPE DHT11                                   // Используемый датчик DHT 11
  // #define DHTTYPE DHT21
  // #define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);                               // Инициализируем датчик

  float temperature = 0;  // запрос на считывание температуры
//  float humidity = 0;     //  влажность не читаем, датчик врёт


ESP8266ZabbixSender zSender;

/* WiFi settings */
String ssid = "zopukh@home";
String pass = "zn3GXAj41T";

/* Zabbix host setting */
IPAddress ip(192, 168, 12, 13);      // host IP
IPAddress gateway(192, 168, 12, 1);  // gateway IP
IPAddress subnet(255, 255, 255, 0);  // network mask

/* Zabbix server setting */
#define SERVERADDR 192, 168, 12, 3  // Zabbix server Address
#define ZABBIXPORT 10051            // Zabbix erver Port
#define ZABBIXAGHOST "IOTBOARD_00"  // Zabbix item's host name

boolean checkConnection();


// ----------------------------------------------------------------------------
//  SETUP
void setup() {

  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  WiFi.begin(ssid.c_str(), pass.c_str());
  WiFi.config(ip, gateway, subnet);
  while (!checkConnection()) {
  }
  zSender.Init(IPAddress(SERVERADDR), ZABBIXPORT, ZABBIXAGHOST); // Init zabbix server information
  dht.begin();                                          // Инициализация DHT

}

void loop() {
   temperature = dht.readTemperature();                  // Запрос на считывание температуры
//   humidity = dht.readHumidity();                          //  влажность не читаем, датчик врёт

  
  checkConnection();                // Check wifi connection
  zSender.ClearItem();              // Clear ZabbixSender's item list
  zSender.AddItem("temperature", (float)temperature); // Exmaple value of zabbix trapper item
  //  zSender.AddItem("humidity", (float)humidity); // Exmaple value of zabbix trapper item
  if (zSender.Send() == EXIT_SUCCESS) {     // Send zabbix items
    Serial.println("ZABBIX SEND: OK");
  } else {
    Serial.println("ZABBIX SEND: NG");
  }
  delay(10000);  //  конский делай в 10 секунд 
}

boolean checkConnection() {
  int count = 0;
  Serial.print("Waiting for Wi-Fi connection");
  while (count < 300) {
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println();
      Serial.println("Connected!");
      return (true);
    }
    delay(500);
    Serial.print(".");
    count++;
  }
  Serial.println("Timed out.");
  return false;
}

В Zabbix создаем узел сети (в общем-то стандартный). В нем элемент данных с ключём temperature и типом Zabbix trapper, тип данных -- числовой с плавающей точкой. Остальное по вкусу.

Запускаем, наслаждаемся.

ratman
Offline
Зарегистрирован: 11.10.2015

Более причёсанный код:

zabbixsender_20190215_02.ino:


// ----------------------------------------------------------------------------
//  Таймер потока 01
uint8_t avrTthread01(uint16_t span) {
  static uint32_t future = 0;
  if (millis() < future) return 0;
  future += span;
  return 1;
}

// ----------------------------------------------------------------------------
//  Таймер потока 02
uint8_t avrTthread02(uint16_t span) {
  static uint32_t future = 0;
  if (millis() < future) return 0;
  future += span;
  return 1;
}


// ----------------------------------------------------------------------------
//  SETUP
void setup() {

  Serial.begin(115200);  // инициализация последовательного порта
  esp8266_setup();       // инициализация ESP8266
  dht_setup();           // инициализация DHT

  return;
}


// ----------------------------------------------------------------------------
//  LOOP
void loop() {

  // опрос датчика dht-11
  if (avrTthread01(15000)) {
    // Serial.println("thread 1 ");
    dht_read();  // Запрос на считывание температуры
  }

  // отправка данных в Zabbix
  if (avrTthread02(60000)) {
    // Serial.println("thread 2 ");
    esp8266_sendMessage();
  }

  return;
}

dht_sensor.ino:

#include "DHT.h"                                        // Подключаем библиотеку DHT

#define DHTPIN 2                                        // Пин к которому подключен датчик
#define DHTTYPE DHT11                                   // Используемый датчик DHT 11
// #define DHTTYPE DHT21
// #define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);                               // Инициализируем датчик

/* DHT variable*/
float temperature = 0;     // запрос на считывание температуры
// float humidity = 0;        //  влажность не читаем, датчик врёт

const uint8_t averageFactor = 5;  // коэффициент сглаживания показаний (0 = не сглаживать)

// ----------------------------------------------------------------------------
//  Первоначальная инициализация сенсора
void dht_setup() {

  dht.begin();                                          // инициализация DHT
  temperature = dht.readTemperature();                  // считывание температуры
  //  humidity = dht.readHumidity();                        // влажность не читаем, датчик врёт

  return;
}


// ----------------------------------------------------------------------------
//  Чтение показаний сенсора
void dht_read() {

  if (temperature != dht.readTemperature()) {
    // усреднение показаний для устранения "скачков"
    if (averageFactor > 0) {
      // <новое среднее> = (<старое среднее>*4 + <текущее значение>) / фактор сглаживания
      temperature = (temperature * (averageFactor - 1) + dht.readTemperature()) / averageFactor;
    } else {
      temperature = dht.readTemperature();  // не делаем усреднений, что прочитали то и считаем выводом
    }
  }

  /*    //  влажность не читаем, датчик безбожно врёт
    if (humidity != dht.readHumidity()) {
      // усреднение показаний для устранения "скачков"
      if (averageFactor > 0) {
        // <новое среднее> = (<старое среднее>*4 + <текущее значение>) / фактор сглаживания
        humidity = (humidity * (averageFactor - 1) + dht.readHumidity()) / averageFactor;
      } else {
        humidity = dht.readHumidity();  // не делаем усреднений, что прочитали то и считаем выводом
      }
    }
  */

  return;
}

esp8266_sender.ino:

#include <ESP8266ZabbixSender.h>

ESP8266ZabbixSender zSender;

/* WiFi settings */
String ssid = "zopukh@home";
String pass = "zn3GXAj41T";

/* Zabbix host setting */
IPAddress ip(192, 168, 12, 14);      // host IP
IPAddress gateway(192, 168, 12, 1);  // gateway IP
IPAddress subnet(255, 255, 255, 0);  // network mask

/* Zabbix server setting */
#define SERVERADDR 192, 168, 12, 3  // Zabbix server Address
#define ZABBIXPORT 10051            // Zabbix server Port
#define ZABBIXAGHOST "IOTBOARD_01"  // Zabbix item's host name


// ----------------------------------------------------------------------------
//  Инициализация esp8266
void esp8266_setup() {

  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  WiFi.begin(ssid.c_str(), pass.c_str());
  WiFi.config(ip, gateway, subnet);
  while (!checkConnection()) {
  }
  zSender.Init(IPAddress(SERVERADDR), ZABBIXPORT, ZABBIXAGHOST); // Init zabbix server information

  return;
}


// ----------------------------------------------------------------------------
//  Передача данных в Zabbix
void esp8266_sendMessage () {

  checkConnection();                // Check wifi connection
  zSender.ClearItem();              // Clear ZabbixSender's item list
  zSender.AddItem("temperature", (float)temperature); // Exmaple value of zabbix trapper item
  //  zSender.AddItem("humidity", (float)humidity); // Exmaple value of zabbix trapper item
  if (zSender.Send() == EXIT_SUCCESS) {     // Send zabbix items
    Serial.println("ZABBIX SEND: OK");
  } else {
    Serial.println("ZABBIX SEND: NG");
  }

  return;
}


// ----------------------------------------------------------------------------
//  Проверка соединения
boolean checkConnection() {
  int count = 0;
  
  Serial.print("Waiting for Wi-Fi connection");
  while (count < 300) {
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println();
      Serial.println("Connected!");
      return (true);
    }
    delay(500);
    Serial.print(".");
    count++;
  }
  Serial.println("Timed out.");
  return false;
}

 

ratman
Offline
Зарегистрирован: 11.10.2015

Настройки хоста:

Настройки элементов данных:

Графичек:

ratman
Offline
Зарегистрирован: 11.10.2015

Немного дёгтя от модулей ESP-01S DHT11 https://ru.aliexpress.com/item/A21-ESP8266-ESP-01-ESP-01S-DHT11/32840839415.html

Дело в том, что на плате расположен линейный стабилизатор 5-3.3V. Радиатором ему служит традиционно фольга печатки. При работе этот стабилизатор даёт тепловую помеху примерно +10°C. После сборки и упаковки в корпус у меня получилось вообще +14°C. То есть, если кто будет собирать, на этом барахле, после сборки необходимо провести "юстировку" и загнать в скетч полученную поправку.

esp8266user
Offline
Зарегистрирован: 10.04.2019

Привет! Всё классно, всё работает. Но есть нюанс, у меня в esp8266 крутятся и другие клиенты http для забора данных с openweather.org, так вот походу твой zclent не закрывает сессию и другой клиент не может коннектится. Хотя может причина в другом, я не большой специалист) можно ли как-то пофиксить?

sadman41
Offline
Зарегистрирован: 19.10.2016

Похоже, что ZabbixSender не закрывает соединение сам, сваливает эту работу на сервер ;)

esp8266user
Offline
Зарегистрирован: 10.04.2019

Похоже, я пробовал там ставить zclient.stop(); но особо не помогло)

sadman41
Offline
Зарегистрирован: 19.10.2016

В обычном эзернет-варианте помогало жестко привязываться к сокету, но в ESP я не шарю.

esp8266user
Offline
Зарегистрирован: 10.04.2019

Подскажи хоть как в эзернете делается?

sadman41
Offline
Зарегистрирован: 19.10.2016

Типа

EthernetClient client(1); client.connect(...);

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

esp8266user
Offline
Зарегистрирован: 10.04.2019

Ок, завтра попробуем, спасибо.

ratman
Offline
Зарегистрирован: 11.10.2015

Должен заметить что sadman использует свой собственный проект zabbuino, завязанный на ethernet. Я же способен от силы криво скопипастить пару кусков кода, потому и получилось это поделие с zabbixsender. Правда, пока оно до воплощения в натуре доросло, оно мутировало в mqtt-клиента. Если интересует, выложу код, хотя откровений там ни каких.

esp8266user
Offline
Зарегистрирован: 10.04.2019

ratman

Ну я примерно как и ты, хотя благодаря твоему проекту, я понял как соединить zabbix и esp, а значит есть переспективы для творческого росат в этом направлении. Так что спасибо большое!

Пока про mqtt только слышал и ролики смотрел, но сам не дорос. Но думаю, что на будущее будет интересно узнать, так что выкладывай)

sadman41
Offline
Зарегистрирован: 19.10.2016

У MQTT есть одна проблема - он не оперирует таймштампами. Т.е. никогда не знаешь к какому моменту времени относится то или иное значение метрики. 

ratman
Offline
Зарегистрирован: 11.10.2015

Установка MQTT брокера Mosquitto

Оригинал статьи: https://www.8host.com/blog/ustanovka-brokera-soobshhenij-mosquitto-v-centos-7

УСТАНОВКА БРОКЕРА СООБЩЕНИЙ MOSQUITTO В CENTOS 7
MQTT – это легковесный протокол сообщений, предназначенный для общения между устройствами (machine-to-machine) интернета вещей. Он используется для отслеживания перемещения транспортных средств, домашней автоматизации и сбора данных.
Mosquitto – это популярный MQTT-сервер (или брокер). Он прост в установке и настройке и активно поддерживается сообществом.
Данное руководство поможет установить Mosquitto, получить для него сертификат SSL от сервиса Let’s Encrypt и настроить безопасное взаимодействие устройств по MQTT.
Требования:
- Сервер CentOS 7 (читайте руководство по начальной настройке сервера).
- Пользователь с доступом к команде sudo.
- Доменное имя (в руководстве используется условный домен mqtt.example.com).
Официальный репозиторий CentOS 7 не предоставляет пакета mosquitto. Найти этот пакет можно в репозитории EPEL (Extra Packages for Enterprise Linux).
Войдите в сессию пользователя с доступом к sudo и установите пакет epel-release.
sudo yum -y install epel-release
Опция –y автоматически подтверждает запросы. Теперь можно установить пакет mosquitto.
sudo yum -y install mosquitto

Пакет предоставляет простые базовые настройки. Запустите его:

sudo systemctl start mosquitto

Включите сервис mosquitto, чтобы автоматизировать запуск программы:

sudo systemctl enable mosquitto

Теперь нужно проверить настройки по умолчанию. Пакет mosquitto поставляется с MQTT-клиентами командной строки. Используйте один из них, чтобы подписаться на тему.

Темы – это метки, которые присваиваются опубликованным заметкам. Они расположены в виде иерархии (например, sensors/outside/temp или sensors/outside/humidity). Упорядочивание тем полностью зависит от ваших потребностей.
Откройте ещё одну сессию терминала, в результате у вас должно быть два терминала. Запустите в новом терминале команду mosquitto_sub, чтобы подписаться:
mosquitto_sub -h localhost -t test

Флаг –h указывает имя хоста сервера MQTT, -t – тему. После запуска команды на экране не появится вывода, поскольку команда mosquitto_sub ждет получения сообщений. Вернитесь в первый терминал и опубликуйте сообщение:

mosquitto_pub -h localhost -t test -m "hello world"

Команда mosquitto_pub использует те же опции, что и mosquitto_sub, однако в этот раз используется дополнительный флаг –m (он позволяет ввести текст сообщения). Нажмите Enter, и вы увидите в другом терминале MQTT-сообщение hello world.

 
ratman
Offline
Зарегистрирован: 11.10.2015
Обучаем Zabbix работать с MQTT протоколом
 
 
Вносим дополнения в конец файла конфигурации zabbix агента на сервере
sudo mcedit /etc/zabbix/zabbix_agentd.conf

Добавляем пользовательский параметр MQTT

UserParameter=mqtt[*],/usr/bin/mosquitto_sub -h 127.0.0.1 -t $1 -C 1 -N 2>/dev/null

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

Warning: Unable to locate configuration directory, default config not loaded.

Переходим в панель управления Zabbix.

Теперь нам доступна возможность создавать элементы данных содержащих ключи следующего вида:
mqtt[адресс необходимого топика]
mqtt[/room213/door1/lock/status]
mqtt[/garage/smoke/level]
mqtt[/room/sensors/temperature1]

Каждый ключ соответствует адресу топика с которого нужно взять ту или иную информацию. И сама структура топика просто идеальна для иерархии оборудования или ветвления расположений объектов. Но Вы и так это видите.

Создаем узел сети с ip адресом Zabbix сервера или просто 127.0.0.1, тип проверки  "Zabbix агент". Указываем интересующий нас топик и слушаем.
 
ВАЖНО: Клиенты рассылающие сообщения должны использовать параметр "-r, --retain" для сохранения сообщения у брокера. Без этого параметра Zabbix не сможет получить данные т.к не поддерживает постоянную связь с брокером, а лишь забирает последние данные по установленному интервалу времени.
 
ratman
Offline
Зарегистрирован: 11.10.2015

Теперь, ради чего это затевалось. Набор железа тот же, что и в стартовом сообщении.

Скетчи:

mqtt_esp8266_20190316_013.ino

/* ************************************************************************************************
************************************************************************************************ */

long lastMsg = 0;
char msg[50];
// int value = 0;

uint32_t taskPeriod_01 = 30000;
uint32_t taskPeriod_02 = 60000;


// ############################################################################
//  SETUP
void setup() {

  Serial.begin(115200);
  setup_wifi();
//  client.setServer(mqtt_server, mqtt_port);
//  client.setCallback(callback);
  setup_sensor();

  return;
}


// ############################################################################
//  LOOP
void loop() {

  // опрос сенсора
  if (avrTask01(taskPeriod_01)) {
    read_sensor();
  }

  //
  if (avrTask02(taskPeriod_02)) {
    send_message();
  }

}


// ------------------------------------------------------------------------------------------------
//  Таймер потока 01
uint8_t avrTask01(uint32_t span) {
  static uint32_t future = 0;
  if (millis() < future) return 0;
  future += span;
  return 1;
}
// ------------------------------------------------------------------------------------------------
//  Таймер потока 02
uint8_t avrTask02(uint32_t span) {
  static uint32_t future = 0;
  if (millis() < future) return 0;
  future += span;
  return 1;
}

dht_sensor.ino

/* ************************************************************************************************
  Библиотека DHT.h ( https://github.com/adafruit/DHT-sensor-library ) дополнительно понадобится
  библиотека Adafruit_Sensor.h ( https://github.com/adafruit/Adafruit_Sensor )
  Настройки датчика DHT-11(22)
************************************************************************************************ */

#include "DHT.h"                                        // подключить библиотеку DHT

#define DHTPIN 2                                        // пин к которому подключен датчик
#define DHTTYPE DHT11                                   // используемый датчик DHT 11
// #define DHTTYPE DHT21
// #define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);                               // инициализировать датчик

/* DHT variable*/
float temperature = 0.0;              // текущее значение температуры
float temperatureCorrection = -15.0;  // поправка температуры
float humidity = 0;                   // текущее значение влажности (датчик врёт)

const uint8_t averageFactor = 1;      // коэффициент сглаживания показаний (0 = не сглаживать)


// ----------------------------------------------------------------------------
//  Первоначальная инициализация сенсора
void setup_sensor() {

  dht.begin();                          // инициализация DHT
  delay(100);  //--
  temperature = dht.readTemperature();  // считывание температуры
  humidity = dht.readHumidity();        // считывание влажности (датчик врёт)

  return;
}


// ----------------------------------------------------------------------------
//  Чтение показаний сенсора
void read_sensor() {

  // считываем температуру, сглаживаем значение
  if (temperature != dht.readTemperature()) {
    // усреднение показаний для устранения "скачков"
    if (averageFactor > 0) {
      // <новое среднее> = (<старое среднее>*4 + <текущее значение>) / фактор сглаживания
      temperature = (temperature * (averageFactor - 1) + dht.readTemperature()) / averageFactor;
    } else {
      temperature = dht.readTemperature();  // не делаем усреднений, что прочитали то и считаем выводом
    }
  }
  

  // считываем влажность, сглаживаем значение
  if (humidity != dht.readHumidity()) {
    // усреднение показаний для устранения "скачков"
    if (averageFactor > 0) {
      // <новое среднее> = (<старое среднее>*4 + <текущее значение>) / фактор сглаживания
      humidity = (humidity * (averageFactor - 1) + dht.readHumidity()) / averageFactor;
    } else {
      humidity = dht.readHumidity();  // не делаем усреднений, что прочитали то и считаем выводом
    }
  }


  return;
}

mqtt_sender.ino

/* ************************************************************************************************
  Библиотека ESP8266WiFi.h (  )
  Настройки модуля ESP8266 (01)
************************************************************************************************ */

#include <ESP8266WiFi.h>

// Update these with values suitable for your network.
IPAddress  ip(192, 168, 12, 14);         // host IP
IPAddress  subnet(255, 255, 255, 0);  // network mask
IPAddress  gateway(192, 168, 12, 1);    // gateway IP

const char*  ssid = "zopukh@home";
const char*  password = "zn3GXAj41T";


/* ************************************************************************************************
  Библиотека PubSubClient.h ( https://github.com/knolleary/pubsubclient )
  MQTT подписчик/издатель для платформы Arduino
************************************************************************************************ */

#include <PubSubClient.h>

const char*     mqtt_server = "192.168.12.3";
const uint16_t  mqtt_port = 1883;

WiFiClient    espClient;
PubSubClient  client(espClient);


void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  WiFi.config(ip, gateway, subnet);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);

}


void callback(char* topic, byte* payload, unsigned int length) {

  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (uint8_t i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  
/*
  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is active low on the ESP-01)
  } else {
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }
*/

  return;
}


void reconnect() {
	
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


void send_message() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

    snprintf (msg, 50, "%f", temperature + temperatureCorrection);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("/espboard_01/temperature", msg, true);

    snprintf (msg, 50, "%f", humidity);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("/espboard_01/humidity", msg, true);

  
  return;
}

В Zabbix создаём элемент данных с ключём "mqtt[/espboard_01/temperature]" и типом "Zabbix агент" и наслаждаемся.

ratman
Offline
Зарегистрирован: 11.10.2015

sadman41 пишет:

У MQTT есть одна проблема - он не оперирует таймштампами. Т.е. никогда не знаешь к какому моменту времени относится то или иное значение метрики. 

А зачем? Юникстайм события обычно не нужен, по крайней мере для градусника. А вачдога посадить просто. Гоним параллельно те же миллисы, или вообще рандомную ерунду, если пять минут не меняется то аллармим.

P.S. Надо, кстати, запилить, а то неуютно без вачдога.

sadman41
Offline
Зарегистрирован: 19.10.2016

Да тут и MQTT не нужен, но я же молчу )) Пока этот велосипед используется в пределах LAN для пары неважных метрик - ничего необычного, в целом, замечать не будете. Но при масштабировании системы можете получить неиллюзорную головную боль.

Для меня ценность мониторинга - в синхронизированных по времени значениях метрик. А если температура сегодняшняя, а влажность (или миллис тот же) позавчерашняя - никакого смысла в таком мониторинге нет, считаю. 

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

 

ratman
Offline
Зарегистрирован: 11.10.2015

А откуда берётся уверенность, что данные полученные траппером актуальны, а не "пролежали на полке" месяц? Если они вообще имеют осмысленное значение? =)

sadman41
Offline
Зарегистрирован: 19.10.2016

На которой полке? Вы датчик прочитали, сендером в траппер пихнули. Zabbix поставил на них таймштамп получения. Т.е. данные актуальны в пределах времени, затраченного на отправку. Если траппер не ответил или не принял значения метрики  - данные не попали в мониторинг вообще. В следующую отправку попадут уже новые, актуализированные значения.

В случае с MQTT Zabbix при подключении, осуществленном в роли клиента, получит значения метрики, попавшие на MQTT неведомо когда и хранимые неизвестно сколько. Ведь данные на MQTT хранятся (при определенном QOS) ровно до того момента, когда их заберут. Т.е., при проблемах в канале, вероятность получить от MQTT числа, которые ESP положила туда позавчера, стремится к 100%. А при попадании в Zabbix они будут иметь таймштамп времени забора с MQTT (удачного коннекта). И что в итоге ? На графике видим вчерашнюю жару, которая как будто началась три минуты назад. А коли еще триггеров и экшнов навесите на метрики, то получите вовсе веселые последствия.

ratman
Offline
Зарегистрирован: 11.10.2015

Так! Устройство сбора информации по своему графику датчик опросило, данные получило, приклеило к ним свой таймштамп, отправило брокеру. Zabbix по своему графику брокера опросил, получил данные и таймштамп, сверил таймштамп с предыдущим, если не сошлось, то данные свежие, если сошлось, то источник данных мёртв. Да, получаем задержку между публикацией и чтением, но опять же всего лиш. На "последнем метре" (от монитора до стула) задержка будет на порядки больше.

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

sadman41
Offline
Зарегистрирован: 19.10.2016

Покажите-ка мне в коде где к humidity цепляется таймштамп и как заббикс его оттуда получает... Может я что-то пропустил.

ratman
Offline
Зарегистрирован: 11.10.2015

Ну, как вариант:

 void send_message() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  snprintf (tpcBuffer, 50, "/%s/temperature", BOARD_NAME);
  snprintf (msgBuffer, 50, "%f", temperature + temperatureCorrection);
  Serial.print("Publish message: ");
  Serial.println(msgBuffer);
  client.publish(tpcBuffer, msgBuffer, true);

  snprintf (tpcBuffer, 50, "/%s/wdt", BOARD_NAME);
  snprintf (msgBuffer, 50, "%ld", millis());
  Serial.print("Publish message: ");
  Serial.println(msgBuffer);
  client.publish(tpcBuffer, msgBuffer, true);

  return;
}

На брокере получаем два топика:

/espboard_01/temperature
/espboard_01/wdt

Разбор в Zabbikse ключами:

mqtt[/espboard_01/temperature]
mqtt[/espboard_01/wdt]

То, что таймштампы Zabbix'а и источника не совпадают, так они в принципе совпадать не могут, каждый живет по своему времени.

sadman41
Offline
Зарегистрирован: 19.10.2016

В данном случае вы послали две независимые метрики, которые могут придти в мониторинг вразнобой, с разницей в пару периодов опроса и не всегда в одном и том же порядке (вы же знаете, что такое очередь проверок в Zabbix?). Причем - одна из них на вполне законных основаниях может вообще не уйти на MQTT, а туда попадет значение метрики из следующей итерации.

Вы не думайте, что у меня есть цель переубедить в чем-то. Просто вспомните все вышенаписанное когда Zabbix повыключает сервера, получив вчерашнюю температуру в серверной.