removed orderbutton, plantcare and ws2812

This commit is contained in:
Boernsman 2019-05-10 15:35:14 +02:00
parent e6347ba0a9
commit 5acaa6409e
23 changed files with 0 additions and 3675 deletions

51
debian/control vendored
View File

@ -403,22 +403,6 @@ Description: nymea.io plugin for openweathermap
This package will install the nymea.io plugin for openweathermap
Package: nymea-plugin-orderbutton
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-translations,
Replaces: guh-plugin-orderbutton
Description: nymea.io plugin for orderbutton
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for orderbutton
Package: nymea-plugin-osdomotics
Architecture: any
Depends: ${shlibs:Depends},
@ -451,22 +435,6 @@ Description: nymea.io plugin for philipshue
This package will install the nymea.io plugin for philipshue
Package: nymea-plugin-plantcare
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-translations,
Replaces: guh-plugin-plantcare
Description: nymea.io plugin for plantcare
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for plantcare
Package: nymea-plugin-pushbullet
Architecture: any
Depends: ${shlibs:Depends},
@ -577,22 +545,6 @@ Description: nymea.io plugin for wemo
This package will install the nymea.io plugin for wemo
Package: nymea-plugin-ws2812
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-translations,
Replaces: guh-plugin-ws2812
Description: nymea.io plugin for ws2812
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for ws2812
Package: nymea-plugin-tcpcommander
Architecture: any
Depends: ${shlibs:Depends},
@ -829,9 +781,6 @@ Package: nymea-plugins-merkurboard
Section: libs
Architecture: all
Depends: nymea-plugin-osdomotics,
nymea-plugin-plantcare,
nymea-plugin-ws2812,
nymea-plugin-orderbutton,
Replaces: guh-plugins-merkurboard
Description: Plugins for nymea IoT server - Meta package for 6LoWPAN Merkur boards
The nymea daemon is a plugin based IoT (Internet of Things) server. The

View File

@ -1 +0,0 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginorderbutton.so

View File

@ -1 +0,0 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginplantcare.so

View File

@ -1 +0,0 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginws2812.so

View File

@ -28,10 +28,8 @@ PLUGIN_DIRS = \
netatmo \
networkdetector \
openweathermap \
orderbutton \
osdomotics \
philipshue \
plantcare \
pushbullet \
remotessh \
senic \
@ -46,7 +44,6 @@ PLUGIN_DIRS = \
unitec \
wakeonlan \
wemo \
ws2812 \
message(============================================)

View File

@ -1,518 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page orderbutton.html
\title Orderbutton
\brief Demonstration of an orderbutton based on 6LoWPAN networking.
\ingroup plugins
\ingroup nymea-plugins-merkur
\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}.
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
\quotefile plugins/deviceplugins/orderbutton/devicepluginorderbutton.json
*/
#include "devicepluginorderbutton.h"
#include "plugin/device.h"
#include "plugininfo.h"
#include "network/networkaccessmanager.h"
DevicePluginOrderButton::DevicePluginOrderButton()
{
}
DevicePluginOrderButton::~DevicePluginOrderButton()
{
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginOrderButton::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginOrderButton::onPluginTimer);
}
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(orderbuttonDeviceHostParamTypeId).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(orderButtonPluginRplParamTypeId).toString());
qCDebug(dcOrderButton) << "Scan for new nodes on RPL" << address.toString();
QUrl url;
url.setScheme("http");
url.setHost(address.toString());
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOrderButton::onNetworkReplyFinished);
m_asyncNodeScans.insert(reply, deviceClassId);
return DeviceManager::DeviceErrorAsync;
}
void DevicePluginOrderButton::postSetupDevice(Device *device)
{
// Try to ping the device after a successful setup
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(orderbuttonConnectedStateTypeId).toBool()) {
qCWarning(dcOrderButton) << "Device not reachable.";
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
// Check which action sould be executed
if (action.actionTypeId() == orderbuttonResetActionTypeId) {
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(orderbuttonDeviceHostParamTypeId).toString());
url.setPath("/s/count");
CoapReply *reply = m_coap->post(CoapRequest(url), QByteArray("count=0"));
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() == orderbuttonLedActionTypeId) {
bool led = action.param(orderbuttonLedActionLedParamTypeId).value().toBool();
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(orderbuttonDeviceHostParamTypeId).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(orderbuttonDeviceHostParamTypeId).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(orderbuttonDeviceHostParamTypeId).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(orderbuttonDeviceHostParamTypeId).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(orderbuttonDeviceHostParamTypeId).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(orderbuttonDeviceHostParamTypeId).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(orderbuttonDeviceHostParamTypeId).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(orderbuttonConnectedStateTypeId).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(orderbuttonConnectedStateTypeId, 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(orderbuttonDeviceHostParamTypeId).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(orderbuttonDeviceHostParamTypeId).toString() == address.toString()) {
return device;
}
}
return nullptr;
}
void DevicePluginOrderButton::onPluginTimer()
{
// 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);
}
}
}
void DevicePluginOrderButton::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
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(orderbuttonDeviceHostParamTypeId, 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::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(orderbuttonConnectedStateTypeId).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(orderbuttonCountStateTypeId, 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(orderbuttonButtonEventTypeId, device->id()));
} else if (urlPath == "/s/battery") {
qCDebug(dcOrderButton()) << "Updated battery value:" << reply->payload();
device->setStateValue(orderbuttonBatteryStateTypeId, reply->payload().toDouble());
} else if (urlPath == "/a/led") {
qCDebug(dcOrderButton()) << "Updated led value:" << reply->payload();
device->setStateValue(orderbuttonLedStateTypeId, 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(orderbuttonLedStateTypeId, action.param(orderbuttonLedActionLedParamTypeId).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(orderbuttonButtonEventTypeId, device->id()));
//device->setStateValue(buttonStateTypeId, QVariant(payload.toInt()).toBool());
} else if (resource.url().path() == "/s/battery") {
device->setStateValue(orderbuttonBatteryStateTypeId, payload.toDouble());
} else if (resource.url().path() == "/a/led") {
device->setStateValue(orderbuttonLedStateTypeId, QVariant(payload.toInt()).toBool());
} else if (resource.url().path() == "/s/count") {
device->setStateValue(orderbuttonCountStateTypeId, payload.toInt());
}
}

View File

@ -1,90 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2015 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DEVICEPLUGINORDERBUTTON_H
#define DEVICEPLUGINORDERBUTTON_H
#include "plugin/deviceplugin.h"
#include "types/action.h"
#include "coap/coap.h"
#include "plugintimer.h"
#include <QHash>
#include <QNetworkReply>
class DevicePluginOrderButton : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginorderbutton.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginOrderButton();
~DevicePluginOrderButton();
void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void postSetupDevice(Device *device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private:
PluginTimer *m_pluginTimer = nullptr;
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 onPluginTimer();
void onNetworkReplyFinished();
void coapReplyFinished(CoapReply *reply);
void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload);
};
#endif // DEVICEPLUGINORDERBUTTON_H

View File

@ -1,91 +0,0 @@
{
"displayName": "Order Button",
"name": "orderButton",
"id": "939a6557-649d-43de-990b-3484f972ad86",
"paramTypes": [
{
"id": "e917e779-e01c-4095-9d62-ab46fc2deecc",
"name": "rpl",
"displayName": "RPL address",
"type": "QString",
"inputType": "TextLine",
"defaultValue": "fdaa:e9b8:d03a::ff:fe00:1"
}
],
"vendors": [
{
"displayName": "nymea",
"name": "nymea",
"id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
"deviceClasses": [
{
"id": "af4df281-2b3b-490f-8352-2b99ff23fc15",
"displayName": "OrderButton",
"name": "orderbutton",
"createMethods": ["discovery"],
"interfaces": ["gateway"],
"paramTypes": [
{
"id": "53a00a7b-e168-4917-86b5-d4329a0a720c",
"name": "host",
"displayName": "host",
"type": "QString",
"inputType": "TextLine"
}
],
"stateTypes": [
{
"id": "a4d83813-10f3-4830-be2e-60d4815906c4",
"name": "battery",
"displayName": "battery voltage",
"displayNameEvent": "battery voltage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "2df871fc-1888-4b04-8f02-f17b26642534",
"name": "count",
"displayName": "count",
"displayNameEvent": "count changed",
"type": "int",
"defaultValue": 0
},
{
"id": "783e74ee-ffd6-4dd7-ade5-3a961452cf15",
"name": "connected",
"displayNameEvent": "reachable changed",
"displayName": "reachable",
"type": "bool",
"defaultValue": false
},
{
"id": "b184ccc8-e7d9-4e94-8683-07f81484bbda",
"name": "led",
"displayName": "led",
"displayNameEvent": "led changed",
"displayNameAction": "Set led",
"type": "bool",
"defaultValue": false,
"writable": true
}
],
"actionTypes": [
{
"id": "b8e5da6c-501c-493e-8b0f-8ef09efb9057",
"name": "reset",
"displayName": "reset"
}
],
"eventTypes": [
{
"id": "2077a9ad-7f4b-4dd4-ae1c-7ecbe0a92dc0",
"name": "button",
"displayName": "button"
}
]
}
]
}
]
}

View File

@ -1,11 +0,0 @@
include(../plugins.pri)
QT += network
TARGET = $$qtLibraryTarget(nymea_devicepluginorderbutton)
SOURCES += \
devicepluginorderbutton.cpp
HEADERS += \
devicepluginorderbutton.h

View File

@ -1,106 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<context>
<name>orderButton</name>
<message>
<location filename="../plugininfo.h" line="48"/>
<source>RPL address</source>
<extracomment>The name of the ParamType (DeviceClass: orderButton, Type: plugin, ID: e917e779-e01c-4095-9d62-ab46fc2deecc)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="54"/>
<source>OrderButton</source>
<extracomment>The name of the DeviceClass (af4df281-2b3b-490f-8352-2b99ff23fc15)</extracomment>
<translation>Bestellknopf</translation>
</message>
<message>
<location filename="../plugininfo.h" line="57"/>
<source>host</source>
<extracomment>The name of the ParamType (DeviceClass: orderbutton, Type: device, ID: 53a00a7b-e168-4917-86b5-d4329a0a720c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="60"/>
<source>battery voltage changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: orderbutton, StateType: battery, ID: a4d83813-10f3-4830-be2e-60d4815906c4)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="45"/>
<source>Order Button</source>
<extracomment>The name of the plugin orderButton (939a6557-649d-43de-990b-3484f972ad86)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="51"/>
<source>nymea</source>
<extracomment>The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="63"/>
<source>battery voltage</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: orderbutton, StateType: battery, ID: a4d83813-10f3-4830-be2e-60d4815906c4</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="66"/>
<source>count changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: orderbutton, StateType: count, ID: 2df871fc-1888-4b04-8f02-f17b26642534)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="69"/>
<source>count</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: orderbutton, StateType: count, ID: 2df871fc-1888-4b04-8f02-f17b26642534</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="72"/>
<source>reachable changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: orderbutton, StateType: connected, ID: 783e74ee-ffd6-4dd7-ade5-3a961452cf15)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="75"/>
<source>reachable</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: orderbutton, StateType: connected, ID: 783e74ee-ffd6-4dd7-ade5-3a961452cf15</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="78"/>
<source>led changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: orderbutton, StateType: led, ID: b184ccc8-e7d9-4e94-8683-07f81484bbda)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="81"/>
<location filename="../plugininfo.h" line="87"/>
<source>led</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: orderbutton, StateType: led, ID: b184ccc8-e7d9-4e94-8683-07f81484bbda
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: orderbutton, StateType: led, ID: b184ccc8-e7d9-4e94-8683-07f81484bbda)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="84"/>
<source>Set led</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: orderbutton, StateType: led, ID: b184ccc8-e7d9-4e94-8683-07f81484bbda)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="90"/>
<source>reset</source>
<extracomment>The name of the ActionType b8e5da6c-501c-493e-8b0f-8ef09efb9057 of deviceClass orderbutton</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="93"/>
<source>button</source>
<extracomment>The name of the EventType 2077a9ad-7f4b-4dd4-ae1c-7ecbe0a92dc0 of deviceClass orderbutton</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,106 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>orderButton</name>
<message>
<location filename="../plugininfo.h" line="48"/>
<source>RPL address</source>
<extracomment>The name of the ParamType (DeviceClass: orderButton, Type: plugin, ID: e917e779-e01c-4095-9d62-ab46fc2deecc)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="54"/>
<source>OrderButton</source>
<extracomment>The name of the DeviceClass (af4df281-2b3b-490f-8352-2b99ff23fc15)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="57"/>
<source>host</source>
<extracomment>The name of the ParamType (DeviceClass: orderbutton, Type: device, ID: 53a00a7b-e168-4917-86b5-d4329a0a720c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="60"/>
<source>battery voltage changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: orderbutton, StateType: battery, ID: a4d83813-10f3-4830-be2e-60d4815906c4)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="45"/>
<source>Order Button</source>
<extracomment>The name of the plugin orderButton (939a6557-649d-43de-990b-3484f972ad86)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="51"/>
<source>nymea</source>
<extracomment>The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="63"/>
<source>battery voltage</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: orderbutton, StateType: battery, ID: a4d83813-10f3-4830-be2e-60d4815906c4</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="66"/>
<source>count changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: orderbutton, StateType: count, ID: 2df871fc-1888-4b04-8f02-f17b26642534)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="69"/>
<source>count</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: orderbutton, StateType: count, ID: 2df871fc-1888-4b04-8f02-f17b26642534</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="72"/>
<source>reachable changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: orderbutton, StateType: connected, ID: 783e74ee-ffd6-4dd7-ade5-3a961452cf15)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="75"/>
<source>reachable</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: orderbutton, StateType: connected, ID: 783e74ee-ffd6-4dd7-ade5-3a961452cf15</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="78"/>
<source>led changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: orderbutton, StateType: led, ID: b184ccc8-e7d9-4e94-8683-07f81484bbda)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="81"/>
<location filename="../plugininfo.h" line="87"/>
<source>led</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: orderbutton, StateType: led, ID: b184ccc8-e7d9-4e94-8683-07f81484bbda
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: orderbutton, StateType: led, ID: b184ccc8-e7d9-4e94-8683-07f81484bbda)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="84"/>
<source>Set led</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: orderbutton, StateType: led, ID: b184ccc8-e7d9-4e94-8683-07f81484bbda)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="90"/>
<source>reset</source>
<extracomment>The name of the ActionType b8e5da6c-501c-493e-8b0f-8ef09efb9057 of deviceClass orderbutton</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="93"/>
<source>button</source>
<extracomment>The name of the EventType 2077a9ad-7f4b-4dd4-ae1c-7ecbe0a92dc0 of deviceClass orderbutton</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,601 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page plantcare.html
\title Plantcare
\brief Plugin for the nymea Plantcare example based on 6LoWPAN networking.
\ingroup plugins
\ingroup nymea-plugins-merkur
This allows to control the nymea plantcare demo for 6LoWPAN networks.
\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}.
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
\quotefile plugins/deviceplugins/plantcare/devicepluginplantcare.json
*/
#include "devicepluginplantcare.h"
#include "plugin/device.h"
#include "plugininfo.h"
#include "network/networkaccessmanager.h"
DevicePluginPlantCare::DevicePluginPlantCare()
{
}
DevicePluginPlantCare::~DevicePluginPlantCare()
{
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginPlantCare::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginPlantCare::onPluginTimer);
}
DeviceManager::DeviceSetupStatus DevicePluginPlantCare::setupDevice(Device *device)
{
qCDebug(dcPlantCare) << "Setup Plant Care" << device->name() << device->params();
// Check if device already added with this address
if (deviceAlreadyAdded(QHostAddress(device->paramValue(plantCareDeviceHostParamTypeId).toString()))) {
qCWarning(dcPlantCare) << "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 DevicePluginPlantCare::deviceRemoved(Device *device)
{
Q_UNUSED(device)
// Delete the CoAP socket if there are no devices left
if (myDevices().isEmpty()) {
m_coap->deleteLater();
}
}
void DevicePluginPlantCare::postSetupDevice(Device *device)
{
// Try to ping the device after a successful setup
pingDevice(device);
}
DeviceManager::DeviceError DevicePluginPlantCare::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
// Perform a HTTP GET on the RPL router address
QHostAddress address(configuration().paramValue(plantCarePluginRplParamTypeId).toString());
qCDebug(dcPlantCare) << "Scan for new nodes on RPL" << address.toString();
QUrl url;
url.setScheme("http");
url.setHost(address.toString());
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginPlantCare::onNetworkReplyFinished);
m_asyncNodeScans.insert(reply, deviceClassId);
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::DeviceError DevicePluginPlantCare::executeAction(Device *device, const Action &action)
{
if (device->deviceClassId() != plantCareDeviceClassId)
return DeviceManager::DeviceErrorDeviceClassNotFound;
qCDebug(dcPlantCare) << "Execute action" << device->name() << action.params();
// Check if the device is reachable
if (!device->stateValue(plantCareConnectedStateTypeId).toBool()) {
qCWarning(dcPlantCare) << "Device not reachable.";
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
// Check which action sould be executed
if (action.actionTypeId() == plantCareToggleLedActionTypeId) {
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/a/toggle");
CoapReply *reply = m_coap->post(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_toggleLightRequests.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
} else if(action.actionTypeId() == plantCareLedPowerActionTypeId) {
int power = action.param(plantCareLedPowerActionLedPowerParamTypeId).value().toInt();
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/a/light");
QByteArray payload = QString("pwm=%1").arg(QString::number(power)).toUtf8();
qCDebug(dcPlantCare()) << "Sending" << payload << url.path();
CoapReply *reply = m_coap->post(CoapRequest(url), payload);
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "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;
} else if(action.actionTypeId() == plantCareWaterPumpActionTypeId) {
bool pump = action.param(plantCareWaterPumpActionWaterPumpParamTypeId).value().toBool();
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/a/pump");
QByteArray payload = QString("mode=%1").arg(QString::number((int)pump)).toUtf8();
qCDebug(dcPlantCare()) << "Sending" << payload;
CoapReply *reply = m_coap->post(CoapRequest(url), payload);
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_setPumpPower.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
void DevicePluginPlantCare::pingDevice(Device *device)
{
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
m_pingReplies.insert(m_coap->ping(CoapRequest(url)), device);
}
void DevicePluginPlantCare::updateBattery(Device *device)
{
qCDebug(dcPlantCare) << "Update" << device->name() << "battery value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/s/battery");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginPlantCare::updateMoisture(Device *device)
{
qCDebug(dcPlantCare) << "Update" << device->name() << "moisture value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/s/moisture");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginPlantCare::updateWater(Device *device)
{
qCDebug(dcPlantCare) << "Update" << device->name() << "water value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/s/water");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginPlantCare::updateBrightness(Device *device)
{
qCDebug(dcPlantCare) << "Update" << device->name() << "brightness value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/a/light");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginPlantCare::updatePump(Device *device)
{
qCDebug(dcPlantCare) << "Update" << device->name() << "pump value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/a/pump");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginPlantCare::enableNotifications(Device *device)
{
qCDebug(dcPlantCare) << "Enable" << device->name() << "notifications";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(plantCareDeviceHostParamTypeId).toString());
url.setPath("/s/water");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/s/moisture");
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/light");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/a/pump");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
}
void DevicePluginPlantCare::setReachable(Device *device, const bool &reachable)
{
if (device->stateValue(plantCareConnectedStateTypeId).toBool() != reachable) {
if (!reachable) {
// Warn just once that the device is not reachable
qCWarning(dcPlantCare()) << device->name() << "reachable changed" << reachable;
} else {
qCDebug(dcPlantCare()) << device->name() << "reachable changed" << reachable;
// Get current state values after a reconnect
updateBattery(device);
updateBrightness(device);
updateMoisture(device);
updateWater(device);
updatePump(device);
// Make sure the notifications are enabled
enableNotifications(device);
}
}
device->setStateValue(plantCareConnectedStateTypeId, reachable);
}
bool DevicePluginPlantCare::deviceAlreadyAdded(const QHostAddress &address)
{
// Check if we already have a device with the given address
foreach (Device *device, myDevices()) {
if (device->paramValue(plantCareDeviceHostParamTypeId).toString() == address.toString()) {
return true;
}
}
return false;
}
Device *DevicePluginPlantCare::findDevice(const QHostAddress &address)
{
// Return the device pointer with the given address (otherwise 0)
foreach (Device *device, myDevices()) {
if (device->paramValue(plantCareDeviceHostParamTypeId).toString() == address.toString()) {
return device;
}
}
return nullptr;
}
void DevicePluginPlantCare::onPluginTimer()
{
// Try to ping each device every 10 seconds to make sure it is still reachable
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == plantCareDeviceClassId) {
pingDevice(device);
}
}
}
void DevicePluginPlantCare::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
if (m_asyncNodeScans.keys().contains(reply)) {
DeviceClassId deviceClassId = m_asyncNodeScans.take(reply);
// Check HTTP status code
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
qCWarning(dcPlantCare) << "Node scan reply HTTP error:" << reply->errorString();
emit devicesDiscovered(deviceClassId, QList<DeviceDescriptor>());
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
qCDebug(dcPlantCare) << "Node discovery finished:" << endl << data;
QList<DeviceDescriptor> deviceDescriptors;
QList<QByteArray> lines = data.split('\n');
qCDebug(dcPlantCare) << lines;
foreach (const QByteArray &line, lines) {
if (line.isEmpty())
continue;
QHostAddress address(QString(line.left(line.length() - 4)));
if (address.isNull())
continue;
qCDebug(dcPlantCare) << "Found node" << address.toString();
// Create a deviceDescriptor for each found address
DeviceDescriptor descriptor(deviceClassId, "Plant Care", address.toString());
ParamList params;
params.append(Param(plantCareDeviceHostParamTypeId, 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 DevicePluginPlantCare::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(plantCareConnectedStateTypeId).toBool())
qCWarning(dcPlantCare) << "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(dcPlantCare) << "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(dcPlantCare) << "Update resource" << urlPath << "status code error:" << reply;
reply->deleteLater();
return;
}
// Update corresponding device state
if (urlPath == "/s/moisture") {
qCDebug(dcPlantCare()) << "Updated moisture value:" << reply->payload();
device->setStateValue(plantCareMoistureStateTypeId, qRound(reply->payload().toInt() * 100.0 / 1023.0));
} else if (urlPath == "/s/water") {
qCDebug(dcPlantCare()) << "Updated water value:" << reply->payload();
device->setStateValue(plantCareWaterStateTypeId, QVariant(reply->payload().toInt()).toBool());
} else if (urlPath == "/s/battery") {
qCDebug(dcPlantCare()) << "Updated battery value:" << reply->payload();
device->setStateValue(plantCareBatteryStateTypeId, reply->payload().toDouble());
} else if (urlPath == "/a/pump") {
qCDebug(dcPlantCare()) << "Updated pump value:" << reply->payload();
device->setStateValue(plantCareWaterPumpStateTypeId, QVariant(reply->payload().toInt()).toBool());
} else if (urlPath == "/a/light") {
qCDebug(dcPlantCare()) << "Updated led power value:" << reply->payload();
int powerValue = reply->payload().toInt();
if (powerValue > 0) {
device->setStateValue(plantCareLedPowerStateTypeId, false);
} else {
device->setStateValue(plantCareLedPowerStateTypeId, true);
}
}
} else if (m_toggleLightRequests.contains(reply)) {
Action action = m_toggleLightRequests.take(reply);
Device *device = m_asyncActions.take(action.id());
// Check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP reply toggle light 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(dcPlantCare) << "Toggle light 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(dcPlantCare) << "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(dcPlantCare) << "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(plantCareLedPowerStateTypeId, action.param(plantCareLedPowerActionLedPowerParamTypeId).value().toBool());
// Tell the user about the action execution result
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorNoError);
} else if (m_setPumpPower.contains(reply)) {
Action action = m_setPumpPower.take(reply);
Device *device = m_asyncActions.take(action.id());
// check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcPlantCare) << "CoAP set pump 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(dcPlantCare) << "Set pump 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(plantCareWaterPumpStateTypeId, action.param(plantCareWaterPumpActionWaterPumpParamTypeId).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(dcPlantCare) << "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(dcPlantCare) << "Enable notifications for" << reply->request().url().toString() << "reply status code error" << reply->errorString();
reply->deleteLater();
return;
}
qCDebug(dcPlantCare()) << "Enabled successfully notifications for" << device->name() << reply->request().url().path();
}
// Delete the CoAP reply
reply->deleteLater();
}
void DevicePluginPlantCare::onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload)
{
qCDebug(dcPlantCare) << " --> Got notification nr." << notificationNumber << resource.url().toString() << payload;
Device *device = findDevice(QHostAddress(resource.url().host()));
if (!device) {
qCWarning(dcPlantCare()) << "Could not find device for this notification";
return;
}
// Update the corresponding device state
if (resource.url().path() == "/s/moisture") {
device->setStateValue(plantCareMoistureStateTypeId, qRound(payload.toInt() * 100.0 / 1023.0));
} else if (resource.url().path() == "/s/water") {
device->setStateValue(plantCareWaterStateTypeId, QVariant(payload.toInt()).toBool());
} else if (resource.url().path() == "/s/battery") {
device->setStateValue(plantCareBatteryStateTypeId, payload.toDouble());
} else if (resource.url().path() == "/a/pump") {
device->setStateValue(plantCareWaterPumpStateTypeId, QVariant(payload.toInt()).toBool());
} else if (resource.url().path() == "/a/light") {
int powerValue = QVariant(payload).toInt();
if (powerValue > 0) {
device->setStateValue(plantCareLedPowerStateTypeId, false);
} else {
device->setStateValue(plantCareLedPowerStateTypeId, true);
}
}
}

View File

@ -1,91 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2015 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DEVICEPLUGINPLANTCARE_H
#define DEVICEPLUGINPLANTCARE_H
#include "plugin/deviceplugin.h"
#include "types/action.h"
#include "coap/coap.h"
#include "plugintimer.h"
#include <QHash>
#include <QNetworkReply>
class DevicePluginPlantCare : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginplantcare.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginPlantCare();
~DevicePluginPlantCare();
void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void postSetupDevice(Device *device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private:
PluginTimer *m_pluginTimer = nullptr;
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_toggleLightRequests;
QHash<CoapReply *, Action> m_setLedPower;
QHash<CoapReply *, Action> m_setPumpPower;
void pingDevice(Device *device);
void updateBattery(Device *device);
void updateMoisture(Device *device);
void updateWater(Device *device);
void updateBrightness(Device *device);
void updatePump(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 onPluginTimer();
void onNetworkReplyFinished();
void coapReplyFinished(CoapReply *reply);
void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload);
};
#endif // DEVICEPLUGINPLANTCARE_H

View File

@ -1,103 +0,0 @@
{
"displayName": "Plant Care",
"name": "PlantCare",
"id": "80ea115f-2a9f-49b3-9575-9e36d137c8d6",
"paramTypes": [
{
"id": "138e19bd-a8db-472a-b3a4-f6497ef2e50c",
"name": "rpl",
"displayName": "RPL address",
"type": "QString",
"inputType": "TextLine",
"defaultValue": "fdaa:e9b8:d03a::ff:fe00:1"
}
],
"vendors": [
{
"displayName": "nymea",
"name": "nymea",
"id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
"deviceClasses": [
{
"id": "3245db46-5c6f-42d6-9001-753150763385",
"displayName": "Plant Care",
"name": "plantCare",
"createMethods": ["discovery"],
"interfaces": ["gateway"],
"paramTypes": [
{
"id": "7ab5f794-459f-45f5-855e-40a76f494e20",
"name": "host",
"displayName": "host",
"type": "QString",
"inputType": "TextLine"
}
],
"stateTypes": [
{
"id": "2b4b5123-14b7-4aa1-9c83-27cef333395d",
"name": "battery",
"displayName": "battery voltage",
"displayNameEvent": "battery voltage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "8a7efda1-b6b7-41c8-ad07-4d892a532d1c",
"name": "moisture",
"displayName": "moisture",
"displayNameEvent": "moisture changed",
"type": "int",
"unit": "Percentage",
"defaultValue": 0
},
{
"id": "26deeba1-487a-4dee-940a-a3bd48344f33",
"name": "water",
"displayName": "water empty",
"displayNameEvent": "water empty changed",
"type": "bool",
"defaultValue": false
},
{
"id": "819aca98-25e5-4733-81e0-5921478b3e89",
"name": "ledPower",
"displayName": "led power",
"displayNameEvent": "led power changed",
"displayNameAction": "Set reachable",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "6c65ae32-18ce-400f-afd6-47fb5b805ccd",
"name": "waterPump",
"displayName": "water pump power",
"displayNameEvent": "water pump power changed",
"displayNameAction": "Set water pump power",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "8384e07b-8b91-492a-b6c8-e72b325ba0b4",
"name": "connected",
"displayName": "reachable",
"displayNameEvent": "reachable changed",
"type": "bool",
"defaultValue": false
}
],
"actionTypes": [
{
"id": "9afbcc80-1c97-4c18-bc08-5209d6297f2e",
"name": "toggleLed",
"displayName": "toggle led"
}
]
}
]
}
]
}

