mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-07-24 14:07:16 +02:00
clarifying method/variable/class names
This commit is contained in:
@ -15,7 +15,6 @@ https://www.airgradient.com/documentation/diy-v4/
|
||||
Following libraries need to be installed:
|
||||
“WifiManager by tzapu, tablatronix” tested with version 2.0.16-rc.2
|
||||
"Arduino_JSON" by Arduino version 0.2.0
|
||||
"U8g2" by oliver version 2.34.22
|
||||
|
||||
Please make sure you have esp8266 board manager installed. Tested with
|
||||
version 3.1.2.
|
||||
@ -32,15 +31,15 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
|
||||
|
||||
*/
|
||||
|
||||
#include <AirGradient.h>
|
||||
#include "AgSchedule.h"
|
||||
#include "AgConfigure.h"
|
||||
#include "AgApiClient.h"
|
||||
#include "AgConfigure.h"
|
||||
#include "AgSchedule.h"
|
||||
#include "AgWiFiConnector.h"
|
||||
#include <AirGradient.h>
|
||||
#include <Arduino_JSON.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiManager.h>
|
||||
|
||||
#define WIFI_CONNECT_COUNTDOWN_MAX 180 /** sec */
|
||||
#define WIFI_CONNECT_RETRY_MS 10000 /** ms */
|
||||
@ -61,20 +60,19 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
|
||||
|
||||
/** Create airgradient instance for 'DIY_BASIC' board */
|
||||
static AirGradient ag = AirGradient(DIY_BASIC);
|
||||
static AgConfigure localConfig(Serial);
|
||||
static AgApiClient apiClient(Serial, localConfig);
|
||||
static Configuration configuration(Serial);
|
||||
static AgApiClient apiClient(Serial, configuration);
|
||||
static WifiConnector wifiConnector(Serial);
|
||||
|
||||
static int co2Ppm = -1;
|
||||
static int pm25 = -1;
|
||||
static float temp = -1001;
|
||||
static int hum = -1;
|
||||
static long val;
|
||||
static String wifiSSID = "";
|
||||
static bool wifiHasConfig = false; /** */
|
||||
|
||||
static void boardInit(void);
|
||||
static void failedHandler(String msg);
|
||||
static void co2Calibration(void);
|
||||
static void executeCo2Calibration(void);
|
||||
static void updateServerConfiguration(void);
|
||||
static void co2Update(void);
|
||||
static void pmUpdate(void);
|
||||
@ -82,7 +80,6 @@ static void tempHumUpdate(void);
|
||||
static void sendDataToServer(void);
|
||||
static void dispHandler(void);
|
||||
static String getDevId(void);
|
||||
static void updateWiFiConnect(void);
|
||||
static void showNr(void);
|
||||
|
||||
bool hasSensorS8 = true;
|
||||
@ -112,23 +109,24 @@ void setup() {
|
||||
/** Init AirGradient server */
|
||||
apiClient.begin();
|
||||
apiClient.setAirGradient(&ag);
|
||||
wifiConnector.setAirGradient(&ag);
|
||||
|
||||
/** Show boot display */
|
||||
displayShowText("DIY basic", "Lib:" + ag.getVersion(), "");
|
||||
delay(2000);
|
||||
|
||||
/** WiFi connect */
|
||||
connectToWifi();
|
||||
// connectToWifi();
|
||||
if (wifiConnector.connect()) {
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
wifiHasConfig = true;
|
||||
sendPing();
|
||||
sendDataToAg();
|
||||
|
||||
apiClient.fetchServerConfiguration();
|
||||
if (localConfig.isCo2CalibrationRequested()) {
|
||||
co2Calibration();
|
||||
if (configuration.isCo2CalibrationRequested()) {
|
||||
executeCo2Calibration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Show serial number display */
|
||||
ag.display.clear();
|
||||
ag.display.setCursor(1, 1);
|
||||
@ -162,13 +160,13 @@ void loop() {
|
||||
tempHumSchedule.run();
|
||||
}
|
||||
|
||||
updateWiFiConnect();
|
||||
wifiConnector.handle();
|
||||
|
||||
/** Read PMS on loop */
|
||||
ag.pms5003.handle();
|
||||
}
|
||||
|
||||
static void sendPing() {
|
||||
static void sendDataToAg() {
|
||||
JSONVar root;
|
||||
root["wifi"] = WiFi.RSSI();
|
||||
root["boot"] = 0;
|
||||
@ -197,39 +195,6 @@ void displayShowText(String ln1, String ln2, String ln3) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// Wifi Manager
|
||||
void connectToWifi() {
|
||||
WiFiManager wifiManager;
|
||||
wifiSSID = "AG-" + String(ESP.getChipId(), HEX);
|
||||
wifiManager.setConfigPortalBlocking(false);
|
||||
wifiManager.setConfigPortalTimeout(WIFI_CONNECT_COUNTDOWN_MAX);
|
||||
wifiManager.autoConnect(wifiSSID.c_str(), WIFI_HOTSPOT_PASSWORD_DEFAULT);
|
||||
|
||||
uint32_t lastTime = millis();
|
||||
int count = WIFI_CONNECT_COUNTDOWN_MAX;
|
||||
displayShowText(String(WIFI_CONNECT_COUNTDOWN_MAX) + " sec",
|
||||
"SSID:", wifiSSID);
|
||||
while (wifiManager.getConfigPortalActive()) {
|
||||
wifiManager.process();
|
||||
uint32_t ms = (uint32_t)(millis() - lastTime);
|
||||
if (ms >= 1000) {
|
||||
lastTime = millis();
|
||||
displayShowText(String(count) + " sec", "SSID:", wifiSSID);
|
||||
count--;
|
||||
|
||||
// Timeout
|
||||
if (count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!WiFi.isConnected()) {
|
||||
displayShowText("Booting", "offline", "mode");
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(DISPLAY_DELAY_SHOW_CONTENT_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static void boardInit(void) {
|
||||
/** Init SHT sensor */
|
||||
if (ag.sht.begin(Wire) == false) {
|
||||
@ -264,7 +229,7 @@ static void failedHandler(String msg) {
|
||||
}
|
||||
}
|
||||
|
||||
static void co2Calibration(void) {
|
||||
static void executeCo2Calibration(void) {
|
||||
/** Count down for co2CalibCountdown secs */
|
||||
for (int i = 0; i < SENSOR_CO2_CALIB_COUNTDOWN_MAX; i++) {
|
||||
displayShowText("CO2 calib", "after",
|
||||
@ -291,25 +256,25 @@ static void co2Calibration(void) {
|
||||
|
||||
static void updateServerConfiguration(void) {
|
||||
if (apiClient.fetchServerConfiguration()) {
|
||||
if (localConfig.isCo2CalibrationRequested()) {
|
||||
if (configuration.isCo2CalibrationRequested()) {
|
||||
if (hasSensorS8) {
|
||||
co2Calibration();
|
||||
executeCo2Calibration();
|
||||
} else {
|
||||
Serial.println("CO2 S8 not available, calib ignored");
|
||||
}
|
||||
}
|
||||
if (localConfig.getCO2CalirationAbcDays() > 0) {
|
||||
if (configuration.getCO2CalibrationAbcDays() > 0) {
|
||||
if (hasSensorS8) {
|
||||
int newHour = localConfig.getCO2CalirationAbcDays() * 24;
|
||||
int newHour = configuration.getCO2CalibrationAbcDays() * 24;
|
||||
Serial.printf("abcDays config: %d days(%d hours)\r\n",
|
||||
localConfig.getCO2CalirationAbcDays(), newHour);
|
||||
configuration.getCO2CalibrationAbcDays(), newHour);
|
||||
int curHour = ag.s8.getAbcPeriod();
|
||||
Serial.printf("Current config: %d (hours)\r\n", curHour);
|
||||
if (curHour == newHour) {
|
||||
Serial.println("set 'abcDays' ignored");
|
||||
} else {
|
||||
if (ag.s8.setAbcPeriod(localConfig.getCO2CalirationAbcDays() * 24) ==
|
||||
false) {
|
||||
if (ag.s8.setAbcPeriod(configuration.getCO2CalibrationAbcDays() *
|
||||
24) == false) {
|
||||
Serial.println("Set S8 abcDays period calib failed");
|
||||
} else {
|
||||
Serial.println("Set S8 abcDays period calib success");
|
||||
@ -388,7 +353,7 @@ static void dispHandler() {
|
||||
String ln2 = "";
|
||||
String ln3 = "";
|
||||
|
||||
if (localConfig.isPmStandardInUSAQI()) {
|
||||
if (configuration.isPmStandardInUSAQI()) {
|
||||
if (pm25 < 0) {
|
||||
ln1 = "AQI: -";
|
||||
} else {
|
||||
@ -415,7 +380,7 @@ static void dispHandler() {
|
||||
|
||||
String _temp = "-";
|
||||
|
||||
if (localConfig.isTemperatureUnitInF()) {
|
||||
if (configuration.isTemperatureUnitInF()) {
|
||||
if (temp > -1001) {
|
||||
_temp = String((temp * 9 / 5) + 32).substring(0, 4);
|
||||
}
|
||||
@ -431,27 +396,6 @@ static void dispHandler() {
|
||||
|
||||
static String getDevId(void) { return getNormalizedMac(); }
|
||||
|
||||
/**
|
||||
* @brief WiFi reconnect handler
|
||||
*/
|
||||
static void updateWiFiConnect(void) {
|
||||
static uint32_t lastRetry;
|
||||
if (wifiHasConfig == false) {
|
||||
return;
|
||||
}
|
||||
if (WiFi.isConnected()) {
|
||||
lastRetry = millis();
|
||||
return;
|
||||
}
|
||||
uint32_t ms = (uint32_t)(millis() - lastRetry);
|
||||
if (ms >= WIFI_CONNECT_RETRY_MS) {
|
||||
lastRetry = millis();
|
||||
WiFi.reconnect();
|
||||
|
||||
Serial.printf("Re-Connect WiFi\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void showNr(void) {
|
||||
Serial.println();
|
||||
Serial.println("Serial nr: " + getDevId());
|
||||
|
68
examples/OneOpenAir/LocalServer.cpp
Normal file
68
examples/OneOpenAir/LocalServer.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include "LocalServer.h"
|
||||
|
||||
LocalServer::LocalServer(Stream &log, OpenMetrics &openMetrics,
|
||||
Measurements &measure, Configuration &config,
|
||||
WifiConnector &wifiConnector)
|
||||
: PrintLog(log, "LocalServer"), openMetrics(openMetrics), measure(measure),
|
||||
config(config), wifiConnector(wifiConnector) {}
|
||||
|
||||
LocalServer::~LocalServer() {}
|
||||
|
||||
bool LocalServer::begin(void) {
|
||||
server.on("/measures/current", HTTP_GET, [this]() { _GET_measure(); });
|
||||
server.on(openMetrics.getApi(), HTTP_GET, [this]() { _GET_metrics(); });
|
||||
server.on("/config", HTTP_GET, [this]() { _GET_config(); });
|
||||
server.on("/config", HTTP_PUT, [this]() { _PUT_config(); });
|
||||
server.begin();
|
||||
|
||||
if (xTaskCreate(
|
||||
[](void *param) {
|
||||
LocalServer *localServer = (LocalServer *)param;
|
||||
for (;;) {
|
||||
localServer->_handle();
|
||||
}
|
||||
},
|
||||
"webserver", 1024 * 4, this, 5, NULL) != pdTRUE) {
|
||||
Serial.println("Create task handle webserver failed");
|
||||
}
|
||||
logInfo("Init: " + getHostname() + ".local");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LocalServer::setAirGraident(AirGradient *ag) { this->ag = ag; }
|
||||
|
||||
String LocalServer::getHostname(void) {
|
||||
return "airgradient_" + ag->deviceId();
|
||||
}
|
||||
|
||||
void LocalServer::_handle(void) { server.handleClient(); }
|
||||
|
||||
void LocalServer::_GET_config(void) {
|
||||
server.send(200, "application/json", config.toString());
|
||||
}
|
||||
|
||||
void LocalServer::_PUT_config(void) {
|
||||
String data = server.arg(0);
|
||||
String response = "";
|
||||
int statusCode = 400; // Status code for data invalid
|
||||
if (config.parse(data, true)) {
|
||||
statusCode = 200;
|
||||
response = "Success";
|
||||
} else {
|
||||
response = "Set for cloud configuration. Local configuration ignored";
|
||||
}
|
||||
server.send(statusCode, "text/plain", response);
|
||||
}
|
||||
|
||||
void LocalServer::_GET_metrics(void) {
|
||||
server.send(200, openMetrics.getApiContentType(), openMetrics.getPayload());
|
||||
}
|
||||
|
||||
void LocalServer::_GET_measure(void) {
|
||||
server.send(
|
||||
200, "application/json",
|
||||
measure.toString(true, fwMode, wifiConnector.RSSI(), ag, &config));
|
||||
}
|
||||
|
||||
void LocalServer::setFwMode(AgFirmwareMode fwMode) { this->fwMode = fwMode; }
|
38
examples/OneOpenAir/LocalServer.h
Normal file
38
examples/OneOpenAir/LocalServer.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef _LOCAL_SERVER_H_
|
||||
#define _LOCAL_SERVER_H_
|
||||
|
||||
#include "AgConfigure.h"
|
||||
#include "AgValue.h"
|
||||
#include "AirGradient.h"
|
||||
#include "OpenMetrics.h"
|
||||
#include "AgWiFiConnector.h"
|
||||
#include <Arduino.h>
|
||||
#include <WebServer.h>
|
||||
|
||||
class LocalServer : public PrintLog {
|
||||
private:
|
||||
AirGradient *ag;
|
||||
OpenMetrics &openMetrics;
|
||||
Measurements &measure;
|
||||
Configuration &config;
|
||||
WifiConnector &wifiConnector;
|
||||
WebServer server;
|
||||
AgFirmwareMode fwMode;
|
||||
|
||||
public:
|
||||
LocalServer(Stream &log, OpenMetrics &openMetrics, Measurements &measure,
|
||||
Configuration &config, WifiConnector& wifiConnector);
|
||||
~LocalServer();
|
||||
|
||||
bool begin(void);
|
||||
void setAirGraident(AirGradient *ag);
|
||||
String getHostname(void);
|
||||
void setFwMode(AgFirmwareMode fwMode);
|
||||
void _handle(void);
|
||||
void _GET_config(void);
|
||||
void _PUT_config(void);
|
||||
void _GET_metrics(void);
|
||||
void _GET_measure(void);
|
||||
};
|
||||
|
||||
#endif /** _LOCAL_SERVER_H_ */
|
File diff suppressed because it is too large
Load Diff
186
examples/OneOpenAir/OpenMetrics.cpp
Normal file
186
examples/OneOpenAir/OpenMetrics.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
#include "OpenMetrics.h"
|
||||
|
||||
OpenMetrics::OpenMetrics(Measurements &measure, Configuration &config,
|
||||
WifiConnector &wifiConnector, AgApiClient &apiClient)
|
||||
: measure(measure), config(config), wifiConnector(wifiConnector),
|
||||
apiClient(apiClient) {}
|
||||
|
||||
OpenMetrics::~OpenMetrics() {}
|
||||
|
||||
void OpenMetrics::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
|
||||
const char *OpenMetrics::getApiContentType(void) {
|
||||
return "application/openmetrics-text; version=1.0.0; charset=utf-8";
|
||||
}
|
||||
|
||||
const char *OpenMetrics::getApi(void) { return "/metrics"; }
|
||||
|
||||
String OpenMetrics::getPayload(void) {
|
||||
String response;
|
||||
String current_metric_name;
|
||||
const auto add_metric = [&](const String &name, const String &help,
|
||||
const String &type, const String &unit = "") {
|
||||
current_metric_name = "airgradient_" + name;
|
||||
if (!unit.isEmpty())
|
||||
current_metric_name += "_" + unit;
|
||||
response += "# HELP " + current_metric_name + " " + help + "\n";
|
||||
response += "# TYPE " + current_metric_name + " " + type + "\n";
|
||||
if (!unit.isEmpty())
|
||||
response += "# UNIT " + current_metric_name + " " + unit + "\n";
|
||||
};
|
||||
const auto add_metric_point = [&](const String &labels, const String &value) {
|
||||
response += current_metric_name + "{" + labels + "} " + value + "\n";
|
||||
};
|
||||
|
||||
add_metric("info", "AirGradient device information", "info");
|
||||
add_metric_point("airgradient_serial_number=\"" + ag->deviceId() +
|
||||
"\",airgradient_device_type=\"" + ag->getBoardName() +
|
||||
"\",airgradient_library_version=\"" + ag->getVersion() +
|
||||
"\"",
|
||||
"1");
|
||||
|
||||
add_metric("config_ok",
|
||||
"1 if the AirGradient device was able to successfully fetch its "
|
||||
"configuration from the server",
|
||||
"gauge");
|
||||
add_metric_point("", apiClient.isFetchConfigureFailed() ? "0" : "1");
|
||||
|
||||
add_metric(
|
||||
"post_ok",
|
||||
"1 if the AirGradient device was able to successfully send to the server",
|
||||
"gauge");
|
||||
add_metric_point("", apiClient.isPostToServerFailed() ? "0" : "1");
|
||||
|
||||
add_metric(
|
||||
"wifi_rssi",
|
||||
"WiFi signal strength from the AirGradient device perspective, in dBm",
|
||||
"gauge", "dbm");
|
||||
add_metric_point("", String(wifiConnector.RSSI()));
|
||||
|
||||
if (config.hasSensorS8 && measure.CO2 >= 0) {
|
||||
add_metric("co2",
|
||||
"Carbon dioxide concentration as measured by the AirGradient S8 "
|
||||
"sensor, in parts per million",
|
||||
"gauge", "ppm");
|
||||
add_metric_point("", String(measure.CO2));
|
||||
}
|
||||
|
||||
float _temp = -1001;
|
||||
float _hum = -1;
|
||||
int pm01 = -1;
|
||||
int pm25 = -1;
|
||||
int pm10 = -1;
|
||||
int pm03PCount = -1;
|
||||
if (config.hasSensorPMS1 && config.hasSensorPMS2) {
|
||||
_temp = (measure.temp_1 + measure.temp_2) / 2.0f;
|
||||
_hum = (measure.hum_1 + measure.hum_2) / 2.0f;
|
||||
pm01 = (measure.pm01_1 + measure.pm01_2) / 2;
|
||||
pm25 = (measure.pm25_1 + measure.pm25_2) / 2;
|
||||
pm10 = (measure.pm10_1 + measure.pm10_2) / 2;
|
||||
pm03PCount = (measure.pm03PCount_1 + measure.pm03PCount_2) / 2;
|
||||
} else {
|
||||
if (ag->isOne()) {
|
||||
if (config.hasSensorSHT) {
|
||||
_temp = measure.Temperature;
|
||||
_hum = measure.Humidity;
|
||||
}
|
||||
} else {
|
||||
if (config.hasSensorPMS1) {
|
||||
_temp = measure.temp_1;
|
||||
_hum = measure.hum_1;
|
||||
pm01 = measure.pm01_1;
|
||||
pm25 = measure.pm25_1;
|
||||
pm10 = measure.pm10_1;
|
||||
pm03PCount = measure.pm03PCount_1;
|
||||
}
|
||||
if (config.hasSensorPMS2) {
|
||||
_temp = measure.temp_2;
|
||||
_hum = measure.hum_2;
|
||||
pm01 = measure.pm01_2;
|
||||
pm25 = measure.pm25_2;
|
||||
pm10 = measure.pm10_2;
|
||||
pm03PCount = measure.pm03PCount_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.hasSensorPMS1 || config.hasSensorPMS2) {
|
||||
if (pm01 >= 0) {
|
||||
add_metric("pm1",
|
||||
"PM1.0 concentration as measured by the AirGradient PMS "
|
||||
"sensor, in micrograms per cubic meter",
|
||||
"gauge", "ugm3");
|
||||
add_metric_point("", String(pm01));
|
||||
}
|
||||
if (pm25 >= 0) {
|
||||
add_metric("pm2d5",
|
||||
"PM2.5 concentration as measured by the AirGradient PMS "
|
||||
"sensor, in micrograms per cubic meter",
|
||||
"gauge", "ugm3");
|
||||
add_metric_point("", String(pm25));
|
||||
}
|
||||
if (pm10 >= 0) {
|
||||
add_metric("pm10",
|
||||
"PM10 concentration as measured by the AirGradient PMS "
|
||||
"sensor, in micrograms per cubic meter",
|
||||
"gauge", "ugm3");
|
||||
add_metric_point("", String(pm10));
|
||||
}
|
||||
if (pm03PCount >= 0) {
|
||||
add_metric("pm0d3",
|
||||
"PM0.3 concentration as measured by the AirGradient PMS "
|
||||
"sensor, in number of particules per 100 milliliters",
|
||||
"gauge", "p100ml");
|
||||
add_metric_point("", String(pm03PCount));
|
||||
}
|
||||
}
|
||||
|
||||
if (config.hasSensorSGP) {
|
||||
if (measure.TVOC >= 0) {
|
||||
add_metric("tvoc_index",
|
||||
"The processed Total Volatile Organic Compounds (TVOC) index "
|
||||
"as measured by the AirGradient SGP sensor",
|
||||
"gauge");
|
||||
add_metric_point("", String(measure.TVOC));
|
||||
}
|
||||
if (measure.TVOCRaw >= 0) {
|
||||
add_metric("tvoc_raw",
|
||||
"The raw input value to the Total Volatile Organic Compounds "
|
||||
"(TVOC) index as measured by the AirGradient SGP sensor",
|
||||
"gauge");
|
||||
add_metric_point("", String(measure.TVOCRaw));
|
||||
}
|
||||
if (measure.NOx >= 0) {
|
||||
add_metric("nox_index",
|
||||
"The processed Nitrous Oxide (NOx) index as measured by the "
|
||||
"AirGradient SGP sensor",
|
||||
"gauge");
|
||||
add_metric_point("", String(measure.NOx));
|
||||
}
|
||||
if (measure.NOxRaw >= 0) {
|
||||
add_metric("nox_raw",
|
||||
"The raw input value to the Nitrous Oxide (NOx) index as "
|
||||
"measured by the AirGradient SGP sensor",
|
||||
"gauge");
|
||||
add_metric_point("", String(measure.NOxRaw));
|
||||
}
|
||||
}
|
||||
|
||||
if (_temp > -1001) {
|
||||
add_metric("temperature",
|
||||
"The ambient temperature as measured by the AirGradient SHT "
|
||||
"sensor, in degrees Celsius",
|
||||
"gauge", "celsius");
|
||||
add_metric_point("", String(_temp));
|
||||
}
|
||||
if (_hum >= 0) {
|
||||
add_metric(
|
||||
"humidity",
|
||||
"The relative humidity as measured by the AirGradient SHT sensor",
|
||||
"gauge", "percent");
|
||||
add_metric_point("", String(_hum));
|
||||
}
|
||||
|
||||
response += "# EOF\n";
|
||||
return response;
|
||||
}
|
28
examples/OneOpenAir/OpenMetrics.h
Normal file
28
examples/OneOpenAir/OpenMetrics.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef _OPEN_METRICS_H_
|
||||
#define _OPEN_METRICS_H_
|
||||
|
||||
#include "AgConfigure.h"
|
||||
#include "AgValue.h"
|
||||
#include "AgWiFiConnector.h"
|
||||
#include "AirGradient.h"
|
||||
#include "AgApiClient.h"
|
||||
|
||||
class OpenMetrics{
|
||||
private:
|
||||
AirGradient *ag;
|
||||
Measurements &measure;
|
||||
Configuration &config;
|
||||
WifiConnector &wifiConnector;
|
||||
AgApiClient &apiClient;
|
||||
|
||||
public:
|
||||
OpenMetrics(Measurements &measure, Configuration &conig,
|
||||
WifiConnector &wifiConnector, AgApiClient& apiClient);
|
||||
~OpenMetrics();
|
||||
void setAirGradient(AirGradient *ag);
|
||||
const char *getApiContentType(void);
|
||||
const char* getApi(void);
|
||||
String getPayload(void);
|
||||
};
|
||||
|
||||
#endif /** _OPEN_METRICS_H_ */
|
@ -9,7 +9,7 @@
|
||||
#include <HTTPClient.h>
|
||||
#endif
|
||||
|
||||
AgApiClient::AgApiClient(Stream &debug, AgConfigure &config)
|
||||
AgApiClient::AgApiClient(Stream &debug, Configuration &config)
|
||||
: PrintLog(debug, "ApiClient"), config(config) {}
|
||||
|
||||
AgApiClient::~AgApiClient() {}
|
||||
|
@ -18,14 +18,14 @@
|
||||
|
||||
class AgApiClient : public PrintLog {
|
||||
private:
|
||||
AgConfigure &config;
|
||||
Configuration &config;
|
||||
AirGradient *ag;
|
||||
|
||||
bool getConfigFailed;
|
||||
bool postToServerFailed;
|
||||
|
||||
public:
|
||||
AgApiClient(Stream &stream, AgConfigure &config);
|
||||
AgApiClient(Stream &stream, Configuration &config);
|
||||
~AgApiClient();
|
||||
|
||||
void begin(void);
|
||||
|
@ -18,7 +18,7 @@ const char *LED_BAR_MODE_NAMES[] = {
|
||||
* @param mode LedBarMode value
|
||||
* @return String
|
||||
*/
|
||||
String AgConfigure::getLedBarModeName(LedBarMode mode) {
|
||||
String Configuration::getLedBarModeName(LedBarMode mode) {
|
||||
if (mode == LedBarModeOff) {
|
||||
return String(LED_BAR_MODE_NAMES[LedBarModeOff]);
|
||||
} else if (mode == LedBarModePm) {
|
||||
@ -33,7 +33,7 @@ String AgConfigure::getLedBarModeName(LedBarMode mode) {
|
||||
* @brief Save configure to device storage (EEPROM)
|
||||
*
|
||||
*/
|
||||
void AgConfigure::saveConfig(void) {
|
||||
void Configuration::saveConfig(void) {
|
||||
config._check = 0;
|
||||
int len = sizeof(config) - sizeof(config._check);
|
||||
uint8_t *data = (uint8_t *)&config;
|
||||
@ -51,7 +51,7 @@ void AgConfigure::saveConfig(void) {
|
||||
logInfo("Save Config");
|
||||
}
|
||||
|
||||
void AgConfigure::loadConfig(void) {
|
||||
void Configuration::loadConfig(void) {
|
||||
bool readSuccess = false;
|
||||
#ifdef ESP8266
|
||||
uint8_t *data = (uint8_t *)&config;
|
||||
@ -87,7 +87,7 @@ void AgConfigure::loadConfig(void) {
|
||||
* @brief Set configuration default
|
||||
*
|
||||
*/
|
||||
void AgConfigure::defaultConfig(void) {
|
||||
void Configuration::defaultConfig(void) {
|
||||
// Default country is null
|
||||
memset(config.country, 0, sizeof(config.country));
|
||||
// Default MQTT broker is null.
|
||||
@ -111,20 +111,21 @@ void AgConfigure::defaultConfig(void) {
|
||||
* @brief Show configuration as JSON string message over log
|
||||
*
|
||||
*/
|
||||
void AgConfigure::printConfig(void) { logInfo(toString().c_str()); }
|
||||
void Configuration::printConfig(void) { logInfo(toString().c_str()); }
|
||||
|
||||
/**
|
||||
* @brief Construct a new Ag Configure:: Ag Configure object
|
||||
*
|
||||
* @param debugLog Serial Stream
|
||||
*/
|
||||
AgConfigure::AgConfigure(Stream &debugLog) : PrintLog(debugLog, "Configure") {}
|
||||
Configuration::Configuration(Stream &debugLog)
|
||||
: PrintLog(debugLog, "Configure") {}
|
||||
|
||||
/**
|
||||
* @brief Destroy the Ag Configure:: Ag Configure object
|
||||
*
|
||||
*/
|
||||
AgConfigure::~AgConfigure() {}
|
||||
Configuration::~Configuration() {}
|
||||
|
||||
/**
|
||||
* @brief Initialize configuration
|
||||
@ -132,7 +133,7 @@ AgConfigure::~AgConfigure() {}
|
||||
* @return true Success
|
||||
* @return false Failure
|
||||
*/
|
||||
bool AgConfigure::begin(void) {
|
||||
bool Configuration::begin(void) {
|
||||
EEPROM.begin(512);
|
||||
loadConfig();
|
||||
printConfig();
|
||||
@ -149,7 +150,7 @@ bool AgConfigure::begin(void) {
|
||||
* @return true Success
|
||||
* @return false Failure
|
||||
*/
|
||||
bool AgConfigure::parse(String data, bool isLocal) {
|
||||
bool Configuration::parse(String data, bool isLocal) {
|
||||
JSONVar root = JSON.parse(data);
|
||||
if (JSON.typeof_(root) == "undefined") {
|
||||
logError("Configuration JSON invalid");
|
||||
@ -392,6 +393,7 @@ bool AgConfigure::parse(String data, bool isLocal) {
|
||||
}
|
||||
printConfig();
|
||||
|
||||
udpated = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -400,7 +402,7 @@ bool AgConfigure::parse(String data, bool isLocal) {
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String AgConfigure::toString(void) {
|
||||
String Configuration::toString(void) {
|
||||
JSONVar root;
|
||||
|
||||
/** "country" */
|
||||
@ -453,7 +455,7 @@ String AgConfigure::toString(void) {
|
||||
* @return true F
|
||||
* @return false C
|
||||
*/
|
||||
bool AgConfigure::isTemperatureUnitInF(void) {
|
||||
bool Configuration::isTemperatureUnitInF(void) {
|
||||
return (config.temperatureUnit == 'f');
|
||||
}
|
||||
|
||||
@ -462,7 +464,7 @@ bool AgConfigure::isTemperatureUnitInF(void) {
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String AgConfigure::getCountry(void) { return String(config.country); }
|
||||
String Configuration::getCountry(void) { return String(config.country); }
|
||||
|
||||
/**
|
||||
* @brief PM unit standard (USAQI, ugm3)
|
||||
@ -470,21 +472,21 @@ String AgConfigure::getCountry(void) { return String(config.country); }
|
||||
* @return true USAQI
|
||||
* @return false ugm3
|
||||
*/
|
||||
bool AgConfigure::isPmStandardInUSAQI(void) { return config.inUSAQI; }
|
||||
bool Configuration::isPmStandardInUSAQI(void) { return config.inUSAQI; }
|
||||
|
||||
/**
|
||||
* @brief Get CO2 calibration ABC time
|
||||
*
|
||||
* @return int Number of day
|
||||
*/
|
||||
int AgConfigure::getCO2CalirationAbcDays(void) { return config.abcDays; }
|
||||
int Configuration::getCO2CalibrationAbcDays(void) { return config.abcDays; }
|
||||
|
||||
/**
|
||||
* @brief Get Led Bar Mode
|
||||
*
|
||||
* @return LedBarMode
|
||||
*/
|
||||
LedBarMode AgConfigure::getLedBarMode(void) {
|
||||
LedBarMode Configuration::getLedBarMode(void) {
|
||||
return (LedBarMode)config.useRGBLedBar;
|
||||
}
|
||||
|
||||
@ -493,7 +495,7 @@ LedBarMode AgConfigure::getLedBarMode(void) {
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String AgConfigure::getLedBarModeName(void) {
|
||||
String Configuration::getLedBarModeName(void) {
|
||||
return getLedBarModeName((LedBarMode)config.useRGBLedBar);
|
||||
}
|
||||
|
||||
@ -503,14 +505,16 @@ String AgConfigure::getLedBarModeName(void) {
|
||||
* @return true On
|
||||
* @return false Off
|
||||
*/
|
||||
bool AgConfigure::getDisplayMode(void) { return config.displayMode; }
|
||||
bool Configuration::getDisplayMode(void) { return config.displayMode; }
|
||||
|
||||
/**
|
||||
* @brief Get MQTT uri
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String AgConfigure::getMqttBrokerUri(void) { return String(config.mqttBroker); }
|
||||
String Configuration::getMqttBrokerUri(void) {
|
||||
return String(config.mqttBroker);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get configuratoin post data to AirGradient cloud
|
||||
@ -518,7 +522,7 @@ String AgConfigure::getMqttBrokerUri(void) { return String(config.mqttBroker); }
|
||||
* @return true Post
|
||||
* @return false No-Post
|
||||
*/
|
||||
bool AgConfigure::isPostDataToAirGradient(void) {
|
||||
bool Configuration::isPostDataToAirGradient(void) {
|
||||
return config.postDataToAirGradient;
|
||||
}
|
||||
|
||||
@ -527,7 +531,7 @@ bool AgConfigure::isPostDataToAirGradient(void) {
|
||||
*
|
||||
* @return ConfigurationControl
|
||||
*/
|
||||
ConfigurationControl AgConfigure::getConfigurationControl(void) {
|
||||
ConfigurationControl Configuration::getConfigurationControl(void) {
|
||||
return (ConfigurationControl)config.configurationControl;
|
||||
}
|
||||
|
||||
@ -538,7 +542,7 @@ ConfigurationControl AgConfigure::getConfigurationControl(void) {
|
||||
* @return true Requested
|
||||
* @return false Not requested
|
||||
*/
|
||||
bool AgConfigure::isCo2CalibrationRequested(void) {
|
||||
bool Configuration::isCo2CalibrationRequested(void) {
|
||||
bool requested = co2CalibrationRequested;
|
||||
co2CalibrationRequested = false; // clear requested
|
||||
return requested;
|
||||
@ -551,7 +555,7 @@ bool AgConfigure::isCo2CalibrationRequested(void) {
|
||||
* @return true Requested
|
||||
* @return false Not requested
|
||||
*/
|
||||
bool AgConfigure::isLedBarTestRequested(void) {
|
||||
bool Configuration::isLedBarTestRequested(void) {
|
||||
bool requested = ledBarTestRequested;
|
||||
ledBarTestRequested = false;
|
||||
return requested;
|
||||
@ -560,7 +564,7 @@ bool AgConfigure::isLedBarTestRequested(void) {
|
||||
/**
|
||||
* @brief Reset default configure
|
||||
*/
|
||||
void AgConfigure::reset(void) {
|
||||
void Configuration::reset(void) {
|
||||
defaultConfig();
|
||||
logInfo("Reset to default configure");
|
||||
printConfig();
|
||||
@ -571,4 +575,10 @@ void AgConfigure::reset(void) {
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String AgConfigure::getModel(void) { return String(config.model); }
|
||||
String Configuration::getModel(void) { return String(config.model); }
|
||||
|
||||
bool Configuration::isUpdated(void) {
|
||||
bool updated = this->udpated;
|
||||
this->udpated = false;
|
||||
return updated;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_JSON.h>
|
||||
|
||||
class AgConfigure : public PrintLog {
|
||||
class Configuration : public PrintLog {
|
||||
private:
|
||||
struct Config {
|
||||
char model[20];
|
||||
@ -32,6 +32,7 @@ private:
|
||||
struct Config config;
|
||||
bool co2CalibrationRequested;
|
||||
bool ledBarTestRequested;
|
||||
bool udpated;
|
||||
|
||||
String getLedBarModeName(LedBarMode mode);
|
||||
void saveConfig(void);
|
||||
@ -40,8 +41,14 @@ private:
|
||||
void printConfig(void);
|
||||
|
||||
public:
|
||||
AgConfigure(Stream &debugLog);
|
||||
~AgConfigure();
|
||||
Configuration(Stream &debugLog);
|
||||
~Configuration();
|
||||
|
||||
bool hasSensorS8 = true;
|
||||
bool hasSensorPMS1 = true;
|
||||
bool hasSensorPMS2 = true;
|
||||
bool hasSensorSGP = true;
|
||||
bool hasSensorSHT = true;
|
||||
|
||||
bool begin(void);
|
||||
bool parse(String data, bool isLocal);
|
||||
@ -49,7 +56,7 @@ public:
|
||||
bool isTemperatureUnitInF(void);
|
||||
String getCountry(void);
|
||||
bool isPmStandardInUSAQI(void);
|
||||
int getCO2CalirationAbcDays(void);
|
||||
int getCO2CalibrationAbcDays(void);
|
||||
LedBarMode getLedBarMode(void);
|
||||
String getLedBarModeName(void);
|
||||
bool getDisplayMode(void);
|
||||
@ -60,6 +67,7 @@ public:
|
||||
bool isLedBarTestRequested(void);
|
||||
void reset(void);
|
||||
String getModel(void);
|
||||
bool isUpdated(void);
|
||||
};
|
||||
|
||||
#endif /** _AG_CONFIG_H_ */
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
* @param hasStatus
|
||||
*/
|
||||
void AgOledDisplay::showTempHum(bool hasStatus) {
|
||||
void OledDisplay::showTempHum(bool hasStatus) {
|
||||
char buf[10];
|
||||
if (value.Temperature > -1001) {
|
||||
if (config.isTemperatureUnitInF()) {
|
||||
@ -53,20 +53,20 @@ void AgOledDisplay::showTempHum(bool hasStatus) {
|
||||
* @brief Construct a new Ag Oled Display:: Ag Oled Display object
|
||||
*
|
||||
* @param config AgConfiguration
|
||||
* @param value AgValue
|
||||
* @param value Measurements
|
||||
* @param log Serial Stream
|
||||
*/
|
||||
AgOledDisplay::AgOledDisplay(AgConfigure &config, AgValue &value, Stream &log)
|
||||
: PrintLog(log, "AgOledDisplay"), config(config), value(value) {}
|
||||
OledDisplay::OledDisplay(Configuration &config, Measurements &value, Stream &log)
|
||||
: PrintLog(log, "OledDisplay"), config(config), value(value) {}
|
||||
|
||||
/**
|
||||
* @brief Set AirGradient instance
|
||||
*
|
||||
* @param ag Point to AirGradient instance
|
||||
*/
|
||||
void AgOledDisplay::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
void OledDisplay::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
|
||||
AgOledDisplay::~AgOledDisplay() {}
|
||||
OledDisplay::~OledDisplay() {}
|
||||
|
||||
/**
|
||||
* @brief Initialize display
|
||||
@ -74,7 +74,7 @@ AgOledDisplay::~AgOledDisplay() {}
|
||||
* @return true Success
|
||||
* @return false Failure
|
||||
*/
|
||||
bool AgOledDisplay::begin(void) {
|
||||
bool OledDisplay::begin(void) {
|
||||
if (isBegin) {
|
||||
logWarning("Already begin, call 'end' and try again");
|
||||
return true;
|
||||
@ -102,14 +102,14 @@ bool AgOledDisplay::begin(void) {
|
||||
* @brief De-Initialize display
|
||||
*
|
||||
*/
|
||||
void AgOledDisplay::end(void) {
|
||||
void OledDisplay::end(void) {
|
||||
if (!isBegin) {
|
||||
logWarning("Already end, call 'begin' and try again");
|
||||
return;
|
||||
}
|
||||
|
||||
/** Free u8g2 */
|
||||
delete u8g2;
|
||||
delete DISP();
|
||||
u8g2 = NULL;
|
||||
|
||||
isBegin = false;
|
||||
@ -123,7 +123,7 @@ void AgOledDisplay::end(void) {
|
||||
* @param line2
|
||||
* @param line3
|
||||
*/
|
||||
void AgOledDisplay::setText(String &line1, String &line2, String &line3) {
|
||||
void OledDisplay::setText(String &line1, String &line2, String &line3) {
|
||||
setText(line1.c_str(), line2.c_str(), line3.c_str());
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ void AgOledDisplay::setText(String &line1, String &line2, String &line3) {
|
||||
* @param line2
|
||||
* @param line3
|
||||
*/
|
||||
void AgOledDisplay::setText(const char *line1, const char *line2,
|
||||
void OledDisplay::setText(const char *line1, const char *line2,
|
||||
const char *line3) {
|
||||
DISP()->firstPage();
|
||||
do {
|
||||
@ -153,7 +153,7 @@ void AgOledDisplay::setText(const char *line1, const char *line2,
|
||||
* @param line3
|
||||
* @param line4
|
||||
*/
|
||||
void AgOledDisplay::setText(String &line1, String &line2, String &line3,
|
||||
void OledDisplay::setText(String &line1, String &line2, String &line3,
|
||||
String &line4) {
|
||||
setText(line1.c_str(), line2.c_str(), line3.c_str(), line4.c_str());
|
||||
}
|
||||
@ -166,7 +166,7 @@ void AgOledDisplay::setText(String &line1, String &line2, String &line3,
|
||||
* @param line3
|
||||
* @param line4
|
||||
*/
|
||||
void AgOledDisplay::setText(const char *line1, const char *line2,
|
||||
void OledDisplay::setText(const char *line1, const char *line2,
|
||||
const char *line3, const char *line4) {
|
||||
DISP()->firstPage();
|
||||
do {
|
||||
@ -182,13 +182,13 @@ void AgOledDisplay::setText(const char *line1, const char *line2,
|
||||
* @brief Update dashboard content
|
||||
*
|
||||
*/
|
||||
void AgOledDisplay::showDashboard(void) { showDashboard(NULL); }
|
||||
void OledDisplay::showDashboard(void) { showDashboard(NULL); }
|
||||
|
||||
/**
|
||||
* @brief Update dashboard content and error status
|
||||
*
|
||||
*/
|
||||
void AgOledDisplay::showDashboard(const char *status) {
|
||||
void OledDisplay::showDashboard(const char *status) {
|
||||
char strBuf[10];
|
||||
|
||||
DISP()->firstPage();
|
||||
@ -244,8 +244,8 @@ void AgOledDisplay::showDashboard(const char *status) {
|
||||
/** Draw PM2.5 value */
|
||||
DISP()->setFont(u8g2_font_t0_22b_tf);
|
||||
if (config.isPmStandardInUSAQI()) {
|
||||
if (value.PM25 >= 0) {
|
||||
sprintf(strBuf, "%d", ag->pms5003.convertPm25ToUsAqi(value.PM25));
|
||||
if (value.pm25_1 >= 0) {
|
||||
sprintf(strBuf, "%d", ag->pms5003.convertPm25ToUsAqi(value.pm25_1));
|
||||
} else {
|
||||
sprintf(strBuf, "%s", "-");
|
||||
}
|
||||
@ -253,8 +253,8 @@ void AgOledDisplay::showDashboard(const char *status) {
|
||||
DISP()->setFont(u8g2_font_t0_12_tf);
|
||||
DISP()->drawUTF8(48, 61, "AQI");
|
||||
} else {
|
||||
if (value.PM25 >= 0) {
|
||||
sprintf(strBuf, "%d", value.PM25);
|
||||
if (value.pm25_1 >= 0) {
|
||||
sprintf(strBuf, "%d", value.pm25_1);
|
||||
} else {
|
||||
sprintf(strBuf, "%s", "-");
|
||||
}
|
||||
|
@ -7,19 +7,19 @@
|
||||
#include "Main/PrintLog.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
class AgOledDisplay : public PrintLog {
|
||||
class OledDisplay : public PrintLog {
|
||||
private:
|
||||
AgConfigure &config;
|
||||
Configuration &config;
|
||||
AirGradient *ag;
|
||||
bool isBegin = false;
|
||||
void *u8g2 = NULL;
|
||||
AgValue &value;
|
||||
Measurements &value;
|
||||
|
||||
void showTempHum(bool hasStatus);
|
||||
public:
|
||||
AgOledDisplay(AgConfigure &config, AgValue &value,
|
||||
OledDisplay(Configuration &config, Measurements &value,
|
||||
Stream &log);
|
||||
~AgOledDisplay();
|
||||
~OledDisplay();
|
||||
|
||||
void setAirGradient(AirGradient *ag);
|
||||
bool begin(void);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#define LED_SHORT_BLINK_DELAY 500 /** ms */
|
||||
#define LED_LONG_BLINK_DELAY 2000 /** ms */
|
||||
|
||||
#define SENSOR_CO2_CALIB_COUNTDOWN_MAX 5 /** sec */
|
||||
|
||||
/**
|
||||
* @brief Animation LED bar with color
|
||||
*
|
||||
@ -12,7 +14,7 @@
|
||||
* @param g
|
||||
* @param b
|
||||
*/
|
||||
void AgStateMachine::ledBarSingleLedAnimation(uint8_t r, uint8_t g, uint8_t b) {
|
||||
void StateMachine::ledBarSingleLedAnimation(uint8_t r, uint8_t g, uint8_t b) {
|
||||
if (ledBarAnimationCount < 0) {
|
||||
ledBarAnimationCount = 0;
|
||||
ag->ledBar.setColor(r, g, b, ledBarAnimationCount);
|
||||
@ -30,7 +32,7 @@ void AgStateMachine::ledBarSingleLedAnimation(uint8_t r, uint8_t g, uint8_t b) {
|
||||
*
|
||||
* @param ms Miliseconds
|
||||
*/
|
||||
void AgStateMachine::ledStatusBlinkDelay(uint32_t ms) {
|
||||
void StateMachine::ledStatusBlinkDelay(uint32_t ms) {
|
||||
ag->statusLed.setOn();
|
||||
delay(ms);
|
||||
ag->statusLed.setOff();
|
||||
@ -41,13 +43,13 @@ void AgStateMachine::ledStatusBlinkDelay(uint32_t ms) {
|
||||
* @brief Led bar show led color status
|
||||
*
|
||||
*/
|
||||
void AgStateMachine::sensorLedHandle(void) {
|
||||
void StateMachine::sensorhandleLeds(void) {
|
||||
switch (config.getLedBarMode()) {
|
||||
case LedBarMode::LedBarModeCO2:
|
||||
co2LedHandle();
|
||||
co2handleLeds();
|
||||
break;
|
||||
case LedBarMode::LedBarModePm:
|
||||
pm25LedHandle();
|
||||
pm25handleLeds();
|
||||
break;
|
||||
default:
|
||||
ag->ledBar.clear();
|
||||
@ -59,7 +61,7 @@ void AgStateMachine::sensorLedHandle(void) {
|
||||
* @brief Show CO2 LED status
|
||||
*
|
||||
*/
|
||||
void AgStateMachine::co2LedHandle(void) {
|
||||
void StateMachine::co2handleLeds(void) {
|
||||
int co2Value = value.CO2;
|
||||
if (co2Value <= 400) {
|
||||
/** G; 1 */
|
||||
@ -142,8 +144,8 @@ void AgStateMachine::co2LedHandle(void) {
|
||||
* @brief Show PM2.5 LED status
|
||||
*
|
||||
*/
|
||||
void AgStateMachine::pm25LedHandle(void) {
|
||||
int pm25Value = value.PM25;
|
||||
void StateMachine::pm25handleLeds(void) {
|
||||
int pm25Value = value.pm25_1;
|
||||
if (pm25Value <= 5) {
|
||||
/** G; 1 */
|
||||
ag->ledBar.setColor(0, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
|
||||
@ -221,29 +223,182 @@ void AgStateMachine::pm25LedHandle(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void StateMachine::co2Calibration(void) {
|
||||
if (config.isCo2CalibrationRequested() && config.hasSensorS8) {
|
||||
logInfo("CO2 Calibration");
|
||||
|
||||
/** Count down to 0 then start */
|
||||
for (int i = 0; i < SENSOR_CO2_CALIB_COUNTDOWN_MAX; i++) {
|
||||
if (ag->isOne()) {
|
||||
String str =
|
||||
"after " + String(SENSOR_CO2_CALIB_COUNTDOWN_MAX - i) + " sec";
|
||||
disp.setText("Start CO2 calib", str.c_str(), "");
|
||||
} else {
|
||||
logInfo("Start CO2 calib after " +
|
||||
String(SENSOR_CO2_CALIB_COUNTDOWN_MAX - i) + " sec");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
if (ag->s8.setBaselineCalibration()) {
|
||||
if (ag->isOne()) {
|
||||
disp.setText("Calibration", "success", "");
|
||||
} else {
|
||||
logInfo("CO2 Calibration: success");
|
||||
}
|
||||
delay(1000);
|
||||
if (ag->isOne()) {
|
||||
disp.setText("Wait for", "calib finish", "...");
|
||||
} else {
|
||||
logInfo("CO2 Calibration: Wait for calibration finish...");
|
||||
}
|
||||
|
||||
/** Count down wait for finish */
|
||||
int count = 0;
|
||||
while (ag->s8.isBaseLineCalibrationDone() == false) {
|
||||
delay(1000);
|
||||
count++;
|
||||
}
|
||||
if (ag->isOne()) {
|
||||
String str = "after " + String(count);
|
||||
disp.setText("Calib finish", str.c_str(), "sec");
|
||||
} else {
|
||||
logInfo("CO2 Calibration: finish after " + String(count) + " sec");
|
||||
}
|
||||
delay(2000);
|
||||
} else {
|
||||
if (ag->isOne()) {
|
||||
disp.setText("Calibration", "failure!!!", "");
|
||||
} else {
|
||||
logInfo("CO2 Calibration: failure!!!");
|
||||
}
|
||||
delay(2000);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.getCO2CalibrationAbcDays() > 0 && config.hasSensorS8) {
|
||||
int newHour = config.getCO2CalibrationAbcDays() * 24;
|
||||
logInfo("Requested abcDays setting: " +
|
||||
String(config.getCO2CalibrationAbcDays()) + "days (" +
|
||||
String(newHour) + "hours)");
|
||||
int curHour = ag->s8.getAbcPeriod();
|
||||
logInfo("Current S8 abcDays setting: " + String(curHour) + "(hours)");
|
||||
if (curHour == newHour) {
|
||||
logInfo("'abcDays' unchanged");
|
||||
} else {
|
||||
if (ag->s8.setAbcPeriod(config.getCO2CalibrationAbcDays() * 24) ==
|
||||
false) {
|
||||
logError("Set S8 abcDays period failed");
|
||||
} else {
|
||||
logInfo("Set S8 abcDays period success");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logWarning("CO2 S8 not available, set 'abcDays' ignored");
|
||||
}
|
||||
}
|
||||
|
||||
void StateMachine::ledBarTest(void) {
|
||||
if (config.isLedBarTestRequested()) {
|
||||
if (config.getCountry() == "TH") {
|
||||
uint32_t tstart = millis();
|
||||
logInfo("Start run LED test for 2 min");
|
||||
while (1) {
|
||||
ledBarRunTest();
|
||||
uint32_t ms = (uint32_t)(millis() - tstart);
|
||||
if (ms >= (60 * 1000 * 2)) {
|
||||
logInfo("LED test after 2 min finish");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ledBarRunTest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StateMachine::ledBarRunTest(void) {
|
||||
disp.setText("LED Test", "running", ".....");
|
||||
runLedTest('r');
|
||||
ag->ledBar.show();
|
||||
delay(1000);
|
||||
runLedTest('g');
|
||||
ag->ledBar.show();
|
||||
delay(1000);
|
||||
runLedTest('b');
|
||||
ag->ledBar.show();
|
||||
delay(1000);
|
||||
runLedTest('w');
|
||||
ag->ledBar.show();
|
||||
delay(1000);
|
||||
runLedTest('n');
|
||||
ag->ledBar.show();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void StateMachine::runLedTest(char color) {
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
int b = 0;
|
||||
switch (color) {
|
||||
case 'g':
|
||||
g = 255;
|
||||
break;
|
||||
case 'y':
|
||||
r = 255;
|
||||
g = 255;
|
||||
break;
|
||||
case 'o':
|
||||
r = 255;
|
||||
g = 128;
|
||||
break;
|
||||
case 'r':
|
||||
r = 255;
|
||||
break;
|
||||
case 'b':
|
||||
b = 255;
|
||||
break;
|
||||
case 'w':
|
||||
r = 255;
|
||||
g = 255;
|
||||
b = 255;
|
||||
break;
|
||||
case 'p':
|
||||
r = 153;
|
||||
b = 153;
|
||||
break;
|
||||
case 'z':
|
||||
r = 102;
|
||||
break;
|
||||
case 'n':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ag->ledBar.setColor(r, g, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a new Ag State Machine:: Ag State Machine object
|
||||
*
|
||||
* @param disp AgOledDisplay
|
||||
* @param disp OledDisplay
|
||||
* @param log Serial Stream
|
||||
* @param value AgValue
|
||||
* @param config AgConfigure
|
||||
* @param value Measurements
|
||||
* @param config Configuration
|
||||
*/
|
||||
AgStateMachine::AgStateMachine(AgOledDisplay &disp, Stream &log, AgValue &value,
|
||||
AgConfigure &config)
|
||||
: PrintLog(log, "AgStateMachine"), disp(disp), value(value),
|
||||
config(config) {}
|
||||
StateMachine::StateMachine(OledDisplay &disp, Stream &log, Measurements &value,
|
||||
Configuration &config)
|
||||
: PrintLog(log, "StateMachine"), disp(disp), value(value), config(config) {}
|
||||
|
||||
AgStateMachine::~AgStateMachine() {}
|
||||
StateMachine::~StateMachine() {}
|
||||
|
||||
/**
|
||||
* @brief OLED display show content from state value
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
void AgStateMachine::displayHandle(AgStateMachineState state) {
|
||||
void StateMachine::displayHandle(AgStateMachineState state) {
|
||||
// Ignore handle if not ONE_INDOOR board
|
||||
if (!ag->isOneIndoor()) {
|
||||
if (!ag->isOne()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -320,6 +475,9 @@ void AgStateMachine::displayHandle(AgStateMachineState state) {
|
||||
disp.showDashboard();
|
||||
break;
|
||||
}
|
||||
case AgStateMachineCo2Calibration:
|
||||
co2Calibration();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -329,27 +487,25 @@ void AgStateMachine::displayHandle(AgStateMachineState state) {
|
||||
* @brief OLED display show content as previous state updated
|
||||
*
|
||||
*/
|
||||
void AgStateMachine::displayHandle(void) { displayHandle(dispState); }
|
||||
void StateMachine::displayHandle(void) { displayHandle(dispState); }
|
||||
|
||||
/**
|
||||
* @brief Update status add to dashboard
|
||||
*
|
||||
*/
|
||||
void AgStateMachine::displaySetAddToDashBoard(void) {
|
||||
void StateMachine::displaySetAddToDashBoard(void) {
|
||||
addToDashBoard = true;
|
||||
addToDashboardTime = millis();
|
||||
}
|
||||
|
||||
void AgStateMachine::displayClearAddToDashBoard(void) {
|
||||
addToDashBoard = false;
|
||||
}
|
||||
void StateMachine::displayClearAddToDashBoard(void) { addToDashBoard = false; }
|
||||
|
||||
/**
|
||||
* @brief Set WiFi connection coundown on dashboard
|
||||
*
|
||||
* @param count Seconds
|
||||
*/
|
||||
void AgStateMachine::displayWiFiConnectCountDown(int count) {
|
||||
void StateMachine::displayWiFiConnectCountDown(int count) {
|
||||
wifiConnectCountDown = count;
|
||||
}
|
||||
|
||||
@ -357,21 +513,21 @@ void AgStateMachine::displayWiFiConnectCountDown(int count) {
|
||||
* @brief Init before start LED bar animation
|
||||
*
|
||||
*/
|
||||
void AgStateMachine::ledAnimationInit(void) { ledBarAnimationCount = -1; }
|
||||
void StateMachine::ledAnimationInit(void) { ledBarAnimationCount = -1; }
|
||||
|
||||
/**
|
||||
* @brief Handle LED from state
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
void StateMachine::handleLeds(AgStateMachineState state) {
|
||||
if (state > AgStateMachineNormal) {
|
||||
logError("ledHandle: state invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
ledState = state;
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.clear(); // Set all LED OFF
|
||||
}
|
||||
switch (state) {
|
||||
@ -379,7 +535,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
/** In WiFi Manager Mode */
|
||||
/** Turn LED OFF */
|
||||
/** Turn midle LED Color */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(0, 0, 255, ag->ledBar.getNumberOfLeds() / 2);
|
||||
} else {
|
||||
ag->statusLed.setToggle();
|
||||
@ -388,7 +544,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
}
|
||||
case AgStateMachineWiFiManagerPortalActive: {
|
||||
/** WiFi Manager has connected to mobile phone */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(0, 0, 255);
|
||||
} else {
|
||||
ag->statusLed.setOn();
|
||||
@ -398,7 +554,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
case AgStateMachineWiFiManagerStaConnecting: {
|
||||
/** after SSID and PW entered and OK clicked, connection to WiFI network is
|
||||
* attempted */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ledBarSingleLedAnimation(255, 255, 255);
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
@ -407,7 +563,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
}
|
||||
case AgStateMachineWiFiManagerStaConnected: {
|
||||
/** Connecting to WiFi worked */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(255, 255, 255);
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
@ -416,7 +572,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
}
|
||||
case AgStateMachineWiFiOkServerConnecting: {
|
||||
/** once connected to WiFi an attempt to reach the server is performed */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ledBarSingleLedAnimation(0, 255, 0);
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
@ -425,7 +581,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
}
|
||||
case AgStateMachineWiFiOkServerConnected: {
|
||||
/** Server is reachable, all fine */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(0, 255, 0);
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
@ -441,7 +597,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
}
|
||||
case AgStateMachineWiFiManagerConnectFailed: {
|
||||
/** Cannot connect to WiFi (e.g. wrong password, WPA Enterprise etc.) */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(255, 0, 0);
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
@ -459,7 +615,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
case AgStateMachineWiFiOkServerConnectFailed: {
|
||||
/** Connected to WiFi but server not reachable, e.g. firewall block/
|
||||
* whitelisting needed etc. */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(233, 183, 54); /** orange */
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
@ -475,7 +631,7 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
}
|
||||
case AgStateMachineWiFiOkServerOkSensorConfigFailed: {
|
||||
/** Server reachable but sensor not configured correctly */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(139, 24, 248); /** violet */
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
@ -492,12 +648,12 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
case AgStateMachineWiFiLost: {
|
||||
/** Connection to WiFi network failed credentials incorrect encryption not
|
||||
* supported etc. */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
/** WIFI failed status LED color */
|
||||
ag->ledBar.setColor(255, 0, 0, 0);
|
||||
/** Show CO2 or PM color status */
|
||||
// sensorLedColorHandler();
|
||||
sensorLedHandle();
|
||||
sensorhandleLeds();
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
}
|
||||
@ -506,11 +662,11 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
case AgStateMachineServerLost: {
|
||||
/** Connected to WiFi network but the server cannot be reached through the
|
||||
* internet, e.g. blocked by firewall */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(233, 183, 54, 0);
|
||||
|
||||
/** Show CO2 or PM color status */
|
||||
sensorLedHandle();
|
||||
sensorhandleLeds();
|
||||
// sensorLedColorHandler();
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
@ -520,30 +676,33 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
case AgStateMachineSensorConfigFailed: {
|
||||
/** Server is reachable but there is some configuration issue to be fixed on
|
||||
* the server side */
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.setColor(139, 24, 248, 0);
|
||||
|
||||
/** Show CO2 or PM color status */
|
||||
sensorLedHandle();
|
||||
sensorhandleLeds();
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AgStateMachineNormal: {
|
||||
if (ag->isOneIndoor()) {
|
||||
sensorLedHandle();
|
||||
if (ag->isOne()) {
|
||||
sensorhandleLeds();
|
||||
} else {
|
||||
ag->statusLed.setOff();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AgStateMachineLedBarTest:
|
||||
ledBarTest();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Show LED bar color
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ag->ledBar.show();
|
||||
}
|
||||
}
|
||||
@ -552,14 +711,14 @@ void AgStateMachine::ledHandle(AgStateMachineState state) {
|
||||
* @brief Handle LED as previous state updated
|
||||
*
|
||||
*/
|
||||
void AgStateMachine::ledHandle(void) { ledHandle(ledState); }
|
||||
void StateMachine::handleLeds(void) { handleLeds(ledState); }
|
||||
|
||||
/**
|
||||
* @brief Set display state
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
void AgStateMachine::setDisplayState(AgStateMachineState state) {
|
||||
void StateMachine::setDisplayState(AgStateMachineState state) {
|
||||
dispState = state;
|
||||
}
|
||||
|
||||
@ -568,18 +727,26 @@ void AgStateMachine::setDisplayState(AgStateMachineState state) {
|
||||
*
|
||||
* @return AgStateMachineState
|
||||
*/
|
||||
AgStateMachineState AgStateMachine::getDisplayState(void) { return dispState; }
|
||||
AgStateMachineState StateMachine::getDisplayState(void) { return dispState; }
|
||||
|
||||
/**
|
||||
* @brief Set AirGradient instance
|
||||
*
|
||||
* @param ag Point to AirGradient instance
|
||||
*/
|
||||
void AgStateMachine::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
void StateMachine::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
|
||||
/**
|
||||
* @brief Get current LED state
|
||||
*
|
||||
* @return AgStateMachineState
|
||||
*/
|
||||
AgStateMachineState AgStateMachine::getLedState(void) { return ledState; }
|
||||
AgStateMachineState StateMachine::getLedState(void) { return ledState; }
|
||||
|
||||
void StateMachine::executeCo2Calibration(void) {
|
||||
displayHandle(AgStateMachineCo2Calibration);
|
||||
}
|
||||
|
||||
void StateMachine::executeLedBarTest(void) {
|
||||
handleLeds(AgStateMachineLedBarTest);
|
||||
}
|
||||
|
@ -7,15 +7,15 @@
|
||||
#include "Main/PrintLog.h"
|
||||
#include "App/AppDef.h"
|
||||
|
||||
class AgStateMachine : public PrintLog {
|
||||
class StateMachine : public PrintLog {
|
||||
private:
|
||||
// AgStateMachineState state;
|
||||
AgStateMachineState ledState;
|
||||
AgStateMachineState dispState;
|
||||
AirGradient *ag;
|
||||
AgOledDisplay &disp;
|
||||
AgValue &value;
|
||||
AgConfigure &config;
|
||||
OledDisplay &disp;
|
||||
Measurements &value;
|
||||
Configuration &config;
|
||||
|
||||
bool addToDashBoard = false;
|
||||
uint32_t addToDashboardTime;
|
||||
@ -24,14 +24,18 @@ private:
|
||||
|
||||
void ledBarSingleLedAnimation(uint8_t r, uint8_t g, uint8_t b);
|
||||
void ledStatusBlinkDelay(uint32_t delay);
|
||||
void sensorLedHandle(void);
|
||||
void co2LedHandle(void);
|
||||
void pm25LedHandle(void);
|
||||
void sensorhandleLeds(void);
|
||||
void co2handleLeds(void);
|
||||
void pm25handleLeds(void);
|
||||
void co2Calibration(void);
|
||||
void ledBarTest(void);
|
||||
void ledBarRunTest(void);
|
||||
void runLedTest(char color);
|
||||
|
||||
public:
|
||||
AgStateMachine(AgOledDisplay &disp, Stream &log,
|
||||
AgValue &value, AgConfigure& config);
|
||||
~AgStateMachine();
|
||||
StateMachine(OledDisplay &disp, Stream &log,
|
||||
Measurements &value, Configuration& config);
|
||||
~StateMachine();
|
||||
void setAirGradient(AirGradient* ag);
|
||||
void displayHandle(AgStateMachineState state);
|
||||
void displayHandle(void);
|
||||
@ -39,11 +43,13 @@ public:
|
||||
void displayClearAddToDashBoard(void);
|
||||
void displayWiFiConnectCountDown(int count);
|
||||
void ledAnimationInit(void);
|
||||
void ledHandle(AgStateMachineState state);
|
||||
void ledHandle(void);
|
||||
void handleLeds(AgStateMachineState state);
|
||||
void handleLeds(void);
|
||||
void setDisplayState(AgStateMachineState state);
|
||||
AgStateMachineState getDisplayState(void);
|
||||
AgStateMachineState getLedState(void);
|
||||
void executeCo2Calibration(void);
|
||||
void executeLedBarTest(void);
|
||||
};
|
||||
|
||||
#endif /** _AG_STATE_MACHINE_H_ */
|
||||
|
151
src/AgValue.cpp
Normal file
151
src/AgValue.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
#include "AgValue.h"
|
||||
#include "AgConfigure.h"
|
||||
#include "AirGradient.h"
|
||||
#include <Arduino_JSON.h>
|
||||
|
||||
String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi,
|
||||
void *_ag, void *_config) {
|
||||
AirGradient *ag = (AirGradient *)_ag;
|
||||
Configuration *config = (Configuration *)_config;
|
||||
|
||||
JSONVar root;
|
||||
root["wifi"] = rssi;
|
||||
if (localServer) {
|
||||
root["serialno"] = ag->deviceId();
|
||||
}
|
||||
if (config->hasSensorS8) {
|
||||
if (this->CO2 >= 0) {
|
||||
root["rco2"] = this->CO2;
|
||||
}
|
||||
}
|
||||
|
||||
if (ag->isOne()) {
|
||||
if (config->hasSensorPMS1) {
|
||||
if (this->pm01_1 >= 0) {
|
||||
root["pm01"] = this->pm01_1;
|
||||
}
|
||||
if (this->pm25_1 >= 0) {
|
||||
root["pm02"] = this->pm25_1;
|
||||
}
|
||||
if (this->pm10_1 >= 0) {
|
||||
root["pm10"] = this->pm10_1;
|
||||
}
|
||||
if (this->pm03PCount_1 >= 0) {
|
||||
if (localServer) {
|
||||
root["pm003Count"] = this->pm03PCount_1;
|
||||
} else {
|
||||
root["pm003_count"] = this->pm03PCount_1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config->hasSensorSHT) {
|
||||
if (this->Temperature > -1001) {
|
||||
root["atmp"] = ag->round2(this->Temperature);
|
||||
}
|
||||
if (this->Humidity >= 0) {
|
||||
root["rhum"] = this->Humidity;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (config->hasSensorPMS1 && config->hasSensorPMS2) {
|
||||
root["pm01"] = ag->round2((this->pm01_1 + this->pm01_2) / 2.0);
|
||||
root["pm02"] = ag->round2((this->pm25_1 + this->pm25_2) / 2.0);
|
||||
root["pm10"] = ag->round2((this->pm10_1 + this->pm10_2) / 2.0);
|
||||
if (localServer) {
|
||||
root["pm003Count"] =
|
||||
ag->round2((this->pm03PCount_1 + this->pm03PCount_2) / 2.0);
|
||||
} else {
|
||||
root["pm003_count"] =
|
||||
ag->round2((this->pm03PCount_1 + this->pm03PCount_2) / 2.0);
|
||||
}
|
||||
root["atmp"] = ag->round2((this->temp_1 + this->temp_2) / 2.0);
|
||||
root["rhum"] = ag->round2((this->hum_1 + this->hum_2) / 2.0);
|
||||
}
|
||||
|
||||
if (fwMode == FW_MDOE_O_1PS || fwMode == FW_MODE_O_1PST) {
|
||||
if (config->hasSensorPMS1) {
|
||||
root["pm01"] = this->pm01_1;
|
||||
root["pm02"] = this->pm25_1;
|
||||
root["pm10"] = this->pm10_1;
|
||||
if (localServer) {
|
||||
root["pm003Count"] = this->pm03PCount_1;
|
||||
} else {
|
||||
root["pm003_count"] = this->pm03PCount_1;
|
||||
}
|
||||
root["atmp"] = ag->round2(this->temp_1);
|
||||
root["rhum"] = this->hum_1;
|
||||
}
|
||||
if (config->hasSensorPMS2) {
|
||||
root["pm01"] = this->pm01_2;
|
||||
root["pm02"] = this->pm25_2;
|
||||
root["pm10"] = this->pm10_2;
|
||||
if (localServer) {
|
||||
root["pm003Count"] = this->pm03PCount_2;
|
||||
} else {
|
||||
root["pm003_count"] = this->pm03PCount_2;
|
||||
}
|
||||
root["atmp"] = ag->round2(this->temp_2);
|
||||
root["rhum"] = this->hum_2;
|
||||
}
|
||||
} else {
|
||||
if (config->hasSensorPMS1) {
|
||||
root["channels"]["1"]["pm01"] = this->pm01_1;
|
||||
root["channels"]["1"]["pm02"] = this->pm25_1;
|
||||
root["channels"]["1"]["pm10"] = this->pm10_1;
|
||||
if (localServer) {
|
||||
root["channels"]["1"]["pm003Count"] = this->pm03PCount_1;
|
||||
} else {
|
||||
root["channels"]["1"]["pm003_count"] = this->pm03PCount_1;
|
||||
}
|
||||
root["channels"]["1"]["atmp"] = ag->round2(this->temp_1);
|
||||
root["channels"]["1"]["rhum"] = this->hum_1;
|
||||
}
|
||||
if (config->hasSensorPMS2) {
|
||||
root["channels"]["2"]["pm01"] = this->pm01_2;
|
||||
root["channels"]["2"]["pm02"] = this->pm25_2;
|
||||
root["channels"]["2"]["pm10"] = this->pm10_2;
|
||||
if (localServer) {
|
||||
root["channels"]["2"]["pm003Count"] = this->pm03PCount_2;
|
||||
} else {
|
||||
root["channels"]["2"]["pm003_count"] = this->pm03PCount_2;
|
||||
}
|
||||
root["channels"]["2"]["atmp"] = ag->round2(this->temp_2);
|
||||
root["channels"]["2"]["rhum"] = this->hum_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config->hasSensorSGP) {
|
||||
if (this->TVOC >= 0) {
|
||||
if (localServer) {
|
||||
root["tvocIndex"] = this->TVOC;
|
||||
} else {
|
||||
root["tvoc_index"] = this->TVOC;
|
||||
}
|
||||
}
|
||||
if (this->TVOCRaw >= 0) {
|
||||
root["tvoc_raw"] = this->TVOCRaw;
|
||||
}
|
||||
if (this->NOx >= 0) {
|
||||
if (localServer) {
|
||||
root["noxIndex"] = this->NOx;
|
||||
} else {
|
||||
root["nox_index"] = this->NOx;
|
||||
}
|
||||
}
|
||||
if (this->NOxRaw >= 0) {
|
||||
root["nox_raw"] = this->NOxRaw;
|
||||
}
|
||||
}
|
||||
root["boot"] = bootCount;
|
||||
|
||||
if (localServer) {
|
||||
root["ledMode"] = config->getLedBarModeName();
|
||||
root["firmwareVersion"] = ag->getVersion();
|
||||
root["fwMode"] = AgFirmwareModeName(fwMode);
|
||||
}
|
||||
|
||||
return JSON.stringify(root);
|
||||
}
|
@ -1,20 +1,76 @@
|
||||
#ifndef _AG_VALUE_H_
|
||||
#define _AG_VALUE_H_
|
||||
|
||||
class AgValue {
|
||||
#include <Arduino.h>
|
||||
#include "App/AppDef.h"
|
||||
|
||||
class Measurements {
|
||||
private:
|
||||
public:
|
||||
AgValue() {}
|
||||
~AgValue() {}
|
||||
Measurements() {
|
||||
pm25_1 = -1;
|
||||
pm01_1 = -1;
|
||||
pm10_1 = -1;
|
||||
pm03PCount_1 = -1;
|
||||
temp_1 = -1001;
|
||||
hum_1 = -1;
|
||||
|
||||
float Temperature = -1001;
|
||||
int Humidity = -1;
|
||||
int CO2 = -1;
|
||||
int PM25 = -1;
|
||||
int TVOC = -1;
|
||||
int TVOCRaw = -1;
|
||||
int NOx = -1;
|
||||
int NOxRaw = -1;
|
||||
pm25_2 = -1;
|
||||
pm01_2 = -1;
|
||||
pm10_2 = -1;
|
||||
pm03PCount_2 = -1;
|
||||
temp_2 = -1001;
|
||||
hum_2 = -1;
|
||||
|
||||
Temperature = -1001;
|
||||
Humidity = -1;
|
||||
CO2 = -1;
|
||||
TVOC = -1;
|
||||
TVOCRaw = -1;
|
||||
NOx = -1;
|
||||
NOxRaw = -1;
|
||||
}
|
||||
~Measurements() {}
|
||||
|
||||
float Temperature;
|
||||
int Humidity;
|
||||
int CO2;
|
||||
int TVOC;
|
||||
int TVOCRaw;
|
||||
int NOx;
|
||||
int NOxRaw;
|
||||
|
||||
int pm25_1;
|
||||
int pm01_1;
|
||||
int pm10_1;
|
||||
int pm03PCount_1;
|
||||
float temp_1;
|
||||
int hum_1;
|
||||
|
||||
int pm25_2;
|
||||
int pm01_2;
|
||||
int pm10_2;
|
||||
int pm03PCount_2;
|
||||
float temp_2;
|
||||
int hum_2;
|
||||
|
||||
int pm1Value01;
|
||||
int pm1Value25;
|
||||
int pm1Value10;
|
||||
int pm1PCount;
|
||||
int pm1temp;
|
||||
int pm1hum;
|
||||
int pm2Value01;
|
||||
int pm2Value25;
|
||||
int pm2Value10;
|
||||
int pm2PCount;
|
||||
int pm2temp;
|
||||
int pm2hum;
|
||||
int countPosition;
|
||||
const int targetCount = 20;
|
||||
int bootCount;
|
||||
|
||||
String toString(bool isLocal, AgFirmwareMode fwMode, int rssi, void* _ag, void* _config);
|
||||
};
|
||||
|
||||
#endif /** _AG_VALUE_H_ */
|
||||
|
@ -1,5 +1,3 @@
|
||||
#ifdef ESP32
|
||||
|
||||
#include "AgWiFiConnector.h"
|
||||
#include "Libraries/WiFiManager/WiFiManager.h"
|
||||
|
||||
@ -8,25 +6,28 @@
|
||||
|
||||
#define WIFI() ((WiFiManager *)(this->wifi))
|
||||
|
||||
/**
|
||||
* @brief Construct a new Ag Wi Fi Connector:: Ag Wi Fi Connector object
|
||||
*
|
||||
* @param disp AgOledDisplay
|
||||
* @param log Stream
|
||||
* @param sm AgStateMachine
|
||||
*/
|
||||
AgWiFiConnector::AgWiFiConnector(AgOledDisplay &disp, Stream &log,
|
||||
AgStateMachine &sm)
|
||||
: PrintLog(log, "AgWiFiConnector"), disp(disp), sm(sm) {}
|
||||
|
||||
AgWiFiConnector::~AgWiFiConnector() {}
|
||||
|
||||
/**
|
||||
* @brief Set reference AirGradient instance
|
||||
*
|
||||
* @param ag Point to AirGradient instance
|
||||
*/
|
||||
void AgWiFiConnector::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
void WifiConnector::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
|
||||
#ifdef ESP32
|
||||
/**
|
||||
* @brief Construct a new Ag Wi Fi Connector:: Ag Wi Fi Connector object
|
||||
*
|
||||
* @param disp OledDisplay
|
||||
* @param log Stream
|
||||
* @param sm StateMachine
|
||||
*/
|
||||
WifiConnector::WifiConnector(OledDisplay &disp, Stream &log, StateMachine &sm)
|
||||
: PrintLog(log, "WifiConnector"), disp(disp), sm(sm) {}
|
||||
#else
|
||||
WifiConnector::WifiConnector(Stream &log) : PrintLog(log, "WiFiConnector") {}
|
||||
#endif
|
||||
|
||||
WifiConnector::~WifiConnector() {}
|
||||
|
||||
/**
|
||||
* @brief Connection to WIFI AP process. Just call one times
|
||||
@ -34,7 +35,7 @@ void AgWiFiConnector::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
* @return true Success
|
||||
* @return false Failure
|
||||
*/
|
||||
bool AgWiFiConnector::connect(void) {
|
||||
bool WifiConnector::connect(void) {
|
||||
if (wifi == NULL) {
|
||||
wifi = new WiFiManager();
|
||||
if (wifi == NULL) {
|
||||
@ -46,23 +47,27 @@ bool AgWiFiConnector::connect(void) {
|
||||
WIFI()->setConfigPortalBlocking(false);
|
||||
WIFI()->setTimeout(WIFI_CONNECT_COUNTDOWN_MAX);
|
||||
|
||||
#ifdef ESP32
|
||||
WIFI()->setAPCallback([this](WiFiManager *obj) { _wifiApCallback(); });
|
||||
WIFI()->setSaveConfigCallback([this]() { _wifiSaveConfig(); });
|
||||
WIFI()->setSaveParamsCallback([this]() { _wifiSaveParamCallback(); });
|
||||
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
disp.setText("Connecting to", "WiFi", "...");
|
||||
} else {
|
||||
logInfo("Connecting to WiFi...");
|
||||
}
|
||||
|
||||
ssid = "airgradient-" + ag->deviceId();
|
||||
#else
|
||||
ssid = "AG-" + String(ESP.getChipId(), HEX);
|
||||
#endif
|
||||
WIFI()->setConfigPortalTimeout(WIFI_CONNECT_COUNTDOWN_MAX);
|
||||
WIFI()->autoConnect(ssid.c_str(), WIFI_HOTSPOT_PASSWORD_DEFAULT);
|
||||
|
||||
#ifdef ESP32
|
||||
// Task handle WiFi connection.
|
||||
xTaskCreate(
|
||||
[](void *obj) {
|
||||
AgWiFiConnector *connector = (AgWiFiConnector *)obj;
|
||||
WifiConnector *connector = (WifiConnector *)obj;
|
||||
while (connector->_wifiConfigPortalActive()) {
|
||||
connector->_wifiProcess();
|
||||
}
|
||||
@ -81,7 +86,7 @@ bool AgWiFiConnector::connect(void) {
|
||||
if (WiFi.isConnected() == false) {
|
||||
/** Display countdown */
|
||||
uint32_t ms;
|
||||
if (ag->isOneIndoor()) {
|
||||
if (ag->isOne()) {
|
||||
ms = (uint32_t)(millis() - dispPeriod);
|
||||
if (ms >= 1000) {
|
||||
dispPeriod = millis();
|
||||
@ -98,7 +103,7 @@ bool AgWiFiConnector::connect(void) {
|
||||
ms = (uint32_t)(millis() - ledPeriod);
|
||||
if (ms >= 100) {
|
||||
ledPeriod = millis();
|
||||
sm.ledHandle();
|
||||
sm.handleLeds();
|
||||
}
|
||||
|
||||
/** Check for client connect to change led color */
|
||||
@ -106,11 +111,11 @@ bool AgWiFiConnector::connect(void) {
|
||||
if (clientConnected != clientConnectChanged) {
|
||||
clientConnectChanged = clientConnected;
|
||||
if (clientConnectChanged) {
|
||||
sm.ledHandle(AgStateMachineWiFiManagerPortalActive);
|
||||
sm.handleLeds(AgStateMachineWiFiManagerPortalActive);
|
||||
} else {
|
||||
sm.ledAnimationInit();
|
||||
sm.ledHandle(AgStateMachineWiFiManagerMode);
|
||||
if (ag->isOneIndoor()) {
|
||||
sm.handleLeds(AgStateMachineWiFiManagerMode);
|
||||
if (ag->isOne()) {
|
||||
sm.displayHandle(AgStateMachineWiFiManagerMode);
|
||||
}
|
||||
}
|
||||
@ -121,15 +126,18 @@ bool AgWiFiConnector::connect(void) {
|
||||
}
|
||||
/** Show display wifi connect result failed */
|
||||
if (WiFi.isConnected() == false) {
|
||||
sm.ledHandle(AgStateMachineWiFiManagerConnectFailed);
|
||||
if (ag->isOneIndoor()) {
|
||||
sm.handleLeds(AgStateMachineWiFiManagerConnectFailed);
|
||||
if (ag->isOne()) {
|
||||
sm.displayHandle(AgStateMachineWiFiManagerConnectFailed);
|
||||
}
|
||||
delay(6000);
|
||||
} else {
|
||||
hasConfig = true;
|
||||
logInfo("WiFi Connected: " + WiFi.SSID() + " IP: " + localIpStr());
|
||||
}
|
||||
|
||||
#else
|
||||
_wifiProcess();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -137,50 +145,69 @@ bool AgWiFiConnector::connect(void) {
|
||||
* @brief Disconnect to current connected WiFi AP
|
||||
*
|
||||
*/
|
||||
void AgWiFiConnector::disconnect(void) {
|
||||
void WifiConnector::disconnect(void) {
|
||||
if (WiFi.isConnected()) {
|
||||
logInfo("Disconnect");
|
||||
WiFi.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
#else
|
||||
void WifiConnector::displayShowText(String ln1, String ln2, String ln3) {
|
||||
char buf[9];
|
||||
ag->display.clear();
|
||||
|
||||
ag->display.setCursor(1, 1);
|
||||
ag->display.setText(ln1);
|
||||
ag->display.setCursor(1, 19);
|
||||
ag->display.setText(ln2);
|
||||
ag->display.setCursor(1, 37);
|
||||
ag->display.setText(ln3);
|
||||
|
||||
ag->display.show();
|
||||
delay(100);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Has wifi STA connected to WIFI softAP (this device)
|
||||
*
|
||||
* @return true Connected
|
||||
* @return false Not connected
|
||||
*/
|
||||
bool AgWiFiConnector::wifiClientConnected(void) {
|
||||
bool WifiConnector::wifiClientConnected(void) {
|
||||
return WiFi.softAPgetStationNum() ? true : false;
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
/**
|
||||
* @brief Handle WiFiManage softAP setup completed callback
|
||||
*
|
||||
*/
|
||||
void AgWiFiConnector::_wifiApCallback(void) {
|
||||
void WifiConnector::_wifiApCallback(void) {
|
||||
sm.displayWiFiConnectCountDown(WIFI_CONNECT_COUNTDOWN_MAX);
|
||||
sm.setDisplayState(AgStateMachineWiFiManagerMode);
|
||||
sm.ledAnimationInit();
|
||||
sm.ledHandle(AgStateMachineWiFiManagerMode);
|
||||
sm.handleLeds(AgStateMachineWiFiManagerMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle WiFiManager save configuration callback
|
||||
*
|
||||
*/
|
||||
void AgWiFiConnector::_wifiSaveConfig(void) {
|
||||
void WifiConnector::_wifiSaveConfig(void) {
|
||||
sm.setDisplayState(AgStateMachineWiFiManagerStaConnected);
|
||||
sm.ledHandle(AgStateMachineWiFiManagerStaConnected);
|
||||
sm.handleLeds(AgStateMachineWiFiManagerStaConnected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle WiFiManager save parameter callback
|
||||
*
|
||||
*/
|
||||
void AgWiFiConnector::_wifiSaveParamCallback(void) {
|
||||
void WifiConnector::_wifiSaveParamCallback(void) {
|
||||
sm.ledAnimationInit();
|
||||
sm.ledHandle(AgStateMachineWiFiManagerStaConnecting);
|
||||
sm.handleLeds(AgStateMachineWiFiManagerStaConnecting);
|
||||
sm.setDisplayState(AgStateMachineWiFiManagerStaConnecting);
|
||||
}
|
||||
|
||||
@ -190,21 +217,52 @@ void AgWiFiConnector::_wifiSaveParamCallback(void) {
|
||||
* @return true Active
|
||||
* @return false Not-Active
|
||||
*/
|
||||
bool AgWiFiConnector::_wifiConfigPortalActive(void) {
|
||||
bool WifiConnector::_wifiConfigPortalActive(void) {
|
||||
return WIFI()->getConfigPortalActive();
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* @brief Process WiFiManager connection
|
||||
*
|
||||
*/
|
||||
void AgWiFiConnector::_wifiProcess() { WIFI()->process(); }
|
||||
void WifiConnector::_wifiProcess() {
|
||||
#ifdef ESP32
|
||||
WIFI()->process();
|
||||
#else
|
||||
int count = WIFI_CONNECT_COUNTDOWN_MAX;
|
||||
displayShowText(String(WIFI_CONNECT_COUNTDOWN_MAX) + " sec", "SSID:", ssid);
|
||||
while (WIFI()->getConfigPortalActive()) {
|
||||
WIFI()->process();
|
||||
|
||||
uint32_t lastTime = millis();
|
||||
uint32_t ms = (uint32_t)(millis() - lastTime);
|
||||
if (ms >= 1000) {
|
||||
lastTime = millis();
|
||||
|
||||
displayShowText(String(count) + " sec", "SSID:", ssid);
|
||||
|
||||
count--;
|
||||
|
||||
// Timeout
|
||||
if (count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!WiFi.isConnected()) {
|
||||
displayShowText("Booting", "offline", "mode");
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(2500);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle and reconnect WiFi
|
||||
*
|
||||
*/
|
||||
void AgWiFiConnector::handle(void) {
|
||||
void WifiConnector::handle(void) {
|
||||
// Ignore if WiFi is not configured
|
||||
if (hasConfig == false) {
|
||||
return;
|
||||
@ -232,27 +290,25 @@ void AgWiFiConnector::handle(void) {
|
||||
* @return true Connected
|
||||
* @return false Disconnected
|
||||
*/
|
||||
bool AgWiFiConnector::isConnected(void) { return WiFi.isConnected(); }
|
||||
bool WifiConnector::isConnected(void) { return WiFi.isConnected(); }
|
||||
|
||||
/**
|
||||
* @brief Reset WiFi configuretion and connection, disconnect wifi before call
|
||||
* this method
|
||||
*
|
||||
*/
|
||||
void AgWiFiConnector::reset(void) { WIFI()->resetSettings(); }
|
||||
void WifiConnector::reset(void) { WIFI()->resetSettings(); }
|
||||
|
||||
/**
|
||||
* @brief Get wifi RSSI
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int AgWiFiConnector::RSSI(void) { return WiFi.RSSI(); }
|
||||
int WifiConnector::RSSI(void) { return WiFi.RSSI(); }
|
||||
|
||||
/**
|
||||
* @brief Get WIFI IP as string format ex: 192.168.1.1
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String AgWiFiConnector::localIpStr(void) { return WiFi.localIP().toString(); }
|
||||
|
||||
#endif
|
||||
String WifiConnector::localIpStr(void) { return WiFi.localIP().toString(); }
|
||||
|
@ -1,5 +1,3 @@
|
||||
#ifdef ESP32
|
||||
|
||||
#ifndef _AG_WIFI_CONNECTOR_H_
|
||||
#define _AG_WIFI_CONNECTOR_H_
|
||||
|
||||
@ -10,11 +8,15 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class AgWiFiConnector : public PrintLog {
|
||||
class WifiConnector : public PrintLog {
|
||||
private:
|
||||
AirGradient *ag;
|
||||
AgOledDisplay &disp;
|
||||
AgStateMachine &sm;
|
||||
#ifdef ESP32
|
||||
OledDisplay &disp;
|
||||
StateMachine &sm;
|
||||
#else
|
||||
void displayShowText(String ln1, String ln2, String ln3);
|
||||
#endif
|
||||
String ssid;
|
||||
void *wifi = NULL;
|
||||
bool hasConfig;
|
||||
@ -23,17 +25,23 @@ private:
|
||||
bool wifiClientConnected(void);
|
||||
|
||||
public:
|
||||
AgWiFiConnector(AgOledDisplay &disp, Stream &log, AgStateMachine &sm);
|
||||
~AgWiFiConnector();
|
||||
|
||||
void setAirGradient(AirGradient *ag);
|
||||
#ifdef ESP32
|
||||
WifiConnector(OledDisplay &disp, Stream &log, StateMachine &sm);
|
||||
#else
|
||||
WifiConnector(Stream &log);
|
||||
#endif
|
||||
~WifiConnector();
|
||||
|
||||
bool connect(void);
|
||||
void disconnect(void);
|
||||
void handle(void);
|
||||
#ifdef ESP32
|
||||
void _wifiApCallback(void);
|
||||
void _wifiSaveConfig(void);
|
||||
void _wifiSaveParamCallback(void);
|
||||
bool _wifiConfigPortalActive(void);
|
||||
#endif
|
||||
void _wifiProcess();
|
||||
bool isConnected(void);
|
||||
void reset(void);
|
||||
@ -42,6 +50,3 @@ public:
|
||||
};
|
||||
|
||||
#endif /** _AG_WIFI_CONNECTOR_H_ */
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -50,7 +50,13 @@ String AirGradient::getBoardName(void) {
|
||||
return String(getBoardDefName(boardType));
|
||||
}
|
||||
|
||||
bool AirGradient::isOneIndoor(void) {
|
||||
/**
|
||||
* @brief Board Type is ONE_INDOOR
|
||||
*
|
||||
* @return true ONE_INDOOR
|
||||
* @return false Other
|
||||
*/
|
||||
bool AirGradient::isOne(void) {
|
||||
return boardType == BoardType::ONE_INDOOR;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
* @return true Yes
|
||||
* @return false No
|
||||
*/
|
||||
bool isOneIndoor(void);
|
||||
bool isOne(void);
|
||||
|
||||
/**
|
||||
* @brief Get device Id
|
||||
|
@ -54,6 +54,14 @@ enum AgStateMachineState {
|
||||
the server side */
|
||||
AgStateMachineSensorConfigFailed,
|
||||
|
||||
/** CO2 calibration */
|
||||
AgStateMachineCo2Calibration,
|
||||
|
||||
/* LED bar testing */
|
||||
AgStateMachineLedBarTest,
|
||||
|
||||
/** LED: Show working state.
|
||||
* Display: Show dashboard */
|
||||
AgStateMachineNormal,
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user