WioLTE で収集した温度湿度を grafana で表示する

![IMG_20210825_092910.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/59209353-041a-1f87-3c22-15def8b894ee.jpeg)


次のように表示します。
![grafana_aug25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/ed315956-9526-cb60-86bd-e6d5770727fa.png)

サーバーで次のソフトが動いていることを確認

1) Grafana

>```bash
sudo systemctl status grafana-server
```

>バージョン
>v8.1.2
![grafana_version.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/ca5d3908-5eb4-a658-d6cd-f1454ae1e68c.png)

2) InfluxDB 2.0

>```bash
sudo systemctl status influxdb
```

>バージョン

>```text
$ influx version
Influx CLI 2.0.8 (git: e91d41810f) build_date: 2021-08-13T18:22:30Z
```

3) Telegraf

>```bash
sudo systemctl status telegraf
```

>バージョン

>```text
$ telegraf --version
Telegraf 1.19.3 (git: HEAD a799489f)
```

データの流れ

>WioLTE -> Telegraf -> Influxdb 2.0 -> Grafana

UDP 8092 で Telegraf に入ってきたデータを Influxdb 2.0 に入れる方法はこちら
[Telegraf で InfluxDB 2.0 にデータを入れる](https://qiita.com/ekzemplaro/items/1156e8371aea84604d13)

Grafana と InfluxDB 2.0 を接続する方法はこちら
[https://qiita.com/ekzemplaro/items/f462dfc0d81329b39c09](https://qiita.com/ekzemplaro/items/f462dfc0d81329b39c09)

Grafana でパネルを作る方法

Data source を InfluxDB にします。
![grafana_aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/34d5601b-91f9-0062-5734-8657020f137a.png)

Sample Query で Simple Query を選びます。
![grafana_bb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/cf5347c3-6570-4215-08a7-8aa0f81cbda5.png)

次のような Query が出来るので、これを編集します。
>バケット名は、b01
>Measurement は、 aaa
>です。

```text
from(bucket: "db/rp")
  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)
  |> filter(fn: (r) =>
    r._measurement == "example-measurement" and
    r._field == "example-field"
  )
```

温度の Query

```text
from(bucket: "b01")
  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)
  |> filter(fn: (r) =>
    r._measurement == "aaa" and
    r._field == "temperature"
  )
```

湿度の Query

```text
from(bucket: "b01")
  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)
  |> filter(fn: (r) =>
    r._measurement == "aaa" and
    r._field == "humidity"
  )
```

ここまでの流れを確認するスクリプトです。
>UDP 8092 にデータを送ります。

```bash
#
echo 'aaa temperature=22.1,humidity=36.9' | ncat -4 -u -w 1 localhost 8092
sleep 10 
echo 'aaa temperature=23.2,humidity=37.8' | ncat -4 -u -w 1 localhost 8092
sleep 10
echo 'aaa temperature=24.3,humidity=35.7' | ncat -4 -u -w 1 localhost 8092
sleep 10
echo 'aaa temperature=25.4,humidity=34.6' | ncat -4 -u -w 1 localhost 8092
sleep 10
echo 'aaa temperature=26.5,humidity=33.6' | ncat -4 -u -w 1 localhost 8092
sleep 10
echo 'aaa temperature=25.6,humidity=31.7' | ncat -4 -u -w 1 localhost 8092
```

WioLTE のプログラム
>温湿度計は次のものを使います。
>DHT22/AM2302 デジタル温・湿度センサー モジュール

フォルダー構造

```text
$ tree udp_temp_humi/
udp_temp_humi/
├── setupLTE.ino
├── temp_humi_dht22.ino
├── udp.ino
└── udp_temp_humi.ino
```

```text:udp_temp_humi.ino
// ---------------------------------------------------------------
/*
	udp_temp_humi.ino

					Aug/24/2021
*/
// ---------------------------------------------------------------
#include <WioLTEforArduino.h>
#include <stdio.h>

#define SENSOR_PIN	(WIOLTE_D38)

// #define INTERVAL  (10000)
// #define INTERVAL  (20000)
#define INTERVAL  (30000)
// #define INTERVAL  (60000)

#define RECEIVE_TIMEOUT (10000)

WioLTE Wio;
int TemperatureAndHumidityPin;

int icount = 0;

// ---------------------------------------------------------------
void setup()
{
	setupLTE();

	Wio.PowerSupplyGrove(true);

	TemperatureAndHumidityBegin(SENSOR_PIN);

	SerialUSB.println("*** udp_temp_humi.ino *** Aug/24/2021 PM 21:30");
}

// ---------------------------------------------------------------
void loop()
{
	char data_json[128];

	SerialUSB.println("icount = " + String(icount));

float temp;
float humi;
temp_humi_dht22_proc(&temp,&humi);

// char data_send[] = "aaa temperature=24.4,humidity=71.5";

// char *chx = (char *)malloc(256);
char chx[256];

chx[0] = '\0';

char charBuf[50];
String ss = String(temp);
String sh = String(humi);

strcat(chx,"aaa temperature=");

ss.toCharArray(charBuf, 50);
strcat(chx,charBuf);

strcat(chx,",humidity=");
sh.toCharArray(charBuf, 50);
strcat(chx,charBuf);


char url[] = "example.com";
int port = 8092;
int connectId = udp_open_proc(url,port);

if (0 <= connectId)
	{
	SerialUSB.println("connectId = " + String(connectId));
  
	boolean result = udp_send_proc(connectId,chx);
	SerialUSB.println("result = " + String(result));
/*
	if (result)
	 {
		result = udp_receive_proc(connectId);
	}
*/
}

// free(chx);

	udp_close_proc(connectId);
	
	delay(INTERVAL);
	icount++;
}

// ---------------------------------------------------------------
```

```text:temp_humi_dht22.ino
// ---------------------------------------------------------------
/*
	temp_humi_dht22.ino

					Aug/24/2021

	D38	Temperature & Humidity
*/
// ---------------------------------------------------------------
void temp_humi_dht22_proc(float *atemp, float *ahumi)
{
	if (!TemperatureAndHumidityRead(atemp, ahumi))
		{
		SerialUSB.println("*** ERROR! TemperatureAndHumidityRead ***");
		}
	else
		{
		SerialUSB.print("temperature = ");
		SerialUSB.print(*atemp);
		SerialUSB.print("C  ");
		SerialUSB.print("humidity = ");
		SerialUSB.print(*ahumi);
		SerialUSB.println("%");
		}
}

// ---------------------------------------------------------------
void TemperatureAndHumidityBegin(int pin)
{
	TemperatureAndHumidityPin = pin;
	DHT22Init(TemperatureAndHumidityPin);
}

// ---------------------------------------------------------------
bool TemperatureAndHumidityRead(float* temperature, float* humidity)
{
	byte data[5];
	float ff = NAN;

	DHT22Start(TemperatureAndHumidityPin);
	for (int i = 0; i < 5; i++) data[i] = DHT22ReadByte(TemperatureAndHumidityPin);

	DHT22Finish(TemperatureAndHumidityPin);

	if (!DHT22Check(data, sizeof (data))) return false;
	ff = data[0];
	ff *= 256;
	ff += data[1];
	ff *= 0.1;
	*humidity = ff;

	ff = data[2] & 0x7F;
	ff *= 256;
	ff += data[3];
	ff *= 0.1;
	if (data[2] & 0x80) {
		ff *= -1;
	}
	*temperature = ff;

	return true;
}

// ---------------------------------------------------------------
void DHT22Init(int pin)
{
	digitalWrite(pin, HIGH);
	pinMode(pin, OUTPUT);
}

// ---------------------------------------------------------------
void DHT22Start(int pin)
{
	// Host the start of signal
	digitalWrite(pin, LOW);
	delay(18);

	// Pulled up to wait for
	pinMode(pin, INPUT);
	while (!digitalRead(pin)) ;

	// Response signal
	while (digitalRead(pin)) ;

	// Pulled ready to output
	while (!digitalRead(pin)) ;
}

// ---------------------------------------------------------------
byte DHT22ReadByte(int pin)
{
	byte data = 0;

	for (int i = 0; i < 8; i++) {
		while (digitalRead(pin)) ;

		while (!digitalRead(pin)) ;
		unsigned long start = micros();

		while (digitalRead(pin)) ;
		unsigned long finish = micros();

		if ((unsigned long)(finish - start) > 50) data |= 1 << (7 - i);
	}

	return data;
}

// ---------------------------------------------------------------
void DHT22Finish(int pin)
{
	// Releases the bus
	while (!digitalRead(pin)) ;
	digitalWrite(pin, HIGH);
	pinMode(pin, OUTPUT);
}

// ---------------------------------------------------------------
bool DHT22Check(const byte* data, int dataSize)
{
	if (dataSize != 5) return false;

	byte sum = 0;
	for (int i = 0; i < dataSize - 1; i++) {
		sum += data[i];
	}

	return data[dataSize - 1] == sum;
}

// ---------------------------------------------------------------
```

setupLTE.ino と udp.ino はこちら
[UDP で温度と湿度を Harvest に送る](https://qiita.com/ekzemplaro/items/690faa6f56003272299f)