Going to see if namespaces help structuring the code.

This commit is contained in:
Maurice Makaay 2020-07-12 01:52:08 +02:00
parent 6b49d62257
commit 3f8eb8b2b8
10 changed files with 206 additions and 196 deletions

View File

@ -36,7 +36,7 @@ DataController::DataController() : _temperatureMeasurements(
_logger("DATA")
{
_ui = DoughUI::Instance();
_mqtt = DoughMQTT::Instance();
_mqtt = Dough::MQTT::Instance();
}
// ----------------------------------------------------------------------
@ -48,7 +48,7 @@ void DataController::setup()
_containerHeight = 0.00;
_containerHeightSet = false;
DoughMQTT *mqtt = DoughMQTT::Instance();
Dough::MQTT *mqtt = Dough::MQTT::Instance();
mqtt->onConnect(DataController::handleMqttConnect);
mqtt->onMessage(DataController::handleMqttMessage);
@ -57,7 +57,7 @@ void DataController::setup()
_distanceMeasurements.setup();
}
void DataController::handleMqttConnect(DoughMQTT *mqtt)
void DataController::handleMqttConnect(Dough::MQTT *mqtt)
{
mqtt->subscribe("container_height");
}

View File

@ -33,7 +33,7 @@
#include "Sensors/HumiditySensor.h"
#include "Sensors/DistanceSensor.h"
#include "Network/DoughWiFi.h"
#include "Network/DoughMQTT.h"
#include "Network/MQTT.h"
#include "UI/DoughUI.h"
#include "UI/DoughLogger.h"
@ -58,14 +58,14 @@ public:
void clearHistory();
void setContainerHeight(int height);
bool isConfigured();
static void handleMqttConnect(DoughMQTT *mqtt);
static void handleMqttConnect(Dough::MQTT *mqtt);
static void handleMqttMessage(String &key, String &value);
private:
DataController();
static DataController *_instance;
DoughUI *_ui;
DoughMQTT *_mqtt;
Dough::MQTT *_mqtt;
Measurements _temperatureMeasurements;
Measurements _humidityMeasurements;
Measurements _distanceMeasurements;

View File

@ -13,7 +13,7 @@ Measurements::Measurements(
_storageSize = storageSize;
_significantChange = significantChange;
_minimumPublishTime = minimumPublishTime;
_mqtt = DoughMQTT::Instance();
_mqtt = Dough::MQTT::Instance();
}
void Measurements::setup()

View File

@ -4,7 +4,7 @@
#include <Arduino.h>
#include "Sensors/SensorBase.h"
#include "Data/Measurement.h"
#include "Network/DoughMQTT.h"
#include "Network/MQTT.h"
/**
* This class is used to store measurements for a sensor and to keep
@ -43,7 +43,7 @@ public:
void clearHistory();
private:
DoughMQTT *_mqtt;
Dough::MQTT *_mqtt;
const char *_mqttKey;
char *_mqttAverageKey;
SensorBase *_sensor;

View File

@ -1,133 +0,0 @@
#include "DoughMQTT.h"
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
DoughMQTT *DoughMQTT::_instance = nullptr;
DoughMQTT *DoughMQTT::Instance()
{
if (DoughMQTT::_instance == nullptr)
{
DoughMQTT::_instance = new DoughMQTT();
}
return DoughMQTT::_instance;
}
DoughMQTT::DoughMQTT() : _logger("MQTT") {}
// ----------------------------------------------------------------------
// Setup
// ----------------------------------------------------------------------
void DoughMQTT::setup()
{
DoughWiFi *network = DoughWiFi::Instance();
#ifdef MQTT_DEVICE_ID
_mqttDeviceId = MQTT_DEVICE_ID;
#else
_mqttDeviceId = network->getMacAddress();
#endif
_logger.log("ss", "Device ID = ", _mqttDeviceId);
_mqttClient.begin(MQTT_BROKER, MQTT_PORT, network->client);
}
void DoughMQTT::onConnect(DoughMQTTConnectHandler callback)
{
_onConnect = callback;
}
void DoughMQTT::onMessage(MQTTClientCallbackSimple callback)
{
_onMessage = callback;
}
// ----------------------------------------------------------------------
// Loop
// ----------------------------------------------------------------------
bool DoughMQTT::isConnected()
{
return _mqttClient.connected();
}
bool DoughMQTT::connect()
{
_logger.log("sssi", "Broker = ", MQTT_BROKER, ":", MQTT_PORT);
_mqttClient.connect(_mqttDeviceId, MQTT_USERNAME, MQTT_PASSWORD);
// Check if the connection to the broker was successful.
if (!_mqttClient.connected())
{
_logger.log("s", "ERROR - Connection to broker failed");
return false;
}
_mqttClient.onMessage(DoughMQTT::handleMessage);
if (_onConnect != nullptr)
{
_onConnect(this);
}
return true;
}
void DoughMQTT::procesIncomingsMessages()
{
_mqttClient.loop();
}
void DoughMQTT::handleMessage(String &topic, String &payload)
{
DoughMQTT::Instance()->_logger.log("sSsS", "<<< ", topic, " = ", payload);
DoughMQTT *mqtt = DoughMQTT::Instance();
if (mqtt->_onMessage != nullptr)
{
int pos = topic.lastIndexOf('/');
if (pos != -1)
{
topic.remove(0, pos + 1);
mqtt->_onMessage(topic, payload);
}
}
}
void DoughMQTT::subscribe(const char *key)
{
char topic[200];
snprintf(topic, sizeof(topic) / sizeof(topic[0]), "%s/%s/%s", MQTT_TOPIC_PREFIX, _mqttDeviceId, key);
_logger.log("ss", "Subscribe to ", topic);
_mqttClient.subscribe(topic);
}
void DoughMQTT::publish(const char *key, const char *payload)
{
char topic[200];
snprintf(topic, sizeof(topic) / sizeof(topic[0]), "%s/%s/%s", MQTT_TOPIC_PREFIX, _mqttDeviceId, key);
_logger.log("ssss", ">>> ", topic, " = ", payload);
_mqttClient.publish(topic, payload);
}
void DoughMQTT::publish(const char *key, int payload)
{
char buf[16];
snprintf(buf, 16, "%d", payload);
publish(key, buf);
}
void DoughMQTT::publish(const char *key, Measurement measurement)
{
if (measurement.ok)
{
publish(key, measurement.value);
}
else
{
publish(key, "null");
}
}

View File

@ -1,46 +0,0 @@
#ifndef DOUGH_MQTT_H
#define DOUGH_MQTT_H
#include <MQTT.h>
#include <MQTTClient.h>
#include "Network/DoughWiFi.h"
#include "Data/Measurement.h"
#include "UI/DoughLogger.h"
#include "config.h"
/**
* This class encapsulates the connection to the MQTT broker.
* MQTT is used to publish measurements and to store configuration data.
*/
class DoughMQTT;
typedef void (*DoughMQTTConnectHandler)(DoughMQTT *mqtt);
typedef void (*DoughMQTTMessageHandler)(String &key, String &value);
class DoughMQTT
{
public:
static DoughMQTT *Instance();
void setup();
void onConnect(DoughMQTTConnectHandler callback);
void onMessage(DoughMQTTMessageHandler callback);
bool isConnected();
bool connect();
void subscribe(const char *key);
void procesIncomingsMessages();
void publish(const char *key, const char *payload);
void publish(const char *key, int payload);
void publish(const char *key, Measurement measurement);
private:
DoughMQTT();
static DoughMQTT *_instance;
MQTTClient _mqttClient;
DoughLogger _logger;
DoughMQTTConnectHandler _onConnect = nullptr;
MQTTClientCallbackSimple _onMessage = nullptr;
static void handleMessage(String &topic, String &payload);
char *_mqttDeviceId;
};
#endif

138
src/Network/MQTT.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "MQTT.h"
namespace Dough
{
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
MQTT *MQTT::_instance = nullptr;
MQTT *MQTT::Instance()
{
if (MQTT::_instance == nullptr)
{
MQTT::_instance = new MQTT();
}
return MQTT::_instance;
}
MQTT::MQTT() : _logger("MQTT") {}
// ----------------------------------------------------------------------
// Setup
// ----------------------------------------------------------------------
void MQTT::setup()
{
DoughWiFi *network = DoughWiFi::Instance();
#ifdef MQTT_DEVICE_ID
_mqttDeviceId = MQTT_DEVICE_ID;
#else
_mqttDeviceId = network->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;
}
// ----------------------------------------------------------------------
// Loop
// ----------------------------------------------------------------------
bool MQTT::isConnected()
{
return _mqttClient.connected();
}
bool MQTT::connect()
{
_logger.log("sssi", "Broker = ", MQTT_BROKER, ":", MQTT_PORT);
_mqttClient.connect(_mqttDeviceId, MQTT_USERNAME, MQTT_PASSWORD);
// Check if the connection to the broker was successful.
if (!_mqttClient.connected())
{
_logger.log("s", "ERROR - Connection to broker failed");
return false;
}
_mqttClient.onMessage(MQTT::handleMessage);
if (_onConnect != nullptr)
{
_onConnect(this);
}
return true;
}
void MQTT::procesIncomingsMessages()
{
_mqttClient.loop();
}
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);
}
}
}
void MQTT::subscribe(const char *key)
{
char topic[200];
snprintf(topic, sizeof(topic) / sizeof(topic[0]), "%s/%s/%s", MQTT_TOPIC_PREFIX, _mqttDeviceId, key);
_logger.log("ss", "Subscribe to ", topic);
_mqttClient.subscribe(topic);
}
void MQTT::publish(const char *key, const char *payload)
{
char topic[200];
snprintf(topic, sizeof(topic) / sizeof(topic[0]), "%s/%s/%s", MQTT_TOPIC_PREFIX, _mqttDeviceId, key);
_logger.log("ssss", ">>> ", topic, " = ", payload);
_mqttClient.publish(topic, payload);
}
void MQTT::publish(const char *key, int payload)
{
char buf[16];
snprintf(buf, 16, "%d", payload);
publish(key, buf);
}
void MQTT::publish(const char *key, Measurement measurement)
{
if (measurement.ok)
{
publish(key, measurement.value);
}
else
{
publish(key, "null");
}
}
} // namespace Dough

50
src/Network/MQTT.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef DOUGH_MQTT_H
#define DOUGH_MQTT_H
#include <MQTT.h>
#include <MQTTClient.h>
#include "Network/DoughWiFi.h"
#include "Data/Measurement.h"
#include "UI/DoughLogger.h"
#include "config.h"
namespace Dough
{
/**
* This class encapsulates the connection to the MQTT broker.
* MQTT is used to publish measurements and to store configuration data.
*/
class MQTT;
typedef void (*MQTTConnectHandler)(MQTT *mqtt);
typedef void (*MQTTMessageHandler)(String &key, String &value);
class MQTT
{
public:
static MQTT *Instance();
void setup();
void onConnect(MQTTConnectHandler callback);
void onMessage(MQTTMessageHandler callback);
bool isConnected();
bool connect();
void subscribe(const char *key);
void procesIncomingsMessages();
void publish(const char *key, const char *payload);
void publish(const char *key, int payload);
void publish(const char *key, Measurement measurement);
private:
MQTT();
static MQTT *_instance;
MQTTClient _mqttClient;
DoughLogger _logger;
MQTTConnectHandler _onConnect = nullptr;
MQTTClientCallbackSimple _onMessage = nullptr;
static void handleMessage(String &topic, String &payload);
char *_mqttDeviceId;
};
} // namespace Dough
#endif

View File

@ -1,5 +1,6 @@
#include "main.h"
// TODO: move code to Dough namespace
// TODO: move config to a separate class
// TODO: see if I can give each sensor its own built-in loop schedule for sampling, the DoughData class might be overkill in the latest setup.
// TOOD: implement the calibration logic
@ -15,7 +16,7 @@ void setup()
HumiditySensor::Instance()->setup();
DistanceSensor::Instance()->setup();
DoughWiFi::Instance()->setup();
DoughMQTT::Instance()->setup();
Dough::MQTT::Instance()->setup();
DataController::Instance()->setup();
auto ui = DoughUI::Instance();
ui->setup();
@ -28,7 +29,7 @@ void loop()
{
auto ui = DoughUI::Instance();
auto data = DataController::Instance();
auto mqtt = DoughMQTT::Instance();
auto mqtt = Dough::MQTT::Instance();
ui->processButtonEvents();
@ -73,7 +74,7 @@ bool setupNetworkConnection()
auto ui = DoughUI::Instance();
auto network = DoughWiFi::Instance();
auto mqtt = DoughMQTT::Instance();
auto mqtt = Dough::MQTT::Instance();
if (!network->isConnected())
{
@ -149,7 +150,7 @@ void setStateToConfiguring()
ui->led1.on();
ui->led2.blink()->fast();
ui->led3.off();
DoughMQTT::Instance()->publish("state", "configuring");
Dough::MQTT::Instance()->publish("state", "configuring");
}
void setStateToMeasuring()
@ -160,7 +161,7 @@ void setStateToMeasuring()
ui->led1.on();
ui->led2.on();
ui->led3.on();
DoughMQTT::Instance()->publish("state", "measuring");
Dough::MQTT::Instance()->publish("state", "measuring");
}
void setStateToPaused()
@ -171,7 +172,7 @@ void setStateToPaused()
ui->led1.on();
ui->led2.on();
ui->led3.pulse();
DoughMQTT::Instance()->publish("state", "paused");
Dough::MQTT::Instance()->publish("state", "paused");
}
void setStateToCalibrating()
@ -182,5 +183,5 @@ void setStateToCalibrating()
ui->led1.on();
ui->led2.blink()->slow();
ui->led3.off();
DoughMQTT::Instance()->publish("state", "calibrating");
Dough::MQTT::Instance()->publish("state", "calibrating");
}

View File

@ -6,7 +6,7 @@
#include "Sensors/HumiditySensor.h"
#include "Sensors/DistanceSensor.h"
#include "Network/DoughWiFi.h"
#include "Network/DoughMQTT.h"
#include "Network/MQTT.h"
#include "Data/DataController.h"
#include "UI/DoughButton.h"
#include "UI/DoughUI.h"