Code:
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
extern "C" {
#include "user_interface.h" //os_timer
}
// wenn aktiv: Meldungen per Serial
#define SERIAL
// wenn auskommentiert: delay()
// wenn aktiv: deep sleep nutzen (Hardwaremodifikation notwendig)
#define DEEP
//sekunden zwischen Aufwachvorgängen
#define WAIT 120
// WiFi Configuration
const char* cfg_wifi_ssid = "Cisco ASA 5585-X";
const char* cfg_wifi_password = "xx";
#define USE_VOLKSZAEHLER
const char* vz_url = "http://192.168.178.xx:8080/data/";
const char* vz_addcmd = ".json?operation=add&value=";
//For UUIDs: Use "" to skip this measurement
const char* vz_uuid_temp = "82adef20-951a-11e9-87ed-c194a10be6a4"; //Temperature (°C)
const char* vz_uuid_dew = "5d51be80-9520-11e9-a449-a1f56d6c2ddf"; //Dew point (°C)
const char* vz_uuid_hum = "a936add0-9520-11e9-a01f-b31470a72ea0"; //Absolute humidity (g/m3)
const char* vz_uuid_hum_r = "a1dec260-951a-11e9-b909-5777fcfa3e66"; //Relative humidity (%)
const char* vz_uuid_pres = "65738e60-951a-11e9-a1b4-83b43679b17a"; //Absolute atmospheric pressure
const char* vz_uuid_pres_r = "e972db80-9520-11e9-8294-47b6b4fea595"; //Relative atmospheric pressure (hPa @ sea level)
//periodic status reports
const unsigned int stats_interval = 60; // Update statistics and measure every 60 seconds
#define ALTITUDE 280 //Altitude of your location (m above sea level)
Adafruit_BME280 bme; // I2C
ESP8266WebServer server(80);
const float cToKOffset = 273.15;
float absoluteHumidity(float temperature, float humidity);
float saturationVaporPressure(float temperature);
float dewPoint(float temperature, float humidity);
os_timer_t Timer1;
bool sendStats = true;
WiFiClientSecure espClient;
void timerCallback(void *arg) {
sendStats = true;
}
uint8_t rssiToPercentage(int32_t rssi) {
//@author Marvin Roger - https://github.com/marvinroger/homie-esp8266/blob/ad876b2cd0aaddc7bc30f1c76bfc22cd815730d9/src/Homie/Utils/Helpers.cpp#L12
uint8_t quality;
if (rssi <= -100) {
quality = 0;
} else if (rssi >= -50) {
quality = 100;
} else {
quality = 2 * (rssi + 100);
}
return quality;
}
void ipToString(const IPAddress& ip, char * str) {
//@author Marvin Roger - https://github.com/marvinroger/homie-esp8266/blob/ad876b2cd0aaddc7bc30f1c76bfc22cd815730d9/src/Homie/Utils/Helpers.cpp#L82
snprintf(str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
}
#ifdef USE_VOLKSZAEHLER
bool sendVz(const char* uuid, float value) {
if (strlen(uuid) == 0) return true;
HTTPClient http;
bool ret = false;
String url = vz_url;
url += uuid;
url += vz_addcmd;
url += (String)value;
Serial.print(F("[vz] HTTP-Request: "));
Serial.print(url);
Serial.print(F(" -> "));
http.begin(url);
int httpCode = http.GET();
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
Serial.println(F("OK"));
ret = true;
} else {
Serial.print(F("ERR: "));
Serial.println(httpCode);
}
} else {
Serial.print(F("ERR: "));
Serial.println('0');
}
http.end();
return ret;
}
#endif
void sendStatsInterval(void) {
char buf[16]; //v4 only atm
ipToString(WiFi.localIP(), buf);
float temperature = bme.readTemperature();
float humidity_r = bme.readHumidity();
float humidity = absoluteHumidity(temperature, humidity_r);
float pressure = bme.readPressure() / 100.0F;
float pressure_r = bme.seaLevelForAltitude(ALTITUDE, pressure);
float dew = dewPoint(temperature, humidity_r);
Serial.print(F("T: "));
Serial.print((String)temperature);
Serial.print(F(" *C\nDP: "));
Serial.print((String)dew);
Serial.print(F(" *C\nH: "));
Serial.print((String)humidity_r);
Serial.print(F(" %\nAH: "));
Serial.print((String)humidity);
Serial.print(F(" g/m3\nRP: "));
Serial.print((String)pressure_r);
Serial.print(F(" hPa\nP: "));
Serial.print((String)pressure);
Serial.println(F(" hPa"));
Serial.flush();
yield();
#ifdef USE_VOLKSZAEHLER
sendVz(vz_uuid_temp, temperature);
sendVz(vz_uuid_dew, dew);
sendVz(vz_uuid_hum, humidity);
sendVz(vz_uuid_hum_r, humidity_r);
sendVz(vz_uuid_pres, pressure);
sendVz(vz_uuid_pres_r, pressure_r);
#endif
/*//Deepsleep
#ifdef DEEP
Serial.println("Going into deep sleep...");
ESP.deepSleep(1000000 * WAIT, WAKE_RF_DEFAULT);
//delay(00);
#else
//@todo disconnect WiFi to save power?
delay(1000 * WAIT);
#endif
// Deepsleep */
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print(F("Connecting to "));
Serial.println(cfg_wifi_ssid);
WiFi.mode(WIFI_STA); // Disable the built-in WiFi access point.
WiFi.begin(cfg_wifi_ssid, cfg_wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print('.');
}
Serial.println();
Serial.println(F("WiFi connected"));
Serial.println(F("IP address: "));
Serial.println(WiFi.localIP());
}
void handleRoot() {
float temperature = bme.readTemperature();
float humidity_r = bme.readHumidity();
float pressure = bme.readPressure() / 100.0F;
String out = "Temperature: ";
out += temperature;
out += "*C\nDew point: ";
out += dewPoint(temperature, humidity_r);
out += "*C\nRelative Humidity: ";
out += humidity_r;
out += "%\nAbsolute Humidity: ";
out += absoluteHumidity(temperature, humidity_r);
out += "g/m3\nRelative Pressure: ";
out += bme.seaLevelForAltitude(ALTITUDE, pressure);
out += "hPa\nAbsolute Pressure: ";
out += pressure;
out += "hPa";
server.send(200, "text/plain", out);
}
void handleOTA() {
server.send(200, "text/plain", "OTA START");
ArduinoOTA.begin();
unsigned long timeout = millis() + (120 * 1000); // Max 2 minutes
os_timer_disarm(&Timer1);
while (true) {
yield();
ArduinoOTA.handle();
if (millis() > timeout) break;
}
os_timer_arm(&Timer1, stats_interval * 1000, true);
return;
}
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}
void setup() {
Serial.begin(115200);
Serial.println(F("BME280 HTTP-POST,HTTP-SRV"));
bool status;
// default settings
// (you can also pass in a Wire library object like &Wire2)
status = bme.begin(0x76);
if (!status) {
Serial.println(F("Could not find a valid BME280 sensor, check wiring!"));
while (1);
}
if (MDNS.begin(((String)WiFi.macAddress()).c_str())) {
Serial.println(F("MDNS responder started"));
}
server.on("/", handleRoot);
server.on("/ota", handleOTA);
server.onNotFound(handleNotFound);
server.begin();
Serial.println(F("HTTP-SRV started"));
setup_wifi();
ArduinoOTA.setHostname(((String)WiFi.macAddress()).c_str());
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println(F("\nEnd"));
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println(F("Auth Failed"));
else if (error == OTA_BEGIN_ERROR) Serial.println(F("Begin Failed"));
else if (error == OTA_CONNECT_ERROR) Serial.println(F("Connect Failed"));
else if (error == OTA_RECEIVE_ERROR) Serial.println(F("Receive Failed"));
else if (error == OTA_END_ERROR) Serial.println(F("End Failed"));
});
// Send boot info
Serial.println(F("Announcing boot..."));
os_timer_setfn(&Timer1, timerCallback, (void *)0);
os_timer_arm(&Timer1, stats_interval * 1000, true);
}
void loop() {
server.handleClient();
if (sendStats) {
sendStatsInterval();
sendStats = false;
}
}
// Relative to absolute humidity
// Based on https://carnotcycle.wordpress.com/2012/08/04/how-to-convert-relative-humidity-to-absolute-humidity/
float absoluteHumidity(float temperature, float humidity) {
return (13.2471 * pow(EULER, 17.67 * temperature / (temperature + 243.5)) * humidity / (cToKOffset + temperature));
}
// Calculate saturation vapor pressure
// Based on dew.js, Copyright 2011 Wolfgang Kuehn, Apache License 2.0
float saturationVaporPressure(float temperature) {
if (temperature < 173 || temperature > 678) return -112; //Temperature out of range
float svp = 0;
if (temperature <= cToKOffset) {
/**
-100-0°C -> Saturation vapor pressure over ice
ITS-90 Formulations by Bob Hardy published in
"The Proceedings of the Third International
Symposium on Humidity & Moisture",
Teddington, London, England, April 1998
*/
svp = exp(-5.8666426e3 / temperature + 2.232870244e1 + (1.39387003e-2 + (-3.4262402e-5 + (2.7040955e-8 * temperature)) * temperature) * temperature + 6.7063522e-1 * log(temperature));
} else {
/**
0°C-400°C -> Saturation vapor pressure over water
IAPWS Industrial Formulation 1997
for the Thermodynamic Properties of Water and Steam
by IAPWS (International Association for the Properties
of Water and Steam), Erlangen, Germany, September 1997.
Equation 30 in Section 8.1 "The Saturation-Pressure
Equation (Basic Equation)"
*/
const float th = temperature + -0.23855557567849 / (temperature - 0.65017534844798e3);
const float a = (th + 0.11670521452767e4) * th + -0.72421316703206e6;
const float b = (-0.17073846940092e2 * th + 0.12020824702470e5) * th + -0.32325550322333e7;
const float c = (0.14915108613530e2 * th + -0.48232657361591e4) * th + 0.40511340542057e6;
svp = 2 * c / (-b + sqrt(b * b - 4 * a * c));
svp *= svp;
svp *= svp;
svp *= 1e6;
}
yield();
return svp;
}
// Calculate dew point in °C
// Based on dew.js, Copyright 2011 Wolfgang Kuehn, Apache License 2.0
float dewPoint(float temperature, float humidity)
{
temperature += cToKOffset; //Celsius to Kelvin
if (humidity < 0 || humidity > 100) return -111; //Invalid humidity
if (temperature < 173 || temperature > 678) return -112; //Temperature out of range
humidity = humidity / 100 * saturationVaporPressure(temperature);
byte mc = 10;
float xNew;
float dx;
float z;
do {
dx = temperature / 1000;
z = saturationVaporPressure(temperature);
xNew = temperature + dx * (humidity - z) / (saturationVaporPressure(temperature + dx) - z);
if (abs((xNew - temperature) / xNew) < 0.0001) {
return xNew - cToKOffset;
}
temperature = xNew;
mc--;
} while (mc > 0);
return -113; //Solver did not get a close result
}
Lesezeichen