More shuffling of functionality, getting things to match with my standards for 'clean code'.

This commit is contained in:
Maurice Makaay 2020-07-18 14:55:41 +02:00
parent 7f5f60a6ac
commit 09f3be6dcb
19 changed files with 158 additions and 135 deletions

View File

@ -12,21 +12,25 @@ namespace Dough
ui(onoffButtonInterruptCallback, setupButtonInterruptCallback),
wifi(),
mqtt(&wifi, mqttOnConnectCallback, mqttOnMessageCallback),
temperatureSensor(
&mqtt, "temperature", TemperatureSensor::Instance(),
TEMPERATURE_AVERAGE_STORAGE,
TEMPERATURE_MEASURE_INTERVAL, sensorOnMeasureCallback,
MINIMUM_PUBLISH_INTERVAL, sensorOnPublishCallback),
humiditySensor(
&mqtt, "humidity", HumiditySensor::Instance(),
HUMIDITY_AVERAGE_STORAGE,
HUMIDITY_MEASURE_INTERVAL, sensorOnMeasureCallback,
MINIMUM_PUBLISH_INTERVAL, sensorOnPublishCallback),
sensorControllerPlugin(&mqtt, &ui),
distanceSensor(
&mqtt, "distance", DistanceSensor::Instance(),
&sensorControllerPlugin,
&mqtt, "distance", distanceSensorX,
DISTANCE_AVERAGE_STORAGE,
DISTANCE_MEASURE_INTERVAL, sensorOnMeasureCallback,
MINIMUM_PUBLISH_INTERVAL, sensorOnPublishCallback),
DISTANCE_MEASURE_INTERVAL,
MINIMUM_PUBLISH_INTERVAL),
temperatureSensor(
&sensorControllerPlugin,
&mqtt, "temperature", temperatureSensorX,
TEMPERATURE_AVERAGE_STORAGE,
TEMPERATURE_MEASURE_INTERVAL,
MINIMUM_PUBLISH_INTERVAL),
humiditySensor(
&sensorControllerPlugin,
&mqtt, "humidity", humiditySensorX,
HUMIDITY_AVERAGE_STORAGE,
HUMIDITY_MEASURE_INTERVAL,
MINIMUM_PUBLISH_INTERVAL),
_logger("APP") {}
void App::setup()
@ -41,8 +45,11 @@ namespace Dough
void App::measure()
{
if (config.isOk())
if (!config.isOk())
{
return;
}
// Get measurements from the sensors. Suspend the user interface
// interrupts in the meanwhile, to not disturb the timing-sensitive
// sensor readings.
@ -52,7 +59,6 @@ namespace Dough
distanceSensor.loop();
ui.resume();
}
}
void App::clearHistory()
{

View File

@ -5,10 +5,11 @@
#include "UI/UI.h"
#include "App/Configuration.h"
#include "App/callbacks.h"
#include "Data/SensorController.h"
#include "Sensors/TemperatureSensor.h"
#include "Sensors/HumiditySensor.h"
#include "Sensors/DistanceSensor.h"
#include "Sensors/SensorController.h"
#include "App/SensorControllerPlugin.h"
#include "Sensors/HighLevel/TemperatureSensor.h"
#include "Sensors/HighLevel/HumiditySensor.h"
#include "Sensors/HighLevel/DistanceSensor.h"
#include "config.h"
namespace Dough
@ -21,9 +22,13 @@ namespace Dough
UI ui;
WiFi wifi;
MQTT mqtt;
SensorController temperatureSensor;
SensorController humiditySensor;
SensorControllerPlugin sensorControllerPlugin;
DistanceSensor distanceSensorX;
SensorController distanceSensor;
TemperatureSensor temperatureSensorX;
SensorController temperatureSensor;
HumiditySensor humiditySensorX;
SensorController humiditySensor;
void setup();
void measure();

View File

@ -0,0 +1,22 @@
#include "App/SensorControllerPlugin.h"
namespace Dough
{
SensorControllerPlugin::SensorControllerPlugin(MQTT *mqtt, UI *ui) : _mqtt(mqtt), _ui(ui)
{
}
void SensorControllerPlugin::doPublish(SensorController *controller) {
Serial.println(">>>>>>>>>> YO PLUGIN HERE! <<<<<<<<<<<");
}
void SensorControllerPlugin::beforeMeasure(SensorController *controller)
{
_ui->notifySensorActivity();
}
void SensorControllerPlugin::beforePublish(SensorController *controller)
{
_ui->notifyNetworkActivity();
}
}

View File

@ -0,0 +1,28 @@
#ifndef DOUGH_SENSORCONTROLLER_PLUGINS_H
#define DOUGH_SENSORCONTROLLER_PLUGINS_H
#include <Arduino.h>
#include "UI/Logger.h"
#include "Sensors/SensorController.h"
#include "Network/MQTT.h"
#include "UI/UI.h"
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.
class SensorControllerPlugin : public SensorControllerPluginBase
{
public:
SensorControllerPlugin(MQTT *mqtt, UI *ui);
virtual void beforeMeasure(SensorController *controller);
virtual void beforePublish(SensorController *controller);
virtual void doPublish(SensorController *controller);
private:
MQTT *_mqtt;
UI *_ui;
};
} // namespace Dough
#endif

