ESP32 で Zabbix にデータを送ってみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f46e88cc-4c74-16d3-9f98-c8be07102e2c.png)

Zabbix はネットワーク管理ソフトウェア。様々なものを取得、DBにデータを格納し、Webで可視化できる。

Zabbix はポーリングで取得する方法と、監視対象からデータをプッシュするやり方がある。

データをプッシュするには snmp や、zabbix sender という CLI プログラムを使う方法がある。

zabbix sender は Zabbix agents パッケージに含まれていて、 Unix 系や Windows 系が提供されている。


https://www.zabbix.com/download_agents?version=6.4&release=6.4.0&os=Windows&os_version=Any&hardware=amd64&encryption=OpenSSL&packaging=MSI&show_legacy=0


今回は ESP32 上で zabbix sender と同じように使用することのできる方法を試してみます。




# 環境

- Arduino 1.8.19
- ポータブル化済
- esp32 by Espressif Systems version 2.0.4
- Ubuntu Linux 22.04
- Zabbix サーバ
以下でインストールしたもの
「Zabbix を Raspberry Pi にインストール」
https://qiita.com/nanbuwks/items/42a3c7e740e721bffbf7

# 用語

- エージェント 
監視対象。snmp の知識があると、snmp ではデータ収集するところがエージェントというのでエージェントの言葉の意味が逆になるので注意。

- サーバ
監視対象のデータを収集し、DBに格納し、Webサーバでビューする役目を持つ。フロントエンドはLAMP環境などで動くPHPプログラム。




# ライブラリ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/dcb6b729-0cd1-f47f-38ca-d507cd015515.png)

https://github.com/leruetkins/ESP32ZabbixSender
を試してみます。

# ライブラリ導入

ポータブル化しているので、ポータブル環境ディレクトリから以下のようにして作業します。

```
$ cd porable/sketchbook/libraries
$ git clone https://github.com/leruetkins/ESP32ZabbixSender.git
$ ls -alh
.
.
.
drwxrwxr-x  4 nanbuwks nanbuwks 4.0K  3月 23 00:52 ESP32ZabbixSender
.
.
.
```

これだけだとダメで、以下の作業が必要でした。

```

$ cd ESP32ZabbixSender/
$ ls
ESP8266ZabbixSender.cpp  ESP8266ZabbixSender.h  README.md  sample_ESP32ZabbixSender
$ mv ESP8266ZabbixSender.h ESP32ZabbixSender.h
$ mv ESP8266ZabbixSender.cpp ESP32ZabbixSender.cpp
```


# サンプルプログラム


まずは、センサーとか何もつけずに Zabbix との通信のみを実現しt見ます。

sample_ESP32ZabbixSender 

```
#include <ESP32ZabbixSender.h>

ESP32ZabbixSender zSender;

/* WiFi settings */
String ssid = "AP_SSID";
String pass = "AP_PASSWD";

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

boolean checkConnection();

void setup() {
	Serial.begin(115200);
	WiFi.mode(WIFI_STA);
	WiFi.disconnect();
	delay(100);
	WiFi.begin(ssid.c_str(), pass.c_str());
	while (!checkConnection()) {
	}
	zSender.Init(IPAddress(SERVERADDR), ZABBIXPORT, ZABBIXAGHOST); // Init zabbix server information
}

void loop() {
	static int counter1 = 1;
	static int counter2 = 1;
	checkConnection();							  // Check wifi connection
	zSender.ClearItem();						  // Clear ZabbixSender's item list
	zSender.AddItem("counter1", (float)counter1); // Exmaple value of zabbix trapper item
	zSender.AddItem("counter2", (float)counter2); // 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");
	}
	counter1 += 1;
	counter2 *= 2;
	delay(1000); // wait 1sec
}

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;
}
```

適宜書き換えます。

- wifi-settings をネットワーク環境にあわせて書き直し
- zabbix サーバに対して書き直し

```
#define SERVERADDR 192, 168, 42, 65
#define ZABBIXPORT 10051
#define ZABBIXAGHOST "PLANT_01"  // Zabbix item's host name
```

- loop を以下のように書き直し

