---
title: "Do your sensors yourself"
date: 2020-08-17T18:00:00+02:00
---

A big question I've asked myself during this project is what is the best place to put my storage servers? There are
multiple environmental variables to watch out: **temperature**, **humidity** and **noise**. If components are too hot,
they could be damaged in the long run. Of course, water and electricity are not friends. You can add a fan to move air
out of the case and reduce both temperature and humidity but the computer will become noisy. We need to measure those
variables. Unfortunately, all systems have different set of built-in sensors but not all of them are exposed to the
operating system. So I decided to build my own sensors. 

# Sensors hardware

I'm a newbie in electronics. I never weld anything. In the DIY[^1] world, there is a open-source micro-controller, the
[Arduino Uno](https://store.arduino.cc/arduino-uno-rev3), that costs only a few bucks (20€). There are cheaper
alternatives available like the Elegoo Uno (11€). To build sensors, you'll need good sensors like the
[DHT22](https://www.waveshare.com/wiki/DHT22_Temperature-Humidity_Sensor) for temperature and humidity and
[KY-037](https://electropeak.com/learn/how-to-use-ky-037-sound-detection-sensor-with-arduino/) for capturing sound.  To
connect everything together, you'll need a [breadboard](https://en.wikipedia.org/wiki/Breadboard),
[resistors](https://en.wikipedia.org/wiki/Resistor) and cables.

Components:
- [Elegoo Uno R3](https://www.amazon.fr/dp/B01N91PVIS/ref=cm_sw_r_tw_dp_x_8NtkFbHZ6X6K9)
- [DHT22 sensor](https://www.amazon.fr/dp/B07TTJNY1C/ref=cm_sw_r_tw_dp_x_QOtkFbBM2ZAAD)
- [KY-037 sensor](https://www.amazon.fr/dp/B07ZHGX5T6/ref=cm_sw_r_tw_dp_x_kPtkFbXRRK7ZP)
- [10k Ω resistor](https://www.amazon.fr/dp/B06XKQLPFV/ref=cm_sw_r_tw_dp_x_EPtkFbB24855X)
- [breadboard](https://www.amazon.fr/dp/B06XKZWCJB/ref=cm_sw_r_tw_dp_x_.PtkFb01X4WNW)
- [cables](https://www.amazon.fr/dp/B01JD5WCG2/ref=cm_sw_r_tw_dp_x_QQtkFbRA6PSG0)

In electronics, you need to build closed circuits going from the power supply ("+") to the ground ("-"). The Arduino
card can be plugged on an USB port which provides power to the card, on the "5V" pin. The end of the circuit should
return to the "GND" pin, which means "ground". The breadboard can help you extending the circuit and plug more than one
element (resistors and sensors at the same time). The top and bottom parts are connected horizontally. The central part
connects elements vertically. Horizontal and vertical parts are isolated from each other. Resistors role is to regulate
electrical intensity. They act like a tap for distributing water. If there is too much water at a time, the glass can be
full too quickly and water can spit everywhere. We'll put a resistor in front of the DHT22 to have valid values and to
prevent damages.

The circuit looks like this:

{{< rawhtml >}}
<p style="text-align: center;"><img src="/sensors.svg" alt="Sensors circuit" style="width: 65%;"></p>
{{< /rawhtml >}}

The DHT22 sensor has three pins: **power**, **digital** and **ground** (and not four like in the schema). The KY-037
sensor has four pins: **analog**, **ground**, **power** and **digital** (and not three like in the schema). We'll use
the analog pin to gather data from the sound sensor.

# Sensors software

The circuit is plugged to a computer via USB and it's ready to be used. To be able to read values, we need to compile
low-level code and execute it on the board. For this purpose, you can install the [Arduino
IDE](https://www.arduino.cc/en/Main/Software) which is available on multiple platforms. My personal computer runs on
Ubuntu (no joke please) and I tried to use the packages from the repositories. However, they are too old to work. You
should [install the IDE yourself](https://www.arduino.cc/en/Guide/Linux). I've added my own user to the "dialout" group
to be able to use the serial interface to send compiled code to the board. The code itself is called a "sketch". You can
find mine [here](https://github.com/jouir/arduino-sensors-toolkit/blob/master/sensors2serial.ino). Click on "Upload",
job done.

# Multiplexing

Values are sent to the serial port but only one program can read this interface at a time. No luck, we would like to
send those metrics to the alerting and trending systems. Both have their own schedules. They will try to access this
interface at the same time. Moreover, programs that would like to read the serial port will have to wait for, at least,
four seconds. In the IoT[^2] world, we often see the usage of [MQTT](https://en.wikipedia.org/wiki/MQTT), a queuing
protocol. To solve the performance issue, I've developed a simple daemon that reads values from the serial interface and
publishes them to an MQTT broker called [serial2mqtt](https://github.com/jouir/arduino-sensors-toolkit/#serial2mqtt).
I've installed [Mosquitto](https://mosquitto.org/) on storage servers so the multiplexing happens locally.

# Thresholds

What is the **critical temperature**? I [found](https://www.apc.com/us/en/faqs/FA157464/) that UPS batteries should not
run in an environment where temperatures exceed 25°C (warning) and must not go over 40°C (critical). This summer, I had
multiple buzzer alerts on storage3 and the temperature was over 29°C every time.

What is the **critical humidity**? Humidity is the concentration of water in a volume of air. In tropical regions of the
world, we often see a 100% humidity level, with working computers. Humidity is proportional to the temperature. The
hotter it is, the more water can be contained in the air. Generally, temperature in a computer case is warmer than the
ambient temperature. What is dangerous is not the quantity of water in the air, it's when water condense. A good rule of
thumb is to avoid going over 80%. But 100% should not be a problem.

# Alerting

On Nagios, I use the [check-mqtt](https://github.com/jpmens/check-mqtt) script on the monitored storage host under an
NRPE command:

```
# Sensors
command[check_ambient_temperature]=/usr/local/bin/python3.7 /usr/local/libexec/nagios/check-mqtt.py -m 10 --readonly -t sensors/temperature -H localhost -P 1883 -u nagios -p ***** -w "float(payload) > 25.0" -c "float(payload) > 40.0"
command[check_ambient_humidity]=/usr/local/bin/python3.7 /usr/local/libexec/nagios/check-mqtt.py -m 10 --readonly -t sensors/humidity -H localhost -P 1883 -u nagios -p ***** -w "float(payload) > 80.0" -c "float(payload) > 95.0"
```

[![storage2](/sensors-storage2-alert.png)](/sensors-storage2-alert.png)

# Observability

Telegraf has a [mqtt_consumer](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/mqtt_consumer) input
plugin:

```
[[inputs.mqtt_consumer]]
  servers = ["tcp://localhost:1883"]
  topics = [
    "sensors/humidity",
    "sensors/temperature",
    "sensors/sound"
  ]
  persistent_session = true
  client_id = "telegraf"
  data_format = "value"
  data_type = "float"
  username = "telegraf"
  password = "*****"
```

Grafana is able to display environmental variables now:

[![storage1](/sensors-storage1.png)](/sensors-storage1.png)
[![storage2](/sensors-storage2.png)](/sensors-storage2.png)
[![storage3](/sensors-storage3.png)](/sensors-storage3.png)

# In the end

I tried to measure noise but I failed. The KY-037 sensor is designed to detect sound variations like a big noise for a
short period of time. When we try to measure the ambient noise level, it requires a lot of conversions to get values in
[decibel](https://en.wikipedia.org/wiki/Decibel). So I decided to ignore values coming from the sensor and to hear it
myself.

I can put my storage servers in the attic, in a room or in the cellar. The attic is right under the roof which is too
hot in the summer (over 40°C). Rooms are occupied during the night and noise is a problem. I am lucky to have a free
room right now but it's too hot during the summer (over 25°C). There is the cellar left, where all the conditions are
optimal, even humidity. Remote locations all have a cellar which is perfect!

[^1]: Do It Yourself
[^2]: Internet of Things
