Initial implementation of the FSM, also cleaned up webUpdater ino file.

This commit is contained in:
Kai Lauterbach 2022-09-12 15:26:30 +02:00
parent 3cea359c49
commit b25ea99da0
5 changed files with 242 additions and 147 deletions

View file

@ -10,7 +10,7 @@
#define DELAY_LOOP_MS 50
#define POWERSAVING_SLEEP_S 600
#define EMERGENCY_SLEEP_S 172800 // Sleep for 2 days to recover
#define RESET_ESP_TIME_INTERVAL_MS (60*60*3*1000) // (60*60*6*1000) // reset every 3 hours
#define RESET_ESP_TIME_INTERVAL_MS (60*60*12*1000) // reset every 12 hours
#define WIND_SENSOR_MEAS_TIME_S 15
#define INITIAL_WEBSERVER_TIME 20

View file

@ -13,7 +13,6 @@
String DEVICE_NAME = "weatherstation";
// Enable/Disable features
//#define WEBUPDATER_FEATURE
#define INFLUXDB_FEATURE
#define INFLUXDB_VERSION 1 // 1 or 2
#define SERIAL_FEATURE

View file

@ -27,7 +27,9 @@
// constant variables
const uint8_t VALUES = 8; // see constants.h file - count of number of SENSOR_ defines
float currentSensorData[VALUES] = {nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value")};
float currentSensorData[VALUES] = { nanf("no value"), nanf("no value"), nanf("no value"),
nanf("no value"), nanf("no value"), nanf("no value"),
nanf("no value"), nanf("no value") };
float (*sensors[VALUES])() = {};
uint16_t update_sensor_cnt = 0;
@ -36,8 +38,26 @@ uint16_t update_windspeed_exceed_cnt = 0;
boolean validData = false;
const String wifiName = "oko-weather-" + DEVICE_NAME;
uint32_t wifi_check_interval_counter = millis();
WiFiManager wifiManager;
typedef enum fsm_states_et {
FSM_STATE_WU,
FSM_STATE_WSE,
FSM_STATE_RS,
FSM_STATE_BP,
FSM_STATE_WS,
FSM_STATE_US,
FSM_STATE_SC,
FSM_STATE_ID,
FSM_STATE_SD
} t_fsm_states;
t_fsm_states fsm_state = FSM_STATE_WU;
//*************************************************************************//
void debug(String x)
@ -47,6 +67,8 @@ void debug(String x)
#endif
}
//*************************************************************************//
void setup()
{
@ -73,13 +95,54 @@ void setup()
criticalBatCheck();
#endif
wifiConnectionCheck();
wifiConnect();
debug("Connected!");
#ifdef INFLUXDB_FEATURE
influxdb_begin();
#endif
initSensors();
#ifdef WEBUPDATER_FEATURE
#ifndef BATTERY_POWERED
setupWebUpdater(DEVICE_NAME, WiFi.localIP().toString());
#endif
#endif
//It's magic! leave in
delay(100);
#ifdef BATTERY_POWERED
debug("battery powered");
_loop();
digitalWrite(STATUS_LED_PIN, LOW);
criticalBatCheck();
WiFi.mode(WIFI_OFF);
WiFi.forceSleepBegin();
debug("deep sleep");
// the ESP.deepSleep requires microseconds as input, after the
// sleep the system will run into the setup routine
ESP.deepSleep(POWERSAVING_SLEEP_S * 1000000, WAKE_RF_DEFAULT);
delay(100);
#endif
#ifdef ENABLE_WATCHDOG
// Enable the internal watchdog
ESP.wdtEnable(WATCHDOG_TIMEOUT_MS);
#endif
}
//*************************************************************************//
void initSensors()
{
// Initialize and configure the sensors
#ifdef SENSOR_APDS9930
if (sensor_apds9930_begin()) {
@ -111,47 +174,29 @@ void setup()
sensors[SENSOR_BATCHARGESTATE] = &battery_charging;
sensors[SENSOR_ESAVEMODE] = &isEnergySavingMode;
#endif
#ifdef WEBUPDATER_FEATURE
#ifndef BATTERY_POWERED
setupWebUpdater(DEVICE_NAME, WiFi.localIP().toString());
#endif
#endif
//It's magic! leave in
delay(100);
#ifdef BATTERY_POWERED
debug("battery powered");
_loop();
digitalWrite(STATUS_LED_PIN, LOW);
criticalBatCheck();
WiFi.mode(WIFI_OFF);
WiFi.forceSleepBegin();
debug("deep sleep");
// the ESP.deepSleep requires microseconds as input, after the sleep the system will run into the setup routine
ESP.deepSleep(POWERSAVING_SLEEP_S * 1000000, WAKE_RF_DEFAULT);
delay(100);
#endif
#ifdef ENABLE_WATCHDOG
// Enable the internal watchdog
ESP.wdtEnable(WATCHDOG_TIMEOUT_MS);
#endif
}
//*************************************************************************//
void wifiConnectionCheck()
{
// Establish WiFi connection
String wifiName = "oko-weather-" + DEVICE_NAME;
if (millis() - wifi_check_interval_counter < WIFI_CHECK_INVERVAL_MS)
{
// if check interval is not exceeded abort check
return;
}
wifi_check_interval_counter = millis();
wifiConnect();
}
void wifiConnect()
{
// Establish WiFi connection if not already applied
wifiManager.setMinimumSignalQuality(WIFI_MINIMUM_SIGNAL_QUALITY);
// the time in seconds to wait for the known wifi connection
@ -161,7 +206,6 @@ void wifiConnectionCheck()
while (!wifiManager.autoConnect(wifiName.c_str(), "DEADBEEF"))
{
debug("WiFi connection failed, try again in 5 seconds...");
// If autoconnect to WLAN failed and no client connected, go to deep sleep
#ifdef SLEEP_IF_NO_WLAN_CONNECTION
ESP.deepSleep(POWERSAVING_SLEEP_S * 1000000, WAKE_RF_DEFAULT);
@ -169,6 +213,7 @@ void wifiConnectionCheck()
#endif
#ifndef SLEEP_IF_NO_WLAN_CONNECTION
// sleep a few seconds and go on trying to connect
debug("WiFi connection failed, try again in 5 seconds...");
delay(5000);
#endif
}
@ -191,6 +236,8 @@ void criticalBatCheck()
}
#endif
//*************************************************************************//
void loop()
{
@ -223,122 +270,158 @@ void loop()
}
//*************************************************************************//
void _loop()
{
switch (fsm_state)
{
case FSM_STATE_WU:
#ifdef WEBUPDATER_FEATURE
if (UPDATE_WEBSERVER_INTVERVAL_S * 1000 / DELAY_LOOP_MS <= update_webserver_cnt)
{
update_webserver_cnt = 0;
doWebUpdater();
}
#endif
#ifdef HTTP_CALL_ON_WINDSPEED_EXCEED
if (HTTP_CALL_ON_WINDSPEED_INTERVAL_S * 1000 / DELAY_LOOP_MS <= update_windspeed_exceed_cnt)
{
debug("Reading wind sensor because of exceed call functionality");
if (sensors[SENSOR_WINDSPEED])
{
// read from windspeed sensorSTATUS_LED_PIN
digitalWrite(STATUS_LED_PIN, HIGH);
currentSensorData[SENSOR_WINDSPEED] = sensors[SENSOR_WINDSPEED]();
digitalWrite(STATUS_LED_PIN, LOW);
if (currentSensorData[SENSOR_WINDSPEED] >= HTTP_CALL_ON_WINDSPEED_EXCEED_MPS)
if (UPDATE_WEBSERVER_INTVERVAL_S * 1000 / DELAY_LOOP_MS <= update_webserver_cnt)
{
digitalWrite(STATUS_LED_PIN, HIGH);
// call the url HTTP_CALL_ON_WINDSPEED_URL
WiFiClient client;
HTTPClient http;
http.begin(client, String(HTTP_CALL_ON_WINDSPEED_URL).c_str());
// Send HTTP GET request
int httpResponseCode = http.GET();
if (httpResponseCode > 0) {
String response = http.getString();
#ifdef DEBUG
Serial.println("http response code: " + String(httpResponseCode) + " = " + response);
#endif
// TODO handle response
}
http.end();
debug("Called windspeed exceed callout");
digitalWrite(STATUS_LED_PIN, LOW);
update_webserver_cnt = 0;
doWebUpdater();
}
} else {
currentSensorData[SENSOR_WINDSPEED] = nan("no value");
}
update_windspeed_exceed_cnt = 0;
}
#endif
fsm_state = FSM_STATE_WSE;
break;
case FSM_STATE_WSE:
#ifdef HTTP_CALL_ON_WINDSPEED_EXCEED
if (HTTP_CALL_ON_WINDSPEED_INTERVAL_S * 1000 / DELAY_LOOP_MS <= update_windspeed_exceed_cnt)
{
debug("Reading wind sensor because of exceed call functionality");
if (sensors[SENSOR_WINDSPEED])
{
// read from windspeed sensorSTATUS_LED_PIN
digitalWrite(STATUS_LED_PIN, HIGH);
currentSensorData[SENSOR_WINDSPEED] = sensors[SENSOR_WINDSPEED]();
digitalWrite(STATUS_LED_PIN, LOW);
if (currentSensorData[SENSOR_WINDSPEED] >= HTTP_CALL_ON_WINDSPEED_EXCEED_MPS)
{
digitalWrite(STATUS_LED_PIN, HIGH);
// call the url HTTP_CALL_ON_WINDSPEED_URL
WiFiClient client;
HTTPClient http;
http.begin(client, String(HTTP_CALL_ON_WINDSPEED_URL).c_str());
// Send HTTP GET request
int httpResponseCode = http.GET();
if (httpResponseCode > 0) {
String response = http.getString();
#ifdef DEBUG
Serial.println("http response code: " + String(httpResponseCode) + " = " + response);
#endif
// TODO handle response
}
http.end();
debug("Called windspeed exceed callout");
digitalWrite(STATUS_LED_PIN, LOW);
}
} else {
currentSensorData[SENSOR_WINDSPEED] = nan("no value");
}
update_windspeed_exceed_cnt = 0;
}
#endif
fsm_state = FSM_STATE_RS;
break;
case FSM_STATE_RS:
#ifdef RESET_ESP_TIME_INTERVAL
// if millis() reached interval restart ESP
if (RESET_ESP_TIME_INTERVAL_MS <= millis())
{
debug("Resetting firmware intentionally");
// Push reset button after flashing once or do a manual power cycle to get the functionality working.
ESP.restart();
}
// if millis() reached interval restart ESP
if (RESET_ESP_TIME_INTERVAL_MS <= millis())
{
debug("Resetting firmware intentionally");
// Push reset button after flashing once or do a manual power cycle to get the functionality working.
ESP.restart();
}
#endif
fsm_state = FSM_STATE_BP;
break;
case FSM_STATE_BP:
#ifndef BATTERY_POWERED
if (UPDATE_SENSOR_INTERVAL_S * 1000 / DELAY_LOOP_MS > update_sensor_cnt)
{
return;
}
if (UPDATE_SENSOR_INTERVAL_S * 1000 / DELAY_LOOP_MS > update_sensor_cnt)
{
return;
}
#endif
fsm_state = FSM_STATE_WS;
break;
case FSM_STATE_WS:
#ifdef defined(BATTERY_POWERED) && defined(SENSOR_WIND)
if (energySavingMode() == 1) {
// Disable expensive tasks
sensors[SENSOR_WINDSPEED] = 0;
} else {
sensors[SENSOR_WINDSPEED] = &wind_speed;
}
if (energySavingMode() == 1) {
// Disable expensive tasks
sensors[SENSOR_WINDSPEED] = 0;
} else {
sensors[SENSOR_WINDSPEED] = &wind_speed;
}
#endif
fsm_state = FSM_STATE_US;
break;
update_sensor_cnt = 0;
for (uint8_t i = 0; i < VALUES; i++)
{
if (sensors[i]) {
currentSensorData[i] = sensors[i]();
} else {
currentSensorData[i] = nan("no value");
}
}
case FSM_STATE_US:
update_sensor_cnt = 0;
for (uint8_t i = 0; i < VALUES; i++)
{
if (sensors[i]) {
currentSensorData[i] = sensors[i]();
} else {
currentSensorData[i] = nan("no value");
}
}
fsm_state = FSM_STATE_SC;
break;
case FSM_STATE_SC:
#ifdef SERIAL_FEATURE
logToSerial(currentSensorData);
logToSerial(currentSensorData);
#endif
fsm_state = FSM_STATE_ID;
break;
delay(100);
//delay(100); // TODO warum?
case FSM_STATE_ID:
#ifdef INFLUXDB_FEATURE
for (uint8_t i = 0; i < 5 and validData == false; i++)
{
if (currentSensorData[i] != 0)
{
validData = true; // at least one value is not zero, the data
}
}
if (validData == true)
{
// send data only if valid data is available
pushToInfluxDB(DEVICE_NAME, currentSensorData);
}
for (uint8_t i = 0; i < 5 and validData == false; i++)
{
if (currentSensorData[i] != 0)
{
validData = true; // at least one value is not zero, the data
}
}
if (validData == true)
{
// send data only if valid data is available
pushToInfluxDB(DEVICE_NAME, currentSensorData);
}
#endif
fsm_state = FSM_STATE_SD;
break;
case FSM_STATE_SD:
#ifdef WEBUPDATER_FEATURE
setSensorData(currentSensorData);
setSensorData(currentSensorData);
#endif
fsm_state = FSM_STATE_WU;
break;
default:
fsm_state = FSM_STATE_WU;
break;
} // close of switch
}
void logToSerial(float sensorValues[])

View file

@ -7,6 +7,8 @@
Influxdb _influxdb(INFLUXDB_HOST, INFLUXDB_PORT);
const String msg = "weather,device=" + device + " ";
void influxdb_begin() {
// Init variables to influxdb config - doesn't talk to database
_influxdb.opendb(INFLUXDB_DB, INFLUXDB_USER, INFLUXDB_PASS);
@ -16,7 +18,6 @@ void pushToInfluxDB(String device, float sensorValues[]) {
uint8_t tries = 0;
boolean addComma = false;
String msg = "weather,device=" + device + " ";
if (!(isnan(sensorValues[SENSOR_TEMPERATURE])))
{
msg += "temperature=" + String(sensorValues[SENSOR_TEMPERATURE]);
@ -172,7 +173,8 @@ void pushToInfluxDB(String device, float sensorValues[]) {
}
void _writePoint() {
void _writePoint()
{
// wait unitl ready
do {

View file

@ -23,15 +23,19 @@ String _webUpdater_ip = "127.0.0.1";
String _webUpdater_dev = "unknown";
float _webUpdater_sensValues[VALUES];
String hb_ws_msg_start = "{";
String hb_ws_msg_temp = "\"temperature\": ";
String hb_ws_msg_humi = "\"humidity\": ";
String hb_ws_msg_light = "\"lightlevel\": ";
String hb_ws_msg_windspeed = "\"windspeed\": ";
String hb_ws_msg_pressure = "\"pressure\": ";
String hb_ws_msg_timestamp = "\"timestamp\": ";
String hb_ws_msg_valid = "\"valid\": ";
String hb_ws_msg_end = "}";
const String hb_ws_msg_start = "{";
const String hb_ws_msg_temp = "\"temperature\": ";
const String hb_ws_msg_humi = "\"humidity\": ";
const String hb_ws_msg_light = "\"lightlevel\": ";
const String hb_ws_msg_windspeed = "\"windspeed\": ";
const String hb_ws_msg_pressure = "\"pressure\": ";
const String hb_ws_msg_timestamp = "\"timestamp\": ";
const String hb_ws_msg_valid = "\"valid\": ";
const String hb_ws_msg_end = "}";
#define TR_TD_START_STR "<tr><td>"
#define TR_TD_END_STR "</td></tr>"
#define TD_TD_MID_STR "</td><td>"
boolean wuValidData = false;
@ -87,20 +91,22 @@ void showHTMLMain(void)
"</head><body>"
"<br><a href=\"http://" + _webUpdater_ip + ":8080/update\">firmware update</a><br><br>"
"<table>"
"<tr><td>temperature</td><td>" + String(_webUpdater_sensValues[SENSOR_TEMPERATURE]) + "</td></tr>"
"<tr><td>humidity</td><td>" + String(_webUpdater_sensValues[SENSOR_HUMIDITY]) + "</td></tr>"
"<tr><td>light</td><td>" + String(_webUpdater_sensValues[SENSOR_LIGHT]) + "</td></tr>"
"<tr><td>windspeed</td><td>" + String(_webUpdater_sensValues[SENSOR_WINDSPEED]) + "</td></tr>"
"<tr><td>pressure</td><td>" + String(_webUpdater_sensValues[SENSOR_PRESSURE]) + "</td></tr>"
"<tr><td>batvoltage</td><td>" + String(_webUpdater_sensValues[SENSOR_BAT_VOLTAGE]) + "</td></tr>"
"<tr><td>millis</td><td>" + String(millis()) + "</td></tr>"
"<tr><td>valid</td><td>" + String(wuValidData) + "</td></tr>"
TR_TD_START_STR + "temperature" + TD_TD_MID_STR + String(_webUpdater_sensValues[SENSOR_TEMPERATURE]) + TR_TD_END_STR
TR_TD_START_STR + "humidity" + TD_TD_MID_STR + String(_webUpdater_sensValues[SENSOR_HUMIDITY]) + TR_TD_END_STR
TR_TD_START_STR + "light" + TD_TD_MID_STR + String(_webUpdater_sensValues[SENSOR_LIGHT]) + TR_TD_END_STR
TR_TD_START_STR + "windspeed" + TD_TD_MID_STR + String(_webUpdater_sensValues[SENSOR_WINDSPEED]) + TR_TD_END_STR
TR_TD_START_STR + "pressure" + TD_TD_MID_STR + String(_webUpdater_sensValues[SENSOR_PRESSURE]) + TR_TD_END_STR
TR_TD_START_STR + "batvoltage" + TD_TD_MID_STR + String(_webUpdater_sensValues[SENSOR_BAT_VOLTAGE]) + TR_TD_END_STR
TR_TD_START_STR + "millis" + TD_TD_MID_STR + String(millis()) + TR_TD_END_STR
TR_TD_START_STR + "valid" + TD_TD_MID_STR + String(wuValidData) + TR_TD_END_STR
TR_TD_START_STR + "wifi rssi" + TD_TD_MID_STR + WiFi.RSSI() + TR_TD_END_STR
"</table>"
"</body></html>";
httpServer.send(200, "text/html", message);
}
#ifdef HOMEBRIDGE_WEBSTAT
void hb_webstat_send(void)
{
String msg = hb_ws_msg_start +
@ -128,6 +134,7 @@ void hb_webstat_send(void)
httpServer.send(200, "text/html", msg);
}
#endif
void resetWifiManager()
{
@ -151,6 +158,8 @@ void resetWifiManager()
ESP.restart();
}
#ifdef DEBUG_WINDSPEED_MEASUREMENT
#ifdef SENSOR_WIND
void measureWindspeed()
{
@ -168,3 +177,5 @@ void measureWindspeed()
httpServer.send(200, "text/html", message);
}
#endif
#endif