removed orderbutton, plantcare and ws2812
This commit is contained in:
parent
e6347ba0a9
commit
5acaa6409e
51
debian/control
vendored
51
debian/control
vendored
@ -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
|
||||
|
||||
1
debian/nymea-plugin-orderbutton.install.in
vendored
1
debian/nymea-plugin-orderbutton.install.in
vendored
@ -1 +0,0 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginorderbutton.so
|
||||
1
debian/nymea-plugin-plantcare.install.in
vendored
1
debian/nymea-plugin-plantcare.install.in
vendored
@ -1 +0,0 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginplantcare.so
|
||||
1
debian/nymea-plugin-ws2812.install.in
vendored
1
debian/nymea-plugin-ws2812.install.in
vendored
@ -1 +0,0 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginws2812.so
|
||||
@ -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(============================================)
|
||||
|
||||
@ -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 ¶ms)
|
||||
{
|
||||
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 ¬ificationNumber, 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());
|
||||
}
|
||||
}
|
||||
@ -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 ¶ms) 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 ¬ificationNumber, const QByteArray &payload);
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINORDERBUTTON_H
|
||||
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT += network
|
||||
|
||||
TARGET = $$qtLibraryTarget(nymea_devicepluginorderbutton)
|
||||
|
||||
SOURCES += \
|
||||
devicepluginorderbutton.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginorderbutton.h
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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 ¶ms)
|
||||
{
|
||||
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 ¬ificationNumber, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 ¶ms) 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 ¬ificationNumber, const QByteArray &payload);
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINPLANTCARE_H
|
||||
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT += network
|
||||
|
||||
TARGET = $$qtLibraryTarget(nymea_devicepluginplantcare)
|
||||
|
||||
SOURCES += \
|
||||
devicepluginplantcare.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginplantcare.h
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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 ¶ms)
|
||||
{
|
||||
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 ¬ificationNumber, 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());
|
||||
}
|
||||
}
|
||||
@ -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 ¶ms) 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 ¬ificationNumber, const QByteArray &payload);
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINWS2812_H
|
||||
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -1,11 +0,0 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT += network
|
||||
|
||||
TARGET = $$qtLibraryTarget(nymea_devicepluginws2812)
|
||||
|
||||
SOURCES += \
|
||||
devicepluginws2812.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginws2812.h
|
||||
Loading…
x
Reference in New Issue
Block a user