ESP8266WeatherStation/src/main.cpp

186 lines
4.3 KiB
C++

#include <sstream>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <LittleFS.h>
#include <Adafruit_BME680.h>
#include <ESP8266WebServer.h>
#include "Config.h"
#define ENDLESS_LOOP() while(true) { delay(100); }
#define BME680_UPDATE_INTERVAL 10000 // milliseconds
ESP8266WiFiMulti wiFiMulti;
ESP8266WebServer httpServer(80);
Adafruit_BME680 bme680;
unsigned long bme680LastReadingTime;
unsigned long bme680ReadingDuration;
String bme680_json_cache;
void httpHandleIndex(void)
{
httpServer.send(200, F("application/json"), bme680_json_cache);
}
void httpHandle404(void)
{
httpServer.send(404, F("text/plain"), F("This is not the page you are looking for."));
}
void wifi_setup(void)
{
Serial.println(F("Trying to connect..."));
//WiFi.setHostname(F("mlmini");
bool led_on = true;
for(size_t tries = 0; tries < 300; tries++)
{
if(wiFiMulti.run() == WL_CONNECTED) {
Serial.println(F(""));
Serial.println(F("WiFi connected"));
Serial.println(F("IP address: "));
Serial.println(WiFi.localIP());
break;
}
led_on = !led_on;
digitalWrite(LED_BUILTIN, led_on);
delay(100);
Serial.print(F("."));
}
if(WiFi.status() != WL_CONNECTED) {
Serial.println(F("Connection failed, setting up access point..."));
IPAddress apIP(192, 168, 42, 1);
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(F("☀️🌧️🌩️"), F("How'sTheWeather?"));
WiFi.enableAP(true);
digitalWrite(LED_BUILTIN, false); // LED ON (active low)
} else {
digitalWrite(LED_BUILTIN, true); // LED OFF (active low)
}
}
void bme680_setup(void)
{
if(!bme680.begin()) {
Serial.println(F("Could not initialize BME680 sensor!"));
ENDLESS_LOOP();
}
// Set up oversampling and filter initialization
bme680.setTemperatureOversampling(BME680_OS_8X);
bme680.setHumidityOversampling(BME680_OS_2X);
bme680.setPressureOversampling(BME680_OS_4X);
bme680.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme680.setGasHeater(320, 150); // 320*C for 150 ms
}
void httpserver_setup()
{
httpServer.on("/", httpHandleIndex);
httpServer.onNotFound(httpHandle404);
httpServer.begin();
}
void setup()
{
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println(F("Hello World!"));
if(!LittleFS.begin()) {
Serial.println(F("LittleFS setup failed!"));
ENDLESS_LOOP();
}
bme680_setup();
Config::instance().load();
// Connect the WiFi network (or start an AP if that doesn't work)
for (auto &net : Config::instance().getWLANList())
{
Serial.print(F("Adding network "));
Serial.println(net.ssid.c_str());
wiFiMulti.addAP(net.ssid.c_str(), net.password.c_str());
}
wifi_setup();
httpserver_setup();
bme680LastReadingTime = millis() + 10000;
bme680ReadingDuration = 0;
bme680_json_cache = F("{}");
}
void update_bme680_json(void)
{
std::ostringstream oss;
oss << "{\n";
oss << "\"temperature\": {\"value\": " << bme680.temperature << ", \"unit\": \"°C\"},\n";
oss << "\"pressure\": {\"value\": " << (bme680.pressure / 100.0) << ", \"unit\": \"hPa\"},\n";
oss << "\"humidity\": {\"value\": " << bme680.humidity << ", \"unit\": \"%rH\"},\n";
oss << "\"gas_resistance\": {\"value\": " << bme680.gas_resistance << ", \"unit\": \"Ohm\"},\n";
oss << "\"generated_at_millis\": " << millis() << "\n";
oss << "}";
bme680_json_cache = oss.str().c_str();
}
void loop() {
unsigned long now = millis();
if((now - bme680LastReadingTime) >= BME680_UPDATE_INTERVAL) {
// Tell BME680 to begin measurement.
bme680ReadingDuration = bme680.beginReading();
if (bme680ReadingDuration == 0) {
Serial.println(F("Failed to begin BME680 reading :(F("));
return;
}
bme680LastReadingTime = now;
bme680ReadingDuration -= now; // so far, the "duration" contained the absolute end time. Make it relative to the current timestamp
}
if((bme680ReadingDuration != 0) && ((millis() - bme680LastReadingTime) >= bme680ReadingDuration)) {
if(!bme680.endReading()) {
Serial.println(F("Could not finalize BME680 reading."));
} else {
// reading is good
update_bme680_json();
}
bme680ReadingDuration = 0;
}
// TODO: do something else?
httpServer.handleClient();
}