View File

@ -37,16 +37,6 @@ void setupButtonInterruptCallback()
Dough::App::Instance()->ui.setupButton.handleButtonState();
}
void sensorOnMeasureCallback()
{
Dough::App::Instance()->ui.notifySensorActivity();
}
void sensorOnPublishCallback()
{
Dough::App::Instance()->ui.notifyNetworkActivity();
}
// 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.

View File

@ -4,6 +4,7 @@
#include "Network/MQTT.h"
#include "UI/Logger.h"
#include "App/App.h"
#include "Sensors/SensorController.h"
// This header file defines various callback functions that
// live in the global namespace. All callbacks are bundled here
@ -17,8 +18,4 @@ void mqttOnMessageCallback(String &topic, String &payload);
void onoffButtonInterruptCallback();
void setupButtonInterruptCallback();
// Callbacks from the Dough::SensorController module.
void sensorOnMeasureCallback();
void sensorOnPublishCallback();
#endif

View File

@ -5,12 +5,10 @@ namespace Dough
MQTT::MQTT(
WiFi *wifi,
MQTTConnectHandler onConnect,
MQTTMessageHandler onMessage) : _logger("MQTT")
{
_wifi = wifi;
_onConnect = onConnect;
_onMessage = onMessage;
}
MQTTMessageHandler onMessage) : _logger("MQTT"),
_wifi(wifi),
_onConnect(onConnect),
_onMessage(onMessage) {}
void MQTT::setup()
{
@ -42,12 +40,12 @@ namespace Dough
}
_logger.log("s", "Connection to broker successful");
// Incoming messages will be passed on to the _onMessage() function.
_mqttClient.onMessage(_onMessage);
if (_onConnect != nullptr)
{
// Call the _onConnect() function to notify the system that the connection
// to the MQTT broker was setup successfully.
_onConnect(this);
}
return true;
}
@ -93,4 +91,4 @@ namespace Dough
publish(key, "null");
}
}
}
} // namespace Dough

View File

@ -31,8 +31,8 @@ namespace Dough
void publish(const char *key, Measurement measurement);
private:
WiFi *_wifi;
Logger _logger;
WiFi *_wifi;
MQTTClient _mqttClient;
MQTTConnectHandler _onConnect;
MQTTClientCallbackSimple _onMessage;

View File

@ -2,15 +2,8 @@
namespace Dough
{
DistanceSensor *DistanceSensor::Instance()
{
static DistanceSensor *_instance = new DistanceSensor();
return _instance;
}
DistanceSensor::DistanceSensor() : _logger("DISTANCE")
{
_logger.log("s", "INIT distance sensor object");// TODO
_hcsr04 = new SensorHCSR04(HCSR04_TRIG_PIN, HCSR04_ECHO_PIN);
}

View File

@ -1,7 +1,7 @@
#ifndef DOUGH_DISTANCE_SENSOR_H
#define DOUGH_DISTANCE_SENSOR_H
#include "Sensors/SensorBase.h"
#include "Sensors/HighLevel/SensorBase.h"
#include "Sensors/LowLevel/SensorHCSR04.h"
#include "UI/Logger.h"
#include "Data/Measurement.h"
@ -13,7 +13,7 @@ namespace Dough
class DistanceSensor : public SensorBase
{
public:
static DistanceSensor *Instance();
DistanceSensor();
void setTemperature(int temperature);
void setHumidity(int humidity);
virtual void setup();
@ -21,7 +21,6 @@ namespace Dough
virtual unsigned int getPrecision();
private:
DistanceSensor();
Logger _logger;
SensorHCSR04 *_hcsr04;
};

View File

@ -2,12 +2,6 @@
namespace Dough
{
HumiditySensor *HumiditySensor::Instance()
{
static HumiditySensor *_instance = new HumiditySensor();
return _instance;
}
HumiditySensor::HumiditySensor() : _logger("HUMIDITY") {}
void HumiditySensor::setup()
@ -26,7 +20,6 @@ namespace Dough
else
{
_logger.log("sis", "Humidity = ", int(t), "%");
DistanceSensor::Instance()->setHumidity(int(t));
return Measurement::Value(int(t));
}
}
@ -35,4 +28,4 @@ namespace Dough
{
return 2; // prevent flapping when transitioning from value A to value B
}
}
} // namespace Dough

