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:
parent
e0bd4b64b8
commit
49115a0545
|
@ -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");
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef DOUGH_DATA_MEASUREMENT_H
|
||||
#define DOUGH_DATA_MEASUREMENT_H
|
||||
#ifndef DOUGH_MEASUREMENT_H
|
||||
#define DOUGH_MEASUREMENT_H
|
||||
|
||||
namespace Dough
|
||||
{
|
||||
|
|
|
@ -4,18 +4,19 @@
|
|||
namespace Dough
|
||||
{
|
||||
SensorController::SensorController(
|
||||
MQTT *mqtt,
|
||||
const char *mqttKey,
|
||||
SensorBase *sensor,
|
||||
unsigned int storageSize,
|
||||
unsigned int minimumMeasureTime,
|
||||
unsigned int minimumPublishTime)
|
||||
{
|
||||
_mqtt = mqtt;
|
||||
_mqttKey = mqttKey;
|
||||
_sensor = sensor;
|
||||
_storageSize = storageSize;
|
||||
_minimumMeasureTime = minimumMeasureTime;
|
||||
_minimumPublishTime = minimumPublishTime;
|
||||
_mqtt = MQTT::Instance();
|
||||
_ui = UI::Instance();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef DOUGH_DATA_MEASUREMENTS_H
|
||||
#define DOUGH_DATA_MEASUREMENTS_H
|
||||
#ifndef DOUGH_MEASUREMENTS_H
|
||||
#define DOUGH_MEASUREMENTS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "Sensors/SensorBase.h"
|
||||
|
@ -19,6 +19,8 @@ namespace Dough
|
|||
public:
|
||||
// Create a new Measurements object.
|
||||
//
|
||||
// @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
|
||||
|
@ -34,6 +36,7 @@ namespace Dough
|
|||
// The number of seconds after which to forcibly publish measurements
|
||||
// to MQTT, even when no significant changes to measurements were seen.
|
||||
SensorController(
|
||||
MQTT *mqtt,
|
||||
const char *mqttKey,
|
||||
SensorBase *sensor,
|
||||
unsigned int storageSize,
|
||||
|
|
|
@ -2,45 +2,26 @@
|
|||
|
||||
namespace Dough
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
MQTT *MQTT::Instance()
|
||||
MQTT::MQTT(
|
||||
WiFi *network,
|
||||
MQTTConnectHandler onConnect,
|
||||
MQTTMessageHandler onMessage) : _logger("MQTT")
|
||||
{
|
||||
static MQTT *_instance = new MQTT();
|
||||
return _instance;
|
||||
_wifi = network;
|
||||
_onConnect = onConnect;
|
||||
_onMessage = onMessage;
|
||||
}
|
||||
|
||||
MQTT::MQTT() : _logger("MQTT") {}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Setup
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void MQTT::setup()
|
||||
{
|
||||
WiFi *network = WiFi::Instance();
|
||||
|
||||
#ifdef MQTT_DEVICE_ID
|
||||
_mqttDeviceId = MQTT_DEVICE_ID;
|
||||
#else
|
||||
_mqttDeviceId = network->getMacAddress();
|
||||
_mqttDeviceId = _wifi->getMacAddress();
|
||||
#endif
|
||||
_logger.log("ss", "Device ID = ", _mqttDeviceId);
|
||||
|
||||
_mqttClient.begin(MQTT_BROKER, MQTT_PORT, network->client);
|
||||
}
|
||||
|
||||
void MQTT::onConnect(MQTTConnectHandler callback)
|
||||
{
|
||||
_onConnect = callback;
|
||||
}
|
||||
|
||||
void MQTT::onMessage(MQTTClientCallbackSimple callback)
|
||||
{
|
||||
_onMessage = callback;
|
||||
_mqttClient.begin(MQTT_BROKER, MQTT_PORT, _wifi->client);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
@ -63,8 +44,9 @@ namespace Dough
|
|||
_logger.log("s", "ERROR - Connection to broker failed");
|
||||
return false;
|
||||
}
|
||||
_logger.log("s", "Connection to broker successful");
|
||||
|
||||
_mqttClient.onMessage(MQTT::handleMessage);
|
||||
_mqttClient.onMessage(_onMessage);
|
||||
|
||||
if (_onConnect != nullptr)
|
||||
{
|
||||
|
@ -81,21 +63,22 @@ namespace Dough
|
|||
_mqttClient.loop();
|
||||
}
|
||||
|
||||
void MQTT::handleMessage(String &topic, String &payload)
|
||||
{
|
||||
MQTT::Instance()->_logger.log("sSsS", "<<< ", topic, " = ", payload);
|
||||
// // static
|
||||
// void MQTT::handleMessage(String &topic, String &payload)
|
||||
// {
|
||||
// MQTT::Instance()->_logger.log("sSsS", "<<< ", topic, " = ", payload);
|
||||
|
||||
MQTT *mqtt = MQTT::Instance();
|
||||
if (mqtt->_onMessage != nullptr)
|
||||
{
|
||||
int pos = topic.lastIndexOf('/');
|
||||
if (pos != -1)
|
||||
{
|
||||
topic.remove(0, pos + 1);
|
||||
mqtt->_onMessage(topic, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
// MQTT *mqtt = MQTT::Instance();
|
||||
// if (mqtt->_onMessage != nullptr)
|
||||
// {
|
||||
// int pos = topic.lastIndexOf('/');
|
||||
// if (pos != -1)
|
||||
// {
|
||||
// topic.remove(0, pos + 1);
|
||||
// mqtt->_onMessage(topic, payload);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
void MQTT::subscribe(const char *key)
|
||||
{
|
||||
|
|
|
@ -20,10 +20,8 @@ namespace Dough
|
|||
class MQTT
|
||||
{
|
||||
public:
|
||||
static MQTT *Instance();
|
||||
MQTT(WiFi *network, MQTTConnectHandler onConnect, MQTTMessageHandler onMessage);
|
||||
void setup();
|
||||
void onConnect(MQTTConnectHandler callback);
|
||||
void onMessage(MQTTMessageHandler callback);
|
||||
bool isConnected();
|
||||
bool connect();
|
||||
void subscribe(const char *key);
|
||||
|
@ -33,15 +31,13 @@ namespace Dough
|
|||
void publish(const char *key, Measurement measurement);
|
||||
|
||||
private:
|
||||
MQTT();
|
||||
MQTTClient _mqttClient;
|
||||
WiFi *_wifi;
|
||||
Logger _logger;
|
||||
MQTTConnectHandler _onConnect = nullptr;
|
||||
MQTTClientCallbackSimple _onMessage = nullptr;
|
||||
static void handleMessage(String &topic, String &payload);
|
||||
MQTTClient _mqttClient;
|
||||
MQTTConnectHandler _onConnect;
|
||||
MQTTClientCallbackSimple _onMessage;
|
||||
char *_mqttDeviceId;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,23 +2,13 @@
|
|||
|
||||
namespace Dough
|
||||
{
|
||||
// ----------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
WiFi *WiFi::Instance()
|
||||
{
|
||||
static WiFi *_instance = new WiFi();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
WiFi::WiFi() : _logger("WIFI") {}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Setup
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void WiFi::_setMacAddress()
|
||||
void WiFi::_storeMacAddress()
|
||||
{
|
||||
byte mac[6];
|
||||
::WiFi.macAddress(mac);
|
||||
|
@ -29,13 +19,14 @@ namespace Dough
|
|||
|
||||
void WiFi::setup()
|
||||
{
|
||||
_setMacAddress();
|
||||
_storeMacAddress();
|
||||
_logger.log("ss", "MAC address = ", getMacAddress());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Loop
|
||||
// ----------------------------------------------------------------------
|
||||
char *WiFi::getMacAddress()
|
||||
{
|
||||
return _macAddress;
|
||||
}
|
||||
|
||||
bool WiFi::isConnected()
|
||||
{
|
||||
|
@ -77,9 +68,4 @@ namespace Dough
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char *WiFi::getMacAddress()
|
||||
{
|
||||
return _macAddress;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef DOUGH_NETWORK_H
|
||||
#define DOUGH_NETWORK_H
|
||||
#ifndef DOUGH_WIFI_H
|
||||
#define DOUGH_WIFI_H
|
||||
|
||||
#include <WiFiNINA.h>
|
||||
#include "UI/Logger.h"
|
||||
|
@ -11,7 +11,7 @@ namespace Dough
|
|||
class WiFi
|
||||
{
|
||||
public:
|
||||
static WiFi *Instance();
|
||||
WiFi();
|
||||
char *getMacAddress();
|
||||
void setup();
|
||||
void loop();
|
||||
|
@ -20,8 +20,7 @@ namespace Dough
|
|||
WiFiClient client;
|
||||
|
||||
private:
|
||||
WiFi();
|
||||
void _setMacAddress();
|
||||
void _storeMacAddress();
|
||||
char _macAddress[18]; // max MAC address length + 1
|
||||
Logger _logger;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef DOUGH_SENSORS_DISTANCE_H
|
||||
#define DOUGH_SENSORS_DISTANCE_H
|
||||
#ifndef DOUGH_DISTANCE_SENSOR_H
|
||||
#define DOUGH_DISTANCE_SENSOR_H
|
||||
|
||||
#include "Sensors/SensorBase.h"
|
||||
#include "Sensors/LowLevel/SensorHCSR04.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef DOUGH_SENSORS_HUMIDITY_H
|
||||
#define DOUGH_SENSORS_HUMIDITY_H
|
||||
#ifndef DOUGH_HUMIDITY_SENSOR_H
|
||||
#define DOUGH_HUMIDITY_SENSOR_H
|
||||
|
||||
#include "Sensors/SensorBase.h"
|
||||
#include "Sensors/LowLevel/SensorDHT11.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef DOUGH_SENSORS_DHT11_H
|
||||
#define DOUGH_SENSORS_DHT11_H
|
||||
#ifndef DOUGH_SENSOR_DHT11_H
|
||||
#define DOUGH_SENSOR_DHT11_H
|
||||
|
||||
#include <DHT.h>
|
||||
#include "config.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef HCSR04_H
|
||||
#define HCSR04_H
|
||||
#ifndef DOUGH_SENSOR_HCSR04_H
|
||||
#define DOUGH_SENSOR_HCSR04_H
|
||||
|
||||
// The minimum and maximum distance that can be measured in mm.
|
||||
// This is based on the specifications of the HCSR04 sensor.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef DOUGH_SENSORS_BASE_H
|
||||
#define DOUGH_SENSORS_BASE_H
|
||||
#ifndef DOUGH_SENSOR_BASE_H
|
||||
#define DOUGH_SENSOR_BASE_H
|
||||
|
||||
#include "Data/Measurement.h"
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef DOUGH_SENSORS_TEMPERATURE_H
|
||||
#define DOUGH_SENSORS_TEMPERATURE_H
|
||||
#ifndef DOUGH_TEMPERATURE_SENSOR_H
|
||||
#define DOUGH_TEMPERATURE_SENSOR_H
|
||||
|
||||
#include "Sensors/SensorBase.h"
|
||||
#include "Sensors/LowLevel/SensorDHT11.h"
|
||||
|
|
|
@ -7,6 +7,18 @@ namespace Dough
|
|||
_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()
|
||||
{
|
||||
_suspended = true;
|
||||
|
@ -70,4 +82,4 @@ namespace Dough
|
|||
|
||||
Serial.println("");
|
||||
}
|
||||
}
|
||||
} // namespace Dough
|
|
@ -7,6 +7,7 @@
|
|||
#include <Arduino.h>
|
||||
#include <stdarg.h>
|
||||
#include <WiFiNINA.h>
|
||||
#include "config.h"
|
||||
|
||||
namespace Dough
|
||||
{
|
||||
|
@ -15,6 +16,7 @@ namespace Dough
|
|||
class Logger
|
||||
{
|
||||
public:
|
||||
static void setup();
|
||||
Logger(const char *section);
|
||||
void log(const char *fmt, ...);
|
||||
void suspend();
|
||||
|
|
|
@ -30,15 +30,6 @@ namespace Dough
|
|||
|
||||
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.
|
||||
onoffButton.setup();
|
||||
onoffButton.onInterrupt(UI::onoffButtonISR);
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
#ifndef 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 <stdarg.h>
|
||||
#include "UI/Button.h"
|
||||
|
|
16
src/config.h
16
src/config.h
|
@ -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.
|
||||
#define ONOFF_BUTTON_PIN 2
|
||||
#define SETUP_BUTTON_PIN 3
|
||||
|
@ -26,6 +36,12 @@
|
|||
#define DISTANCE_MEASURE_INTERVAL 1 // measure every second
|
||||
#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
|
||||
// definitions are stored in a separate header file, which is
|
||||
// not stored in the repository. Before compiling this code,
|
||||
|
|
49
src/main.cpp
49
src/main.cpp
|
@ -12,13 +12,9 @@ auto logger = Dough::Logger("MAIN");
|
|||
|
||||
void setup()
|
||||
{
|
||||
Dough::Logger::setup();
|
||||
logger.log("s", "Initializing device");
|
||||
Dough::TemperatureSensor::Instance()->setup();
|
||||
Dough::HumiditySensor::Instance()->setup();
|
||||
Dough::DistanceSensor::Instance()->setup();
|
||||
Dough::WiFi::Instance()->setup();
|
||||
Dough::MQTT::Instance()->setup();
|
||||
Dough::DataController::Instance()->setup();
|
||||
Dough::App::Instance()->setup();
|
||||
auto ui = Dough::UI::Instance();
|
||||
ui->setup();
|
||||
ui->onoffButton.onPress(handleOnoffButtonPress);
|
||||
|
@ -28,9 +24,9 @@ void setup()
|
|||
|
||||
void loop()
|
||||
{
|
||||
auto app = Dough::App::Instance();
|
||||
auto mqtt = app->mqtt;
|
||||
auto ui = Dough::UI::Instance();
|
||||
auto data = Dough::DataController::Instance();
|
||||
auto mqtt = Dough::MQTT::Instance();
|
||||
|
||||
ui->processButtonEvents();
|
||||
|
||||
|
@ -39,19 +35,19 @@ void loop()
|
|||
return;
|
||||
}
|
||||
|
||||
mqtt->procesIncomingsMessages();
|
||||
mqtt.procesIncomingsMessages();
|
||||
|
||||
if (state == CONFIGURING && data->isConfigured())
|
||||
if (state == CONFIGURING && app->config.isOk())
|
||||
{
|
||||
setStateToMeasuring();
|
||||
}
|
||||
else if (state == MEASURING && !data->isConfigured())
|
||||
else if (state == MEASURING && !app->config.isOk())
|
||||
{
|
||||
setStateToConfiguring();
|
||||
}
|
||||
else if (state == MEASURING)
|
||||
{
|
||||
Dough::DataController::Instance()->loop();
|
||||
app->measure();
|
||||
}
|
||||
else if (state == CALIBRATING)
|
||||
{
|
||||
|
@ -60,7 +56,7 @@ void loop()
|
|||
}
|
||||
else if (state == PAUSED)
|
||||
{
|
||||
Dough::DataController::Instance()->clearHistory();
|
||||
app->clearHistory();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,11 +67,12 @@ bool setupNetworkConnection()
|
|||
{
|
||||
static auto connectionState = CONNECTING_WIFI;
|
||||
|
||||
auto app = Dough::App::Instance();
|
||||
auto ui = Dough::UI::Instance();
|
||||
auto network = Dough::WiFi::Instance();
|
||||
auto mqtt = Dough::MQTT::Instance();
|
||||
auto network = app->wifi;
|
||||
auto mqtt = app->mqtt;
|
||||
|
||||
if (!network->isConnected())
|
||||
if (!network.isConnected())
|
||||
{
|
||||
if (connectionState == CONNECTED)
|
||||
{
|
||||
|
@ -89,9 +86,9 @@ bool setupNetworkConnection()
|
|||
ui->led1.blink()->slow();
|
||||
ui->led2.off();
|
||||
ui->led3.off();
|
||||
network->connect();
|
||||
network.connect();
|
||||
}
|
||||
if (network->isConnected() && !mqtt->isConnected())
|
||||
if (network.isConnected() && !mqtt.isConnected())
|
||||
{
|
||||
if (connectionState == CONNECTED)
|
||||
{
|
||||
|
@ -102,12 +99,12 @@ bool setupNetworkConnection()
|
|||
logger.log("s", "Connecting to the MQTT broker ...");
|
||||
}
|
||||
connectionState = CONNECTING_MQTT;
|
||||
ui->led1.blink()->fast();
|
||||
ui->led2.off();
|
||||
ui->led1.on();
|
||||
ui->led2.blink()->slow();
|
||||
ui->led3.off();
|
||||
mqtt->connect();
|
||||
mqtt.connect();
|
||||
}
|
||||
if (network->isConnected() && mqtt->isConnected())
|
||||
if (network.isConnected() && mqtt.isConnected())
|
||||
{
|
||||
if (connectionState != CONNECTED)
|
||||
{
|
||||
|
@ -149,7 +146,7 @@ void setStateToConfiguring()
|
|||
ui->led1.on();
|
||||
ui->led2.blink()->fast();
|
||||
ui->led3.off();
|
||||
Dough::MQTT::Instance()->publish("state", "configuring");
|
||||
Dough::App::Instance()->mqtt.publish("state", "configuring");
|
||||
}
|
||||
|
||||
void setStateToMeasuring()
|
||||
|
@ -160,7 +157,7 @@ void setStateToMeasuring()
|
|||
ui->led1.on();
|
||||
ui->led2.on();
|
||||
ui->led3.on();
|
||||
Dough::MQTT::Instance()->publish("state", "measuring");
|
||||
Dough::App::Instance()->mqtt.publish("state", "measuring");
|
||||
}
|
||||
|
||||
void setStateToPaused()
|
||||
|
@ -171,7 +168,7 @@ void setStateToPaused()
|
|||
ui->led1.on();
|
||||
ui->led2.on();
|
||||
ui->led3.pulse();
|
||||
Dough::MQTT::Instance()->publish("state", "paused");
|
||||
Dough::App::Instance()->mqtt.publish("state", "paused");
|
||||
}
|
||||
|
||||
void setStateToCalibrating()
|
||||
|
@ -182,5 +179,5 @@ void setStateToCalibrating()
|
|||
ui->led1.on();
|
||||
ui->led2.blink()->slow();
|
||||
ui->led3.off();
|
||||
Dough::MQTT::Instance()->publish("state", "calibrating");
|
||||
Dough::App::Instance()->mqtt.publish("state", "calibrating");
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
#define DOUGHBOY_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "App/App.h"
|
||||
#include "Sensors/TemperatureSensor.h"
|
||||
#include "Sensors/HumiditySensor.h"
|
||||
#include "Sensors/DistanceSensor.h"
|
||||
#include "Network/WiFi.h"
|
||||
#include "Network/MQTT.h"
|
||||
#include "Data/DataController.h"
|
||||
#include "UI/Button.h"
|
||||
#include "UI/UI.h"
|
||||
#include "config.h"
|
||||
|
|
Loading…
Reference in New Issue