72 lines
2.4 KiB
C++
72 lines
2.4 KiB
C++
#pragma once
|
|
|
|
#include "esphome/core/component.h"
|
|
#include "esphome/core/helpers.h"
|
|
#include "esphome/components/sensor/sensor.h"
|
|
#include "esphome/components/web_server_base/web_server_base.h"
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <string>
|
|
|
|
namespace esphome::air_quality_web {
|
|
|
|
// Separate IDF listener: do not use WebServerBase or its global instance/headers.
|
|
// The stock begin() has a shared control port and generic POST body processing.
|
|
class AirQualityServer : public AsyncWebServer {
|
|
public:
|
|
AirQualityServer() : AsyncWebServer(8080) {}
|
|
void set_port(uint16_t port) { this->port_ = port; }
|
|
esp_err_t start(esp_err_t (*handler)(httpd_req_t *), void *context);
|
|
};
|
|
|
|
class AirQualityWeb : public PollingComponent {
|
|
public:
|
|
AirQualityWeb() : PollingComponent(1000) {}
|
|
void set_port(uint16_t port) { this->server_.set_port(port); }
|
|
void set_mdns_hostname(const std::string &hostname) { this->mdns_hostname_ = hostname; }
|
|
void set_co2_sensor(sensor::Sensor *value) { this->co2_ = value; }
|
|
void set_temperature_sensor(sensor::Sensor *value) { this->temperature_ = value; }
|
|
void set_humidity_sensor(sensor::Sensor *value) { this->humidity_ = value; }
|
|
void setup() override;
|
|
void update() override;
|
|
void on_shutdown() override { this->server_.end(); }
|
|
float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION - 1.0f; }
|
|
|
|
protected:
|
|
static esp_err_t handle_request_(httpd_req_t *request);
|
|
std::string snapshot_();
|
|
esp_err_t send_history_(httpd_req_t *request);
|
|
|
|
static constexpr uint32_t HISTORY_DURATION_MS = 36000000;
|
|
static constexpr uint32_t HISTORY_INTERVAL_MS = 60000;
|
|
static constexpr size_t HISTORY_CAPACITY = 601;
|
|
struct HistorySample {
|
|
uint32_t timestamp;
|
|
float co2;
|
|
float temperature;
|
|
float humidity;
|
|
};
|
|
static_assert(sizeof(HistorySample) == 16, "History samples must remain compact");
|
|
struct HistorySnapshot {
|
|
uint32_t timestamp;
|
|
size_t count;
|
|
HistorySample samples[HISTORY_CAPACITY];
|
|
};
|
|
|
|
AirQualityServer server_;
|
|
std::string mdns_hostname_;
|
|
sensor::Sensor *co2_{nullptr};
|
|
sensor::Sensor *temperature_{nullptr};
|
|
sensor::Sensor *humidity_{nullptr};
|
|
Mutex snapshot_mutex_;
|
|
HistorySample history_[HISTORY_CAPACITY]{};
|
|
size_t history_head_{0};
|
|
size_t history_count_{0};
|
|
uint32_t last_sample_ms_{0};
|
|
bool has_sample_{false};
|
|
std::string json_{"{\"co2\":null,\"temperature\":null,\"humidity\":null}"};
|
|
};
|
|
|
|
} // namespace esphome::air_quality_web
|