View File

@ -1,11 +1,10 @@
#ifndef DOUGH_HUMIDITY_SENSOR_H
#define DOUGH_HUMIDITY_SENSOR_H
#include "Sensors/SensorBase.h"
#include "Sensors/HighLevel/SensorBase.h"
#include "Sensors/LowLevel/SensorDHT11.h"
#include "UI/Logger.h"
#include "Data/Measurement.h"
#include "Sensors/DistanceSensor.h"
#include "config.h"
namespace Dough
@ -14,13 +13,12 @@ namespace Dough
class HumiditySensor : public SensorBase
{
public:
static HumiditySensor *Instance();
HumiditySensor();
virtual void setup();
virtual Measurement read();
virtual unsigned int getPrecision();
private:
HumiditySensor();
Logger _logger;
};
}

View File

@ -5,7 +5,7 @@
namespace Dough
{
// This interface is implemented by all sensors.
// This interface is implemented by all high level sensors.
class SensorBase
{
public:

View File

@ -2,12 +2,6 @@
namespace Dough
{
TemperatureSensor *TemperatureSensor::Instance()
{
static TemperatureSensor *_instance = new TemperatureSensor();
return _instance;
}
TemperatureSensor::TemperatureSensor() : _logger("TEMPERATURE") {}
void TemperatureSensor::setup()
@ -15,10 +9,6 @@ namespace Dough
SensorDHT11::Instance()->begin();
}
// ----------------------------------------------------------------------
// loop
// ----------------------------------------------------------------------
Measurement TemperatureSensor::read()
{
float t = SensorDHT11::Instance()->readTemperature();
@ -30,7 +20,6 @@ namespace Dough
else
{
_logger.log("sis", "Temperature = ", int(t), "°C");
DistanceSensor::Instance()->setTemperature(int(t));
return Measurement::Value(int(t));
}
}

View File

@ -1,11 +1,10 @@
#ifndef DOUGH_TEMPERATURE_SENSOR_H
#define DOUGH_TEMPERATURE_SENSOR_H
#include "Sensors/SensorBase.h"
#include "Sensors/HighLevel/SensorBase.h"
#include "Sensors/LowLevel/SensorDHT11.h"
#include "UI/Logger.h"
#include "Data/Measurement.h"
#include "Sensors/DistanceSensor.h"
#include "config.h"
namespace Dough
@ -14,13 +13,12 @@ namespace Dough
class TemperatureSensor : public SensorBase
{
public:
static TemperatureSensor *Instance();
TemperatureSensor();
virtual void setup();
virtual Measurement read();
virtual unsigned int getPrecision();
private:
TemperatureSensor();
Logger _logger;
};
}

View File

@ -1,31 +1,28 @@
#include "Data/SensorController.h"
#include "Sensors/SensorController.h"
#include "UI/UI.h"
namespace Dough
{
SensorController::SensorController(
SensorControllerPluginBase *plugin,
MQTT *mqtt,
const char *mqttKey,
SensorBase *sensor,
SensorBase &sensor,
unsigned int storageSize,
unsigned int minimumMeasureTime,
SensorControllerCallback onMeasure,
unsigned int minimumPublishTime,
SensorControllerCallback onPublish)
unsigned int minimumPublishTime) : _plugin(plugin),
_mqtt(mqtt),
_sensor(sensor)
{
_mqtt = mqtt;
_mqttKey = mqttKey;
_sensor = sensor;
_storageSize = storageSize;
_minimumMeasureTime = minimumMeasureTime;
_onMeasure = onMeasure;
_minimumPublishTime = minimumPublishTime;
_onPublish = onPublish;
}
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
@ -45,12 +42,16 @@ namespace Dough
{
if (_mustMeasure())
{
_onMeasure();
_plugin->beforeMeasure(this);
_measure();
_plugin->afterMeasure(this);
}
if (_mustPublish())
{
_onPublish();
_plugin->beforePublish(this);
Serial.println("CALLING doPublish() from plugin"); // DEBUG XXX
_plugin->doPublish(this);
_plugin->afterPublish(this);
_publish();
}
}
@ -74,7 +75,7 @@ namespace Dough
{
_lastMeasuredAt = millis();
_store(_sensor->read());
_store(_sensor.read());
}
bool SensorController::_mustPublish()
@ -102,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)
@ -197,4 +198,4 @@ namespace Dough
_storage[i]->clear();
}
}
}
} // namespace Dough

