add orderbutton plugin

add coap to the libguh source for dev package
This commit is contained in:
Simon Stürz 2016-04-11 13:13:50 +02:00 committed by Michael Zanetti
parent 6c99736216
commit e30aace156
10 changed files with 718 additions and 3 deletions

View File

@ -2,3 +2,4 @@ usr/lib/guh/plugins/libguh_devicepluginosdomotics.so
usr/lib/guh/plugins/libguh_deviceplugindollhouse.so usr/lib/guh/plugins/libguh_deviceplugindollhouse.so
usr/lib/guh/plugins/libguh_devicepluginplantcare.so usr/lib/guh/plugins/libguh_devicepluginplantcare.so
usr/lib/guh/plugins/libguh_devicepluginws2812.so usr/lib/guh/plugins/libguh_devicepluginws2812.so
usr/lib/guh/plugins/libguh_devicepluginorderbutton.so

View File

@ -1,5 +1,4 @@
include(../guh.pri) include(../guh.pri)
include(coap/coap.pri)
TARGET = guh TARGET = guh
TEMPLATE = lib TEMPLATE = lib
@ -40,6 +39,15 @@ SOURCES += devicemanager.cpp \
network/upnpdiscovery/upnpdiscoveryrequest.cpp \ network/upnpdiscovery/upnpdiscoveryrequest.cpp \
network/networkmanager.cpp \ network/networkmanager.cpp \
network/oauth2.cpp \ network/oauth2.cpp \
coap/coap.cpp \
coap/coappdu.cpp \
coap/coapoption.cpp \
coap/coaprequest.cpp \
coap/coapreply.cpp \
coap/coappdublock.cpp \
coap/corelinkparser.cpp \
coap/corelink.cpp \
coap/coapobserveresource.cpp \
types/action.cpp \ types/action.cpp \
types/actiontype.cpp \ types/actiontype.cpp \
types/state.cpp \ types/state.cpp \
@ -55,6 +63,7 @@ SOURCES += devicemanager.cpp \
types/ruleactionparam.cpp \ types/ruleactionparam.cpp \
types/statedescriptor.cpp \ types/statedescriptor.cpp \
HEADERS += devicemanager.h \ HEADERS += devicemanager.h \
libguh.h \ libguh.h \
typeutils.h \ typeutils.h \
@ -77,6 +86,15 @@ HEADERS += devicemanager.h \
network/upnpdiscovery/upnpdiscoveryrequest.h \ network/upnpdiscovery/upnpdiscoveryrequest.h \
network/networkmanager.h \ network/networkmanager.h \
network/oauth2.h \ network/oauth2.h \
coap/coap.h \
coap/coappdu.h \
coap/coapoption.h \
coap/coaprequest.h \
coap/coapreply.h \
coap/coappdublock.h \
coap/corelinkparser.h \
coap/corelink.h \
coap/coapobserveresource.h \
types/action.h \ types/action.h \
types/actiontype.h \ types/actiontype.h \
types/state.h \ types/state.h \
@ -92,6 +110,7 @@ HEADERS += devicemanager.h \
types/ruleactionparam.h \ types/ruleactionparam.h \
types/statedescriptor.h \ types/statedescriptor.h \
# install plugininfo python script for libguh-dev # install plugininfo python script for libguh-dev
generateplugininfo.files = $$top_srcdir/plugins/guh-generateplugininfo generateplugininfo.files = $$top_srcdir/plugins/guh-generateplugininfo
generateplugininfo.path = /usr/bin generateplugininfo.path = /usr/bin

View File

@ -23,7 +23,7 @@
\title aWATTar \title aWATTar
\ingroup plugins \ingroup plugins
\ingroup network \ingroup guh-plugins
This plugin allows to receive the current energy market price from the \l{https://www.awattar.com/}{aWATTar GmbH}. This plugin allows to receive the current energy market price from the \l{https://www.awattar.com/}{aWATTar GmbH}.
In order to use this plugin you need to enter the access token from your energy provider. You can find more In order to use this plugin you need to enter the access token from your energy provider. You can find more

View File

@ -23,7 +23,7 @@
\title Time \title Time
\ingroup plugins \ingroup plugins
\ingroup services \ingroup guh-plugins
The time plugin allows you create rules based on the time, day, month, year, weekday or on weekend. The time plugin allows you create rules based on the time, day, month, year, weekday or on weekend.

View File

@ -24,3 +24,4 @@ SUBDIRS += elro \
plantcare \ plantcare \
osdomotics \ osdomotics \
ws2812 \ ws2812 \
orderbutton \

View File

@ -18,6 +18,31 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page dollhouse.html
\title Dollhouse
\ingroup plugins
\ingroup guh-plugins-merkur
The plugin for the guh-dollhouse demo booth.
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
Each \l{DeviceClass} has a list of \l{ParamType}{paramTypes}, \l{ActionType}{actionTypes}, \l{StateType}{stateTypes}
and \l{EventType}{eventTypes}. The \l{DeviceClass::CreateMethod}{createMethods} parameter describes how the \l{Device}
will be created in the system. A device can have more than one \l{DeviceClass::CreateMethod}{CreateMethod}.
The \l{DeviceClass::SetupMethod}{setupMethod} describes the setup method of the \l{Device}.
The detailed implementation of each \l{DeviceClass} can be found in the source code.
\note If a \l{StateType} has the parameter \tt{"writable": {...}}, an \l{ActionType} with the same uuid and \l{ParamType}{ParamTypes}
will be created automatically.
\quotefile plugins/deviceplugins/datetime/deviceplugindollhouse.json
*/
#include "deviceplugindollhouse.h" #include "deviceplugindollhouse.h"
#include "plugininfo.h" #include "plugininfo.h"

View File

@ -0,0 +1,489 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "devicepluginorderbutton.h"
#include "plugin/device.h"
#include "plugininfo.h"
DevicePluginOrderButton::DevicePluginOrderButton()
{
}
DeviceManager::HardwareResources DevicePluginOrderButton::requiredHardware() const
{
// We need the NetworkManager for node discovery and the timer for ping requests
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer;
}
DeviceManager::DeviceSetupStatus DevicePluginOrderButton::setupDevice(Device *device)
{
qCDebug(dcOrderButton) << "Setup Plant Care" << device->name() << device->params();
// Check if device already added with this address
if (deviceAlreadyAdded(QHostAddress(device->paramValue("host").toString()))) {
qCWarning(dcOrderButton) << "Device with this address already added.";
return DeviceManager::DeviceSetupStatusFailure;
}
// Create the CoAP socket if not already created
if (m_coap.isNull()) {
m_coap = new Coap(this);
connect(m_coap.data(), SIGNAL(replyFinished(CoapReply*)), this, SLOT(coapReplyFinished(CoapReply*)));
connect(m_coap.data(), SIGNAL(notificationReceived(CoapObserveResource,int,QByteArray)), this, SLOT(onNotificationReceived(CoapObserveResource,int,QByteArray)));
}
return DeviceManager::DeviceSetupStatusSuccess;
}
void DevicePluginOrderButton::deviceRemoved(Device *device)
{
Q_UNUSED(device)
// Delete the CoAP socket if there are no devices left
if (myDevices().isEmpty()) {
m_coap->deleteLater();
}
}
DeviceManager::DeviceError DevicePluginOrderButton::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
// Perform a HTTP GET on the RPL router address
QHostAddress address(configuration().paramValue("RPL address").toString());
qCDebug(dcOrderButton) << "Scan for new nodes on RPL" << address.toString();
QUrl url;
url.setScheme("http");
url.setHost(address.toString());
m_asyncNodeScans.insert(networkManagerGet(QNetworkRequest(url)), deviceClassId);
return DeviceManager::DeviceErrorAsync;
}
void DevicePluginOrderButton::networkManagerReplyReady(QNetworkReply *reply)
{
if (m_asyncNodeScans.keys().contains(reply)) {
DeviceClassId deviceClassId = m_asyncNodeScans.take(reply);
// Check HTTP status code
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
qCWarning(dcOrderButton) << "Node scan reply HTTP error:" << reply->errorString();
emit devicesDiscovered(deviceClassId, QList<DeviceDescriptor>());
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
qCDebug(dcOrderButton) << "Node discovery finished:" << endl << data;
QList<DeviceDescriptor> deviceDescriptors;
QList<QByteArray> lines = data.split('\n');
qCDebug(dcOrderButton) << lines;
foreach (const QByteArray &line, lines) {
if (line.isEmpty())
continue;
QHostAddress address(QString(line.left(line.length() - 4)));
if (address.isNull())
continue;
qCDebug(dcOrderButton) << "Found node" << address.toString();
// Create a deviceDescriptor for each found address
DeviceDescriptor descriptor(deviceClassId, "Order Button", address.toString());
ParamList params;
params.append(Param("host", address.toString()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
// Inform the user which devices were found
emit devicesDiscovered(deviceClassId, deviceDescriptors);
}
// Delete the HTTP reply
reply->deleteLater();
}
void DevicePluginOrderButton::postSetupDevice(Device *device)
{
// Try to ping the device after a successful setup
pingDevice(device);
}
void DevicePluginOrderButton::guhTimer()
{
// Try to ping each device every 10 seconds to make sure it is still reachable
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == orderbuttonDeviceClassId) {
pingDevice(device);
}
}
}
DeviceManager::DeviceError DevicePluginOrderButton::executeAction(Device *device, const Action &action)
{
if (device->deviceClassId() != orderbuttonDeviceClassId)
return DeviceManager::DeviceErrorDeviceClassNotFound;
qCDebug(dcOrderButton) << "Execute action" << device->name() << action.params();
// Check if the device is reachable
if (!device->stateValue(reachableStateTypeId).toBool()) {
qCWarning(dcOrderButton) << "Device not reachable.";
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
// Check which action sould be executed
if (action.actionTypeId() == resetActionTypeId) {
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue("host").toString());
url.setPath("/a/reset");
CoapReply *reply = m_coap->post(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_resetCounterRequests.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
} else if(action.actionTypeId() == ledActionTypeId) {
bool led = action.param("led").value().toBool();
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue("host").toString());
url.setPath("/a/led");
QByteArray payload = QString("mode=%1").arg(QString::number((int)led)).toUtf8();
qCDebug(dcOrderButton()) << "Sending" << payload;
CoapReply *reply = m_coap->post(CoapRequest(url), payload);
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_setLedPower.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
void DevicePluginOrderButton::pingDevice(Device *device)
{
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue("host").toString());
m_pingReplies.insert(m_coap->ping(CoapRequest(url)), device);
}
void DevicePluginOrderButton::updateBattery(Device *device)
{
qCDebug(dcOrderButton) << "Update" << device->name() << "battery value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue("host").toString());
url.setPath("/s/battery");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginOrderButton::updateCount(Device *device)
{
qCDebug(dcOrderButton) << "Update" << device->name() << "count value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue("host").toString());
url.setPath("/s/count");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginOrderButton::updateButton(Device *device)
{
qCDebug(dcOrderButton) << "Update" << device->name() << "button value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue("host").toString());
url.setPath("/s/button");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginOrderButton::updateLed(Device *device)
{
qCDebug(dcOrderButton) << "Update" << device->name() << "led value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue("host").toString());
url.setPath("/a/led");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginOrderButton::enableNotifications(Device *device)
{
qCDebug(dcOrderButton) << "Enable" << device->name() << "notifications";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue("host").toString());
url.setPath("/s/button");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/s/count");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/s/battery");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/a/led");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
}
void DevicePluginOrderButton::setReachable(Device *device, const bool &reachable)
{
if (device->stateValue(reachableStateTypeId).toBool() != reachable) {
if (!reachable) {
// Warn just once that the device is not reachable
qCWarning(dcOrderButton()) << device->name() << "reachable changed" << reachable;
} else {
qCDebug(dcOrderButton()) << device->name() << "reachable changed" << reachable;
// Get current state values after a reconnect
updateBattery(device);
updateCount(device);
updateButton(device);
updateLed(device);
// Make sure the notifications are enabled
enableNotifications(device);
}
}
device->setStateValue(reachableStateTypeId, reachable);
}
bool DevicePluginOrderButton::deviceAlreadyAdded(const QHostAddress &address)
{
// Check if we already have a device with the given address
foreach (Device *device, myDevices()) {
if (device->paramValue("host").toString() == address.toString()) {
return true;
}
}
return false;
}
Device *DevicePluginOrderButton::findDevice(const QHostAddress &address)
{
// Return the device pointer with the given address (otherwise 0)
foreach (Device *device, myDevices()) {
if (device->paramValue("host").toString() == address.toString()) {
return device;
}
}
return NULL;
}
void DevicePluginOrderButton::coapReplyFinished(CoapReply *reply)
{
if (m_pingReplies.contains(reply)) {
Device *device = m_pingReplies.take(reply);
// Check CoAP reply error
if (reply->error() != CoapReply::NoError) {
if (device->stateValue(reachableStateTypeId).toBool())
qCWarning(dcOrderButton) << "Ping device" << reply->request().url().toString() << "reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
setReachable(device, true);
} else if (m_updateReplies.contains(reply)) {
Device *device = m_updateReplies.take(reply);
QString urlPath = reply->request().url().path();
// Check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "Update resource" << urlPath << "reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
// Check CoAP status code
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcOrderButton) << "Update resource" << urlPath << "status code error:" << reply;
reply->deleteLater();
return;
}
// Update corresponding device state
if (urlPath == "/s/count") {
qCDebug(dcOrderButton()) << "Updated count value:" << reply->payload();
device->setStateValue(countStateTypeId, reply->payload().toInt());
} else if (urlPath == "/s/button") {
qCDebug(dcOrderButton()) << "Updated button value:" << reply->payload();
//device->(buttonStateTypeId, QVariant(reply->payload().toInt()).toBool());
emit emitEvent(Event(buttonEventTypeId, device->id()));
} else if (urlPath == "/s/battery") {
qCDebug(dcOrderButton()) << "Updated battery value:" << reply->payload();
device->setStateValue(batteryStateTypeId, reply->payload().toDouble());
} else if (urlPath == "/a/led") {
qCDebug(dcOrderButton()) << "Updated led value:" << reply->payload();
device->setStateValue(ledStateTypeId, QVariant(reply->payload().toInt()).toBool());
}
} else if (m_resetCounterRequests.contains(reply)) {
Action action = m_resetCounterRequests.take(reply);
Device *device = m_asyncActions.take(action.id());
// Check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "CoAP reply reset counter finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorHardwareFailure);
return;
}
// Check CoAP status code
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcOrderButton) << "reset counter status code error:" << reply;
reply->deleteLater();
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorHardwareFailure);
return;
}
// Tell the user about the action execution result
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorNoError);
}else if (m_setLedPower.contains(reply)) {
Action action = m_setLedPower.take(reply);
Device *device = m_asyncActions.take(action.id());
// check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "CoAP set led power reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorHardwareFailure);
return;
}
// Check CoAP status code
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcOrderButton) << "Set led power status code error:" << reply;
reply->deleteLater();
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorHardwareFailure);
return;
}
// Update the state here, so we don't have to wait for the notification
device->setStateValue(ledStateTypeId, action.param("led").value().toBool());
// Tell the user about the action execution result
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorNoError);
} else if (m_enableNotification.contains(reply)) {
Device *device = m_enableNotification.take(reply);
// check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcOrderButton) << "Enable notifications for" << reply->request().url().toString() << "reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
// Check CoAP status code
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcOrderButton) << "Enable notifications for" << reply->request().url().toString() << "reply status code error" << reply->errorString();
reply->deleteLater();
return;
}
qCDebug(dcOrderButton()) << "Enabled successfully notifications for" << device->name() << reply->request().url().path();
}
// Delete the CoAP reply
reply->deleteLater();
}
void DevicePluginOrderButton::onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload)
{
qCDebug(dcOrderButton) << " --> Got notification nr." << notificationNumber << resource.url().toString() << payload;
Device *device = findDevice(QHostAddress(resource.url().host()));
if (!device) {
qCWarning(dcOrderButton()) << "Could not find device for this notification";
return;
}
// Update the corresponding device state
if (resource.url().path() == "/s/button") {
emit emitEvent(Event(buttonEventTypeId, device->id()));
//device->setStateValue(buttonStateTypeId, QVariant(payload.toInt()).toBool());
} else if (resource.url().path() == "/s/battery") {
device->setStateValue(batteryStateTypeId, payload.toDouble());
} else if (resource.url().path() == "/a/led") {
device->setStateValue(ledStateTypeId, QVariant(payload.toInt()).toBool());
} else if (resource.url().path() == "/s/count") {
device->setStateValue(countStateTypeId, payload.toInt());
}
}

View File

@ -0,0 +1,86 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* Copyright (C) 2015 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DEVICEPLUGINORDERBUTTON_H
#define DEVICEPLUGINORDERBUTTON_H
#include "plugin/deviceplugin.h"
#include "types/action.h"
#include "coap/coap.h"
#include <QHash>
class DevicePluginOrderButton : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "devicepluginorderbutton.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginOrderButton();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void postSetupDevice(Device *device) override;
void guhTimer() override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private:
QPointer<Coap> m_coap;
QHash<QNetworkReply *, DeviceClassId> m_asyncNodeScans;
QHash<CoapReply *, Device *> m_enableNotification;
QHash<CoapReply *, Device *> m_pingReplies;
// State updates
QHash<CoapReply *, Device *> m_updateReplies;
// Actions
QHash<ActionId, Device *> m_asyncActions;
QHash<CoapReply *, Action> m_resetCounterRequests;
QHash<CoapReply *, Action> m_setCount;
QHash<CoapReply *, Action> m_setLedPower;
void pingDevice(Device *device);
void updateBattery(Device *device);
void updateCount(Device *device);
void updateButton(Device *device);
void updateLed(Device *device);
void enableNotifications(Device *device);
void setReachable(Device *device, const bool &reachable);
bool deviceAlreadyAdded(const QHostAddress &address);
Device *findDevice(const QHostAddress &address);
private slots:
void coapReplyFinished(CoapReply *reply);
void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload);
};
#endif // DEVICEPLUGINORDERBUTTON_H

