Stashing this as a feature branch, something's broken in the MQTT department and I first have to find out what.

This commit is contained in:
Maurice Makaay 2020-07-14 01:21:07 +02:00
parent e0bd4b64b8
commit 49115a0545
26 changed files with 370 additions and 347 deletions

75
src/App/App.cpp Normal file
View File

@ -0,0 +1,75 @@
#include "App/App.h"
namespace Dough
{
App *App::Instance()
{
static App *_instance = new App();
return _instance;
}
App::App() : config(),
wifi(),
mqtt(&wifi, mqttOnConnect, mqttOnMessage),
temperatureSensor(
&mqtt,
"temperature",
TemperatureSensor::Instance(),
TEMPERATURE_AVERAGE_STORAGE,
TEMPERATURE_MEASURE_INTERVAL,
MINIMUM_PUBLISH_INTERVAL),
humiditySensor(
&mqtt,
"humidity",
HumiditySensor::Instance(),
HUMIDITY_AVERAGE_STORAGE,
HUMIDITY_MEASURE_INTERVAL,
MINIMUM_PUBLISH_INTERVAL),
distanceSensor(
&mqtt,
"distance",
DistanceSensor::Instance(),
DISTANCE_AVERAGE_STORAGE,
DISTANCE_MEASURE_INTERVAL,
MINIMUM_PUBLISH_INTERVAL)
{
}
void App::setup()
{
wifi.setup();
mqtt.setup();
temperatureSensor.setup();
humiditySensor.setup();
distanceSensor.setup();
}
void App::measure()
{
if (config.isOk())
{
temperatureSensor.loop();
humiditySensor.loop();
distanceSensor.loop();
}
}
void App::clearHistory()
{
temperatureSensor.clearHistory();
humiditySensor.clearHistory();
distanceSensor.clearHistory();
}
} // namespace Dough
void mqttOnConnect(Dough::MQTT *mqtt)
{
Serial.println("Subscribe to required incoming MQTT topics");
mqtt->subscribe("container_height");
mqtt->subscribe("temperature_offset");
}
void mqttOnMessage(String &topic, String &payload)
{
Serial.println("Handle message");
}

38
src/App/App.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef DOUGH_APP_H
#define DOUGH_APP_H
#include <Arduino.h>
#include "App/Configuration.h"
#include "Data/SensorController.h"
#include "Sensors/TemperatureSensor.h"
#include "Sensors/HumiditySensor.h"
#include "Sensors/DistanceSensor.h"
#include "config.h"
namespace Dough
{
class App
{
public:
static App *Instance();
Configuration config;
WiFi wifi;
MQTT mqtt;
SensorController temperatureSensor;
SensorController humiditySensor;
SensorController distanceSensor;
void setup();
void measure();
void clearHistory();
private:
App();
};
}
// Callback functions that need to live in the global namespace.
void mqttOnConnect(Dough::MQTT*);
void mqttOnMessage(String &topic, String &payload);
#endif

102
src/App/Configuration.cpp Normal file
View File

@ -0,0 +1,102 @@
#include "App/Configuration.h"
namespace Dough
{
Configuration::Configuration() : _logger("CONFIG")
{
// _mqtt = MQTT::Instance();
}
void Configuration::setup()
{
_containerHeight = 0.00;
_containerHeightSet = false;
_temperatureOffset = 0;
// MQTT *mqtt = MQTT::Instance();
// mqtt->onConnect(Configuration::handleMqttConnect);
// mqtt->onMessage(Configuration::handleMqttMessage);
}
// void Configuration::handleMqttConnect(MQTT *mqtt)
// {
// mqtt->subscribe("container_height");
// mqtt->subscribe("temperature_offset");
// }
// void Configuration::handleMqttMessage(String &key, String &payload)
// {
// if (key.equals("container_height"))
// {
// App::Instance()->config.setContainerHeight(payload.toInt());
// }
// if (key.equals("temperature_offset"))
// {
// App::Instance()->config.setTemperatureOffset(payload.toInt());
// }
// else
// {
// App::Instance()->config._logger.log("sS", "ERROR - Unhandled MQTT message, key = ", key);
// }
// }
bool Configuration::isOk()
{
return _containerHeightSet;
}
// Set the container height in mm. This is the distance between the sensor
// and the bottom of the container. It is used to determine the height of
// the starter or dough by subtracting the distance measurement from it.
void Configuration::setContainerHeight(int height)
{
_containerHeightSet = false;
if (height <= HCSR04_MIN_MM)
{
_logger.log("sisis", "ERROR - Container height ", height,
"mm is less than the minimum measuring distance of ",
HCSR04_MIN_MM, "mm");
return;
}
if (height >= HCSR04_MAX_MM)
{
_logger.log("sisis", "ERROR - Container height ", height,
"mm is more than the maximum measuring distance of ",
HCSR04_MAX_MM, "mm");
return;
}
_logger.log("sis", "Set container height to ", height, "mm");
_containerHeight = height;
_containerHeightSet = true;
}
unsigned int Configuration::getContainerHeight()
{
return _containerHeight;
}
// Set the temperature offset in °C, to calibrate the temperature
// as measured by the device. On my device, the temperature raises about
// 5 degrees in the first few minutes, due to the circuitry warming up.
// I will have to fix that in the hardware as well, because 5 degrees is
// just redicoulous, but there might always be a diff that needs to be
// compensated for.
void Configuration::setTemperatureOffset(int offset)
{
// Just a little safety measure. Devices should never need more than
// 10 degrees correction, right?
if (offset < -10 || offset > 10)
{
_logger.log("sisis", "ERROR - Temperature offset ", offset,
"°C is too large (allowed range: -10°C up to +10°C)");
return;
}
_logger.log("sis", "Set temperature offset to ", offset, "°C");
_temperatureOffset = offset;
}
int Configuration::getTemperatureOffset()
{
return _temperatureOffset;
}
}

38
src/App/Configuration.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef DOUGH_CONFIG_H
#define DOUGH_CONFIG_H
#include <Arduino.h>
//#include "App/App.h"
#include "Network/MQTT.h"
#include "UI/Logger.h"
#include "Sensors/LowLevel/SensorHCSR04.h"
namespace Dough
{
// This class is responsible for handling the device configuration.
// Configuration parameters are stored as persistent data in the
// MQTT broker. The device itself has no permanent storage peripheral.
// Therefore, this class hooks into MQTT.
class Configuration
{
public:
Configuration();
void setup();
static void handleMqttConnect(MQTT *mqtt);
static void handleMqttMessage(String &key, String &value);
void setContainerHeight(int height);
unsigned int getContainerHeight();
void setTemperatureOffset(int offset);
int getTemperatureOffset();
bool isOk();
private:
MQTT *_mqtt;
Logger _logger;
unsigned int _containerHeight;
bool _containerHeightSet;
int _temperatureOffset = 0;
};
}
#endif

View File

