commit 1ff7642beafa2d25b589ff042bd7cc7664476bd2 Author: Pim van Pelt Date: Sun Mar 4 16:11:07 2018 +0100 Initial Checkin. Only DHT (AM3202) supported at this time. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..350abb0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +deps/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..9cc0e5f --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Prometheus Sensors + +This is a library that implements a set of sensor types, reading their values +periodically and exposing them to Prometheus using the `prometheus-metrics` +library. + +## Supported Sensors + +### DHT + +This is using `dht` library; each sensor reading takes approximately 32ms (28ms +if there is no sensor on the GPIO in). They are placed on timers so as to +minimize pre-emption of the main application. DHT sensors are polled in order +based on `sensors.dht_gpio` pins and with a period of `sensors.dht_period` +which defaults to 3 seconds. diff --git a/include/mgos_prometheus_sensors.h b/include/mgos_prometheus_sensors.h new file mode 100644 index 0000000..18596f4 --- /dev/null +++ b/include/mgos_prometheus_sensors.h @@ -0,0 +1,7 @@ +#ifndef __MGOS_PROMETHEUS_SENSORS_H +#define __MGOS_PROMETHEUS_SENSORS_H + +#include "mgos.h" +#include "mgos_gpio.h" + +#endif // __MGOS_PROMETHEUS_SENSORS_H diff --git a/mos.yml b/mos.yml new file mode 100644 index 0000000..4ae94f1 --- /dev/null +++ b/mos.yml @@ -0,0 +1,30 @@ +author: Pim van Pelt +description: Library that interfaces sensors to Prometheus Metrics +type: lib +version: 1.0 +platforms: [esp32, esp8266] + +tags: + - c + +# List of files / directories with C sources. No slashes at the end of dir names. +sources: + - src + +includes: + - include + +config_schema: + - ["sensors", "o", {title: "Sensors settings"}] + - ["sensors.dht_gpio", "s", "13,12,14", {title: "Comma Separated list of GPIO pins to enable DHT22/AM2302 sensors on"}] + - ["sensors.dht_period", "i", 3, {title: "Sample period in seconds for DHT sensors"}] + - ["prometheus.pushgateway", "prometheus.example.net:9091"] + + +# List of libraries used by this app, in order of initialisation +libs: + - origin: https://github.com/mongoose-os-libs/dht + - origin: https://github.com/mongoose-os-libs/prometheus-metrics + +# Used by the mos tool to catch mos binaries incompatible with this file format +manifest_version: 2017-05-18 diff --git a/src/dht.c b/src/dht.c new file mode 100644 index 0000000..5cd5913 --- /dev/null +++ b/src/dht.c @@ -0,0 +1,115 @@ +#include "mgos.h" + +#ifdef MGOS_HAVE_DHT +#include "main.h" +#include "mgos_dht.h" +#include "mgos_config.h" +#include "mgos_prometheus_metrics.h" +#include "mqtt.h" + +#define MAX_DHT 8 + +struct dht_sensor { + struct mgos_dht *dht; + float temp; + float humidity; + uint8_t gpio; + uint8_t idx; +}; + +static struct dht_sensor *s_dht_sensor[MAX_DHT]; +static int s_num_dht = 0; + +static void print_chunk(struct mg_connection *nc, char *name, char *fmt, ...) { + char chunk[500]; + int chunklen=0; + va_list ap; + + snprintf(chunk, sizeof(chunk), "%s%s", name, fmt[0]=='{' ? "" : " "); + va_start(ap, fmt); + vsnprintf(chunk+strlen(chunk), sizeof(chunk)-strlen(chunk), fmt, ap); + va_end(ap); + strncat(chunk, "\n", sizeof(chunk)); + chunklen=strlen(chunk); + LOG(LL_DEBUG, ("Chunk '%s' with length %d", chunk, chunklen)); + mg_printf(nc, "%X\r\n%s\r\n", chunklen, chunk); + +} + +static void dht_prometheus_metrics(struct mg_connection *nc, void *user_data) { + int i; + + // BUG -- repeated HELP and TYPE makes Prometheus parser bork :( + mgos_prometheus_metrics_printf(nc, GAUGE, + "temperature", "Temperature in celcius", + "{sensor=\"0\",type=\"DHT\"} %f", s_dht_sensor[0]->temp); + mgos_prometheus_metrics_printf(nc, GAUGE, + "humidity", "Relative humidity percentage", + "{sensor=\"0\",type=\"DHT\"} %f", s_dht_sensor[0]->humidity); + + for (i=1; itemp); + print_chunk(nc, "humidity", "{sensor=\"%d\",type=\"DHT\"} %f", i, s_dht_sensor[i]->humidity); + } + + (void) user_data; +} + +static void dht_timer_cb(void *user_data) { + struct dht_sensor *dht_sensor = (struct dht_sensor *)user_data; + double start; + uint32_t usecs=0; + + if (!dht_sensor) return; + + start=mgos_uptime(); + dht_sensor->temp = mgos_dht_get_temp(dht_sensor->dht); + dht_sensor->humidity = mgos_dht_get_humidity(dht_sensor->dht); + usecs=1000000*(mgos_uptime()-start); + LOG(LL_DEBUG, ("DHT sensor=%u gpio=%u temp=%.2fC humidity=%.0f%% usecs=%u", dht_sensor->idx, dht_sensor->gpio, dht_sensor->temp, dht_sensor->humidity, usecs)); +} + +static bool dht_sensor_create(int pin, enum dht_type type) { + struct dht_sensor *dht_sensor = calloc(1, sizeof(struct dht_sensor)); + if (s_num_dht == MAX_DHT) { + LOG(LL_ERROR, ("No more sensor slots available (%d added)", MAX_DHT)); + free(dht_sensor); + return false; + } + + dht_sensor->dht=mgos_dht_create(pin, type); + if (!dht_sensor->dht) { + LOG(LL_ERROR, ("Could not create DHT sensor on pin %d", pin)); + free(dht_sensor); + return false; + } + dht_sensor->gpio=pin; + dht_sensor->idx=s_num_dht; + s_dht_sensor[dht_sensor->idx] = dht_sensor; + s_num_dht++; + mgos_set_timer(mgos_sys_config_get_sensors_dht_period()*1000, true, dht_timer_cb, (void*)dht_sensor); + return true; +} + +void dht_init() { + char *tok; + + memset(s_dht_sensor, 0, sizeof (struct mgos_dht_sensor *) * MAX_DHT); + tok = strtok((char *)mgos_sys_config_get_sensors_dht_gpio(), ", "); + while (tok) { + int gpio; + gpio = atoi(tok); + tok=strtok(NULL, ", "); + dht_sensor_create(gpio, AM2302); + mgos_msleep(250); + } + + if (s_num_dht>0) + mgos_prometheus_metrics_add_handler(dht_prometheus_metrics, NULL); +} + +#else +void dht_init() { + LOG(LL_ERROR, ("DHT disabled, include library in mos.yml to enable")); +} +#endif diff --git a/src/mgos_prometheus_sensors.c b/src/mgos_prometheus_sensors.c new file mode 100644 index 0000000..0310324 --- /dev/null +++ b/src/mgos_prometheus_sensors.c @@ -0,0 +1,9 @@ +#include "mgos_config.h" +#include "mgos_prometheus_sensors.h" + +void dht_init(); + +bool mgos_prometheus_sensors_init(void) { + dht_init(); + return true; +}