esp32-anduino.ino code
#include <WiFi.h> #include <WiFiMulti.h> WiFiMulti WiFiMulti; #include <DHTesp.h> DHTesp dht; // change values to your own setup const char SSID[] = "xxxxxxxx"; // your WiFi name const char PASSWORD[] = "xxxxxxxxxxxxxx"; // your WiFi password const char * HOST = "xxxxxxxxxxxxx"; // pushGW: ip or dns const uint16_t PORT = 9091; // pushGW: TCP port bool DEBUG = false; // prometheus metadata String JOB = String("dh22"); String INSTANCE = String("dc"); enum DATA_TYPE {CSV, JSON, PROMETHEUS}; // enable serial outputter: CSV, JSON, PROMETHEUS DATA_TYPE SERIAL_OUTPUTTER = CSV; // enable data push to HTTP endpoint CSV, JSON, PROMETHEUS DATA_TYPE PUSH_DATA = PROMETHEUS; //prometheus_metric #include "prometheus_metric.h" Metric temperature(MetricType::gauge, "temperature_celsius", "DHT22 exported temperature value in celsius", 1); Metric humidity(MetricType::gauge, "humidity", "DHT22 exported relative humidity value in percent", 1); Metric absHumidity(MetricType::gauge, "absolute_humidity", "DHT22 computed absolute humidity value", 1); Metric heatIndex(MetricType::gauge, "heat_index", "DHT22 computed heat index value", 1); Metric dewPoint(MetricType::gauge, "dew_point", "DHT22 computed dew point value", 1); Metric tooHot(MetricType::gauge, "too_hot", "DHT22 comfort value too hot", 1); Metric tooCold(MetricType::gauge, "too_cold", "DHT22 comfort value too cold", 1); Metric tooHumid(MetricType::gauge, "too_humid", "DHT22 comfort value too humid", 1); Metric tooDry(MetricType::gauge, "too_dry", "DHT22 comfort value distance too dry", 1); Metric distanceTooHot(MetricType::gauge, "distance_too_hot", "DHT22 comfort value distance to tooHot", 1); Metric distanceTooCold(MetricType::gauge, "distance_too_cold", "DHT22 comfort value distance to tooCold", 1); Metric distanceTooHumid(MetricType::gauge, "distance_too_humid", "DHT22 comfort value distance to tooHumid", 1); Metric distanceTooDry(MetricType::gauge, "distance_too_dry", "DHT22 comfort value distance to tooDry", 1, std::unordered_map<std::string, std::string>() ); Metric comfortStatus(MetricType::gauge, "comfort_status", "DHT22 comfort status value", 1, { {"state", ""}, }); Metric perceptionStatus(MetricType::gauge, "perception_status", "DHT22 perception status value", 1, { {"state", ""}, }); // value object struct MetricData { float temperature; float humidity; // relative // https://en.wikipedia.org/wiki/Humidity#Absolute_humidity float absHumidity; // https://en.wikipedia.org/wiki/Heat_index float heatIndex; // https://en.wikipedia.org/wiki/Dew_point float dewPoint; // comfort status data float distanceTooHot; float distanceTooCold; float distanceTooHumid; float distanceTooDry; bool too Hot; bool tooCold; bool tooHumid; bool tooDry; String comfortStatus; String perceptionStatus; }; // Metrics implements interaction with dht22 to create MetricData and exports to JSON/CSV/Prometheus class Metrics { private: MetricData md; public: MetricData getMetricsData() { return md; } void createMetricsData() { TempAndHumidity tah = dht.getTempAndHumidity(); md.temperature = tah.temperature; md.humidity = tah.humidity; md.absHumidity = dht.computeAbsoluteHumidity(tah.temperature, tah.humidity, false); // in "g/m3" md.heatIndex = dht.computeHeatIndex(tah.temperature, tah.humidity, false); md.dewPoint = dht.computeDewPoint(tah.temperature, tah.humidity, false); ComfortState cf; // if we want to support setting custom comfort ratio //float comfortRatio = dht.getComfortRatio( & amp;cf, tah.temperature, tah.humidity, false); md.comfortStatus = ComfortStatus(cf); ComfortProfile cp = dht.getComfortProfile(); md.tooHot = cp.isTooHot(tah.temperature, tah.humidity); md.tooCold = cp.isTooCold(tah.temperature, tah.humidity); md.tooHumid = cp.isTooHumid(tah.temperature, tah.humidity); md.tooDry = cp.isTooDry(tah.temperature, tah.humidity); md.distanceTooHot = cp.distanceTooHot(tah.temperature, tah.humidity); md.distanceTooCold = cp.distanceTooCold(tah.temperature, tah.humidity); md.distanceTooHumid = cp.distanceTooHumid(tah.temperature, tah.humidity); md.distanceTooDry = cp.distanceTooDry(tah.temperature, tah.humidity); PerceptionState ps = (PerceptionState) dht.computePerception(tah.temperature, tah.humidity, false); md.perceptionStatus = PerceptionStatusString(ps); } String ComfortStatus(ComfortState cf) { String comfortStatus; switch(cf) { case Comfort_OK: comfortStatus = "Comfort_OK"; break; case Comfort_TooHot: comfortStatus = "Comfort_TooHot"; break; case Comfort_TooCold: comfortStatus = "Comfort_TooCold"; break; case Comfort_TooDry: comfortStatus = "Comfort_TooDry"; break; case Comfort_TooHumid: comfortStatus = "Comfort_TooHumid"; break; case Comfort_HotAndHumid: comfortStatus = "Comfort_HotAndHumid"; break; case Comfort_HotAndDry: comfortStatus = "Comfort_HotAndDry"; break; case Comfort_ColdAndHumid: comfortStatus = "Comfort_ColdAndHumid"; break; case Comfort_ColdAndDry: comfortStatus = "Comfort_ColdAndDry"; break; default: comfortStatus = "Unknown:"; break; }; return comfortStatus; } String PerceptionStatusString(PerceptionState ps) { switch(ps) { case Perception_Dry: return "Perception_DRY"; case Perception_VeryComfy: return "Perception_VeryComfy"; case Perception_Comfy: return "Perception_Comfy"; case Perception_Ok: return "Perception_Ok"; case Perception_UnComfy: return "Perception_UnComfy"; case Perception_QuiteUnComfy: return "Perception_QuiteUnComfy"; case Perception_VeryUnComfy: return "Perception_VeryUnComfy"; case Perception_SevereUncomfy: return "Perception_SevereUncomfy"; default: return "Perception_Unknown"; } } String CSV() { return "temperature;humidity;absHumidity;heatIndex;dewPoint;ComfortStatus;tooHot;tooCold;tooHumid;tooDry;distTooHot;distTooCold;distTooHumid;distTooDry;perceptionState\\ " + String(md.temperature) + ";" + String(md.humidity) + ";" + String(md.absHumidity) + ";" + String(md. heatIndex) + ";" + String(md.dewPoint) + ";" + md.comfortStatus + ";" + String(md.tooHot) + ";" + String(md.tooCold) + ";" + String(md.tooHumid) + ";" + String(md.tooDry) + ";" + String(md.distanceTooHot) + ";" + String(md.distanceTooCold) + ";" + String(md.distanceTooHumid) + ";" + String(md.distanceTooDry) + ";" + md.perceptionStatus; } String JSON() { return "{\\ "temperature": " + String(md.temperature) + ",\\ "humidity": " + String(md.humidity) + ",\\ "absHumidity": " + String(md.absHumidity) + ",\\ "heatIndex": " + String(md.heatIndex) + ",\\ "dewPoint": " + String(md.dewPoint) + ",\\ "ComfortStatus": "" + md.comfortStatus + """ + ",\\ "tooHot": " + String(md.tooHot) + ",\\ "tooCold": " + String(md.tooCold) + ",\\ "tooHumid": " + String(md.tooHumid) + ",\\ "tooDry": " + String(md.tooDry) + ",\\ "distTooHot": " + String(md.distanceTooHot) + ",\\ "distTooCold": " + String(md.distanceTooCold) + ",\\ "distTooHumid": " + String(md.distanceTooHumid) + ",\\ "distTooDry": " + String(md.distanceTooDry) + ",\\ "perceptionState": "" + md.perceptionStatus + ""\\ }"; } String Prometheus() { temperature.setValue(md.temperature); humidity. setValue(md. humidity); absHumidity.setValue(md.absHumidity); heatIndex.setValue(md.heatIndex); dewPoint.setValue(md.dewPoint); tooHot. setValue(md. tooHot); tooCold.setValue(md.tooCold); tooDry. setValue(md. tooDry); tooHumid. setValue(md. tooHumid); distanceTooHot.setValue(md.distanceTooHot); distanceTooCold.setValue(md.distanceTooCold); distanceTooHumid.setValue(md.distanceTooHumid); distanceTooDry.setValue(md.distanceTooDry); comfortStatus. setValue(1, { {"state", md.comfortStatus.c_str()}, }); perceptionStatus. setValue(1, { {"state", md.perceptionStatus.c_str()}, }); return temperature. getString() + humidity. getString() + absHumidity. getString() + heatIndex. getString() + dewPoint. getString() + tooHot. getString() + tooCold. getString() + tooHumid. getString() + tooDry. getString() + distanceTooHot. getString() + distanceTooCold. getString() + distanceTooHumid. getString() + distanceTooDry. getString() + comfortStatus. getString() + perceptionStatus. getString(); } }; void setup() { Serial.begin(115200); WiFiMulti.addAP(SSID, PASSWORD); if (DEBUG) { Serial. println(); Serial. println(); Serial.print("Waiting for WiFi... "); } while(WiFiMulti. run() != WL_CONNECTED) { Serial.print("."); delay(500); } if (DEBUG) { Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } // DH22 // wake up DH22 sensor dht.setup(17, DHTesp::AM2302); if (DEBUG) { Serial.print("dht status: "); Serial.println(dht.getStatusString()); } delay(500); } void loop() { if (DEBUG) { Serial.print("Connecting to "); Serial. println(HOST); } // Use WiFiClient class to create TCP connections WiFiClient client; if (!client. connect(HOST, PORT)) { Serial.println("Connection failed."); Serial.println("Waiting 5 seconds before retrying..."); delay(5000); return; } Metrics m = Metrics(); m. createMetricsData(); MetricData md = m.getMetricsData(); String jsonData = m. JSON(); String csvData = m. CSV(); String prometheusData = m. Prometheus(); switch (SERIAL_OUTPUTTER) { case JSON: Serial. println(jsonData); break; case CSV: Serial. println(csvData); break; case PROMETHEUS: Serial.println(prometheusData); break; } switch (PUSH_DATA) { case JSON: client.print("POST /temperature HTTP/1.1\r\\ "); client.print("Content-Type: application/json\r\\ "); client.print("Content-Length: "); client.print(jsonData.length()); client.print("Host: "); client.print(HOST); client.print("\r\\ \r\\ "); client.print(jsonData); break; case CSV: client.print("POST /temperature HTTP/1.1\r\\ "); client.print("Content-Type: text/plain\r\\ "); client.print("Content-Length: "); client.print(csvData.length()); client.print("Host: "); client.print(HOST); client.print("\r\\ \r\\ "); client.print(csvData); break; case PROMETHEUS: client.print("POST /metrics/job/"); client. print(JOB); client.print("/instance/"); client. print(INSTANCE); client.print("HTTP/1.1\r\\ "); client.print("Content-Type: application/x-www-form-urlencoded\r\\ "); client.print("Content-Length: "); client.print(prometheusData.length()); client.print("\r\\ "); client.print("Host: "); client.print(HOST); client.print("\r\\ \r\\ "); client.print(prometheusData); break; } int maxloops = 0; // wait for the server's reply to become available while (!client.available() & amp; & amp; maxloops < 1000) { maxloops++; delay(1); //delay 1 msec } if (client. available() > 0) { while (client. available() > 0) { //read back one line from the server String line = client. readStringUntil('\r\\ '); if (DEBUG) { Serial.print("> "); Serial. println(line); } } } else { Serial.println("HTTP Response timeout from server"); } if (DEBUG) { Serial. println("Closing connection."); } client. stop(); if (DEBUG) { Serial.println("Waiting 5 seconds before restarting..."); } delay(5000); }
DHTesp.h
/********************************************** ********************* DHT Temperature & amp; Humidity Sensor library for Arduino & amp; ESP32. Features: - Support for DHT11 and DHT22/AM2302/RHT03 -Auto detect sensor model - Very low memory footprint -Very small code https://github.com/beegee-tokyo/arduino-DHTesp Written by Mark Ruys, [email protected]. Updated to work with ESP32 by Bernd Giesecke, [email protected] GNU General Public License, check LICENSE for more information. All text above must be included in any redistribution. Datasheets: - http://www.micro4you.com/files/sensor/DHT11.pdf - http://www.adafruit.com/datasheets/DHT22.pdf - http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Weather/RHT03.pdf - http://meteobox.tk/files/AM2302.pdf Changelog: See README.md ***************************************************** *****************/ #ifndef dhtesp_h #define dhtesp_h #if ARDUINO < 100 #include <WProgram.h> #else #include <Arduino.h> #endif // Reference: http://epb.apogee.net/res/refcomf.asp (References invalid) enum ComfortState { Comfort_OK = 0, Comfort_TooHot = 1, Comfort_TooCold = 2, Comfort_TooDry = 4, Comfort_TooHumid = 8, Comfort_HotAndHumid = 9, Comfort_HotAndDry = 5, Comfort_ColdAndHumid = 10, Comfort_ColdAndDry = 6 }; // References https://en.wikipedia.org/wiki/Dew_point ==> Relationship to human comfort enum PerceptionState { Perception_Dry = 0, Perception_VeryComfy = 1, Perception_Comfy = 2, Perception_Ok = 3, Perception_Uncomfy = 4, Perception_QuiteUncomfy = 5, Perception_VeryUncomfy = 6, Perception_SevereUncomfy = 7 }; struct TempAndHumidity { float temperature; float humidity; }; struct ComfortProfile { //Represent the 4 line equations: //dry, humid, hot, cold, using the y = mx + b formula float m_tooHot_m, m_tooHot_b; float m_tooCold_m, m_tooHCold_b; float m_tooDry_m, m_tooDry_b; float m_tooHumid_m, m_tooHumid_b; inline bool isTooHot(float temp, float humidity) {return (temp > (humidity * m_tooHot_m + m_tooHot_b));} inline bool isTooHumid(float temp, float humidity) {return (temp > (humidity * m_tooHumid_m + m_tooHumid_b));} inline bool isTooCold(float temp, float humidity) {return (temp < (humidity * m_tooCold_m + m_tooHCold_b));} inline bool isTooDry(float temp, float humidity) {return (temp < (humidity * m_tooDry_m + m_tooDry_b));} inline float distanceTooHot(float temp, float humidity) {return temp - (humidity * m_tooHot_m + m_tooHot_b);} inline float distanceTooHumid(float temp, float humidity) {return temp - (humidity * m_tooHumid_m + m_tooHumid_b);} inline float distanceTooCold(float temp, float humidity) {return (humidity * m_tooCold_m + m_tooHCold_b) - temp;} inline float distanceTooDry(float temp, float humidity) {return (humidity * m_tooDry_m + m_tooDry_b) - temp;} }; class DHTesp { public: typedef enum { AUTO_DETECT, DHT11, DHT22, AM2302, // Packaged DHT22 RHT03 // Equivalent to DHT22 } DHT_MODEL_t; typedef enum { ERROR_NONE = 0, ERROR_TIMEOUT, ERROR_CHECKSUM } DHT_ERROR_t; TempAndHumidity values; // setup(dhtPin) is deprecated, auto detection is not working well on ESP32. Use setup(dhtPin, DHTesp::DHT11) instead! void setup(uint8_t dhtPin) __attribute__((deprecated)); void setup(uint8_t pin, DHT_MODEL_t model=AUTO_DETECT); void resetTimer(); float getTemperature(); float getHumidity(); TempAndHumidity getTempAndHumidity(); DHT_ERROR_t getStatus() { return error; }; const char* getStatusString(); DHT_MODEL_t getModel() { return model; } int getMinimumSamplingPeriod() { return model == DHT11 ? 1000 : 2000; } int8_t getNumberOfDecimalsTemperature() { return model == DHT11 ? 0 : 1; }; int8_t getLowerBoundTemperature() { return model == DHT11 ? 0 : -40; }; int8_t getUpperBoundTemperature() { return model == DHT11 ? 50 : 125; }; int8_t getNumberOfDecimalsHumidity() { return 0; }; int8_t getLowerBoundHumidity() { return model == DHT11 ? 20 : 0; }; int8_t getUpperBoundHumidity() { return model == DHT11 ? 90 : 100; }; static float toFahrenheit(float from Celcius) { return 1.8 * from Celcius + 32.0; }; static float to Celsius(float from Fahrenheit) { return (from Fahrenheit - 32.0) / 1.8; }; float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=false); float computeDewPoint(float temperature, float percentHumidity, bool isFahrenheit=false); float getComfortRatio(ComfortState & destComfStatus, float temperature, float percentHumidity, bool isFahrenheit=false); ComfortProfile getComfortProfile() {return m_comfort;} void setComfortProfile(ComfortProfile & c) {m_comfort = c;} inline bool isTooHot(float temp, float humidity) {return m_comfort.isTooHot(temp, humidity);} inline bool isTooHumid(float temp, float humidity) {return m_comfort.isTooHumid(temp, humidity);} inline bool isTooCold(float temp, float humidity) {return m_comfort.isTooCold(temp, humidity);} inline bool isTooDry(float temp, float humidity) {return m_comfort.isTooDry(temp, humidity);} byte computePerception(float temperature, float percentHumidity, bool isFahrenheit=false); float computeAbsoluteHumidity(float temperature, float percentHumidity, bool isFahrenheit=false); uint8_t getPin() { return pin; } protected: void readSensor(); float temperature; float humidity; uint8_t pin; private: DHT_MODEL_t model; DHT_ERROR_t error; unsigned long lastReadTime; ComfortProfile m_comfort; }; #endif /*dhtesp_h*/