arduino-doughboy/src/App/App.cpp

171 lines
5.0 KiB
C++

#include "App/App.h"
namespace Dough
{
App *App::Instance()
{
static App *_instance = new App();
return _instance;
}
App::App() : config(),
ui(onoffButtonInterruptCallback, setupButtonInterruptCallback),
wifi(),
mqtt(&wifi, mqttOnConnectCallback, mqttOnMessageCallback),
statePlugin(&ui, &mqtt),
state(&statePlugin),
sensorControllerPlugin(&mqtt, &ui),
distanceSensor(),
distanceController(
&distanceSensor, &sensorControllerPlugin,
DISTANCE_AVERAGE_STORAGE, DISTANCE_MEASURE_INTERVAL, MINIMUM_PUBLISH_INTERVAL),
temperatureController(
new TemperatureSensor(), &sensorControllerPlugin,
TEMPERATURE_AVERAGE_STORAGE, TEMPERATURE_MEASURE_INTERVAL, MINIMUM_PUBLISH_INTERVAL),
humidityController(
new HumiditySensor(), &sensorControllerPlugin,
HUMIDITY_AVERAGE_STORAGE, HUMIDITY_MEASURE_INTERVAL, MINIMUM_PUBLISH_INTERVAL),
_logger("APP")
{
ui.onoffButton.onPress(handleOnoffButtonPress);
ui.setupButton.onPress(handleSetupButtonPress);
}
void App::setup()
{
Dough::Logger::setup();
state.setup();
ui.setup();
wifi.setup();
mqtt.setup();
temperatureController.setup();
humidityController.setup();
distanceController.setup();
}
void App::loop()
{
if (!_setupNetworking())
{
return;
}
ui.processButtonEvents();
mqtt.procesIncomingsMessages();
switch (state.get())
{
case CONFIGURING:
_doConfigure();
break;
case MEASURING:
_doMeasure();
break;
case CALIBRATING:
_doCalibrate();
break;
case PAUSED:
temperatureController.clearHistory();
humidityController.clearHistory();
distanceController.clearHistory();
break;
default:
// NOOP
break;
}
}
bool App::_setupNetworking()
{
if (!wifi.isConnected())
{
state.setWiFiConnected(false);
state.setWiFiConnected(wifi.connect());
return false;
}
if (!mqtt.isConnected())
{
state.setMQTTConnected(false);
state.setMQTTConnected(mqtt.connect());
return false;
}
return true;
}
void App::_doConfigure()
{
if (config.isOk())
{
state.startMeasurements();
}
}
void App::_doMeasure()
{
if (config.isOk())
{
if (temperatureController.loop())
distanceSensor.setTemperature(temperatureController.getLast().value);
if (humidityController.loop())
distanceSensor.setHumidity(humidityController.getLast().value);
if (distanceController.loop())
mqtt.publish("height", config.getContainerHeight() - distanceController.getLast().value);
}
else
{
state.startConfiguration();
}
}
void App::_doCalibrate()
{
int count = 0;
int runningTotal = 0;
unsigned int firstValue = 0;
unsigned int precision = distanceController.getPrecision();
for (;;)
{
// Read a sensor value. When this fails, then restart the calibration.
auto m = distanceController.readSensor();
if (!m.ok)
{
_logger.log("s", "Sensor reading failed, restarting calibration");
return;
}
_logger.log("sisis", "Calibration reading ", count, ": ", m.value, "mm");
count++;
runningTotal += m.value;
// If this is the first value that is read, then use that one to compare
// the upcoming measurements against.
if (count == 1)
{
firstValue = m.value;
}
// Otherwise, check if the new value is within the precision range of the
// distance sensor.
else if (abs(firstValue - m.value) > precision)
{
_logger.log("s", "New reading exceeds sensor precision, restarting calibration");
return;
}
// After reading 10 values in a row that are within the sensor precision,
// then we have a winner.
if (count == 10)
{
break;
}
}
_logger.log("sis", "Calibration completed, container height: ", firstValue, "mm");
unsigned int container_height = int(runningTotal / 10);
config.setContainerHeight(container_height);
mqtt.publish("container_height", container_height, true);
state.pauseDevice();
state.startMeasurements();
}
} // namespace Dough