Code cleanup.
This commit is contained in:
parent
4233764120
commit
f20ff5a4bb
|
@ -14,23 +14,14 @@ namespace Dough
|
|||
mqtt(&wifi, mqttOnConnectCallback, mqttOnMessageCallback),
|
||||
sensorControllerPlugin(&mqtt, &ui),
|
||||
distanceSensor(
|
||||
&sensorControllerPlugin,
|
||||
&mqtt, "distance", distanceSensorX,
|
||||
DISTANCE_AVERAGE_STORAGE,
|
||||
DISTANCE_MEASURE_INTERVAL,
|
||||
MINIMUM_PUBLISH_INTERVAL),
|
||||
new DistanceSensor(), &sensorControllerPlugin,
|
||||
DISTANCE_AVERAGE_STORAGE, DISTANCE_MEASURE_INTERVAL, MINIMUM_PUBLISH_INTERVAL),
|
||||
temperatureSensor(
|
||||
&sensorControllerPlugin,
|
||||
&mqtt, "temperature", temperatureSensorX,
|
||||
TEMPERATURE_AVERAGE_STORAGE,
|
||||
TEMPERATURE_MEASURE_INTERVAL,
|
||||
MINIMUM_PUBLISH_INTERVAL),
|
||||
new TemperatureSensor(), &sensorControllerPlugin,
|
||||
TEMPERATURE_AVERAGE_STORAGE, TEMPERATURE_MEASURE_INTERVAL, MINIMUM_PUBLISH_INTERVAL),
|
||||
humiditySensor(
|
||||
&sensorControllerPlugin,
|
||||
&mqtt, "humidity", humiditySensorX,
|
||||
HUMIDITY_AVERAGE_STORAGE,
|
||||
HUMIDITY_MEASURE_INTERVAL,
|
||||
MINIMUM_PUBLISH_INTERVAL),
|
||||
new HumiditySensor(), &sensorControllerPlugin,
|
||||
HUMIDITY_AVERAGE_STORAGE, HUMIDITY_MEASURE_INTERVAL, MINIMUM_PUBLISH_INTERVAL),
|
||||
_logger("APP") {}
|
||||
|
||||
void App::setup()
|
||||
|
@ -50,14 +41,10 @@ namespace Dough
|
|||
return;
|
||||
}
|
||||
|
||||
// Get measurements from the sensors. Suspend the user interface
|
||||
// interrupts in the meanwhile, to not disturb the timing-sensitive
|
||||
// sensor readings.
|
||||
ui.suspend();
|
||||
// Get measurements from the sensors.
|
||||
temperatureSensor.loop();
|
||||
humiditySensor.loop();
|
||||
distanceSensor.loop();
|
||||
ui.resume();
|
||||
}
|
||||
|
||||
void App::clearHistory()
|
||||
|
|
|
@ -23,11 +23,8 @@ namespace Dough
|
|||
WiFi wifi;
|
||||
MQTT mqtt;
|
||||
SensorControllerPlugin sensorControllerPlugin;
|
||||
DistanceSensor distanceSensorX;
|
||||
SensorController distanceSensor;
|
||||
TemperatureSensor temperatureSensorX;
|
||||
SensorController temperatureSensor;
|
||||
HumiditySensor humiditySensorX;
|
||||
SensorController humiditySensor;
|
||||
|
||||
void setup();
|
||||
|
|
|
@ -2,21 +2,33 @@
|
|||
|
||||
namespace Dough
|
||||
{
|
||||
SensorControllerPlugin::SensorControllerPlugin(MQTT *mqtt, UI *ui) : _mqtt(mqtt), _ui(ui)
|
||||
{
|
||||
}
|
||||
|
||||
void SensorControllerPlugin::doPublish(SensorController *controller) {
|
||||
Serial.println(">>>>>>>>>> YO PLUGIN HERE! <<<<<<<<<<<");
|
||||
}
|
||||
SensorControllerPlugin::SensorControllerPlugin(MQTT *mqtt, UI *ui) : _mqtt(mqtt), _ui(ui) {}
|
||||
|
||||
void SensorControllerPlugin::beforeMeasure(SensorController *controller)
|
||||
{
|
||||
_ui->notifySensorActivity();
|
||||
|
||||
// Suspend the user interface interrupts, to not disturb the timing-sensitive
|
||||
// sensor readings.
|
||||
_ui->suspend();
|
||||
}
|
||||
|
||||
void SensorControllerPlugin::afterMeasure(SensorController *controller)
|
||||
{
|
||||
_ui->resume();
|
||||
}
|
||||
|
||||
void SensorControllerPlugin::beforePublish(SensorController *controller)
|
||||
{
|
||||
_ui->notifyNetworkActivity();
|
||||
}
|
||||
|
||||
void SensorControllerPlugin::doPublish(SensorController *controller, Measurement last, Measurement average)
|
||||
{
|
||||
const char *sensorName = controller->getSensorName();
|
||||
static char mqttAverageKey[50];
|
||||
snprintf(mqttAverageKey, 50, "%s/average", sensorName);
|
||||
_mqtt->publish(sensorName, last);
|
||||
_mqtt->publish(mqttAverageKey, average);
|
||||
}
|
||||
}
|
|
@ -11,13 +11,15 @@ namespace Dough
|
|||
{
|
||||
// This class is a plugin for the Dough::SensorController. It takes care
|
||||
// of notifying events via the device UI and publishing data via the MQTT broker.
|
||||
// This decouples the sensor controller for the network and user interface specifics.
|
||||
class SensorControllerPlugin : public SensorControllerPluginBase
|
||||
{
|
||||
public:
|
||||
SensorControllerPlugin(MQTT *mqtt, UI *ui);
|
||||
virtual void beforeMeasure(SensorController *controller);
|
||||
virtual void afterMeasure(SensorController *controller);
|
||||
virtual void beforePublish(SensorController *controller);
|
||||
virtual void doPublish(SensorController *controller);
|
||||
virtual void doPublish(SensorController *controller, Measurement last, Measurement average);
|
||||
|
||||
private:
|
||||
MQTT *_mqtt;
|
||||
|
|
|
@ -39,7 +39,7 @@ void setupButtonInterruptCallback()
|
|||
|
||||
// This callback is called when the TC4 timer from the UI code hits an overflow
|
||||
// interrupt. It is defined outside the Dough namespace, because TC4_Handler is
|
||||
// a hard-coded root namespace function name.
|
||||
// a hard-coded, root namespace function name.
|
||||
void TC4_Handler()
|
||||
{
|
||||
Dough::App::Instance()->ui.updateLEDs();
|
||||
|
|
|
@ -2,16 +2,19 @@
|
|||
|
||||
namespace Dough
|
||||
{
|
||||
DistanceSensor::DistanceSensor() : _logger("DISTANCE")
|
||||
{
|
||||
_hcsr04 = new SensorHCSR04(HCSR04_TRIG_PIN, HCSR04_ECHO_PIN);
|
||||
}
|
||||
DistanceSensor::DistanceSensor() : _logger(getName()),
|
||||
_hcsr04(new SensorHCSR04(HCSR04_TRIG_PIN, HCSR04_ECHO_PIN)) {}
|
||||
|
||||
void DistanceSensor::setup()
|
||||
{
|
||||
_hcsr04->setup();
|
||||
}
|
||||
|
||||
const char* DistanceSensor::getName()
|
||||
{
|
||||
return "distance";
|
||||
}
|
||||
|
||||
void DistanceSensor::setTemperature(int temperature)
|
||||
{
|
||||
_hcsr04->setTemperature(temperature);
|
||||
|
|
|
@ -14,9 +14,10 @@ namespace Dough
|
|||
{
|
||||
public:
|
||||
DistanceSensor();
|
||||
virtual void setup();
|
||||
virtual const char* getName();
|
||||
void setTemperature(int temperature);
|
||||
void setHumidity(int humidity);
|
||||
virtual void setup();
|
||||
virtual Measurement read();
|
||||
virtual unsigned int getPrecision();
|
||||
|
||||
|
|
|
@ -2,13 +2,18 @@
|
|||
|
||||
namespace Dough
|
||||
{
|
||||
HumiditySensor::HumiditySensor() : _logger("HUMIDITY") {}
|
||||
HumiditySensor::HumiditySensor() : _logger(getName()) {}
|
||||
|
||||
void HumiditySensor::setup()
|
||||
{
|
||||
SensorDHT11::Instance()->begin();
|
||||
}
|
||||
|
||||
const char* HumiditySensor::getName()
|
||||
{
|
||||
return "humidity";
|
||||
}
|
||||
|
||||
Measurement HumiditySensor::read()
|
||||
{
|
||||
float t = SensorDHT11::Instance()->readHumidity();
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace Dough
|
|||
public:
|
||||
HumiditySensor();
|
||||
virtual void setup();
|
||||
virtual const char* getName();
|
||||
virtual Measurement read();
|
||||
virtual unsigned int getPrecision();
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Dough
|
|||
{
|
||||
public:
|
||||
virtual void setup();
|
||||
virtual const char* getName();
|
||||
virtual Measurement read();
|
||||
virtual unsigned int getPrecision();
|
||||
};
|
||||
|
|
|
@ -2,13 +2,18 @@
|
|||
|
||||
namespace Dough
|
||||
{
|
||||
TemperatureSensor::TemperatureSensor() : _logger("TEMPERATURE") {}
|
||||
TemperatureSensor::TemperatureSensor() : _logger(getName()) {}
|
||||
|
||||
void TemperatureSensor::setup()
|
||||
{
|
||||
SensorDHT11::Instance()->begin();
|
||||
}
|
||||
|
||||
const char* TemperatureSensor::getName()
|
||||
{
|
||||
return "temperature";
|
||||
}
|
||||
|
||||
Measurement TemperatureSensor::read()
|
||||
{
|
||||
float t = SensorDHT11::Instance()->readTemperature();
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace Dough
|
|||
public:
|
||||
TemperatureSensor();
|
||||
virtual void setup();
|
||||
virtual const char* getName();
|
||||
virtual Measurement read();
|
||||
virtual unsigned int getPrecision();
|
||||
|
||||
|
|
|
@ -4,32 +4,29 @@
|
|||
namespace Dough
|
||||
{
|
||||
SensorController::SensorController(
|
||||
SensorBase *sensor,
|
||||
SensorControllerPluginBase *plugin,
|
||||
MQTT *mqtt,
|
||||
const char *mqttKey,
|
||||
SensorBase &sensor,
|
||||
unsigned int storageSize,
|
||||
unsigned int minimumMeasureTime,
|
||||
unsigned int minimumPublishTime) : _plugin(plugin),
|
||||
_mqtt(mqtt),
|
||||
_sensor(sensor)
|
||||
unsigned int minimumPublishTime) : _sensor(sensor),
|
||||
_plugin(plugin),
|
||||
_storageSize(storageSize),
|
||||
_minimumMeasureTime(minimumMeasureTime),
|
||||
_minimumPublishTime(minimumPublishTime) {}
|
||||
|
||||
const char* SensorController::getSensorName()
|
||||
{
|
||||
_mqttKey = mqttKey;
|
||||
_storageSize = storageSize;
|
||||
_minimumMeasureTime = minimumMeasureTime;
|
||||
_minimumPublishTime = minimumPublishTime;
|
||||
return _sensor->getName();
|
||||
}
|
||||
|
||||
void SensorController::setup()
|
||||
{
|
||||
_sensor.setup();
|
||||
_sensor->setup();
|
||||
|
||||
// Format the key to use for publishing the average (i.e. "<mqttKey>/average").
|
||||
auto lenAverageKey = strlen(_mqttKey) + 9; // +9 for the "/average\0" suffix
|
||||
_mqttAverageKey = new char[lenAverageKey];
|
||||
snprintf(_mqttAverageKey, lenAverageKey, "%s/average", _mqttKey);
|
||||
|
||||
// Initialize the storage for holding the measurements.
|
||||
// Initialize the storage for holding measurements. This storage is used
|
||||
// as a circular buffer, and it helps in computing an over time average
|
||||
// value for the collected measurements. The bigger the storage size, the
|
||||
// more values will be included for the average computation.
|
||||
_storage = new Measurement *[_storageSize];
|
||||
for (unsigned int i = 0; i < _storageSize; i++)
|
||||
{
|
||||
|
@ -49,10 +46,13 @@ namespace Dough
|
|||
if (_mustPublish())
|
||||
{
|
||||
_plugin->beforePublish(this);
|
||||
Serial.println("CALLING doPublish() from plugin"); // DEBUG XXX
|
||||
_plugin->doPublish(this);
|
||||
auto average = _getAverage();
|
||||
auto last = _getLast();
|
||||
_lastPublishedAt = millis();
|
||||
average.copyTo(&_lastPublishedAverage);
|
||||
last.copyTo(&_lastPublished);
|
||||
_plugin->doPublish(this, last, average);
|
||||
_plugin->afterPublish(this);
|
||||
_publish();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,12 +75,12 @@ namespace Dough
|
|||
{
|
||||
_lastMeasuredAt = millis();
|
||||
|
||||
_store(_sensor.read());
|
||||
_store(_sensor->read());
|
||||
}
|
||||
|
||||
bool SensorController::_mustPublish()
|
||||
{
|
||||
Measurement lastMeasurement = getLast();
|
||||
Measurement lastMeasurement = _getLast();
|
||||
|
||||
// When the measurement failed, then there's no need to publish it.
|
||||
if (lastMeasurement.ok == false)
|
||||
|
@ -103,7 +103,7 @@ namespace Dough
|
|||
return _lastPublishedAt == 0 || delta >= (_minimumPublishTime * 1000);
|
||||
}
|
||||
|
||||
auto precision = _sensor.getPrecision();
|
||||
auto precision = _sensor->getPrecision();
|
||||
|
||||
// When there is a significant change in the sensor value, then publish.
|
||||
if (abs(_lastPublished.value - lastMeasurement.value) >= precision)
|
||||
|
@ -111,7 +111,7 @@ namespace Dough
|
|||
return true;
|
||||
}
|
||||
|
||||
auto average = getAverage();
|
||||
auto average = _getAverage();
|
||||
|
||||
// When there is a significant change in the average value, then publish.
|
||||
if (average.ok && abs(_lastPublishedAverage.value - average.value) >= precision)
|
||||
|
@ -131,19 +131,6 @@ namespace Dough
|
|||
return false;
|
||||
}
|
||||
|
||||
void SensorController::_publish()
|
||||
{
|
||||
auto average = getAverage();
|
||||
auto last = getLast();
|
||||
|
||||
_mqtt->publish(_mqttKey, last);
|
||||
_mqtt->publish(_mqttAverageKey, average);
|
||||
|
||||
_lastPublishedAt = millis();
|
||||
average.copyTo(&_lastPublishedAverage);
|
||||
last.copyTo(&_lastPublished);
|
||||
}
|
||||
|
||||
void SensorController::_store(Measurement measurement)
|
||||
{
|
||||
measurement.copyTo(_storage[_next()]);
|
||||
|
@ -177,12 +164,12 @@ namespace Dough
|
|||
return _index;
|
||||
}
|
||||
|
||||
Measurement SensorController::getLast()
|
||||
Measurement SensorController::_getLast()
|
||||
{
|
||||
return *_storage[_index];
|
||||
}
|
||||
|
||||
Measurement SensorController::getAverage()
|
||||
Measurement SensorController::_getAverage()
|
||||
{
|
||||
return _averageCount > 0
|
||||
? Measurement::Value(round(_averageSum / _averageCount))
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Dough
|
|||
virtual void beforeMeasure(SensorController *controller) {};
|
||||
virtual void afterMeasure(SensorController *controller) {};
|
||||
virtual void beforePublish(SensorController *controller) {};
|
||||
virtual void doPublish(SensorController *controller) {};
|
||||
virtual void doPublish(SensorController *controller, Measurement last, Measurement average) {};
|
||||
virtual void afterPublish(SensorController *controller) {};
|
||||
};
|
||||
|
||||
|
@ -33,67 +33,59 @@ namespace Dough
|
|||
public:
|
||||
// Create a new Measurements object.
|
||||
//
|
||||
// @param plugin
|
||||
// The Dough::SensorControllerPluginBase to use.
|
||||
// @param mqtt
|
||||
// The Dough::MQTT object, which is connected to the MQTT broker.
|
||||
// @param mqttKey
|
||||
// The key to use when publishing sensor values to MQTT.
|
||||
// The full key will be "<prefix>/<mqttKey>" for measurement values
|
||||
// and "<prefix>/<mqttKey>/average" for average values.
|
||||
// @param sensor
|
||||
// The sensor to read, implements SensorBase.
|
||||
// The Dough::SensorBase implementation to wrap in this controller.
|
||||
// @param plugin
|
||||
// The Dough::SensorControllerPluginBase implementation to use.
|
||||
// This plugin is used to decouple network / user interface functionality
|
||||
// from the sensor controller code.
|
||||
// @param storageSize
|
||||
// Number of measurements to keep track of for computing an average.
|
||||
// @param minimumMeasureTime
|
||||
// The number of seconds after which to read the next measurement
|
||||
// from the sensor.
|
||||
// @param onMeasure
|
||||
// A callback function that is called right before a measurement
|
||||
// is taken using the contained sensor object.
|
||||
// @param minimumPublishTime
|
||||
// The number of seconds after which to forcibly publish measurements
|
||||
// to MQTT, even when no significant changes to measurements were seen.
|
||||
// @param onPublish
|
||||
// A callback function that is called right before a measurement
|
||||
// is published.
|
||||
// "Significant change" is defined by the Dough::SensorBase implementation.
|
||||
SensorController(
|
||||
SensorBase *sensor,
|
||||
SensorControllerPluginBase *plugin,
|
||||
MQTT *mqtt,
|
||||
const char *mqttKey,
|
||||
SensorBase &sensor,
|
||||
unsigned int storageSize,
|
||||
unsigned int minimumMeasureTime,
|
||||
unsigned int minimumPublishTime);
|
||||
const char *getSensorName();
|
||||
void setup();
|
||||
void loop();
|
||||
Measurement getLast();
|
||||
Measurement getAverage();
|
||||
void clearHistory();
|
||||
|
||||
private:
|
||||
SensorBase *_sensor;
|
||||
SensorControllerPluginBase *_plugin;
|
||||
MQTT *_mqtt;
|
||||
const char *_mqttKey;
|
||||
char *_mqttAverageKey;
|
||||
SensorBase &_sensor;
|
||||
Measurement _getLast();
|
||||
Measurement _getAverage();
|
||||
|
||||
// Members related to the measurement storage.
|
||||
Measurement **_storage;
|
||||
unsigned int _storageSize;
|
||||
int _averageSum = 0;
|
||||
unsigned int _averageCount = 0;
|
||||
unsigned int _index = 0;
|
||||
void _store(Measurement measurement);
|
||||
unsigned int _next();
|
||||
|
||||
// Members used for controlling measurements.
|
||||
bool _mustMeasure();
|
||||
void _measure();
|
||||
unsigned int _minimumMeasureTime;
|
||||
unsigned long _lastMeasuredAt = 0;
|
||||
|
||||
// Members used for controlling publishing of measurements.
|
||||
bool _mustPublish();
|
||||
void _publish();
|
||||
unsigned int _minimumPublishTime;
|
||||
unsigned long _lastPublishedAt = 0;
|
||||
Measurement _lastPublished;
|
||||
Measurement _lastPublishedAverage;
|
||||
void _store(Measurement measurement);
|
||||
unsigned int _next();
|
||||
};
|
||||
} // namespace Dough
|
||||
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
namespace Dough
|
||||
{
|
||||
LED::LED(int pin)
|
||||
{
|
||||
_pin = pin;
|
||||
}
|
||||
LED::LED(int pin) : _pin(pin) {}
|
||||
|
||||
void LED::setup()
|
||||
{
|
||||
|
|
|
@ -4,7 +4,10 @@ namespace Dough
|
|||
{
|
||||
Logger::Logger(const char *section)
|
||||
{
|
||||
_section = section;
|
||||
strncpy(_section, section, sizeof(_section)/sizeof(_section[0]));
|
||||
for (unsigned int i = 0; i < strlen(_section); i++) {
|
||||
_section[i] = toupper(_section[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::setup()
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#ifndef DOUGH_LOGGER_H
|
||||
#define DOUGH_LOGGER_H
|
||||
|
||||
#define LOGGER_PREFIX_BUFLEN 16
|
||||
#define LOGGER_SECTION_BUFLEN 12
|
||||
#define LOGGER_PREFIX_BUFLEN LOGGER_SECTION_BUFLEN+3
|
||||
#define LOGGER_PREFIX_FORMAT "%11s | "
|
||||
|
||||
#include <Arduino.h>
|
||||
|
@ -23,7 +24,7 @@ namespace Dough
|
|||
void resume();
|
||||
|
||||
private:
|
||||
const char *_section;
|
||||
char _section[LOGGER_SECTION_BUFLEN];
|
||||
bool _suspended = false;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue