mirror of https://github.com/nymea/nymea.git
184 lines
7.5 KiB
C++
184 lines
7.5 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* *
|
|
* Copyright (C) 2018 Michael Zanetti <michael.zanetti@nymea.io> *
|
|
* *
|
|
* This file is part of nymea. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Lesser General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2.1 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
* License along with this library; If not, see *
|
|
* <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*!
|
|
\class MqttProvider
|
|
\brief Provides means of communicating to devices via MQTT
|
|
|
|
\ingroup hardware
|
|
\inmodule libnymea
|
|
|
|
The MQTT provider class offers 2 different ways to establish a MQTT connection to a MQTT enabled IoT device:
|
|
For one it supports establishing a secure channel between the device and the plugin, using nymea's internal MQTT
|
|
broker. The second approach is to provide a generic MQTT client object connected to nymea's internal MQTT broker.
|
|
|
|
Note, if you wish to establish a MQTT connection to an external MQTT broker, you can just create your own MqttClient
|
|
and connect to wherever you need to. The MqttProvider hardware resource only manages connections to the nymea internal
|
|
MQTT broker.
|
|
|
|
If using MqttProvider hardware resource, the MQTT broker will be automatically configured with appropriate policies.
|
|
|
|
\chapter Example 1
|
|
|
|
Establishing a secure MQTT directly between plugin and the MQTT device:
|
|
|
|
\tt devicepluginexample.h
|
|
|
|
\code
|
|
#include "network/mqtt/mqttprovider.h"
|
|
#include "network/mqtt/mqttchannel.h"
|
|
|
|
class DevicePluginExample : public DevicePlugin
|
|
{
|
|
...
|
|
public:
|
|
DeviceManager::DeviceSetupStatus setupDevice(Device* device) override;
|
|
void deviceRemoved(Device* device) override;
|
|
|
|
private slots:
|
|
void onDevicePublishReceived(MqttChannel* channel, const QString &topic, const QByteArray &payload);
|
|
|
|
...
|
|
|
|
};
|
|
|
|
\endcode
|
|
|
|
\tt devicepluginexample.cpp
|
|
|
|
\code
|
|
DeviceManager::DeviceSetupStatus DevicePluginExample::setupDevice(Device *device) {
|
|
MqttChannel *channel = hardware()->mqttProvider()->createChannel(device->id(), "192.168.0.100");
|
|
|
|
// Provision credentials to device:
|
|
QString clientId = channel->clientId();
|
|
QString username = channel->username();
|
|
QString password = channel->password();
|
|
hardwareManager()->networkManager()->post("https://192.168.0.100/setup?clientId=" + username + "&username=" + username);
|
|
|
|
// connect to publishes in this channel
|
|
connect(channel, &MqttChannel::publishReceived, this, onDevicePublishReceived);
|
|
|
|
// publish to the channel
|
|
channel->publish(channel->prefix() + "/my/test/topic", "Hello world");
|
|
}
|
|
|
|
void DevicePluginExample::deviceRemoved(Device* device) {
|
|
hardware()->mqttProvider()->releaseChannel(channel);
|
|
}
|
|
|
|
void DevicePluginExample::onDevicePublishReceibed(MqttChannel *channel, const QString &topic, const QByteArray &payload) {
|
|
qCDebug(dcExample()) << "Publish received from:" << channel->clientId() << topic << payload;
|
|
}
|
|
\endcode
|
|
|
|
\chapter Example 2
|
|
|
|
Obtaining a MQTT client connected to the nymea internal MQTT broker:
|
|
|
|
\tt devicepluginexample.h
|
|
|
|
\code
|
|
#include "network/mqtt/mqttprovider.h"
|
|
#include "<nymea-mqtt/mqttclient.h>
|
|
|
|
class DevicePluginExample : public DevicePlugin
|
|
{
|
|
...
|
|
public:
|
|
DeviceManager::DeviceSetupStatus setupDevice(Device* device) override;
|
|
void deviceRemoved(Device* device) override;
|
|
|
|
private slots:
|
|
void onPublishReceived(const QString &topic, const QByteArray &payload, bool retained);
|
|
|
|
...
|
|
|
|
};
|
|
|
|
\endcode
|
|
|
|
\tt devicepluginexample.cpp
|
|
|
|
\code
|
|
DeviceManager::DeviceSetupStatus DevicePluginExample::setupDevice(Device *device) {
|
|
MqttClient *client = hardware()->mqttProvider()->createInternalClient(device->id());
|
|
|
|
// subscribe to topics
|
|
client->subscribe("/my/test/topic", Mqtt::QuS1);
|
|
|
|
// connect to publishes in this channel
|
|
connect(channel, &MqttClient::publishReceived, this, onPublishReceived);
|
|
|
|
// publish to the broker
|
|
client->publish("/my/test/topic", "Hello world");
|
|
}
|
|
|
|
void DevicePluginExample::deviceRemoved(Device* device) {
|
|
hardware()->mqttProvider()->releaseChannel(channel);
|
|
}
|
|
|
|
void DevicePluginExample::onPublishRecei(const QString &topic, const QByteArray &payload, bool retained) {
|
|
qCDebug(dcExample()) << "Publish received from:" << channel->clientId() << topic << payload << retained;
|
|
}
|
|
\endcode
|
|
|
|
|
|
\sa HardwareResource, HardwareManager::mqttProvider()
|
|
*/
|
|
|
|
/*! \fn MqttChannel *MqttProvider::createChannel(const DeviceId &deviceId, const QHostAddress &clientAddress);
|
|
Creates a new MQTT channel on the internal broker. The returned channel will have the required details for the
|
|
client device to connect to the broker. A temporaray clientId/user/password combination will be created and
|
|
clients connecting to the broker with those credentials will have access to subscribe and post to # within the
|
|
given topic prefix.
|
|
|
|
\sa releaseChannel(MqttChannel *channel)
|
|
*/
|
|
|
|
/*! \fn void MqttProvider::releaseChannel(MqttChannel *channel)
|
|
Releases the given MQTT channel. This means the broker will disconnect any clients connected on this channel
|
|
and remove the policy from the broker. The channel object will be destroyed and must not be accessed any more
|
|
after calling this function.
|
|
|
|
\sa createChannel(const DeviceId &deviceId, const QHostAddress &clientAddress)
|
|
*/
|
|
|
|
/*! \fn MqttClient *MqttProvider::createInternalClient(const DeviceId &deviceId);
|
|
Creates a temporary policy on the internal MQTT broker to allow this client connecting. If that is successful
|
|
it will create a new MqttClient object and connect it to the broker.
|
|
|
|
The client will not be subscribed to any topics yet. See the nymea-mqtt documentation for information on the MqttClient API.
|
|
|
|
The client will be owned by the MqttProvider and cleaned up when the system goes down, however, the user is free to
|
|
delete the client at any point. The policy attached to it will be removed from the MQTT broker.
|
|
*/
|
|
|
|
|
|
#include "mqttprovider.h"
|
|
#include "mqttchannel.h"
|
|
|
|
MqttProvider::MqttProvider(QObject *parent) : HardwareResource("MQTT", parent)
|
|
{
|
|
|
|
}
|