View File

@ -1,25 +1,40 @@
#ifndef DOUGH_MEASUREMENTS_H
#define DOUGH_MEASUREMENTS_H
#ifndef DOUGH_SENSORCONTROLLER_H
#define DOUGH_SENSORCONTROLLER_H
#include <Arduino.h>
#include "Sensors/SensorBase.h"
#include "Sensors/HighLevel/SensorBase.h"
#include "Data/Measurement.h"
#include "Network/MQTT.h"
namespace Dough
{
typedef void (*SensorControllerCallback)();
// This class is used to store measurements for a sensor and to keep
// track of running totals for handling average computations.
// It also provides functionality to decide when to read a measurement
// from a sensor and when to publish measurements to MQTT (after significant
// from a sensor and when to publish measurements (after significant
// changes occur or when the last publish was too long ago).
class SensorController;
// This class can be derived from to create a plugin module for the
// Dough::SensorController. Methods from this interface will be called
// by the Dough::SensorController at appropriate times.
class SensorControllerPluginBase
{
public:
virtual void beforeMeasure(SensorController *controller) {};
virtual void afterMeasure(SensorController *controller) {};
virtual void beforePublish(SensorController *controller) {};
virtual void doPublish(SensorController *controller) {};
virtual void afterPublish(SensorController *controller) {};
};
class SensorController
{
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
@ -35,7 +50,7 @@ namespace Dough
// from the sensor.
// @param onMeasure
// A callback function that is called right before a measurement
// is taken.
// 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.
@ -43,14 +58,13 @@ namespace Dough
// A callback function that is called right before a measurement
// is published.
SensorController(
SensorControllerPluginBase *plugin,
MQTT *mqtt,
const char *mqttKey,
SensorBase *sensor,
SensorBase &sensor,
unsigned int storageSize,
unsigned int minimumMeasureTime,
SensorControllerCallback onMeasure,
unsigned int minimumPublishTime,
SensorControllerCallback onPublish);
unsigned int minimumPublishTime);
void setup();
void loop();
Measurement getLast();
@ -58,22 +72,21 @@ namespace Dough
void clearHistory();
private:
SensorControllerPluginBase *_plugin;
MQTT *_mqtt;
const char *_mqttKey;
char *_mqttAverageKey;
SensorBase *_sensor;
SensorBase &_sensor;
Measurement **_storage;
unsigned int _storageSize;
int _averageSum = 0;
unsigned int _averageCount = 0;
unsigned int _index = 0;
bool _mustMeasure();
SensorControllerCallback _onMeasure;
void _measure();
unsigned int _minimumMeasureTime;
unsigned long _lastMeasuredAt = 0;
bool _mustPublish();
SensorControllerCallback _onPublish ;
void _publish();
unsigned int _minimumPublishTime;
unsigned long _lastPublishedAt = 0;
@ -82,6 +95,6 @@ namespace Dough
void _store(Measurement measurement);
unsigned int _next();
};
}
} // namespace Dough
#endif

View File

@ -1,13 +1,6 @@
// The speed to use for the serial terminal logging.
#define LOG_BAUDRATE 9600
// Define this one to wait for USB serial to come up.
// This can be useful during development, when you want all
// serial messages to appear in the serial monitor.
// Without this, some of the initial serial messages might
// be missing from the output.
//#define LOG_WAIT_SERIAL
// The digital pins to which the push buttons are connected.
#define ONOFF_BUTTON_PIN 2
#define SETUP_BUTTON_PIN 3

View File

@ -3,9 +3,9 @@
#include <Arduino.h>
#include "App/App.h"
#include "Sensors/TemperatureSensor.h"
#include "Sensors/HumiditySensor.h"
#include "Sensors/DistanceSensor.h"
#include "Sensors/HighLevel/TemperatureSensor.h"
#include "Sensors/HighLevel/HumiditySensor.h"
#include "Sensors/HighLevel/DistanceSensor.h"
#include "Network/WiFi.h"
#include "Network/MQTT.h"
#include "UI/Button.h"