186 lines
4.3 KiB
C++
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();
|
|
}
|