View File

@ -1,11 +0,0 @@
include(../plugins.pri)
QT += network
TARGET = $$qtLibraryTarget(nymea_devicepluginplantcare)
SOURCES += \
devicepluginplantcare.cpp
HEADERS += \
devicepluginplantcare.h

View File

@ -1,130 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<context>
<name>PlantCare</name>
<message>
<location filename="../plugininfo.h" line="52"/>
<location filename="../plugininfo.h" line="61"/>
<source>Plant Care</source>
<extracomment>The name of the plugin PlantCare (80ea115f-2a9f-49b3-9575-9e36d137c8d6)
----------
The name of the DeviceClass (3245db46-5c6f-42d6-9001-753150763385)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="55"/>
<source>RPL address</source>
<extracomment>The name of the ParamType (DeviceClass: plantCare, Type: plugin, ID: 138e19bd-a8db-472a-b3a4-f6497ef2e50c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="58"/>
<source>nymea</source>
<extracomment>The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="64"/>
<source>host</source>
<extracomment>The name of the ParamType (DeviceClass: plantCare, Type: device, ID: 7ab5f794-459f-45f5-855e-40a76f494e20)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="67"/>
<source>battery voltage changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: battery, ID: 2b4b5123-14b7-4aa1-9c83-27cef333395d)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="73"/>
<source>moisture changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: moisture, ID: 8a7efda1-b6b7-41c8-ad07-4d892a532d1c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="70"/>
<source>battery voltage</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: battery, ID: 2b4b5123-14b7-4aa1-9c83-27cef333395d</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="76"/>
<source>moisture</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: moisture, ID: 8a7efda1-b6b7-41c8-ad07-4d892a532d1c</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="79"/>
<source>water empty changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: water, ID: 26deeba1-487a-4dee-940a-a3bd48344f33)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="82"/>
<source>water empty</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: water, ID: 26deeba1-487a-4dee-940a-a3bd48344f33</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="85"/>
<source>led power changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: ledPower, ID: 819aca98-25e5-4733-81e0-5921478b3e89)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="88"/>
<location filename="../plugininfo.h" line="94"/>
<source>led power</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: ledPower, ID: 819aca98-25e5-4733-81e0-5921478b3e89
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: plantCare, StateType: ledPower, ID: 819aca98-25e5-4733-81e0-5921478b3e89)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="91"/>
<source>Set reachable</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: plantCare, StateType: ledPower, ID: 819aca98-25e5-4733-81e0-5921478b3e89)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="97"/>
<source>water pump power changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: waterPump, ID: 6c65ae32-18ce-400f-afd6-47fb5b805ccd)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="100"/>
<location filename="../plugininfo.h" line="106"/>
<source>water pump power</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: waterPump, ID: 6c65ae32-18ce-400f-afd6-47fb5b805ccd
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: plantCare, StateType: waterPump, ID: 6c65ae32-18ce-400f-afd6-47fb5b805ccd)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="103"/>
<source>Set water pump power</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: plantCare, StateType: waterPump, ID: 6c65ae32-18ce-400f-afd6-47fb5b805ccd)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="109"/>
<source>reachable changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: connected, ID: 8384e07b-8b91-492a-b6c8-e72b325ba0b4)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="112"/>
<source>reachable</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: connected, ID: 8384e07b-8b91-492a-b6c8-e72b325ba0b4</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="115"/>
<source>toggle led</source>
<extracomment>The name of the ActionType 9afbcc80-1c97-4c18-bc08-5209d6297f2e of deviceClass plantCare</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,130 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>PlantCare</name>
<message>
<location filename="../plugininfo.h" line="52"/>
<location filename="../plugininfo.h" line="61"/>
<source>Plant Care</source>
<extracomment>The name of the plugin PlantCare (80ea115f-2a9f-49b3-9575-9e36d137c8d6)
----------
The name of the DeviceClass (3245db46-5c6f-42d6-9001-753150763385)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="55"/>
<source>RPL address</source>
<extracomment>The name of the ParamType (DeviceClass: plantCare, Type: plugin, ID: 138e19bd-a8db-472a-b3a4-f6497ef2e50c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="58"/>
<source>nymea</source>
<extracomment>The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="64"/>
<source>host</source>
<extracomment>The name of the ParamType (DeviceClass: plantCare, Type: device, ID: 7ab5f794-459f-45f5-855e-40a76f494e20)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="67"/>
<source>battery voltage changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: battery, ID: 2b4b5123-14b7-4aa1-9c83-27cef333395d)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="73"/>
<source>moisture changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: moisture, ID: 8a7efda1-b6b7-41c8-ad07-4d892a532d1c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="70"/>
<source>battery voltage</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: battery, ID: 2b4b5123-14b7-4aa1-9c83-27cef333395d</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="76"/>
<source>moisture</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: moisture, ID: 8a7efda1-b6b7-41c8-ad07-4d892a532d1c</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="79"/>
<source>water empty changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: water, ID: 26deeba1-487a-4dee-940a-a3bd48344f33)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="82"/>
<source>water empty</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: water, ID: 26deeba1-487a-4dee-940a-a3bd48344f33</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="85"/>
<source>led power changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: ledPower, ID: 819aca98-25e5-4733-81e0-5921478b3e89)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="88"/>
<location filename="../plugininfo.h" line="94"/>
<source>led power</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: ledPower, ID: 819aca98-25e5-4733-81e0-5921478b3e89
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: plantCare, StateType: ledPower, ID: 819aca98-25e5-4733-81e0-5921478b3e89)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="91"/>
<source>Set reachable</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: plantCare, StateType: ledPower, ID: 819aca98-25e5-4733-81e0-5921478b3e89)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="97"/>
<source>water pump power changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: waterPump, ID: 6c65ae32-18ce-400f-afd6-47fb5b805ccd)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="100"/>
<location filename="../plugininfo.h" line="106"/>
<source>water pump power</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: waterPump, ID: 6c65ae32-18ce-400f-afd6-47fb5b805ccd
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: plantCare, StateType: waterPump, ID: 6c65ae32-18ce-400f-afd6-47fb5b805ccd)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="103"/>
<source>Set water pump power</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: plantCare, StateType: waterPump, ID: 6c65ae32-18ce-400f-afd6-47fb5b805ccd)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="109"/>
<source>reachable changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: plantCare, StateType: connected, ID: 8384e07b-8b91-492a-b6c8-e72b325ba0b4)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="112"/>
<source>reachable</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: plantCare, StateType: connected, ID: 8384e07b-8b91-492a-b6c8-e72b325ba0b4</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="115"/>
<source>toggle led</source>
<extracomment>The name of the ActionType 9afbcc80-1c97-4c18-bc08-5209d6297f2e of deviceClass plantCare</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,909 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page ws2812.html
\title ws2812
\brief Plugin to control ws2812 LEDs based on 6LoWPAN networking.
\ingroup plugins
\ingroup nymea-plugins-merkur
The plugin for the \l{http://cdn.sparkfun.com/datasheets/Components/LED/WS2812.pdf}{ws2812} led module. This plugin allows to control a ws2812 module over a 6LoWPAN network.
\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}.
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
\quotefile plugins/deviceplugins/ws2812/devicepluginws2812.json
*/
#include "devicepluginws2812.h"
#include "plugin/device.h"
#include "plugininfo.h"
#include "network/networkaccessmanager.h"
#include <QDebug>
#include <QStringList>
#include <QColor>
DevicePluginWs2812::DevicePluginWs2812()
{
}
DevicePluginWs2812::~DevicePluginWs2812()
{
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginWs2812::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginWs2812::onPluginTimer);
}
DeviceManager::DeviceSetupStatus DevicePluginWs2812::setupDevice(Device *device)
{
qCDebug(dcWs2812) << "Setup Plant Care" << device->name() << device->params();
// Check if device already added with this address
if (deviceAlreadyAdded(QHostAddress(device->paramValue(ws2812DeviceHostParamTypeId).toString()))) {
qCWarning(dcWs2812) << "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 DevicePluginWs2812::deviceRemoved(Device *device)
{
Q_UNUSED(device)
// Delete the CoAP socket if there are no devices left
if (myDevices().isEmpty()) {
m_coap->deleteLater();
}
}
DeviceManager::DeviceError DevicePluginWs2812::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
// Perform a HTTP GET on the RPL router address
QHostAddress address(configuration().paramValue(ws2812PluginRplParamTypeId).toString());
qCDebug(dcWs2812) << "Scan for new nodes on RPL" << address.toString();
QUrl url;
url.setScheme("http");
url.setHost(address.toString());
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginWs2812::onNetworkReplyFinished);
m_asyncNodeScans.insert(reply, deviceClassId);
return DeviceManager::DeviceErrorAsync;
}
void DevicePluginWs2812::postSetupDevice(Device *device)
{
// Try to ping the device after a successful setup
pingDevice(device);
}
DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, const Action &action)
{
if (device->deviceClassId() != ws2812DeviceClassId)
return DeviceManager::DeviceErrorDeviceClassNotFound;
qCDebug(dcWs2812) << "Execute action" << device->name() << action.params();
// Check if the device is reachable
if (!device->stateValue(ws2812ConnectedStateTypeId).toBool()) {
qCWarning(dcWs2812) << "Device not reachable.";
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
if(action.actionTypeId() == ws2812EffectColorActionTypeId) {
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/a/color");
QColor newColor = action.param(ws2812EffectColorActionEffectColorParamTypeId).value().value<QColor>().toRgb();
QByteArray message = "color=" + newColor.name().remove("#").toUtf8();
qCDebug(dcWs2812) << "Sending" << url.toString() << message;
CoapReply *reply = m_coap->post(CoapRequest(url), message);
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_setColor.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
} else if(action.actionTypeId() == ws2812SpeedActionTypeId) {
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/a/speed");
int speed = action.param(ws2812SpeedActionSpeedParamTypeId).value().toInt();
qCDebug(dcWs2812) << "Set Speed:" << speed;
QByteArray message = QString("bpm=%1").arg(QString::number(speed)).toUtf8();
qCDebug(dcWs2812) << "Sending" << url.toString() << message;
CoapReply *reply = m_coap->post(CoapRequest(url), message);
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_setSpeed.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
} else if(action.actionTypeId() == ws2812BrightnessActionTypeId) {
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/a/brightness");
int brightness = action.param(ws2812BrightnessActionBrightnessParamTypeId).value().toInt();
qCDebug(dcWs2812) << "Set brightness:" << brightness;
QByteArray message = QString("percent=%1").arg(QString::number(brightness)).toUtf8();
qCDebug(dcWs2812) << "Sending" << url.toString() << message;
CoapReply *reply = m_coap->post(CoapRequest(url), message);
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_setBrightness.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
}else if(action.actionTypeId() == ws2812MaxPixActionTypeId) {
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/p/maxpix");
//QColor color = action.param("color").value().value<QColor>().toHsv();
//QColor newColor = QColor::fromHsv(color.hue(), color.saturation(), 100 * light->brightness() / 255.0);
//QByteArray message = "color=" + newColor.toRgb().name().remove("#").toUtf8();
int max = action.param(ws2812MaxPixActionMaxPixParamTypeId).value().toInt();
qCDebug(dcWs2812) << "Max Pix" << max;
QByteArray message = QString("max=%1").arg(QString::number(max)).toUtf8();
//QByteArray message = "max=" + action.param("maxPix").value().toByteArray();
qCDebug(dcWs2812) << "Sending" << url.toString() << message;
CoapReply *reply = m_coap->post(CoapRequest(url), message);
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_setPix.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
}else if(action.actionTypeId() == ws2812EffectModeActionTypeId) {
int effectmode = 0;
QString effectModeString = action.param(ws2812EffectModeActionEffectModeParamTypeId).value().toString();
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/a/effect");
qCDebug(dcWs2812) << "Set effect mode to:" << effectModeString;
//TODO switch to enum
if (effectModeString == "Off") {
effectmode = 0;
} else if (effectModeString == "Color On") {
effectmode = 1;
} else if (effectModeString == "Color Wave") {
effectmode = 2;
} else if (effectModeString == "Color Fade") {
effectmode = 3;
} else if (effectModeString == "Color Flash") {
effectmode = 4;
} else if (effectModeString == "Rainbow Wave") {
effectmode = 5;
} else if (effectModeString == "Rainbow Flash") {
effectmode = 6;
} else if (effectModeString == "Knight Rider") {
effectmode = 7;
} else if (effectModeString == "Fire") {
effectmode = 8;
} else if (effectModeString == "Tricolore") {
effectmode = 9;
}
QByteArray payload = QString("mode=%1").arg(QString::number(effectmode)).toUtf8();
qCDebug(dcWs2812()) << "Sending" << payload << url.path();
CoapReply *reply = m_coap->post(CoapRequest(url), payload);
if(reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_setEffect.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
}else if(action.actionTypeId() == ws2812Tcolor1ActionTypeId || action.actionTypeId() == ws2812Tcolor2ActionTypeId || action.actionTypeId() == ws2812Tcolor3ActionTypeId) {
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/a/tcolor");
/*
* TODO
* Current Implementation is just a temporary workaround
*
*
*/
if(action.actionTypeId() == ws2812Tcolor1ActionTypeId) {
tColor1 = action.param(ws2812Tcolor1ActionTcolor1ParamTypeId).value().value<QColor>().toRgb();
} else if(action.actionTypeId() == ws2812Tcolor2ActionTypeId){
tColor2 = action.param(ws2812Tcolor2ActionTcolor2ParamTypeId).value().value<QColor>().toRgb();
} else if(action.actionTypeId() == ws2812Tcolor3ActionTypeId){
tColor3 = action.param(ws2812Tcolor3ActionTcolor3ParamTypeId).value().value<QColor>().toRgb();
}
QByteArray message = "color=" + tColor1.name().remove("#").toUtf8() + tColor2.name().remove("#").toUtf8() + tColor3.name().remove("#").toUtf8();
qCDebug(dcWs2812) << "Sending" << url.toString() << message;
CoapReply *reply = m_coap->post(CoapRequest(url), message);
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return DeviceManager::DeviceErrorHardwareFailure;
}
m_setTColor.insert(reply, action);
m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
void DevicePluginWs2812::pingDevice(Device *device)
{
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
m_pingReplies.insert(m_coap->ping(CoapRequest(url)), device);
}
void DevicePluginWs2812::updateBattery(Device *device)
{
qCDebug(dcWs2812) << "Update" << device->name() << "battery value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/s/battery");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginWs2812::updateColor(Device *device)
{
qCDebug(dcWs2812) << "Update" << device->name() << "color value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/a/color");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginWs2812::updateTricolore(Device *device)
{
qCDebug(dcWs2812) << "Update" << device->name() << "tricolore value";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/a/tcolor");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginWs2812::updateEffect(Device *device)
{
qCDebug(dcWs2812) << "Update" << device->name() << "effect mode";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/a/effect");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginWs2812::updateMaxPix(Device *device)
{
qCDebug(dcWs2812) << "Update" << device->name() << "max pix";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/p/maxpix");
CoapReply *reply = m_coap->get(CoapRequest(url));
if (reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false);
reply->deleteLater();
return;
}
m_updateReplies.insert(reply, device);
}
void DevicePluginWs2812::enableNotifications(Device *device)
{
qCDebug(dcWs2812) << "Enable" << device->name() << "notifications";
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(ws2812DeviceHostParamTypeId).toString());
url.setPath("/s/battery");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/p/maxpix");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/a/color");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/a/speed");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/a/brightness");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/a/effect");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
url.setPath("/a/tcolor");
m_enableNotification.insert(m_coap->enableResourceNotifications(CoapRequest(url)), device);
}
void DevicePluginWs2812::setReachable(Device *device, const bool &reachable)
{
if (device->stateValue(ws2812ConnectedStateTypeId).toBool() != reachable) {
if (!reachable) {
// Warn just once that the device is not reachable
qCWarning(dcWs2812()) << device->name() << "reachable changed" << reachable;
} else {
qCDebug(dcWs2812()) << device->name() << "reachable changed" << reachable;
// Get current state values after a reconnect
updateBattery(device);
updateColor(device);
updateEffect(device);
updateMaxPix(device);
updateTricolore(device);
// Make sure the notifications are enabled
enableNotifications(device);
}
}
device->setStateValue(ws2812ConnectedStateTypeId, reachable);
}
bool DevicePluginWs2812::deviceAlreadyAdded(const QHostAddress &address)
{
// Check if we already have a device with the given address
foreach (Device *device, myDevices()) {
if (device->paramValue(ws2812DeviceHostParamTypeId).toString() == address.toString()) {
return true;
}
}
return false;
}
Device *DevicePluginWs2812::findDevice(const QHostAddress &address)
{
// Return the device pointer with the given address (otherwise 0)
foreach (Device *device, myDevices()) {
if (device->paramValue(ws2812DeviceHostParamTypeId).toString() == address.toString()) {
return device;
}
}
return nullptr;
}
void DevicePluginWs2812::onPluginTimer()
{
// Try to ping each device every 10 seconds to make sure it is still reachable
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == ws2812DeviceClassId) {
pingDevice(device);
}
}
}
void DevicePluginWs2812::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
if (m_asyncNodeScans.keys().contains(reply)) {
DeviceClassId deviceClassId = m_asyncNodeScans.take(reply);
// Check HTTP status code
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
qCWarning(dcWs2812) << "Node scan reply HTTP error:" << reply->errorString();
emit devicesDiscovered(deviceClassId, QList<DeviceDescriptor>());
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
qCDebug(dcWs2812) << "Node discovery finished:" << endl << data;
QList<DeviceDescriptor> deviceDescriptors;
QList<QByteArray> lines = data.split('\n');
qCDebug(dcWs2812) << lines;
foreach (const QByteArray &line, lines) {
if (line.isEmpty())
continue;
QHostAddress address(QString(line.left(line.length() - 4)));
if (address.isNull())
continue;
qCDebug(dcWs2812) << "Found node" << address.toString();
// Create a deviceDescriptor for each found address
DeviceDescriptor descriptor(deviceClassId, "ws2812", address.toString());
ParamList params;
params.append(Param(ws2812DeviceHostParamTypeId, 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 DevicePluginWs2812::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(ws2812ConnectedStateTypeId).toBool())
qCWarning(dcWs2812) << "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(dcWs2812) << "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(dcWs2812) << "Update resource" << urlPath << "status code error:" << reply;
reply->deleteLater();
return;
}
// Update corresponding device state
if (urlPath == "/s/battery") {
qCDebug(dcWs2812()) << "Updated battery value:" << reply->payload();
device->setStateValue(ws2812BatteryStateTypeId, reply->payload().toDouble());
} else if (urlPath == "/a/color") {
qCDebug(dcWs2812()) << "Updated color value:" << reply->payload();
device->setStateValue(ws2812EffectColorStateTypeId, QVariant::fromValue(reply->payload()));
} else if (urlPath == "/a/effect") {
qCDebug(dcWs2812()) << "Updated effect value:" << reply->payload();
int effectmode = reply->payload().toInt();
QString effectModeString;
switch (effectmode) {
case 0:
effectModeString = "Off";
break;
case 1:
effectModeString = "Color On";
break;
case 2:
effectModeString = "Color Wave";
break;
case 3:
effectModeString = "Color Fade";
break;
case 4:
effectModeString = "Color Flash";
break;
case 5:
effectModeString = "Rainbow Wave";
break;
case 6:
effectModeString = "Rainbow Flash";
break;
case 7:
effectModeString = "Knight Rider";
break;
case 8:
effectModeString = "Fire";
break;
case 9:
effectModeString = "Tricolore";
break;
default:
effectModeString = "Off";
}
device->setStateValue(ws2812EffectModeStateTypeId, effectModeString);
}else if (urlPath == "/a/brightness") {
qCDebug(dcWs2812()) << "Updated brightness value:" << reply->payload().toInt();
device->setStateValue(ws2812BrightnessStateTypeId, reply->payload().toInt());
}else if (urlPath == "/a/speed") {
qCDebug(dcWs2812()) << "Updated speed value:" << reply->payload().toInt();
device->setStateValue(ws2812SpeedStateTypeId, reply->payload().toInt());
}else if (urlPath == "/p/maxpix") {
qCDebug(dcWs2812()) << "Updated max pix value:" << reply->payload().toInt();
device->setStateValue(ws2812MaxPixStateTypeId, reply->payload().toInt());
}
} else if (m_setEffect.contains(reply)) {
Action action = m_setEffect.take(reply);
Device *device = m_asyncActions.take(action.id());
// Check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply toggle light 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(dcWs2812) << "Set effect 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_setColor.contains(reply)) {
Action action = m_setColor.take(reply);
Device *device = m_asyncActions.take(action.id());
// check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP set color 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(dcWs2812) << "Set color status code error:" << reply;
reply->deleteLater();
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorHardwareFailure);
return;
}
QString tcolor = action.param(ws2812EffectColorActionEffectColorParamTypeId).value().toByteArray();
// Update the state here, so we don't have to wait for the notification
device->setStateValue(ws2812Tcolor1StateTypeId, tcolor.left(6));
device->setStateValue(ws2812Tcolor2StateTypeId, tcolor.mid(6,6));
device->setStateValue(ws2812Tcolor3StateTypeId, tcolor.right(6));
// Tell the user about the action execution result
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorNoError);
} else if (m_setTColor.contains(reply)) {
Action action = m_setTColor.take(reply);
Device *device = m_asyncActions.take(action.id());
// check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP set color 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(dcWs2812) << "Set color 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(ws2812EffectColorStateTypeId, action.param(ws2812EffectColorActionEffectColorParamTypeId).value().toInt());
// Tell the user about the action execution result
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorNoError);
} else if (m_setBrightness.contains(reply)) {
Action action = m_setBrightness.take(reply);
Device *device = m_asyncActions.take(action.id());
// check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP set brightness 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(dcWs2812) << "Set brightness 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(ws2812BrightnessStateTypeId, action.param(ws2812BrightnessActionBrightnessParamTypeId).value().toInt());
// Tell the user about the action execution result
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorNoError);
}else if (m_setSpeed.contains(reply)) {
Action action = m_setSpeed.take(reply);
Device *device = m_asyncActions.take(action.id());
// check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP set speed 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(dcWs2812) << "Set speed 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(ws2812SpeedStateTypeId, action.param(ws2812SpeedActionSpeedParamTypeId).value().toInt());
// Tell the user about the action execution result
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorNoError);
}else if (m_setPix.contains(reply)) {
Action action = m_setPix.take(reply);
Device *device = m_asyncActions.take(action.id());
// check CoAP reply error
if (reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP set maxpix 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(dcWs2812) << "Set max pix 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(ws2812MaxPixStateTypeId, action.param(ws2812MaxPixActionMaxPixParamTypeId).value().toInt());
// 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(dcWs2812) << "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(dcWs2812) << "Enable notifications for" << reply->request().url().toString() << "reply status code error" << reply->errorString();
reply->deleteLater();
return;
}
qCDebug(dcWs2812()) << "Enabled successfully notifications for" << device->name() << reply->request().url().path();
}
// Delete the CoAP reply
reply->deleteLater();
}
void DevicePluginWs2812::onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload)
{
qCDebug(dcWs2812) << " --> Got notification nr." << notificationNumber << resource.url().toString() << payload;
Device *device = findDevice(QHostAddress(resource.url().host()));
if (!device) {
qCWarning(dcWs2812()) << "Could not find device for this notification";
return;
}
// Update the corresponding device state
if (resource.url().path() == "/s/battery") {
device->setStateValue(ws2812BatteryStateTypeId, payload.toDouble());
}else if (resource.url().path() == "/a/color") {
device->setStateValue(ws2812EffectColorStateTypeId, QVariant::fromValue(payload));
}else if (resource.url().path() == "/a/effect") {
int effectmode = payload.toInt();
QString effectModeString;
switch (effectmode) {
case 0:
effectModeString = "Off";
break;
case 1:
effectModeString = "Color On";
break;
case 2:
effectModeString = "Color Wave";
break;
case 3:
effectModeString = "Color Fade";
break;
case 4:
effectModeString = "Color Flash";
break;
case 5:
effectModeString = "Rainbow Wave";
break;
case 6:
effectModeString = "Rainbow Flash";
break;
case 7:
effectModeString = "Knight Rider";
break;
case 8:
effectModeString = "Fire";
break;
case 9:
effectModeString = "Tricolore";
break;
default:
effectModeString = "Off";
}
device->setStateValue(ws2812EffectModeStateTypeId, effectModeString);
}else if (resource.url().path() == "/a/brightness") {
device->setStateValue(ws2812EffectColorStateTypeId, payload.toInt());
}else if (resource.url().path() == "/a/speed") {
device->setStateValue(ws2812EffectColorStateTypeId, payload.toInt());
}else if (resource.url().path() == "/p/maxpix") {
device->setStateValue(ws2812MaxPixStateTypeId, payload.toInt());
}
}

View File

@ -1,99 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2015 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DEVICEPLUGINWS2812_H
#define DEVICEPLUGINWS2812_H
#include "plugin/deviceplugin.h"
#include "types/action.h"
#include "coap/coap.h"
#include "plugintimer.h"
#include <QColor>
#include <QHash>
#include <QNetworkReply>
class DevicePluginWs2812 : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginws2812.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginWs2812();
~DevicePluginWs2812();
void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void postSetupDevice(Device *device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private:
PluginTimer *m_pluginTimer = nullptr;
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_setColor;
QHash<CoapReply *, Action> m_setEffect;
QHash<CoapReply *, Action> m_setPix;
QHash<CoapReply *, Action> m_setBrightness;
QHash<CoapReply *, Action> m_setSpeed;
QHash<CoapReply *, Action> m_setTColor;
void pingDevice(Device *device);
void updateBattery(Device *device);
void updateColor(Device *device);
void updateEffect(Device *device);
void updateMaxPix(Device *device);
void updateTricolore(Device *device);
void enableNotifications(Device *device);
void setReachable(Device *device, const bool &reachable);
bool deviceAlreadyAdded(const QHostAddress &address);
Device *findDevice(const QHostAddress &address);
QColor tColor1;
QColor tColor2;
QColor tColor3;
private slots:
void onPluginTimer();
void onNetworkReplyFinished();
void coapReplyFinished(CoapReply *reply);
void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload);
};
#endif // DEVICEPLUGINWS2812_H

View File

@ -1,159 +0,0 @@
{
"displayName": "WS2812",
"name": "Ws2812",
"id": "60b68c75-3261-4bf1-8912-798d2d3bbd3b",
"paramTypes": [
{
"id": "0a2898cb-ca36-4c6e-8418-993c1d9df434",
"name": "rpl",
"displayName": "RPL address",
"type": "QString",
"inputType": "TextLine",
"defaultValue": "fdaa:e9b8:d03a::ff:fe00:1"
}
],
"vendors": [
{
"displayName": "nymea",
"name": "nymea",
"id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
"deviceClasses": [
{
"id": "3142db46-5c6f-42d6-9001-753150763385",
"displayName": "WS2812",
"name": "ws2812",
"createMethods": ["discovery"],
"interfaces": ["gateway"],
"paramTypes": [
{
"id": "ccf1f6b1-54c4-46c1-b978-6abcf3fad882",
"name": "host",
"displayName": "host",
"type": "QString",
"inputType": "TextLine"
}
],
"stateTypes": [
{
"id": "c9f6042f-1193-4075-94b1-37b29641ec24",
"name": "battery",
"displayName": "battery voltage",
"displayNameEvent": "battery voltage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "08091cde-983d-42f7-bdd7-d89c312ccbed",
"name": "connected",
"displayName": "reachable",
"displayNameEvent": "reachable changed",
"type": "bool",
"defaultValue": false
},
{
"id": "8a73c60a-1da9-4228-8dba-2ffccc6531a6",
"name": "effectColor",
"displayName": "color",
"displayNameEvent": "color changed",
"displayNameAction": "set color",
"type": "QColor",
"defaultValue": "#000000",
"writable": true
},
{
"id": "01da8dbc-1ac8-4d18-bc17-fc4b4c591693",
"name": "brightness",
"displayName": "brightness",
"displayNameEvent": "brightness changed",
"displayNameAction": "set brightness",
"type": "int",
"unit": "Percentage",
"defaultValue": 0,
"minValue": 0,
"maxValue": 100,
"writable": true
},
{
"id": "ac372b72-c2ae-4f0f-9fca-bd7cf654603a",
"name": "maxPix",
"displayName": "leds",
"displayNameEvent": "leds changed",
"displayNameAction": "set leds",
"type": "int",
"defaultValue": 240,
"minValue": 0,
"maxValue": 240,
"writable": true
},
{
"id": "e53ae524-ca10-49c5-b530-e414779ecc1d",
"name": "speed",
"displayName": "speed",
"displayNameEvent": "speed changed",
"displayNameAction": "set speed",
"type": "int",
"defaultValue": 60,
"minValue": 60,
"maxValue": 240,
"writable": true
},
{
"id": "f4fe5d31-1edb-4944-9ddb-c89e7da8bee7",
"name": "effectMode",
"displayName": "effect mode",
"displayNameEvent": "effect mode changed",
"displayNameAction": "set effect mode",
"type": "QString",
"writable": true,
"possibleValues": [
"Off",
"Color On",
"Color Wave",
"Color Fade",
"Color Flash",
"Rainbow Wave",
"Rainbow Flash",
"Knight Rider",
"Fire",
"Tricolore"
],
"defaultValue": "Off"
},
{
"id": "8fe2e42a-7b9d-4c76-ae77-355759c81350",
"displayName": "tricolore color 1",
"displayNameEvent": "tricolore color 1 changed",
"displayNameAction": "set tricolore color 1",
"name": "tcolor1",
"type": "QColor",
"defaultValue": "#000000",
"writable": true
},
{
"id": "dd4ad65b-007a-4eae-8ce0-b76d6cbf093e",
"displayName": "tricolore color 2",
"displayNameEvent": "tricolore color 2 changed",
"displayNameAction": "set tricolore color 2",
"name": "tcolor2",
"type": "QColor",
"defaultValue": "#000000",
"writable": true
},
{
"id": "97c83be0-7ba7-4758-b52b-d997a80bfbe5",
"displayName": "tricolore color 3",
"displayNameEvent": "tricolore color 3 changed",
"displayNameAction": "set tricolore color 3",
"name": "tcolor3",
"type": "QColor",
"defaultValue": "#000000",
"writable": true
}
]
}
]
}
]
}

View File

@ -1,226 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<context>
<name>Ws2812</name>
<message>
<location filename="../plugininfo.h" line="75"/>
<location filename="../plugininfo.h" line="84"/>
<source>WS2812</source>
<extracomment>The name of the plugin Ws2812 (60b68c75-3261-4bf1-8912-798d2d3bbd3b)
----------
The name of the DeviceClass (3142db46-5c6f-42d6-9001-753150763385)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="78"/>
<source>RPL address</source>
<extracomment>The name of the ParamType (DeviceClass: ws2812, Type: plugin, ID: 0a2898cb-ca36-4c6e-8418-993c1d9df434)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="81"/>
<source>nymea</source>
<extracomment>The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="87"/>
<source>host</source>
<extracomment>The name of the ParamType (DeviceClass: ws2812, Type: device, ID: ccf1f6b1-54c4-46c1-b978-6abcf3fad882)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="90"/>
<source>battery voltage changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: battery, ID: c9f6042f-1193-4075-94b1-37b29641ec24)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="96"/>
<source>reachable changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: connected, ID: 08091cde-983d-42f7-bdd7-d89c312ccbed)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="93"/>
<source>battery voltage</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: battery, ID: c9f6042f-1193-4075-94b1-37b29641ec24</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="99"/>
<source>reachable</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: connected, ID: 08091cde-983d-42f7-bdd7-d89c312ccbed</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="102"/>
<source>color changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: effectColor, ID: 8a73c60a-1da9-4228-8dba-2ffccc6531a6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="105"/>
<location filename="../plugininfo.h" line="111"/>
<source>color</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: effectColor, ID: 8a73c60a-1da9-4228-8dba-2ffccc6531a6
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: effectColor, ID: 8a73c60a-1da9-4228-8dba-2ffccc6531a6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="108"/>
<source>set color</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: effectColor, ID: 8a73c60a-1da9-4228-8dba-2ffccc6531a6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="114"/>
<source>brightness changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: brightness, ID: 01da8dbc-1ac8-4d18-bc17-fc4b4c591693)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="117"/>
<location filename="../plugininfo.h" line="123"/>
<source>brightness</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: brightness, ID: 01da8dbc-1ac8-4d18-bc17-fc4b4c591693
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: brightness, ID: 01da8dbc-1ac8-4d18-bc17-fc4b4c591693)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="120"/>
<source>set brightness</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: brightness, ID: 01da8dbc-1ac8-4d18-bc17-fc4b4c591693)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="126"/>
<source>leds changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: maxPix, ID: ac372b72-c2ae-4f0f-9fca-bd7cf654603a)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="129"/>
<location filename="../plugininfo.h" line="135"/>
<source>leds</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: maxPix, ID: ac372b72-c2ae-4f0f-9fca-bd7cf654603a
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: maxPix, ID: ac372b72-c2ae-4f0f-9fca-bd7cf654603a)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="132"/>
<source>set leds</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: maxPix, ID: ac372b72-c2ae-4f0f-9fca-bd7cf654603a)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="138"/>
<source>speed changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: speed, ID: e53ae524-ca10-49c5-b530-e414779ecc1d)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="141"/>
<location filename="../plugininfo.h" line="147"/>
<source>speed</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: speed, ID: e53ae524-ca10-49c5-b530-e414779ecc1d
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: speed, ID: e53ae524-ca10-49c5-b530-e414779ecc1d)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="144"/>
<source>set speed</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: speed, ID: e53ae524-ca10-49c5-b530-e414779ecc1d)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="150"/>
<source>effect mode changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: effectMode, ID: f4fe5d31-1edb-4944-9ddb-c89e7da8bee7)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="153"/>
<location filename="../plugininfo.h" line="159"/>
<source>effect mode</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: effectMode, ID: f4fe5d31-1edb-4944-9ddb-c89e7da8bee7
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: effectMode, ID: f4fe5d31-1edb-4944-9ddb-c89e7da8bee7)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="156"/>
<source>set effect mode</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: effectMode, ID: f4fe5d31-1edb-4944-9ddb-c89e7da8bee7)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="162"/>
<source>tricolore color 1 changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: tcolor1, ID: 8fe2e42a-7b9d-4c76-ae77-355759c81350)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="165"/>
<location filename="../plugininfo.h" line="171"/>
<source>tricolore color 1</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: tcolor1, ID: 8fe2e42a-7b9d-4c76-ae77-355759c81350
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor1, ID: 8fe2e42a-7b9d-4c76-ae77-355759c81350)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="168"/>
<source>set tricolore color 1</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor1, ID: 8fe2e42a-7b9d-4c76-ae77-355759c81350)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="174"/>
<source>tricolore color 2 changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: tcolor2, ID: dd4ad65b-007a-4eae-8ce0-b76d6cbf093e)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="177"/>
<location filename="../plugininfo.h" line="183"/>
<source>tricolore color 2</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: tcolor2, ID: dd4ad65b-007a-4eae-8ce0-b76d6cbf093e
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor2, ID: dd4ad65b-007a-4eae-8ce0-b76d6cbf093e)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="180"/>
<source>set tricolore color 2</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor2, ID: dd4ad65b-007a-4eae-8ce0-b76d6cbf093e)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="186"/>
<source>tricolore color 3 changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: tcolor3, ID: 97c83be0-7ba7-4758-b52b-d997a80bfbe5)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="189"/>
<location filename="../plugininfo.h" line="195"/>
<source>tricolore color 3</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: tcolor3, ID: 97c83be0-7ba7-4758-b52b-d997a80bfbe5
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor3, ID: 97c83be0-7ba7-4758-b52b-d997a80bfbe5)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="192"/>
<source>set tricolore color 3</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor3, ID: 97c83be0-7ba7-4758-b52b-d997a80bfbe5)</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,226 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>Ws2812</name>
<message>
<location filename="../plugininfo.h" line="75"/>
<location filename="../plugininfo.h" line="84"/>
<source>WS2812</source>
<extracomment>The name of the plugin Ws2812 (60b68c75-3261-4bf1-8912-798d2d3bbd3b)
----------
The name of the DeviceClass (3142db46-5c6f-42d6-9001-753150763385)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="78"/>
<source>RPL address</source>
<extracomment>The name of the ParamType (DeviceClass: ws2812, Type: plugin, ID: 0a2898cb-ca36-4c6e-8418-993c1d9df434)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="81"/>
<source>nymea</source>
<extracomment>The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="87"/>
<source>host</source>
<extracomment>The name of the ParamType (DeviceClass: ws2812, Type: device, ID: ccf1f6b1-54c4-46c1-b978-6abcf3fad882)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="90"/>
<source>battery voltage changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: battery, ID: c9f6042f-1193-4075-94b1-37b29641ec24)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="96"/>
<source>reachable changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: connected, ID: 08091cde-983d-42f7-bdd7-d89c312ccbed)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="93"/>
<source>battery voltage</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: battery, ID: c9f6042f-1193-4075-94b1-37b29641ec24</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="99"/>
<source>reachable</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: connected, ID: 08091cde-983d-42f7-bdd7-d89c312ccbed</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="102"/>
<source>color changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: effectColor, ID: 8a73c60a-1da9-4228-8dba-2ffccc6531a6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="105"/>
<location filename="../plugininfo.h" line="111"/>
<source>color</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: effectColor, ID: 8a73c60a-1da9-4228-8dba-2ffccc6531a6
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: effectColor, ID: 8a73c60a-1da9-4228-8dba-2ffccc6531a6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="108"/>
<source>set color</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: effectColor, ID: 8a73c60a-1da9-4228-8dba-2ffccc6531a6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="114"/>
<source>brightness changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: brightness, ID: 01da8dbc-1ac8-4d18-bc17-fc4b4c591693)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="117"/>
<location filename="../plugininfo.h" line="123"/>
<source>brightness</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: brightness, ID: 01da8dbc-1ac8-4d18-bc17-fc4b4c591693
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: brightness, ID: 01da8dbc-1ac8-4d18-bc17-fc4b4c591693)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="120"/>
<source>set brightness</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: brightness, ID: 01da8dbc-1ac8-4d18-bc17-fc4b4c591693)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="126"/>
<source>leds changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: maxPix, ID: ac372b72-c2ae-4f0f-9fca-bd7cf654603a)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="129"/>
<location filename="../plugininfo.h" line="135"/>
<source>leds</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: maxPix, ID: ac372b72-c2ae-4f0f-9fca-bd7cf654603a
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: maxPix, ID: ac372b72-c2ae-4f0f-9fca-bd7cf654603a)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="132"/>
<source>set leds</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: maxPix, ID: ac372b72-c2ae-4f0f-9fca-bd7cf654603a)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="138"/>
<source>speed changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: speed, ID: e53ae524-ca10-49c5-b530-e414779ecc1d)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="141"/>
<location filename="../plugininfo.h" line="147"/>
<source>speed</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: speed, ID: e53ae524-ca10-49c5-b530-e414779ecc1d
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: speed, ID: e53ae524-ca10-49c5-b530-e414779ecc1d)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="144"/>
<source>set speed</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: speed, ID: e53ae524-ca10-49c5-b530-e414779ecc1d)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="150"/>
<source>effect mode changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: effectMode, ID: f4fe5d31-1edb-4944-9ddb-c89e7da8bee7)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="153"/>
<location filename="../plugininfo.h" line="159"/>
<source>effect mode</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: effectMode, ID: f4fe5d31-1edb-4944-9ddb-c89e7da8bee7
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: effectMode, ID: f4fe5d31-1edb-4944-9ddb-c89e7da8bee7)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="156"/>
<source>set effect mode</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: effectMode, ID: f4fe5d31-1edb-4944-9ddb-c89e7da8bee7)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="162"/>
<source>tricolore color 1 changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: tcolor1, ID: 8fe2e42a-7b9d-4c76-ae77-355759c81350)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="165"/>
<location filename="../plugininfo.h" line="171"/>
<source>tricolore color 1</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: tcolor1, ID: 8fe2e42a-7b9d-4c76-ae77-355759c81350
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor1, ID: 8fe2e42a-7b9d-4c76-ae77-355759c81350)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="168"/>
<source>set tricolore color 1</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor1, ID: 8fe2e42a-7b9d-4c76-ae77-355759c81350)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="174"/>
<source>tricolore color 2 changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: tcolor2, ID: dd4ad65b-007a-4eae-8ce0-b76d6cbf093e)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="177"/>
<location filename="../plugininfo.h" line="183"/>
<source>tricolore color 2</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: tcolor2, ID: dd4ad65b-007a-4eae-8ce0-b76d6cbf093e
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor2, ID: dd4ad65b-007a-4eae-8ce0-b76d6cbf093e)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="180"/>
<source>set tricolore color 2</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor2, ID: dd4ad65b-007a-4eae-8ce0-b76d6cbf093e)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="186"/>
<source>tricolore color 3 changed</source>
<extracomment>The name of the autocreated EventType (DeviceClass: ws2812, StateType: tcolor3, ID: 97c83be0-7ba7-4758-b52b-d997a80bfbe5)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="189"/>
<location filename="../plugininfo.h" line="195"/>
<source>tricolore color 3</source>
<extracomment>The name of the ParamType for the autocreated EventType (DeviceClass: ws2812, StateType: tcolor3, ID: 97c83be0-7ba7-4758-b52b-d997a80bfbe5
----------
The name of the ParamType for the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor3, ID: 97c83be0-7ba7-4758-b52b-d997a80bfbe5)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="192"/>
<source>set tricolore color 3</source>
<extracomment>The name of the autocreated ActionType (DeviceClass: ws2812, StateType: tcolor3, ID: 97c83be0-7ba7-4758-b52b-d997a80bfbe5)</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,11 +0,0 @@
include(../plugins.pri)
QT += network
TARGET = $$qtLibraryTarget(nymea_devicepluginws2812)
SOURCES += \
devicepluginws2812.cpp
HEADERS += \
devicepluginws2812.h