Implemented the calibration mode and introduced a 'height' value in the mqtt stream, which is (container height - distance measurement). First implementation, so much might still change. I'm thinking about introducing a virtual sensor, but I'm not sure yet what the cleanest implementation will look like.
This commit is contained in:
parent
e416dab9dd
commit
e48e44f287
130
src/App/App.cpp
130
src/App/App.cpp
|
@ -45,16 +45,8 @@ namespace Dough
|
|||
|
||||
void App::loop()
|
||||
{
|
||||
if (!wifi.isConnected())
|
||||
if (!_setupNetworking())
|
||||
{
|
||||
state.setWiFiConnected(false);
|
||||
state.setWiFiConnected(wifi.connect());
|
||||
return;
|
||||
}
|
||||
if (!mqtt.isConnected())
|
||||
{
|
||||
state.setMQTTConnected(false);
|
||||
state.setMQTTConnected(mqtt.connect());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -64,33 +56,13 @@ namespace Dough
|
|||
switch (state.get())
|
||||
{
|
||||
case CONFIGURING:
|
||||
if (config.isOk())
|
||||
{
|
||||
state.startMeasurements();
|
||||
}
|
||||
_doConfigure();
|
||||
break;
|
||||
case MEASURING:
|
||||
if (config.isOk())
|
||||
{
|
||||
if (temperatureController.loop())
|
||||
distanceSensor.setTemperature(temperatureController.getLast().value);
|
||||
if (humidityController.loop())
|
||||
distanceSensor.setHumidity(humidityController.getLast().value);
|
||||
distanceController.loop();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.startConfiguration();
|
||||
}
|
||||
_doMeasure();
|
||||
break;
|
||||
case CALIBRATING:
|
||||
temperatureController.loop();
|
||||
humidityController.loop();
|
||||
distanceController.loop();
|
||||
|
||||
delay(2000);
|
||||
state.pauseDevice();
|
||||
state.startMeasurements();
|
||||
_doCalibrate();
|
||||
break;
|
||||
case PAUSED:
|
||||
temperatureController.clearHistory();
|
||||
|
@ -102,4 +74,98 @@ namespace Dough
|
|||
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
|
|
@ -39,6 +39,10 @@ namespace Dough
|
|||
private:
|
||||
App();
|
||||
Logger _logger;
|
||||
bool _setupNetworking();
|
||||
void _doConfigure();
|
||||
void _doMeasure();
|
||||
void _doCalibrate();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -65,30 +65,37 @@ namespace Dough
|
|||
_mqttClient.subscribe(topic);
|
||||
}
|
||||
|
||||
void MQTT::publish(const char *key, const char *payload)
|
||||
void MQTT::publish(const char *key, const char *payload, bool retained)
|
||||
{
|
||||
char topic[200];
|
||||
snprintf(topic, sizeof(topic) / sizeof(topic[0]), "%s/%s/%s", MQTT_TOPIC_PREFIX, _mqttDeviceId, key);
|
||||
_logger.log("ssss", "Send message: ", topic, " = ", payload);
|
||||
_mqttClient.publish(topic, payload);
|
||||
}
|
||||
|
||||
void MQTT::publish(const char *key, int payload)
|
||||
if (retained)
|
||||
{
|
||||
char buf[16];
|
||||
snprintf(buf, 16, "%d", payload);
|
||||
publish(key, buf);
|
||||
}
|
||||
|
||||
void MQTT::publish(const char *key, Measurement measurement)
|
||||
{
|
||||
if (measurement.ok)
|
||||
{
|
||||
publish(key, measurement.value);
|
||||
_mqttClient.publish(topic, payload, true, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
publish(key, "null");
|
||||
_mqttClient.publish(topic, payload);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTT::publish(const char *key, int payload, bool retained)
|
||||
{
|
||||
char buf[16];
|
||||
snprintf(buf, 16, "%d", payload);
|
||||
publish(key, buf, retained);
|
||||
}
|
||||
|
||||
void MQTT::publish(const char *key, Measurement measurement, bool retained)
|
||||
{
|
||||
if (measurement.ok)
|
||||
{
|
||||
publish(key, measurement.value, retained);
|
||||
}
|
||||
else
|
||||
{
|
||||
publish(key, "null", retained);
|
||||
}
|
||||
}
|
||||
} // namespace Dough
|
|
@ -26,9 +26,9 @@ namespace Dough
|
|||
bool connect();
|
||||
void subscribe(const char *key);
|
||||
void procesIncomingsMessages();
|
||||
void publish(const char *key, const char *payload);
|
||||
void publish(const char *key, int payload);
|
||||
void publish(const char *key, Measurement measurement);
|
||||
void publish(const char *key, const char *payload, bool retained = false);
|
||||
void publish(const char *key, int payload, bool retained = false);
|
||||
void publish(const char *key, Measurement measurement, bool retained = false);
|
||||
|
||||
private:
|
||||
Logger _logger;
|
||||
|
|
|
@ -19,6 +19,11 @@ namespace Dough
|
|||
return sensor->getName();
|
||||
}
|
||||
|
||||
unsigned int SensorController::getPrecision()
|
||||
{
|
||||
return sensor->getPrecision();
|
||||
}
|
||||
|
||||
void SensorController::setup()
|
||||
{
|
||||
sensor->setup();
|
||||
|
@ -41,24 +46,24 @@ namespace Dough
|
|||
{
|
||||
_plugin->beforeMeasure(this);
|
||||
_lastMeasuredAt = millis();
|
||||
_store(sensor->read());
|
||||
_store(readSensor());
|
||||
_plugin->afterMeasure(this);
|
||||
}
|
||||
|
||||
auto last = getLast();
|
||||
|
||||
if (_mustPublish())
|
||||
{
|
||||
_plugin->beforePublish(this);
|
||||
auto last = getLast();
|
||||
auto average = getAverage();
|
||||
_lastPublishedAt = millis();
|
||||
average.copyTo(&_lastPublishedAverage);
|
||||
last.copyTo(&_lastPublished);
|
||||
_plugin->doPublish(this, last, average);
|
||||
_plugin->afterPublish(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return last.ok;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SensorController::_mustMeasure()
|
||||
|
@ -162,6 +167,11 @@ namespace Dough
|
|||
return _index;
|
||||
}
|
||||
|
||||
Measurement SensorController::readSensor()
|
||||
{
|
||||
return sensor->read();
|
||||
}
|
||||
|
||||
Measurement SensorController::getLast()
|
||||
{
|
||||
return *_storage[_index];
|
||||
|
|
|
@ -60,10 +60,13 @@ namespace Dough
|
|||
// Return the name for the contained sensor.
|
||||
const char *getSensorName();
|
||||
|
||||
// Return the measuring precision for the contained sensor.
|
||||
unsigned int getPrecision();
|
||||
|
||||
// Read the sensor and publish the results when needed.
|
||||
// This method returns true when the last read value was an ok measurement.
|
||||
// This means that after this method returns true, getLast() will return
|
||||
// an ok Dough::Measurement.
|
||||
// This method returns true when the last read value was an ok measurement
|
||||
// and a publish operation was done. This means that after this method returns
|
||||
// true, getLast() will return an ok Dough::Measurement.
|
||||
bool loop();
|
||||
|
||||
// Read a measurement from the sensor.
|
||||
|
|
Loading…
Reference in New Issue