@ -1,148 +0,0 @@
#include "Data/DataController.h"
namespace Dough
{
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
DataController *DataController::Instance()
{
static DataController *_instance = new DataController();
return _instance;
}
DataController::DataController() : _temperatureMeasurements(
"temperature",
TemperatureSensor::Instance(),
TEMPERATURE_AVERAGE_STORAGE,
TEMPERATURE_MEASURE_INTERVAL,
PUBLISH_INTERVAL),
_humidityMeasurements(
"humidity",
HumiditySensor::Instance(),
HUMIDITY_AVERAGE_STORAGE,
HUMIDITY_MEASURE_INTERVAL,
PUBLISH_INTERVAL),
_distanceMeasurements(
"distance",
DistanceSensor::Instance(),
DISTANCE_AVERAGE_STORAGE,
DISTANCE_MEASURE_INTERVAL,
PUBLISH_INTERVAL),
_logger("DATA")
{
_ui = UI::Instance();
_mqtt = MQTT::Instance();
}
// ----------------------------------------------------------------------
// Setup
// ----------------------------------------------------------------------
void DataController::setup()
{
_containerHeight = 0.00;
_containerHeightSet = false;
MQTT *mqtt = MQTT::Instance();
mqtt->onConnect(DataController::handleMqttConnect);
mqtt->onMessage(DataController::handleMqttMessage);
_temperatureMeasurements.setup();
_humidityMeasurements.setup();
_distanceMeasurements.setup();
}
void DataController::handleMqttConnect(MQTT *mqtt)
{
mqtt->subscribe("container_height");
mqtt->subscribe("temperature_offset");
}
void DataController::handleMqttMessage(String &key, String &payload)
{
if (key.equals("container_height"))
{
DataController::Instance()->setContainerHeight(payload.toInt());
}
if (key.equals("temperature_offset"))
{
DataController::Instance()->setTemperatureOffset(payload.toInt());
}
else
{
DataController::Instance()->_logger.log("sS", "ERROR - Unhandled MQTT message, key = ", key);
}
}
bool DataController::isConfigured()
{
return _containerHeightSet;
}
// Set the container height in mm. This is the distance between the sensor
// and the bottom of the container. It is used to determine the height of
// the starter or dough by subtracting the distance measurement from it.
void DataController::setContainerHeight(int height)
{
_containerHeightSet = false;
if (height <= HCSR04_MIN_MM)
{
_logger.log("sisis", "ERROR - Container height ", height,
"mm is less than the minimum measuring distance of ",
HCSR04_MIN_MM, "mm");
return;
}
if (height >= HCSR04_MAX_MM)
{
_logger.log("sisis", "ERROR - Container height ", height,
"mm is more than the maximum measuring distance of ",
HCSR04_MAX_MM, "mm");
return;
}
_logger.log("sis", "Set container height to ", height, "mm");
_containerHeight = height;
_containerHeightSet = true;
}
// Set the temperature offset in °C, to calibrate the temperature
// as measured by the device. On my device, the temperature raises about
// 5 degrees in the first few minutes, due to the circuitry warming up.
// I will have to fix that in the hardware as well, because 5 degrees is
// just redicoulous, but there might always be a diff that needs to be
// compensated for.
void DataController::setTemperatureOffset(int offset)
{
// Just a little safety measure. Devices should never need more than
// 10 degrees correction, right?
if (offset < -10 || offset > 10) {
_logger.log("sisis", "ERROR - Temperature offset ", offset,
"°C is too large (allowed range: -10°C up to +10°C)");
return;
}
_logger.log("sis", "Set temperature offset to ", offset, "°C");
_temperatureOffset = offset;
}
// ----------------------------------------------------------------------
// Loop
// ----------------------------------------------------------------------
void DataController::loop()
{
if (isConfigured())
{
_temperatureMeasurements.loop();
_humidityMeasurements.loop();
_distanceMeasurements.loop();
}
}
void DataController::clearHistory()
{
_temperatureMeasurements.clearHistory();
_humidityMeasurements.clearHistory();
_distanceMeasurements.clearHistory();
}
}

View File

@ -1,59 +0,0 @@
#ifndef DOUGH_DATA_DATACONTROLLER_H
#define DOUGH_DATA_DATACONTROLLER_H
// The minimal interval in seconds at which to forcibly publish measurements to the
// MQTT broker. When significant changes occur in the measurements, then these will
// be published to the MQTT broker at all times, independent from this interval.
#define PUBLISH_INTERVAL 300
#include <Arduino.h>
#include "Data/SensorController.h"
#include "Sensors/TemperatureSensor.h"
#include "Sensors/HumiditySensor.h"
#include "Sensors/DistanceSensor.h"
#include "Network/WiFi.h"
#include "Network/MQTT.h"
#include "UI/UI.h"
#include "UI/Logger.h"
namespace Dough
{
typedef enum
{
SAMPLE_TEMPERATURE,
SAMPLE_HUMIDITY,
SAMPLE_DISTANCE
} DoughSampleType;
// This class is responsible for handling all things "data".
// It holds the device configuration, collects measurements from sensors,
// gathers statistics on these data, and publishing results to the MQTT broker.
class DataController
{
public:
static DataController *Instance();
void setup();
void loop();
void clearHistory();
void setContainerHeight(int height);
void setTemperatureOffset(int offset);
bool isConfigured();
static void handleMqttConnect(MQTT *mqtt);
static void handleMqttMessage(String &key, String &value);
private:
DataController();
UI *_ui;
MQTT *_mqtt;
SensorController _temperatureMeasurements;
SensorController _humidityMeasurements;
SensorController _distanceMeasurements;
Logger _logger;
unsigned int _containerHeight;
bool _containerHeightSet;
int _temperatureOffset = 0;
void _sample();
};
}
#endif

View File

@ -1,5 +1,5 @@
#ifndef DOUGH_DATA_MEASUREMENT_H #ifndef DOUGH_MEASUREMENT_H
#define DOUGH_DATA_MEASUREMENT_H #define DOUGH_MEASUREMENT_H
namespace Dough namespace Dough
{ {

View File

@ -4,18 +4,19 @@
namespace Dough namespace Dough
{ {
SensorController::SensorController( SensorController::SensorController(
MQTT *mqtt,
const char *mqttKey, const char *mqttKey,
SensorBase *sensor, SensorBase *sensor,
unsigned int storageSize, unsigned int storageSize,
unsigned int minimumMeasureTime, unsigned int minimumMeasureTime,
unsigned int minimumPublishTime) unsigned int minimumPublishTime)
{ {
_mqtt = mqtt;
_mqttKey = mqttKey; _mqttKey = mqttKey;
_sensor = sensor; _sensor = sensor;
_storageSize = storageSize; _storageSize = storageSize;
_minimumMeasureTime = minimumMeasureTime; _minimumMeasureTime = minimumMeasureTime;
_minimumPublishTime = minimumPublishTime; _minimumPublishTime = minimumPublishTime;
_mqtt = MQTT::Instance();
_ui = UI::Instance(); _ui = UI::Instance();
} }

View File

@ -1,5 +1,5 @@
#ifndef DOUGH_DATA_MEASUREMENTS_H #ifndef DOUGH_MEASUREMENTS_H
#define DOUGH_DATA_MEASUREMENTS_H #define DOUGH_MEASUREMENTS_H
#include <Arduino.h> #include <Arduino.h>
#include "Sensors/SensorBase.h" #include "Sensors/SensorBase.h"
@ -19,6 +19,8 @@ namespace Dough
public: public:
// Create a new Measurements object. // Create a new Measurements object.
// //
// @param mqtt
// The Dough::MQTT object, which is connected to the MQTT broker.
// @param mqttKey // @param mqttKey
// The key to use when publishing sensor values to MQTT. // The key to use when publishing sensor values to MQTT.
// The full key will be "<prefix>/<mqttKey>" for measurement values // The full key will be "<prefix>/<mqttKey>" for measurement values
@ -34,6 +36,7 @@ namespace Dough
// The number of seconds after which to forcibly publish measurements // The number of seconds after which to forcibly publish measurements
// to MQTT, even when no significant changes to measurements were seen. // to MQTT, even when no significant changes to measurements were seen.
SensorController( SensorController(
MQTT *mqtt,
const char *mqttKey, const char *mqttKey,
SensorBase *sensor, SensorBase *sensor,
unsigned int storageSize, unsigned int storageSize,

View File

@ -2,45 +2,26 @@
namespace Dough namespace Dough
{ {
MQTT::MQTT(
// ---------------------------------------------------------------------- WiFi *network,
// Constructor MQTTConnectHandler onConnect,
// ---------------------------------------------------------------------- MQTTMessageHandler onMessage) : _logger("MQTT")
MQTT *MQTT::Instance()
{ {
static MQTT *_instance = new MQTT(); _wifi = network;
return _instance; _onConnect = onConnect;
_onMessage = onMessage;
} }
MQTT::MQTT() : _logger("MQTT") {}
// ----------------------------------------------------------------------
// Setup
// ----------------------------------------------------------------------
void MQTT::setup() void MQTT::setup()
{ {
WiFi *network = WiFi::Instance();
#ifdef MQTT_DEVICE_ID #ifdef MQTT_DEVICE_ID
_mqttDeviceId = MQTT_DEVICE_ID; _mqttDeviceId = MQTT_DEVICE_ID;
#else #else
_mqttDeviceId = network->getMacAddress(); _mqttDeviceId = _wifi->getMacAddress();
#endif #endif
_logger.log("ss", "Device ID = ", _mqttDeviceId); _logger.log("ss", "Device ID = ", _mqttDeviceId);
_mqttClient.begin(MQTT_BROKER, MQTT_PORT, network->client); _mqttClient.begin(MQTT_BROKER, MQTT_PORT, _wifi->client);
}
void MQTT::onConnect(MQTTConnectHandler callback)
{
_onConnect = callback;
}
void MQTT::onMessage(MQTTClientCallbackSimple callback)
{
_onMessage = callback;
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -63,8 +44,9 @@ namespace Dough
_logger.log("s", "ERROR - Connection to broker failed"); _logger.log("s", "ERROR - Connection to broker failed");
return false; return false;
} }
_logger.log("s", "Connection to broker successful");
_mqttClient.onMessage(MQTT::handleMessage); _mqttClient.onMessage(_onMessage);
if (_onConnect != nullptr) if (_onConnect != nullptr)
{ {
@ -81,21 +63,22 @@ namespace Dough
_mqttClient.loop(); _mqttClient.loop();
} }
void MQTT::handleMessage(String &topic, String &payload) // // static
{ // void MQTT::handleMessage(String &topic, String &payload)
MQTT::Instance()->_logger.log("sSsS", "<<< ", topic, " = ", payload); // {
// MQTT::Instance()->_logger.log("sSsS", "<<< ", topic, " = ", payload);
MQTT *mqtt = MQTT::Instance(); // MQTT *mqtt = MQTT::Instance();
if (mqtt->_onMessage != nullptr) // if (mqtt->_onMessage != nullptr)
{ // {
int pos = topic.lastIndexOf('/'); // int pos = topic.lastIndexOf('/');
if (pos != -1) // if (pos != -1)
{ // {
topic.remove(0, pos + 1); // topic.remove(0, pos + 1);
mqtt->_onMessage(topic, payload); // mqtt->_onMessage(topic, payload);
} // }
} // }
} // }
void MQTT::subscribe(const char *key) void MQTT::subscribe(const char *key)
{ {

View File

@ -20,10 +20,8 @@ namespace Dough
class MQTT class MQTT
{ {
public: public:
static MQTT *Instance(); MQTT(WiFi *network, MQTTConnectHandler onConnect, MQTTMessageHandler onMessage);
void setup(); void setup();
void onConnect(MQTTConnectHandler callback);
void onMessage(MQTTMessageHandler callback);
bool isConnected(); bool isConnected();
bool connect(); bool connect();
void subscribe(const char *key); void subscribe(const char *key);
@ -33,15 +31,13 @@ namespace Dough
void publish(const char *key, Measurement measurement); void publish(const char *key, Measurement measurement);
private: private:
MQTT(); WiFi *_wifi;
MQTTClient _mqttClient;
Logger _logger; Logger _logger;
MQTTConnectHandler _onConnect = nullptr; MQTTClient _mqttClient;
MQTTClientCallbackSimple _onMessage = nullptr; MQTTConnectHandler _onConnect;
static void handleMessage(String &topic, String &payload); MQTTClientCallbackSimple _onMessage;
char *_mqttDeviceId; char *_mqttDeviceId;
}; };
} }
#endif #endif

View File

@ -2,23 +2,13 @@
namespace Dough namespace Dough
{ {
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
WiFi *WiFi::Instance()
{
static WiFi *_instance = new WiFi();
return _instance;
}
WiFi::WiFi() : _logger("WIFI") {} WiFi::WiFi() : _logger("WIFI") {}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Setup // Setup
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
void WiFi::_setMacAddress() void WiFi::_storeMacAddress()
{ {
byte mac[6]; byte mac[6];
::WiFi.macAddress(mac); ::WiFi.macAddress(mac);
@ -29,13 +19,14 @@ namespace Dough
void WiFi::setup() void WiFi::setup()
{ {
_setMacAddress(); _storeMacAddress();
_logger.log("ss", "MAC address = ", getMacAddress()); _logger.log("ss", "MAC address = ", getMacAddress());
} }
// ---------------------------------------------------------------------- char *WiFi::getMacAddress()
// Loop {
// ---------------------------------------------------------------------- return _macAddress;
}
bool WiFi::isConnected() bool WiFi::isConnected()
{ {
@ -77,9 +68,4 @@ namespace Dough
return false; return false;
} }
} }
char *WiFi::getMacAddress()
{
return _macAddress;
}
} }

View File

@ -1,5 +1,5 @@
#ifndef DOUGH_NETWORK_H #ifndef DOUGH_WIFI_H
#define DOUGH_NETWORK_H #define DOUGH_WIFI_H
#include <WiFiNINA.h> #include <WiFiNINA.h>
#include "UI/Logger.h" #include "UI/Logger.h"
@ -11,7 +11,7 @@ namespace Dough
class WiFi class WiFi
{ {
public: public:
static WiFi *Instance(); WiFi();
char *getMacAddress(); char *getMacAddress();
void setup(); void setup();
void loop(); void loop();
@ -20,8 +20,7 @@ namespace Dough
WiFiClient client; WiFiClient client;
private: private:
WiFi(); void _storeMacAddress();
void _setMacAddress();
char _macAddress[18]; // max MAC address length + 1 char _macAddress[18]; // max MAC address length + 1
Logger _logger; Logger _logger;
}; };

View File

@ -1,5 +1,5 @@
#ifndef DOUGH_SENSORS_DISTANCE_H #ifndef DOUGH_DISTANCE_SENSOR_H
#define DOUGH_SENSORS_DISTANCE_H #define DOUGH_DISTANCE_SENSOR_H
#include "Sensors/SensorBase.h" #include "Sensors/SensorBase.h"
#include "Sensors/LowLevel/SensorHCSR04.h" #include "Sensors/LowLevel/SensorHCSR04.h"

View File

@ -1,5 +1,5 @@
#ifndef DOUGH_SENSORS_HUMIDITY_H #ifndef DOUGH_HUMIDITY_SENSOR_H
#define DOUGH_SENSORS_HUMIDITY_H #define DOUGH_HUMIDITY_SENSOR_H
#include "Sensors/SensorBase.h" #include "Sensors/SensorBase.h"
#include "Sensors/LowLevel/SensorDHT11.h" #include "Sensors/LowLevel/SensorDHT11.h"

View File

@ -1,5 +1,5 @@
#ifndef DOUGH_SENSORS_DHT11_H #ifndef DOUGH_SENSOR_DHT11_H
#define DOUGH_SENSORS_DHT11_H #define DOUGH_SENSOR_DHT11_H
#include <DHT.h> #include <DHT.h>
#include "config.h" #include "config.h"

View File

@ -1,5 +1,5 @@
#ifndef HCSR04_H #ifndef DOUGH_SENSOR_HCSR04_H
#define HCSR04_H #define DOUGH_SENSOR_HCSR04_H
// The minimum and maximum distance that can be measured in mm. // The minimum and maximum distance that can be measured in mm.
// This is based on the specifications of the HCSR04 sensor. // This is based on the specifications of the HCSR04 sensor.

View File

@ -1,5 +1,5 @@
#ifndef DOUGH_SENSORS_BASE_H #ifndef DOUGH_SENSOR_BASE_H
#define DOUGH_SENSORS_BASE_H #define DOUGH_SENSOR_BASE_H
#include "Data/Measurement.h" #include "Data/Measurement.h"

View File

@ -1,5 +1,5 @@
#ifndef DOUGH_SENSORS_TEMPERATURE_H #ifndef DOUGH_TEMPERATURE_SENSOR_H
#define DOUGH_SENSORS_TEMPERATURE_H #define DOUGH_TEMPERATURE_SENSOR_H
#include "Sensors/SensorBase.h" #include "Sensors/SensorBase.h"
#include "Sensors/LowLevel/SensorDHT11.h" #include "Sensors/LowLevel/SensorDHT11.h"

View File

@ -7,6 +7,18 @@ namespace Dough
_section = section; _section = section;
} }
void Logger::setup()
{
// Setup the serial port, used for logging.
Serial.begin(LOG_BAUDRATE);
#ifdef LOG_WAIT_SERIAL
while (!Serial)
{
// wait for serial port to connect. Needed for native USB.
}
#endif
}
void Logger::suspend() void Logger::suspend()
{ {
_suspended = true; _suspended = true;
@ -70,4 +82,4 @@ namespace Dough
Serial.println(""); Serial.println("");
} }
} } // namespace Dough

View File

@ -7,6 +7,7 @@
#include <Arduino.h> #include <Arduino.h>
#include <stdarg.h> #include <stdarg.h>
#include <WiFiNINA.h> #include <WiFiNINA.h>
#include "config.h"
namespace Dough namespace Dough
{ {
@ -15,6 +16,7 @@ namespace Dough
class Logger class Logger
{ {
public: public:
static void setup();
Logger(const char *section); Logger(const char *section);
void log(const char *fmt, ...); void log(const char *fmt, ...);
void suspend(); void suspend();

View File

@ -30,15 +30,6 @@ namespace Dough
void UI::setup() void UI::setup()
{ {
// Setup the serial port, used for logging.
Serial.begin(LOG_BAUDRATE);
#ifdef LOG_WAIT_SERIAL
while (!Serial)
{
// wait for serial port to connect. Needed for native USB.
}
#endif
// Setup the buttons. // Setup the buttons.
onoffButton.setup(); onoffButton.setup();
onoffButton.onInterrupt(UI::onoffButtonISR); onoffButton.onInterrupt(UI::onoffButtonISR);

View File

@ -1,15 +1,6 @@
#ifndef DOUGH_UI_H #ifndef DOUGH_UI_H
#define DOUGH_UI_H #define DOUGH_UI_H
#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.
#undef LOG_WAIT_SERIAL
#include <Arduino.h> #include <Arduino.h>
#include <stdarg.h> #include <stdarg.h>
#include "UI/Button.h" #include "UI/Button.h"

View File

@ -1,3 +1,13 @@
// 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.
#undef LOG_WAIT_SERIAL
// The digital pins to which the push buttons are connected. // The digital pins to which the push buttons are connected.
#define ONOFF_BUTTON_PIN 2 #define ONOFF_BUTTON_PIN 2
#define SETUP_BUTTON_PIN 3 #define SETUP_BUTTON_PIN 3
@ -26,6 +36,12 @@
#define DISTANCE_MEASURE_INTERVAL 1 // measure every second #define DISTANCE_MEASURE_INTERVAL 1 // measure every second
#define DISTANCE_AVERAGE_STORAGE 180 // making this a 3 minute average #define DISTANCE_AVERAGE_STORAGE 180 // making this a 3 minute average
// The minimum interval in seconds at which to publish measurements to MQTT.
// This can be seen as keep-alive functionality, allowing the receiving
// side to consider the device off-line when no new data have come in
// after this interval.
#define MINIMUM_PUBLISH_INTERVAL 300
// The network configuration and possibly overrides for the above // The network configuration and possibly overrides for the above
// definitions are stored in a separate header file, which is // definitions are stored in a separate header file, which is
// not stored in the repository. Before compiling this code, // not stored in the repository. Before compiling this code,

View File

@ -12,13 +12,9 @@ auto logger = Dough::Logger("MAIN");
void setup() void setup()
{ {
Dough::Logger::setup();
logger.log("s", "Initializing device"); logger.log("s", "Initializing device");
Dough::TemperatureSensor::Instance()->setup(); Dough::App::Instance()->setup();
Dough::HumiditySensor::Instance()->setup();
Dough::DistanceSensor::Instance()->setup();
Dough::WiFi::Instance()->setup();
Dough::MQTT::Instance()->setup();
Dough::DataController::Instance()->setup();
auto ui = Dough::UI::Instance(); auto ui = Dough::UI::Instance();
ui->setup(); ui->setup();
ui->onoffButton.onPress(handleOnoffButtonPress); ui->onoffButton.onPress(handleOnoffButtonPress);
@ -28,9 +24,9 @@ void setup()
void loop() void loop()
{ {
auto app = Dough::App::Instance();
auto mqtt = app->mqtt;
auto ui = Dough::UI::Instance(); auto ui = Dough::UI::Instance();
auto data = Dough::DataController::Instance();
auto mqtt = Dough::MQTT::Instance();
ui->processButtonEvents(); ui->processButtonEvents();
@ -39,19 +35,19 @@ void loop()
return; return;
} }
mqtt->procesIncomingsMessages(); mqtt.procesIncomingsMessages();
if (state == CONFIGURING && data->isConfigured()) if (state == CONFIGURING && app->config.isOk())
{ {
setStateToMeasuring(); setStateToMeasuring();
} }
else if (state == MEASURING && !data->isConfigured()) else if (state == MEASURING && !app->config.isOk())
{ {
setStateToConfiguring(); setStateToConfiguring();
} }
else if (state == MEASURING) else if (state == MEASURING)
{ {
Dough::DataController::Instance()->loop(); app->measure();
} }
else if (state == CALIBRATING) else if (state == CALIBRATING)
{ {
@ -60,7 +56,7 @@ void loop()
} }
else if (state == PAUSED) else if (state == PAUSED)
{ {
Dough::DataController::Instance()->clearHistory(); app->clearHistory();
} }
} }
@ -71,11 +67,12 @@ bool setupNetworkConnection()
{ {
static auto connectionState = CONNECTING_WIFI; static auto connectionState = CONNECTING_WIFI;
auto app = Dough::App::Instance();
auto ui = Dough::UI::Instance(); auto ui = Dough::UI::Instance();
auto network = Dough::WiFi::Instance(); auto network = app->wifi;
auto mqtt = Dough::MQTT::Instance(); auto mqtt = app->mqtt;
if (!network->isConnected()) if (!network.isConnected())
{ {
if (connectionState == CONNECTED) if (connectionState == CONNECTED)
{ {
@ -89,9 +86,9 @@ bool setupNetworkConnection()
ui->led1.blink()->slow(); ui->led1.blink()->slow();
ui->led2.off(); ui->led2.off();
ui->led3.off(); ui->led3.off();
network->connect(); network.connect();
} }
if (network->isConnected() && !mqtt->isConnected()) if (network.isConnected() && !mqtt.isConnected())
{ {
if (connectionState == CONNECTED) if (connectionState == CONNECTED)
{ {
@ -102,12 +99,12 @@ bool setupNetworkConnection()
logger.log("s", "Connecting to the MQTT broker ..."); logger.log("s", "Connecting to the MQTT broker ...");
} }
connectionState = CONNECTING_MQTT; connectionState = CONNECTING_MQTT;
ui->led1.blink()->fast(); ui->led1.on();
ui->led2.off(); ui->led2.blink()->slow();
ui->led3.off(); ui->led3.off();
mqtt->connect(); mqtt.connect();
} }
if (network->isConnected() && mqtt->isConnected()) if (network.isConnected() && mqtt.isConnected())
{ {
if (connectionState != CONNECTED) if (connectionState != CONNECTED)
{ {
@ -149,7 +146,7 @@ void setStateToConfiguring()
ui->led1.on(); ui->led1.on();
ui->led2.blink()->fast(); ui->led2.blink()->fast();
ui->led3.off(); ui->led3.off();
Dough::MQTT::Instance()->publish("state", "configuring"); Dough::App::Instance()->mqtt.publish("state", "configuring");
} }
void setStateToMeasuring() void setStateToMeasuring()
@ -160,7 +157,7 @@ void setStateToMeasuring()
ui->led1.on(); ui->led1.on();
ui->led2.on(); ui->led2.on();
ui->led3.on(); ui->led3.on();
Dough::MQTT::Instance()->publish("state", "measuring"); Dough::App::Instance()->mqtt.publish("state", "measuring");
} }
void setStateToPaused() void setStateToPaused()
@ -171,7 +168,7 @@ void setStateToPaused()
ui->led1.on(); ui->led1.on();
ui->led2.on(); ui->led2.on();
ui->led3.pulse(); ui->led3.pulse();
Dough::MQTT::Instance()->publish("state", "paused"); Dough::App::Instance()->mqtt.publish("state", "paused");
} }
void setStateToCalibrating() void setStateToCalibrating()
@ -182,5 +179,5 @@ void setStateToCalibrating()
ui->led1.on(); ui->led1.on();
ui->led2.blink()->slow(); ui->led2.blink()->slow();
ui->led3.off(); ui->led3.off();
Dough::MQTT::Instance()->publish("state", "calibrating"); Dough::App::Instance()->mqtt.publish("state", "calibrating");
} }

View File

@ -2,12 +2,12 @@
#define DOUGHBOY_H #define DOUGHBOY_H
#include <Arduino.h> #include <Arduino.h>
#include "App/App.h"
#include "Sensors/TemperatureSensor.h" #include "Sensors/TemperatureSensor.h"
#include "Sensors/HumiditySensor.h" #include "Sensors/HumiditySensor.h"
#include "Sensors/DistanceSensor.h" #include "Sensors/DistanceSensor.h"
#include "Network/WiFi.h" #include "Network/WiFi.h"
#include "Network/MQTT.h" #include "Network/MQTT.h"
#include "Data/DataController.h"
#include "UI/Button.h" #include "UI/Button.h"
#include "UI/UI.h" #include "UI/UI.h"
#include "config.h" #include "config.h"