Files
arduino/src/AgStateMachine.cpp

755 lines
23 KiB
C++
Raw Normal View History

2024-04-03 21:26:04 +07:00
#include "AgStateMachine.h"
#define LED_FAST_BLINK_DELAY 250 /** ms */
#define LED_SLOW_BLINK_DELAY 1000 /** ms */
#define LED_SHORT_BLINK_DELAY 500 /** ms */
#define LED_LONG_BLINK_DELAY 2000 /** ms */
2024-04-07 16:39:01 +07:00
#define SENSOR_CO2_CALIB_COUNTDOWN_MAX 5 /** sec */
2024-04-05 06:39:59 +07:00
/**
* @brief Animation LED bar with color
2024-04-07 16:39:01 +07:00
*
* @param r
* @param g
* @param b
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::ledBarSingleLedAnimation(uint8_t r, uint8_t g, uint8_t b) {
2024-04-03 21:26:04 +07:00
if (ledBarAnimationCount < 0) {
ledBarAnimationCount = 0;
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(r, g, b, ledBarAnimationCount);
2024-04-03 21:26:04 +07:00
} else {
ledBarAnimationCount++;
2024-04-04 10:36:59 +07:00
if (ledBarAnimationCount >= ag->ledBar.getNumberOfLeds()) {
2024-04-03 21:26:04 +07:00
ledBarAnimationCount = 0;
}
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(r, g, b, ledBarAnimationCount);
2024-04-03 21:26:04 +07:00
}
}
2024-04-05 06:39:59 +07:00
/**
* @brief LED status blink with delay
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
* @param ms Miliseconds
*/
2024-04-07 16:39:01 +07:00
void StateMachine::ledStatusBlinkDelay(uint32_t ms) {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOn();
2024-04-03 21:26:04 +07:00
delay(ms);
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
delay(ms);
}
2024-04-05 06:39:59 +07:00
/**
* @brief Led bar show led color status
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::sensorhandleLeds(void) {
2024-04-03 21:26:04 +07:00
switch (config.getLedBarMode()) {
case LedBarMode::LedBarModeCO2:
2024-04-07 16:39:01 +07:00
co2handleLeds();
2024-04-03 21:26:04 +07:00
break;
case LedBarMode::LedBarModePm:
2024-04-07 16:39:01 +07:00
pm25handleLeds();
2024-04-03 21:26:04 +07:00
break;
default:
2024-04-04 10:36:59 +07:00
ag->ledBar.clear();
2024-04-03 21:26:04 +07:00
break;
}
}
2024-04-05 06:39:59 +07:00
/**
* @brief Show CO2 LED status
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::co2handleLeds(void) {
2024-04-03 21:26:04 +07:00
int co2Value = value.CO2;
if (co2Value <= 400) {
/** G; 1 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(0, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
2024-04-03 21:26:04 +07:00
} else if (co2Value <= 700) {
/** GG; 2 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(0, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(0, 255, 0, ag->ledBar.getNumberOfLeds() - 2);
2024-04-03 21:26:04 +07:00
} else if (co2Value <= 1000) {
/** YYY; 3 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 3);
2024-04-03 21:26:04 +07:00
} else if (co2Value <= 1333) {
/** YYYY; 4 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 4);
2024-04-03 21:26:04 +07:00
} else if (co2Value <= 1666) {
/** YYYYY; 5 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 5);
2024-04-03 21:26:04 +07:00
} else if (co2Value <= 2000) {
/** RRRRRR; 6 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
2024-04-03 21:26:04 +07:00
} else if (co2Value <= 2666) {
/** RRRRRRR; 7 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 7);
2024-04-03 21:26:04 +07:00
} else if (co2Value <= 3333) {
/** RRRRRRRR; 8 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 7);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 8);
2024-04-03 21:26:04 +07:00
} else if (co2Value <= 4000) {
/** RRRRRRRRR; 9 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 7);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 8);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 9);
2024-04-03 21:26:04 +07:00
} else { /** > 4000 */
/* PRPRPRPRP; 9 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 7);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 8);
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 9);
2024-04-03 21:26:04 +07:00
}
}
2024-04-05 06:39:59 +07:00
/**
* @brief Show PM2.5 LED status
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::pm25handleLeds(void) {
int pm25Value = value.pm25_1;
2024-04-03 21:26:04 +07:00
if (pm25Value <= 5) {
/** G; 1 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(0, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
2024-04-03 21:26:04 +07:00
} else if (pm25Value <= 10) {
/** GG; 2 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(0, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(0, 255, 0, ag->ledBar.getNumberOfLeds() - 2);
2024-04-03 21:26:04 +07:00
} else if (pm25Value <= 20) {
/** YYY; 3 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 3);
2024-04-03 21:26:04 +07:00
} else if (pm25Value <= 35) {
/** YYYY; 4 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 4);
2024-04-03 21:26:04 +07:00
} else if (pm25Value <= 45) {
/** YYYYY; 5 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 255, 0, ag->ledBar.getNumberOfLeds() - 5);
2024-04-03 21:26:04 +07:00
} else if (pm25Value <= 55) {
/** RRRRRR; 6 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
2024-04-03 21:26:04 +07:00
} else if (pm25Value <= 65) {
/** RRRRRRR; 7 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 7);
2024-04-03 21:26:04 +07:00
} else if (pm25Value <= 150) {
/** RRRRRRRR; 8 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 7);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 8);
2024-04-03 21:26:04 +07:00
} else if (pm25Value <= 250) {
/** RRRRRRRRR; 9 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 7);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 8);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 9);
2024-04-03 21:26:04 +07:00
} else { /** > 250 */
/* PRPRPRPRP; 9 */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 1);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 2);
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 3);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 4);
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 5);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 6);
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 7);
ag->ledBar.setColor(255, 0, 0, ag->ledBar.getNumberOfLeds() - 8);
ag->ledBar.setColor(153, 153, 0, ag->ledBar.getNumberOfLeds() - 9);
2024-04-03 21:26:04 +07:00
}
}
2024-04-07 16:39:01 +07:00
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);
}
}
2024-04-21 16:44:43 +07:00
if (config.getCO2CalibrationAbcDays() >= 0 && config.hasSensorS8) {
2024-04-07 16:39:01 +07:00
int newHour = config.getCO2CalibrationAbcDays() * 24;
int curHour = ag->s8.getAbcPeriod();
if (curHour != newHour) {
String resultStr = "failure";
if (ag->s8.setAbcPeriod(config.getCO2CalibrationAbcDays() * 24)) {
resultStr = "successful";
}
String fromStr = String(curHour/24) + " days";
if(curHour == 0){
fromStr = "off";
}
String toStr = String(config.getCO2CalibrationAbcDays()) + " days";
if(config.getCO2CalibrationAbcDays() == 0) {
toStr = "off";
2024-04-07 16:39:01 +07:00
}
String msg = "Setting S8 from " + fromStr + " to " + toStr + " " + resultStr;
logInfo(msg);
2024-04-07 16:39:01 +07:00
}
} 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);
}
2024-04-05 06:39:59 +07:00
/**
* @brief Construct a new Ag State Machine:: Ag State Machine object
2024-04-07 16:39:01 +07:00
*
* @param disp OledDisplay
2024-04-05 06:39:59 +07:00
* @param log Serial Stream
2024-04-07 16:39:01 +07:00
* @param value Measurements
* @param config Configuration
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
StateMachine::StateMachine(OledDisplay &disp, Stream &log, Measurements &value,
Configuration &config)
: PrintLog(log, "StateMachine"), disp(disp), value(value), config(config) {}
2024-04-03 21:26:04 +07:00
2024-04-07 16:39:01 +07:00
StateMachine::~StateMachine() {}
2024-04-03 21:26:04 +07:00
2024-04-05 06:39:59 +07:00
/**
* @brief OLED display show content from state value
2024-04-07 16:39:01 +07:00
*
* @param state
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::displayHandle(AgStateMachineState state) {
2024-04-04 10:36:59 +07:00
// Ignore handle if not ONE_INDOOR board
2024-04-07 16:39:01 +07:00
if (!ag->isOne()) {
2024-04-04 10:36:59 +07:00
return;
}
2024-04-03 21:26:04 +07:00
if (state > AgStateMachineNormal) {
logError("displayHandle: State invalid");
return;
}
dispState = state;
switch (state) {
case AgStateMachineWiFiManagerMode:
case AgStateMachineWiFiManagerPortalActive: {
if (wifiConnectCountDown >= 0) {
2024-04-30 19:59:43 +07:00
String line1 = String(wifiConnectCountDown) + "s to connect";
String line2 = "to WiFi hotspot:";
String line3 = "\"airgradient-";
String line4 = ag->deviceId() + "\"";
disp.setText(line1, line2, line3, line4);
2024-04-03 21:26:04 +07:00
wifiConnectCountDown--;
}
break;
}
case AgStateMachineWiFiManagerStaConnecting: {
disp.setText("Trying to", "connect to WiFi", "...");
break;
}
case AgStateMachineWiFiManagerStaConnected: {
disp.setText("WiFi connection", "successful", "");
break;
}
case AgStateMachineWiFiOkServerConnecting: {
disp.setText("Connecting to", "Server", "...");
break;
}
case AgStateMachineWiFiOkServerConnected: {
disp.setText("Server", "connection", "successful");
break;
}
case AgStateMachineWiFiManagerConnectFailed: {
disp.setText("WiFi not", "connected", "");
break;
}
case AgStateMachineWiFiOkServerConnectFailed: {
// displayShowText("Server not", "reachable", "");
break;
}
case AgStateMachineWiFiOkServerOkSensorConfigFailed: {
disp.setText("Monitor not", "setup on", "dashboard");
break;
}
case AgStateMachineWiFiLost: {
disp.showDashboard("WiFi N/A");
break;
}
case AgStateMachineServerLost: {
disp.showDashboard("Server N/A");
break;
}
case AgStateMachineSensorConfigFailed: {
uint32_t ms = (uint32_t)(millis() - addToDashboardTime);
if (ms >= 5000) {
addToDashboardTime = millis();
if (addToDashBoard) {
disp.showDashboard("Add to Dashboard");
} else {
2024-04-04 10:36:59 +07:00
disp.showDashboard(ag->deviceId().c_str());
2024-04-03 21:26:04 +07:00
}
addToDashBoard = !addToDashBoard;
}
break;
}
case AgStateMachineNormal: {
disp.showDashboard();
2024-04-05 06:39:59 +07:00
break;
2024-04-03 21:26:04 +07:00
}
2024-04-07 16:39:01 +07:00
case AgStateMachineCo2Calibration:
co2Calibration();
break;
2024-04-03 21:26:04 +07:00
default:
break;
}
}
2024-04-05 06:39:59 +07:00
/**
* @brief OLED display show content as previous state updated
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::displayHandle(void) { displayHandle(dispState); }
2024-04-03 21:26:04 +07:00
2024-04-05 06:39:59 +07:00
/**
* @brief Update status add to dashboard
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::displaySetAddToDashBoard(void) {
2024-04-03 21:26:04 +07:00
addToDashBoard = true;
addToDashboardTime = millis();
}
2024-04-07 16:39:01 +07:00
void StateMachine::displayClearAddToDashBoard(void) { addToDashBoard = false; }
2024-04-03 21:26:04 +07:00
2024-04-05 06:39:59 +07:00
/**
* @brief Set WiFi connection coundown on dashboard
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
* @param count Seconds
*/
2024-04-07 16:39:01 +07:00
void StateMachine::displayWiFiConnectCountDown(int count) {
2024-04-03 21:26:04 +07:00
wifiConnectCountDown = count;
}
2024-04-05 06:39:59 +07:00
/**
* @brief Init before start LED bar animation
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::ledAnimationInit(void) { ledBarAnimationCount = -1; }
2024-04-03 21:26:04 +07:00
2024-04-05 06:39:59 +07:00
/**
* @brief Handle LED from state
2024-04-07 16:39:01 +07:00
*
* @param state
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::handleLeds(AgStateMachineState state) {
2024-04-03 21:26:04 +07:00
if (state > AgStateMachineNormal) {
logError("ledHandle: state invalid");
return;
}
ledState = state;
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.clear(); // Set all LED OFF
2024-04-03 21:26:04 +07:00
}
switch (state) {
case AgStateMachineWiFiManagerMode: {
/** In WiFi Manager Mode */
/** Turn LED OFF */
/** Turn midle LED Color */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(0, 0, 255, ag->ledBar.getNumberOfLeds() / 2);
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setToggle();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiManagerPortalActive: {
/** WiFi Manager has connected to mobile phone */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(0, 0, 255);
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOn();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiManagerStaConnecting: {
/** after SSID and PW entered and OK clicked, connection to WiFI network is
* attempted */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-03 21:26:04 +07:00
ledBarSingleLedAnimation(255, 255, 255);
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiManagerStaConnected: {
/** Connecting to WiFi worked */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 255, 255);
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiOkServerConnecting: {
/** once connected to WiFi an attempt to reach the server is performed */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-03 21:26:04 +07:00
ledBarSingleLedAnimation(0, 255, 0);
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiOkServerConnected: {
/** Server is reachable, all fine */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(0, 255, 0);
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
/** two time slow blink, then off */
for (int i = 0; i < 2; i++) {
ledStatusBlinkDelay(LED_SLOW_BLINK_DELAY);
}
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiManagerConnectFailed: {
/** Cannot connect to WiFi (e.g. wrong password, WPA Enterprise etc.) */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0);
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
for (int j = 0; j < 3; j++) {
for (int i = 0; i < 3; i++) {
ledStatusBlinkDelay(LED_FAST_BLINK_DELAY);
}
delay(2000);
}
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiOkServerConnectFailed: {
/** Connected to WiFi but server not reachable, e.g. firewall block/
* whitelisting needed etc. */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(233, 183, 54); /** orange */
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
for (int j = 0; j < 3; j++) {
for (int i = 0; i < 4; i++) {
ledStatusBlinkDelay(LED_FAST_BLINK_DELAY);
}
delay(2000);
}
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiOkServerOkSensorConfigFailed: {
/** Server reachable but sensor not configured correctly */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(139, 24, 248); /** violet */
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
for (int j = 0; j < 3; j++) {
for (int i = 0; i < 5; i++) {
ledStatusBlinkDelay(LED_FAST_BLINK_DELAY);
}
delay(2000);
}
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineWiFiLost: {
/** Connection to WiFi network failed credentials incorrect encryption not
* supported etc. */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-03 21:26:04 +07:00
/** WIFI failed status LED color */
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(255, 0, 0, 0);
2024-04-03 21:26:04 +07:00
/** Show CO2 or PM color status */
// sensorLedColorHandler();
2024-04-07 16:39:01 +07:00
sensorhandleLeds();
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineServerLost: {
/** Connected to WiFi network but the server cannot be reached through the
* internet, e.g. blocked by firewall */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(233, 183, 54, 0);
2024-04-03 21:26:04 +07:00
/** Show CO2 or PM color status */
2024-04-07 16:39:01 +07:00
sensorhandleLeds();
2024-04-03 21:26:04 +07:00
// sensorLedColorHandler();
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineSensorConfigFailed: {
/** Server is reachable but there is some configuration issue to be fixed on
* the server side */
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.setColor(139, 24, 248, 0);
2024-04-03 21:26:04 +07:00
/** Show CO2 or PM color status */
2024-04-07 16:39:01 +07:00
sensorhandleLeds();
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
case AgStateMachineNormal: {
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
sensorhandleLeds();
2024-04-03 21:26:04 +07:00
} else {
2024-04-04 10:36:59 +07:00
ag->statusLed.setOff();
2024-04-03 21:26:04 +07:00
}
break;
}
2024-04-07 16:39:01 +07:00
case AgStateMachineLedBarTest:
ledBarTest();
break;
2024-04-03 21:26:04 +07:00
default:
break;
}
2024-04-04 10:36:59 +07:00
// Show LED bar color
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ag->ledBar.show();
2024-04-03 21:26:04 +07:00
}
}
2024-04-05 06:39:59 +07:00
/**
* @brief Handle LED as previous state updated
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::handleLeds(void) { handleLeds(ledState); }
2024-04-03 21:26:04 +07:00
2024-04-05 06:39:59 +07:00
/**
* @brief Set display state
2024-04-07 16:39:01 +07:00
*
* @param state
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
void StateMachine::setDisplayState(AgStateMachineState state) {
2024-04-03 21:26:04 +07:00
dispState = state;
}
2024-04-05 06:39:59 +07:00
/**
* @brief Get current display state
2024-04-07 16:39:01 +07:00
*
* @return AgStateMachineState
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
AgStateMachineState StateMachine::getDisplayState(void) { return dispState; }
2024-04-04 10:36:59 +07:00
2024-04-05 06:39:59 +07:00
/**
* @brief Set AirGradient instance
2024-04-07 16:39:01 +07:00
*
2024-04-05 06:39:59 +07:00
* @param ag Point to AirGradient instance
*/
2024-04-07 16:39:01 +07:00
void StateMachine::setAirGradient(AirGradient *ag) { this->ag = ag; }
2024-04-05 06:39:59 +07:00
/**
* @brief Get current LED state
2024-04-07 16:39:01 +07:00
*
* @return AgStateMachineState
2024-04-05 06:39:59 +07:00
*/
2024-04-07 16:39:01 +07:00
AgStateMachineState StateMachine::getLedState(void) { return ledState; }
void StateMachine::executeCo2Calibration(void) {
displayHandle(AgStateMachineCo2Calibration);
}
void StateMachine::executeLedBarTest(void) {
handleLeds(AgStateMachineLedBarTest);
}