```
void loop() {
  static int i = 0;
	static int counter1 = 1;
	static int counter2 = 1;
  static int counter3 = 1;
	checkConnection();							  // Check wifi connection
	zSender.ClearItem();						  // Clear ZabbixSender's item list
	zSender.AddItem("tempW", (float)counter1);
	zSender.AddItem("tempB", (float)counter2);
	zSender.AddItem("tempA", (float)counter3);
  if (zSender.Send() == EXIT_SUCCESS) {		  // Send zabbix items
		Serial.println("ZABBIX SEND: OK");
	} else {
		Serial.println("ZABBIX SEND: NG");
	}
	counter1 = sin((float)i/100)*100;
	counter2 = cos((float)i/100)*120;
  counter3 = i % 200 - 100;
  i++;
	delay(1000); // wait 1sec
}
```

# Zabbix サーバの設定

「設定」「ホストの設定」で以下のようにホストを作る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/b8ea3c02-faa0-a324-f879-613a14783c43.png)

作成した PLANT_01 の「アイテム」を押して


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/0ffb5153-6d8e-5039-50a0-16676991fb38.png)
右上の「アイテムの作成」から以下のようにトラッパーを設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/73365f7f-6e9d-930a-4978-b05fd299737e.png)

「監視データ」-「最新データ」で監視対象にチェックをつけて「グラフ表示」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2e712035-794c-c015-f67b-df8f84dc13a6.png)

以下のように表示できます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f46e88cc-4c74-16d3-9f98-c8be07102e2c.png)

# 実際のセンサー値を表示


「サーミスタを使って安く温度を測定する」
https://qiita.com/nanbuwks/items/faebeac190b02a9fb716

の値を表示してみました。

```

#include <ESP32ZabbixSender.h>

ESP32ZabbixSender zSender;

String ssid = "openforce4";
String pass = "10101000";

#define SERVERADDR 192, 168, 42, 65
#define ZABBIXPORT 10051
#define ZABBIXAGHOST "PLANT_01"  // Zabbix item's host name

boolean checkConnection();

const int BW=3100,BB=3950,BA=3950;
int thermistor_r;
int readW,readB,readA,readF;
float tempW,tempB,tempA;

float termistorRtoTemp(float T, float R, float B){
  float t1 = log( R / T ) ;
  float t2 = log(R/T);
  //Serial.printf("T:%f R:%f B:%f logRT:%f ", T,R,B,R/T);
  //Serial.printf("%f\n", t2);
  float Temp = ((298*B) / ( B + ( 298 * t1 ))) - 273 ;
  return(Temp);
}

void setup() {
	Serial.begin(115200);
	WiFi.mode(WIFI_STA);
	WiFi.disconnect();
  pinMode(25,OUTPUT);
	delay(100);
	WiFi.begin(ssid.c_str(), pass.c_str());
	while (!checkConnection()) {
	}
	zSender.Init(IPAddress(SERVERADDR), ZABBIXPORT, ZABBIXAGHOST); // Init zabbix server information
}

void loop() {
  static int i = 0;
  digitalWrite(25,HIGH);
  readW = analogReadMilliVolts(34)+5;
  readB = analogReadMilliVolts(32)+5;
  readA = analogReadMilliVolts(33)+5;
  readF = analogReadMilliVolts(35)+5;
  digitalWrite(25,LOW);
  Serial.printf("%d %d %d %d ",readW,readB,readA,readF);
 // Serial.printf("%d %d %d  ",readW,readB,readA);
  thermistor_r = ( 1000 * readW )/ (readF - readA );
  tempW = termistorRtoTemp(1000,thermistor_r,3100);
  thermistor_r = ( 10000 * readB )/ (readF - readB );
  tempB = termistorRtoTemp(10000,thermistor_r,3950);
  thermistor_r = ( 10000 * readA )/ (readF - readA );
  tempA = termistorRtoTemp(10000,thermistor_r,3950);
  Serial.printf("%f %f %f \n",tempW,tempB,tempA);

	checkConnection();						
	zSender.ClearItem();		
	zSender.AddItem("tempW", tempW);
	zSender.AddItem("tempB", tempB);
	zSender.AddItem("tempA", tempA);
  if (zSender.Send() == EXIT_SUCCESS) {
    Serial.println("ZABBIX SEND: OK");
	} else {
		Serial.println("ZABBIX SEND: NG");
	}
  i++;
	delay(1000);
}

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;
}


```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/685d394b-169c-6855-83d1-e9efc6273021.png)

これは青色の水温をモニターして、植物育成の値から外れているかどうかをチェックしているところです。