View File

@ -0,0 +1,85 @@
{
"name": "Order Button",
"idName": "OrderButton",
"id": "939a6557-649d-43de-990b-3484f972ad86",
"paramTypes": [
{
"name": "RPL address",
"type": "QString",
"inputType": "TextLine",
"defaultValue": "fdaa:e9b8:d03a::ff:fe00:1"
}
],
"vendors": [
{
"name": "guh",
"idName": "guh",
"id": "76df1ad2-c179-4842-94ea-2da6e4796339",
"deviceClasses": [
{
"deviceClassId": "af4df281-2b3b-490f-8352-2b99ff23fc15",
"name": "OrderButton",
"idName": "orderbutton",
"createMethods": ["discovery"],
"basicTags": [
"Device",
"Gateway"
],
"paramTypes": [
{
"name": "host",
"type": "QString",
"inputType": "TextLine"
}
],
"stateTypes": [
{
"id": "a4d83813-10f3-4830-be2e-60d4815906c4",
"idName": "battery",
"name": "battery voltage",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "2df871fc-1888-4b04-8f02-f17b26642534",
"idName": "count",
"name": "count",
"type": "int",
"defaultValue": 0
},
{
"id": "783e74ee-ffd6-4dd7-ade5-3a961452cf15",
"idName": "reachable",
"name": "reachable",
"type": "bool",
"defaultValue": false
},
{
"id": "b184ccc8-e7d9-4e94-8683-07f81484bbda",
"idName": "led",
"name": "led",
"type": "bool",
"defaultValue": false,
"writable": true
}
],
"actionTypes": [
{
"id": "b8e5da6c-501c-493e-8b0f-8ef09efb9057",
"idName": "reset",
"name": "reset"
}
],
"eventTypes": [
{
"id": "2077a9ad-7f4b-4dd4-ae1c-7ecbe0a92dc0",
"idName": "button",
"name": "button"
}
]
}
]
}
]
}

View File

@ -0,0 +1,9 @@
include(../../plugins.pri)
TARGET = $$qtLibraryTarget(guh_devicepluginorderbutton)
SOURCES += \
devicepluginorderbutton.cpp
HEADERS += \
devicepluginorderbutton.h