diff --git a/src/App/App.cpp b/src/App/App.cpp index f8ca09e..dff250b 100644 --- a/src/App/App.cpp +++ b/src/App/App.cpp @@ -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() diff --git a/src/App/App.h b/src/App/App.h index 1e51441..c289182 100644 --- a/src/App/App.h +++ b/src/App/App.h @@ -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(); diff --git a/src/App/SensorControllerPlugin.cpp b/src/App/SensorControllerPlugin.cpp index 919ccc3..102a128 100644 --- a/src/App/SensorControllerPlugin.cpp +++ b/src/App/SensorControllerPlugin.cpp @@ -2,21 +2,33 @@ namespace Dough { - SensorControllerPlugin::SensorControllerPlugin(MQTT *mqtt, UI *ui) : _mqtt(mqtt), _ui(ui) - { - } + 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(); + _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); + } } \ No newline at end of file diff --git a/src/App/SensorControllerPlugin.h b/src/App/SensorControllerPlugin.h index a18fa0b..bde8a6b 100644 --- a/src/App/SensorControllerPlugin.h +++ b/src/App/SensorControllerPlugin.h @@ -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; diff --git a/src/App/callbacks.cpp b/src/App/callbacks.cpp index c0f2c86..c2ddd3c 100644 --- a/src/App/callbacks.cpp +++ b/src/App/callbacks.cpp @@ -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(); diff --git a/src/Sensors/HighLevel/DistanceSensor.cpp b/src/Sensors/HighLevel/DistanceSensor.cpp index 83e1f94..d56a0f8 100644 --- a/src/Sensors/HighLevel/DistanceSensor.cpp +++ b/src/Sensors/HighLevel/DistanceSensor.cpp @@ -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); diff --git a/src/Sensors/HighLevel/DistanceSensor.h b/src/Sensors/HighLevel/DistanceSensor.h index 0f09d3f..75c3b35 100644 --- a/src/Sensors/HighLevel/DistanceSensor.h +++ b/src/Sensors/HighLevel/DistanceSensor.h @@ -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(); diff --git a/src/Sensors/HighLevel/HumiditySensor.cpp b/src/Sensors/HighLevel/HumiditySensor.cpp index 44afd84..87e9274 100644 --- a/src/Sensors/HighLevel/HumiditySensor.cpp +++ b/src/Sensors/HighLevel/HumiditySensor.cpp @@ -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(); diff --git a/src/Sensors/HighLevel/HumiditySensor.h b/src/Sensors/HighLevel/HumiditySensor.h index 9ad3b6f..17d1e7b 100644 --- a/src/Sensors/HighLevel/HumiditySensor.h +++ b/src/Sensors/HighLevel/HumiditySensor.h @@ -15,6 +15,7 @@ namespace Dough public: HumiditySensor(); virtual void setup(); + virtual const char* getName(); virtual Measurement read(); virtual unsigned int getPrecision(); diff --git a/src/Sensors/HighLevel/SensorBase.h b/src/Sensors/HighLevel/SensorBase.h index b993ac0..994878a 100644 --- a/src/Sensors/HighLevel/SensorBase.h +++ b/src/Sensors/HighLevel/SensorBase.h @@ -10,6 +10,7 @@ namespace Dough { public: virtual void setup(); + virtual const char* getName(); virtual Measurement read(); virtual unsigned int getPrecision(); }; diff --git a/src/Sensors/HighLevel/TemperatureSensor.cpp b/src/Sensors/HighLevel/TemperatureSensor.cpp index ecea912..1922557 100644 --- a/src/Sensors/HighLevel/TemperatureSensor.cpp +++ b/src/Sensors/HighLevel/TemperatureSensor.cpp @@ -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(); diff --git a/src/Sensors/HighLevel/TemperatureSensor.h b/src/Sensors/HighLevel/TemperatureSensor.h index 7abe995..0c00877 100644 --- a/src/Sensors/HighLevel/TemperatureSensor.h +++ b/src/Sensors/HighLevel/TemperatureSensor.h @@ -15,6 +15,7 @@ namespace Dough public: TemperatureSensor(); virtual void setup(); + virtual const char* getName(); virtual Measurement read(); virtual unsigned int getPrecision(); diff --git a/src/Sensors/SensorController.cpp b/src/Sensors/SensorController.cpp index e0705ce..2164eb0 100644 --- a/src/Sensors/SensorController.cpp +++ b/src/Sensors/SensorController.cpp @@ -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. "/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)) diff --git a/src/Sensors/SensorController.h b/src/Sensors/SensorController.h index 6717624..f9d1cbd 100644 --- a/src/Sensors/SensorController.h +++ b/src/Sensors/SensorController.h @@ -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 "/" for measurement values - // and "//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 diff --git a/src/UI/LED.cpp b/src/UI/LED.cpp index b1ec9da..97da34d 100644 --- a/src/UI/LED.cpp +++ b/src/UI/LED.cpp @@ -2,10 +2,7 @@ namespace Dough { - LED::LED(int pin) - { - _pin = pin; - } + LED::LED(int pin) : _pin(pin) {} void LED::setup() { diff --git a/src/UI/Logger.cpp b/src/UI/Logger.cpp index 66f9968..aa89b39 100644 --- a/src/UI/Logger.cpp +++ b/src/UI/Logger.cpp @@ -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() diff --git a/src/UI/Logger.h b/src/UI/Logger.h index 99d0e23..b4eb95c 100644 --- a/src/UI/Logger.h +++ b/src/UI/Logger.h @@ -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 @@ -23,7 +24,7 @@ namespace Dough void resume(); private: - const char *_section; + char _section[LOGGER_SECTION_BUFLEN]; bool _suspended = false; };