Add the ability to add mqtt sensors at runtime
This commit is contained in:
parent
36171a221a
commit
25b9f87285
11 changed files with 208 additions and 0 deletions
|
|
@ -22,6 +22,11 @@ void MainObject::refresh()
|
|||
globalItems.refresh();
|
||||
}
|
||||
|
||||
void MainObject::addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload)
|
||||
{
|
||||
// Default implementation does nothing - derived classes override
|
||||
}
|
||||
|
||||
QJsonObject MainObject::getJsonObjectFromDisk(const QString& filename, bool* error)
|
||||
{
|
||||
QFile file;
|
||||
|
|
@ -89,6 +94,8 @@ PrimaryMainObject::PrimaryMainObject(QIODevice* microDevice, const QString& sett
|
|||
connect(&sunSensorSource, &SunSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
|
||||
connect(µ, &Microcontroller::gotSensorState, &globalSensors, &SensorStore::sensorGotState);
|
||||
connect(&mqttSensorSource, &MqttSensorSource::stateChanged, &globalSensors, &SensorStore::sensorGotState);
|
||||
connect(tcpServer, &TcpServer::sensorAdded, &mqttSensorSource, &MqttSensorSource::onSensorAdded);
|
||||
connect(webServer, &WebSocketServer::sensorAdded, &mqttSensorSource, &MqttSensorSource::onSensorAdded);
|
||||
|
||||
globalItems.registerItemSource(&fixedItems);
|
||||
globalItems.registerItemSource(tcpServer);
|
||||
|
|
@ -174,3 +181,8 @@ SecondaryMainObject::~SecondaryMainObject()
|
|||
{
|
||||
}
|
||||
|
||||
void SecondaryMainObject::addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload)
|
||||
{
|
||||
tcpClient->addSensor(sensor, backend, payload);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
public slots:
|
||||
void refresh();
|
||||
virtual void addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload = {});
|
||||
};
|
||||
|
||||
class PrimaryMainObject : public MainObject
|
||||
|
|
@ -74,6 +75,7 @@ public:
|
|||
public:
|
||||
explicit SecondaryMainObject(QString host, int port, QObject *parent = nullptr);
|
||||
~SecondaryMainObject();
|
||||
void addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload = {}) override;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,25 @@ void MqttSensorSource::start(std::shared_ptr<MqttClient> client, const QJsonObje
|
|||
}
|
||||
}
|
||||
|
||||
void MqttSensorSource::addSensor(const QString& topic, const QString& name)
|
||||
{
|
||||
if(!client)
|
||||
return;
|
||||
|
||||
SensorSubscription sensor;
|
||||
sensor.topic = topic;
|
||||
sensor.name = name;
|
||||
sensor.id = qHash(client->getBaseTopic() + "/" + topic);
|
||||
sensors.push_back(sensor);
|
||||
|
||||
// Subscribe if already connected
|
||||
if(client->getClient()->state() == QMqttClient::ClientState::Connected)
|
||||
{
|
||||
sensor.subscription = client->subscribe(client->getBaseTopic() + "/" + topic);
|
||||
connect(sensor.subscription->subscription, &QMqttSubscription::messageReceived, this, &MqttSensorSource::onMessageReceived);
|
||||
}
|
||||
}
|
||||
|
||||
MqttSensorSource::SensorSubscription& MqttSensorSource::findSubscription(const QString& topic)
|
||||
{
|
||||
for(SensorSubscription& sensor : sensors)
|
||||
|
|
@ -194,3 +213,16 @@ MqttSensorSource::~MqttSensorSource()
|
|||
client->unsubscribe(client->getBaseTopic() + "/" + sub.topic);
|
||||
}
|
||||
|
||||
void MqttSensorSource::onSensorAdded(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload)
|
||||
{
|
||||
if(backend != Sensor::BACKEND_MQTT)
|
||||
return;
|
||||
|
||||
QString topic = payload["Topic"].toString();
|
||||
QString name = payload["Name"].toString();
|
||||
if(topic.isEmpty())
|
||||
return;
|
||||
|
||||
addSensor(topic, name);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,10 +31,14 @@ private slots:
|
|||
void onClientStateChanged(QMqttClient::ClientState state);
|
||||
void onMessageReceived(const QMqttMessage& message);
|
||||
|
||||
public slots:
|
||||
void onSensorAdded(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload);
|
||||
|
||||
public:
|
||||
explicit MqttSensorSource(QObject *parent = nullptr);
|
||||
~MqttSensorSource();
|
||||
void start(std::shared_ptr<MqttClient> client, const QJsonObject& settings);
|
||||
void addSensor(const QString& topic, const QString& name);
|
||||
void store(QJsonObject& json);
|
||||
|
||||
signals:
|
||||
|
|
|
|||
|
|
@ -33,6 +33,12 @@ public:
|
|||
TYPE_DUMMY,
|
||||
} sensor_type_t;
|
||||
|
||||
typedef enum {
|
||||
BACKEND_MICROCONTROLLER = 0,
|
||||
BACKEND_MQTT,
|
||||
BACKEND_SUN,
|
||||
} sensor_backend_type_t;
|
||||
|
||||
sensor_type_t type;
|
||||
uint64_t id;
|
||||
float field;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,17 @@ void Service::sensorEvent(Sensor sensor, sensor_update_type_t type)
|
|||
|
||||
void Service::itemUpdated(ItemUpdateRequest update) {}
|
||||
|
||||
void Service::addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload)
|
||||
{
|
||||
QJsonObject sensorjson;
|
||||
sensor.store(sensorjson);
|
||||
QJsonObject json = createMessage("AddSensor", QJsonArray());
|
||||
json["Sensor"] = sensorjson;
|
||||
json["Backend"] = static_cast<int>(backend);
|
||||
json["Payload"] = payload;
|
||||
sendJson(json);
|
||||
}
|
||||
|
||||
void Service::refresh()
|
||||
{
|
||||
sendJson(createMessage("GetSensors", QJsonArray()));
|
||||
|
|
@ -88,4 +99,12 @@ void Service::processIncomeingJson(const QByteArray& jsonbytes)
|
|||
gotSensor(sensor, SENSOR_UPDATE_REMOTE);
|
||||
}
|
||||
}
|
||||
else if(type == "AddSensor")
|
||||
{
|
||||
QJsonObject sensorjson = json["Sensor"].toObject();
|
||||
Sensor sensor(sensorjson);
|
||||
Sensor::sensor_backend_type_t backend = static_cast<Sensor::sensor_backend_type_t>(json["Backend"].toInt(0));
|
||||
QJsonObject payload = json["Payload"].toObject();
|
||||
emit sensorAdded(sensor, backend, payload);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,11 +21,13 @@ protected:
|
|||
|
||||
signals:
|
||||
void gotSensor(Sensor sensor, sensor_update_type_t type = SENSOR_UPDATE_BACKEND);
|
||||
void sensorAdded(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload);
|
||||
|
||||
public slots:
|
||||
void sensorEvent(Sensor sensor, sensor_update_type_t type);
|
||||
virtual void itemUpdated(ItemUpdateRequest update);
|
||||
virtual void refresh() override;
|
||||
virtual void addSensor(Sensor sensor, Sensor::sensor_backend_type_t backend, QJsonObject payload = {});
|
||||
|
||||
public:
|
||||
Service(QObject* parent = nullptr);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "mainwindow.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
#include "itemscrollbox.h"
|
||||
|
|
@ -9,10 +10,12 @@
|
|||
#include "mainobject.h"
|
||||
#include "programmode.h"
|
||||
#include "items/poweritem.h"
|
||||
#include "sensors/mqttsensorsource.h"
|
||||
|
||||
MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
mainObject(mainObject),
|
||||
colorChooser(this)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
@ -45,6 +48,7 @@ MainWindow::MainWindow(MainObject * const mainObject, QWidget *parent) :
|
|||
ui->button_color->hide();
|
||||
|
||||
connect(ui->pushButton_addItem, &QPushButton::clicked, this, &MainWindow::showItemCreationDialog);
|
||||
connect(ui->pushButton_addSensor, &QPushButton::clicked, this, &MainWindow::showSensorCreationDialog);
|
||||
connect(ui->relayList, &ItemScrollBox::deleteRequest, &globalItems, &ItemStore::removeItem);
|
||||
connect(ui->checkBox_sensorsShowHidden, &QCheckBox::clicked, ui->sensorListView, &SensorListWidget::setShowHidden);
|
||||
|
||||
|
|
@ -90,6 +94,35 @@ void MainWindow::showItemCreationDialog()
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::showSensorCreationDialog()
|
||||
{
|
||||
bool ok;
|
||||
QString topic = QInputDialog::getText(this, "Add MQTT Sensor", "Topic:", QLineEdit::Normal, "", &ok);
|
||||
if(!ok || topic.isEmpty())
|
||||
return;
|
||||
|
||||
QString name = QInputDialog::getText(this, "Add MQTT Sensor", "Name:", QLineEdit::Normal, topic, &ok);
|
||||
if(!ok)
|
||||
return;
|
||||
|
||||
Sensor sensor(Sensor::TYPE_DUMMY, 0, 0, name);
|
||||
QJsonObject payload;
|
||||
payload["Topic"] = topic;
|
||||
payload["Name"] = name;
|
||||
|
||||
PrimaryMainObject* primaryMain = dynamic_cast<PrimaryMainObject*>(mainObject);
|
||||
if(primaryMain)
|
||||
{
|
||||
// Primary mode: add directly to mqttSensorSource
|
||||
primaryMain->mqttSensorSource.addSensor(topic, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Secondary mode: send via TCP to primary
|
||||
mainObject->addSensor(sensor, Sensor::BACKEND_MQTT, payload);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::changeHeaderLableText(QString string)
|
||||
{
|
||||
if(string.size() > 28)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ public:
|
|||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
MainObject* const mainObject;
|
||||
|
||||
QColorDialog colorChooser;
|
||||
|
||||
|
|
@ -40,6 +41,7 @@ private slots:
|
|||
//RGB
|
||||
void showPowerItemDialog();
|
||||
void showItemCreationDialog();
|
||||
void showSensorCreationDialog();
|
||||
|
||||
public slots:
|
||||
|
||||
|
|
|
|||
|
|
@ -230,6 +230,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_addSensor">
|
||||
<property name="text">
|
||||
<string>Add Sensor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_quit">
|
||||
<property name="sizePolicy">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue