Improve initial code, but my sensor seems to be broken
This commit is contained in:
parent
e599b110e2
commit
45ae85594b
23
README.md
23
README.md
|
@ -1,22 +1,27 @@
|
||||||
# prometheus-arduino-dht-exporter
|
# prometheus-esp8266-dht-exporter
|
||||||
|
|
||||||
A Prometheus exporter for IoT temperature and humidity measurements, using an Arduino with a Wi-Fi module and a DHT (temperature + humidity) sensor.
|
A Prometheus exporter for IoT temperature and humidity measurements, using an ESP8266 (Arduino-compatible) with a Wi-Fi module and a DHT (temperature + humidity) sensor.
|
||||||
|
|
||||||
## Hardware
|
## Hardware
|
||||||
|
|
||||||
Arduino-compatible board: [WEMOS D1 Mini](https://wiki.wemos.cc/products:d1:d1_mini) (ESP8266)
|
ESP8266 board: [WEMOS D1 Mini](https://wiki.wemos.cc/products:d1:d1_mini) (ESP8266)
|
||||||
|
|
||||||
DHT sensor: [Wemos DHT Shield](https://wiki.wemos.cc/products:retired:dht_shield_v1.0.0) (DHT11)
|
DHT sensor: [Wemos DHT Shield](https://wiki.wemos.cc/products:retired:dht_shield_v1.0.0) (DHT11)
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- [Arduino IDE](https://www.arduino.cc/en/Main/Software) (download)
|
- [Arduino IDE](https://www.arduino.cc/en/Main/Software)
|
||||||
- [esp8266 library for Arduino](https://github.com/esp8266/Arduino#installing-with-boards-manager) (see instructions)
|
- Download and install.
|
||||||
- [Adafruit DHT sensor library](https://github.com/adafruit/DHT-sensor-library) (install using the library manager, including all dependencies)
|
- [esp8266 library for Arduino](https://github.com/esp8266/Arduino#installing-with-boards-manager)
|
||||||
|
- See the instructions on the page.
|
||||||
|
- [Adafruit DHT sensor library](https://github.com/adafruit/DHT-sensor-library)
|
||||||
|
- Install using the library manager, including all dependencies.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
This uses the Arduino IDE.
|
||||||
|
|
||||||
1. Copy `config.default.h` to `config.h` and fill inn the details.
|
1. Copy `config.default.h` to `config.h` and fill inn the details.
|
||||||
1. Set the correct board settings in Arduino IDE:
|
1. Set the correct settings for the board.
|
||||||
- WEMOS D1 Mini uses board "WeMoS D1 R2 & mini", CPU frequency 160MHz and upload speed 821 600.
|
- WEMOS D1 Mini uses board "WeMoS D1 R2 & mini".
|
||||||
1. Build and upload in Arduino IDE.
|
1. Build and upload using the Arduino IDE.
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Debug mode is enabled if not zero
|
// Debug mode is enabled if not zero
|
||||||
#define DEBUG 0
|
#define DEBUG_MODE 0
|
||||||
// DHT sensor type: DHT11, DHT21 or DHT22
|
// DHT sensor type: DHT11, DHT21 or DHT22
|
||||||
#define DHT_TYPE DHT11
|
#define DHT_TYPE DHT11
|
||||||
// DHT pin
|
// DHT pin
|
||||||
#define DHT_PIN D4
|
#define DHT_PIN D4
|
||||||
|
// HTTP server port
|
||||||
|
#define HTTP_SERVER_PORT 80
|
||||||
|
// HTTP metrics endpoint
|
||||||
|
#define HTTP_METRICS_ENDPOINT "/metrics"
|
||||||
// Temperature offset in degrees Celsius
|
// Temperature offset in degrees Celsius
|
||||||
#define TEMPERATURE_CORRECTION_OFFSET 0
|
#define TEMPERATURE_CORRECTION_OFFSET 0
|
||||||
// Humidity offset in percent
|
// Humidity offset in percent
|
||||||
#define HUMIDITY_CORRECTION_OFFSET 0
|
#define HUMIDITY_CORRECTION_OFFSET 0
|
||||||
// How long to cache the sensor results
|
// How long to cache the sensor results
|
||||||
#define READ_INTERVAL 2000
|
#define READ_INTERVAL 2000
|
||||||
// Retry up to this many times to read the snsor correctly before returning before returning error
|
// How many times to try to read the sensor before returning an error
|
||||||
#define READ_RETRY_COUNT 5
|
#define READ_TRY_COUNT 5
|
||||||
|
|
||||||
// WiFi SSID (required)
|
// WiFi SSID (required)
|
||||||
const char *WIFI_SSID = "";
|
#define WIFI_SSID ""
|
||||||
// WiFi password (required)
|
// WiFi password (required)
|
||||||
const char *WIFI_PASSWORD = "";
|
#define WIFI_PASSWORD ""
|
||||||
|
|
224
src/src.ino
224
src/src.ino
|
@ -5,113 +5,163 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
enum LogLevel {
|
||||||
|
DEBUG,
|
||||||
|
INFO,
|
||||||
|
ERROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup_dht_sensor();
|
||||||
|
void setup_wifi();
|
||||||
|
void setup_http_server();
|
||||||
|
void handle_http_home_client();
|
||||||
|
void handle_http_metrics_client();
|
||||||
|
void read_sensors(boolean force=false);
|
||||||
|
bool read_sensor(float (*function)(), float *value);
|
||||||
|
void log(char const *message, LogLevel level=LogLevel::INFO);
|
||||||
|
|
||||||
DHT dht_sensor(DHT_PIN, DHT_TYPE);
|
DHT dht_sensor(DHT_PIN, DHT_TYPE);
|
||||||
ESP8266WebServer web_server(80);
|
ESP8266WebServer http_server(HTTP_SERVER_PORT);
|
||||||
|
|
||||||
float humidity, temperature;
|
float humidity, temperature;
|
||||||
char str_humidity[10], str_temperature[10];
|
char str_humidity[10], str_temperature[10];
|
||||||
unsigned long previousReadTime = 0;
|
unsigned long previousReadTime = 0;
|
||||||
|
|
||||||
void setup_wifi();
|
|
||||||
void setup_dht();
|
|
||||||
void setup_web();
|
|
||||||
void read_sensors(boolean force=false);
|
|
||||||
void read_sensor(const char *name, float (*function)(), const char *str_format, char *str_result, size_t len_result, float &result);
|
|
||||||
void log(const char *message, boolean error=false);
|
|
||||||
|
|
||||||
void setup(void) {
|
void setup(void) {
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
log("Starting setup ...");
|
setup_dht_sensor();
|
||||||
setup_wifi();
|
setup_wifi();
|
||||||
setup_dht();
|
setup_http_server();
|
||||||
setup_web();
|
}
|
||||||
log("Started setup");
|
|
||||||
|
void setup_dht_sensor() {
|
||||||
|
log("Setting up DHT sensor ...");
|
||||||
|
dht_sensor.begin();
|
||||||
|
// Test read
|
||||||
|
read_sensors(true);
|
||||||
|
log("DHT sensor ready.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_wifi() {
|
void setup_wifi() {
|
||||||
char message[100];
|
char message[100];
|
||||||
snprintf(message, 100, "SSID: %s", WIFI_SSID);
|
snprintf(message, 100, "Using Wi-Fi SSID \"%s\".", WIFI_SSID);
|
||||||
log(message);
|
log(message);
|
||||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
log("Wi-Fi connecting ...");
|
||||||
log("WiFi connecting ...");
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
delay(500);
|
log("Wi-Fi waiting ...", LogLevel::DEBUG);
|
||||||
}
|
delay(500);
|
||||||
const IPAddress &ipaddr = WiFi.localIP();
|
}
|
||||||
snprintf(message, 100, "IP address: %d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
|
const IPAddress &ipaddr = WiFi.localIP();
|
||||||
log(message);
|
log("Wi-Fi connected.");
|
||||||
log("Started WiFi");
|
snprintf(message, 100, "IPv4 address: %d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
|
||||||
|
log(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_dht() {
|
void setup_http_server() {
|
||||||
dht_sensor.begin();
|
http_server.on("/", HTTPMethod::HTTP_GET, handle_http_home_client);
|
||||||
// Initial read
|
http_server.on(HTTP_METRICS_ENDPOINT, HTTPMethod::HTTP_GET, handle_http_metrics_client);
|
||||||
read_sensors(true);
|
http_server.begin();
|
||||||
log("Started DHT sensor");
|
log("HTTP server started.");
|
||||||
}
|
|
||||||
|
|
||||||
void setup_web() {
|
|
||||||
web_server.on("/", [] {
|
|
||||||
read_sensors();
|
|
||||||
char response[100];
|
|
||||||
snprintf(response, 100, "Temperature: %s\nHumidity: %s", str_temperature, str_humidity);
|
|
||||||
web_server.send(200, "text/plain", response);
|
|
||||||
});
|
|
||||||
web_server.begin();
|
|
||||||
log("Started web server");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop(void) {
|
void loop(void) {
|
||||||
web_server.handleClient();
|
http_server.handleClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_http_home_client() {
|
||||||
|
static char const *response =
|
||||||
|
"Prometheus ESP8266 DHT Exporter by HON95.\n"
|
||||||
|
"\n"
|
||||||
|
"Project: https://github.com/HON95/prometheus-esp8266-dht-exporter\n"
|
||||||
|
"\n"
|
||||||
|
"Usage: " HTTP_METRICS_ENDPOINT "\n";
|
||||||
|
http_server.send(200, "text/plain", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_http_metrics_client() {
|
||||||
|
read_sensors();
|
||||||
|
char response[100];
|
||||||
|
snprintf(response, 100, "Temperature: %s\nHumidity: %s", str_temperature, str_humidity);
|
||||||
|
http_server.send(200, "text/plain", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_sensors(boolean force) {
|
void read_sensors(boolean force) {
|
||||||
unsigned long currentTime = millis();
|
// TODO remove caching, the library already does it
|
||||||
if (!force && currentTime - previousReadTime < READ_INTERVAL) {
|
unsigned long currentTime = millis();
|
||||||
// Use cached values
|
if (!force && currentTime - previousReadTime < READ_INTERVAL) {
|
||||||
return;
|
log("Sensors were recently read, will not read again yet.", LogLevel::DEBUG);
|
||||||
}
|
return;
|
||||||
previousReadTime = currentTime;
|
}
|
||||||
|
previousReadTime = currentTime;
|
||||||
// Read temperature as degrees Celsius and force read
|
|
||||||
read_sensor("temperature", []() {
|
read_humidity_sensor();
|
||||||
return dht_sensor.readTemperature(false, true) + TEMPERATURE_CORRECTION_OFFSET;
|
read_temperature_sensor();
|
||||||
}, "%.0f\u00B0C", str_temperature, 10, temperature);
|
// TODO float hic = dht.computeHeatIndex(t, h, false);
|
||||||
|
|
||||||
// Read humidity and force read
|
|
||||||
read_sensor("humidity", []() {
|
|
||||||
return dht_sensor.readHumidity(true) + HUMIDITY_CORRECTION_OFFSET;
|
|
||||||
}, "%.0f%%", str_humidity, 10, humidity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_sensor(const char *name, float (*function)(), const char *str_format, char *str_result, size_t len_result, float &result) {
|
void read_humidity_sensor() {
|
||||||
char message[100];
|
log("Reading humidity sensor ...", LogLevel::DEBUG);
|
||||||
result = function();
|
bool result = read_sensor([] {
|
||||||
for (int i = 0; isnan(result) && i < READ_RETRY_COUNT; i++) {
|
return dht_sensor.readHumidity();
|
||||||
#if DEBUG != 0
|
}, &humidity);
|
||||||
snprintf(message, 100, "Re-reading failed %s ...", name);
|
if (result) {
|
||||||
log(message, true);
|
humidity += HUMIDITY_CORRECTION_OFFSET;
|
||||||
#endif
|
snprintf(str_humidity, 10, "%.0f%%", humidity);
|
||||||
result = function();
|
} else {
|
||||||
}
|
snprintf(str_humidity, 10, "ERROR");
|
||||||
if (!isnan(humidity)) {
|
log("Failed to read humidity sensor.", LogLevel::ERROR);
|
||||||
snprintf(str_result, len_result, str_format, result);
|
}
|
||||||
} else {
|
|
||||||
strcpy(str_result, "ERROR");
|
|
||||||
snprintf(message, 100, "Failed to read %s!", name);
|
|
||||||
log(message, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(const char *message, boolean error) {
|
void read_temperature_sensor() {
|
||||||
float seconds = millis() / 1000.0;
|
log("Reading temperature sensor ...", LogLevel::DEBUG);
|
||||||
char level[10];
|
bool result = read_sensor([] {
|
||||||
if (!error) {
|
return dht_sensor.readTemperature(false);
|
||||||
strcpy(level, "INFO");
|
}, &temperature);
|
||||||
} else {
|
if (result) {
|
||||||
strcpy(level, "ERROR");
|
temperature += TEMPERATURE_CORRECTION_OFFSET;
|
||||||
}
|
snprintf(str_temperature, 10, "%.0f\u00B0C", temperature);
|
||||||
char record[150];
|
} else {
|
||||||
snprintf(record, 150, "[%10.3f] [%-5s] %s", seconds, level, message);
|
snprintf(str_temperature, 10, "ERROR");
|
||||||
Serial.println(record);
|
log("Failed to read temperature sensor.", LogLevel::ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_sensor(float (*function)(), float *value) {
|
||||||
|
bool success = false;
|
||||||
|
for (int i = 0; i < READ_TRY_COUNT; i++) {
|
||||||
|
*value = function();
|
||||||
|
if (!isnan(*value)) {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log("Failed to read sensor.", LogLevel::DEBUG);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log(char const *message, LogLevel level) {
|
||||||
|
if (DEBUG_MODE == 0 && level == LogLevel::DEBUG) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Will overflow after a while
|
||||||
|
float seconds = millis() / 1000.0;
|
||||||
|
char str_level[10];
|
||||||
|
switch (level) {
|
||||||
|
case DEBUG:
|
||||||
|
strcpy(str_level, "DEBUG");
|
||||||
|
break;
|
||||||
|
case INFO:
|
||||||
|
strcpy(str_level, "INFO");
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
strcpy(str_level, "ERROR");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char record[150];
|
||||||
|
snprintf(record, 150, "[%10.3f] [%-5s] %s", seconds, str_level, message);
|
||||||
|
Serial.println(record);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue