Migrate plugin timer

This commit is contained in:
Simon Stürz 2017-11-24 22:54:15 +01:00 committed by Michael Zanetti
parent 0b1991d50a
commit 2b39765d58
72 changed files with 1168 additions and 2211 deletions

View File

@ -44,6 +44,7 @@
#include "plugin/device.h" #include "plugin/device.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/avahi/qtavahiservicebrowser.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -56,8 +57,8 @@ DevicePluginAvahiMonitor::DevicePluginAvahiMonitor()
void DevicePluginAvahiMonitor::init() void DevicePluginAvahiMonitor::init()
{ {
connect(avahiServiceBrowser(), SIGNAL(serviceEntryAdded(AvahiServiceEntry)), this, SLOT(onServiceEntryAdded(AvahiServiceEntry))); connect(hardwareManager()->avahiBrowser(), &QtAvahiServiceBrowser::serviceEntryAdded, this, &DevicePluginAvahiMonitor::onServiceEntryAdded);
connect(avahiServiceBrowser(), SIGNAL(serviceEntryRemoved(AvahiServiceEntry)), this, SLOT(onServiceEntryRemoved(AvahiServiceEntry))); connect(hardwareManager()->avahiBrowser(), &QtAvahiServiceBrowser::serviceEntryRemoved, this, &DevicePluginAvahiMonitor::onServiceEntryRemoved);
} }
DeviceManager::DeviceSetupStatus DevicePluginAvahiMonitor::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginAvahiMonitor::setupDevice(Device *device)
@ -75,7 +76,7 @@ DeviceManager::DeviceError DevicePluginAvahiMonitor::discoverDevices(const Devic
return DeviceManager::DeviceErrorDeviceClassNotFound; return DeviceManager::DeviceErrorDeviceClassNotFound;
QList<DeviceDescriptor> deviceDescriptors; QList<DeviceDescriptor> deviceDescriptors;
foreach (const AvahiServiceEntry &service, avahiServiceBrowser()->serviceEntries()) { foreach (const AvahiServiceEntry &service, hardwareManager()->avahiBrowser()->serviceEntries()) {
DeviceDescriptor deviceDescriptor(avahiDeviceClassId, service.name(), service.hostAddress().toString()); DeviceDescriptor deviceDescriptor(avahiDeviceClassId, service.name(), service.hostAddress().toString());
ParamList params; ParamList params;
params.append(Param(serviceParamTypeId, service.name())); params.append(Param(serviceParamTypeId, service.name()));
@ -89,11 +90,6 @@ DeviceManager::DeviceError DevicePluginAvahiMonitor::discoverDevices(const Devic
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
DeviceManager::HardwareResources DevicePluginAvahiMonitor::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
void DevicePluginAvahiMonitor::onServiceEntryAdded(const AvahiServiceEntry &serviceEntry) void DevicePluginAvahiMonitor::onServiceEntryAdded(const AvahiServiceEntry &serviceEntry)
{ {
foreach (Device *device, myDevices()) { foreach (Device *device, myDevices()) {

View File

@ -25,6 +25,7 @@
#define DEVICEPLUGINAVAHIMONITOR_H #define DEVICEPLUGINAVAHIMONITOR_H
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "network/avahi/avahiserviceentry.h"
#include <QProcess> #include <QProcess>
@ -42,7 +43,6 @@ public:
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::HardwareResources requiredHardware() const override;
private slots: private slots:
void onServiceEntryAdded(const AvahiServiceEntry &serviceEntry); void onServiceEntryAdded(const AvahiServiceEntry &serviceEntry);

View File

@ -69,6 +69,8 @@
#include "devicepluginawattar.h" #include "devicepluginawattar.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "hardwaremanager.h"
#include "network/networkaccessmanager.h"
#include <QDateTime> #include <QDateTime>
#include <QJsonDocument> #include <QJsonDocument>
@ -78,9 +80,15 @@ DevicePluginAwattar::DevicePluginAwattar()
{ {
} }
DeviceManager::HardwareResources DevicePluginAwattar::requiredHardware() const DevicePluginAwattar::~DevicePluginAwattar()
{ {
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer; hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginAwattar::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(15);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginAwattar::onPluginTimer);
} }
DeviceManager::DeviceSetupStatus DevicePluginAwattar::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginAwattar::setupDevice(Device *device)
@ -119,85 +127,6 @@ void DevicePluginAwattar::deviceRemoved(Device *device)
m_device = 0; m_device = 0;
} }
void DevicePluginAwattar::networkManagerReplyReady(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (m_updatePrice.contains(reply)) {
m_updatePrice.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Update reply HTTP error:" << status << reply->errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
// check JSON file
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcAwattar) << "Update reply JSON error:" << error.errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
processPriceData(jsonDoc.toVariant().toMap());
// start user data update
m_updateUserData.append(requestUserData(m_token, m_userUuid));
} else if (m_updateUserData.contains(reply)) {
m_updateUserData.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Update user data reply HTTP error:" << status << reply->errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
// check JSON file
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcAwattar) << "Update user data reply JSON error:" << error.errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
setOnlineStatus(true);
processUserData(jsonDoc.toVariant().toMap());
} else if (m_searchPumpReplies.contains(reply)) {
m_searchPumpReplies.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Search pump reply HTTP error:" << status << reply->errorString();
reply->deleteLater();
return;
}
processPumpSearchData(reply->readAll());
}
reply->deleteLater();
}
void DevicePluginAwattar::guhTimer()
{
if (m_device.isNull())
return;
updateData();
searchHeatPumps();
}
DeviceManager::DeviceError DevicePluginAwattar::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginAwattar::executeAction(Device *device, const Action &action)
{ {
if (m_device.isNull() || m_device != device) if (m_device.isNull() || m_device != device)
@ -244,7 +173,9 @@ QNetworkReply *DevicePluginAwattar::requestPriceData(const QString &token)
QNetworkRequest request(QUrl("https://api.awattar.com/v1/marketdata")); QNetworkRequest request(QUrl("https://api.awattar.com/v1/marketdata"));
request.setRawHeader("Authorization", header.toLocal8Bit()); request.setRawHeader("Authorization", header.toLocal8Bit());
request.setSslConfiguration(QSslConfiguration::defaultConfiguration()); request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
return networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginAwattar::onNetworkReplyFinished);
return reply;
} }
QNetworkReply *DevicePluginAwattar::requestUserData(const QString &token, const QString &userId) QNetworkReply *DevicePluginAwattar::requestUserData(const QString &token, const QString &userId)
@ -255,7 +186,9 @@ QNetworkReply *DevicePluginAwattar::requestUserData(const QString &token, const
QNetworkRequest request(QUrl(QString("https://api.awattar.com/v1/devices/%1/actuators").arg(userId))); QNetworkRequest request(QUrl(QString("https://api.awattar.com/v1/devices/%1/actuators").arg(userId)));
request.setRawHeader("Authorization", header.toLocal8Bit()); request.setRawHeader("Authorization", header.toLocal8Bit());
request.setSslConfiguration(QSslConfiguration::defaultConfiguration()); request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
return networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginAwattar::onNetworkReplyFinished);
return reply;
} }
void DevicePluginAwattar::updateData() void DevicePluginAwattar::updateData()
@ -273,8 +206,8 @@ void DevicePluginAwattar::searchHeatPumps()
} }
QNetworkRequest request(QUrl(QString("http://[%1]").arg(rplAddress.toString()))); QNetworkRequest request(QUrl(QString("http://[%1]").arg(rplAddress.toString())));
QNetworkReply *reply = networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginAwattar::onNetworkReplyFinished);
m_searchPumpReplies.append(reply); m_searchPumpReplies.append(reply);
} }
@ -452,6 +385,86 @@ bool DevicePluginAwattar::heatPumpExists(const QHostAddress &pumpAddress)
return false; return false;
} }
void DevicePluginAwattar::onPluginTimer()
{
if (m_device.isNull())
return;
updateData();
searchHeatPumps();
}
void DevicePluginAwattar::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (m_updatePrice.contains(reply)) {
m_updatePrice.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Update reply HTTP error:" << status << reply->errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
// check JSON file
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcAwattar) << "Update reply JSON error:" << error.errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
processPriceData(jsonDoc.toVariant().toMap());
// start user data update
m_updateUserData.append(requestUserData(m_token, m_userUuid));
} else if (m_updateUserData.contains(reply)) {
m_updateUserData.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Update user data reply HTTP error:" << status << reply->errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
// check JSON file
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcAwattar) << "Update user data reply JSON error:" << error.errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
setOnlineStatus(true);
processUserData(jsonDoc.toVariant().toMap());
} else if (m_searchPumpReplies.contains(reply)) {
m_searchPumpReplies.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Search pump reply HTTP error:" << status << reply->errorString();
reply->deleteLater();
return;
}
processPumpSearchData(reply->readAll());
}
reply->deleteLater();
}
void DevicePluginAwattar::onHeatPumpReachableChanged() void DevicePluginAwattar::onHeatPumpReachableChanged()
{ {
HeatPump *pump = static_cast<HeatPump *>(sender()); HeatPump *pump = static_cast<HeatPump *>(sender());

View File

@ -24,6 +24,8 @@
#define DEVICEPLUGINAWATTAR_H #define DEVICEPLUGINAWATTAR_H
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "plugintimer.h"
#include "heatpump.h" #include "heatpump.h"
#include <QHash> #include <QHash>
@ -39,17 +41,16 @@ class DevicePluginAwattar : public DevicePlugin
public: public:
explicit DevicePluginAwattar(); explicit DevicePluginAwattar();
~DevicePluginAwattar();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void postSetupDevice(Device *device) override; void postSetupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void guhTimer() override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private: private:
PluginTimer *m_pluginTimer = nullptr;
QPointer<Device> m_device; QPointer<Device> m_device;
QList<QPointer<HeatPump> > m_heatPumps; QList<QPointer<HeatPump> > m_heatPumps;
@ -63,7 +64,6 @@ private:
int m_autoSgMode; int m_autoSgMode;
int m_manualSgMode; int m_manualSgMode;
QNetworkReply *requestPriceData(const QString& token); QNetworkReply *requestPriceData(const QString& token);
QNetworkReply *requestUserData(const QString& token, const QString &userId); QNetworkReply *requestUserData(const QString& token, const QString &userId);
@ -79,6 +79,8 @@ private:
bool heatPumpExists(const QHostAddress &pumpAddress); bool heatPumpExists(const QHostAddress &pumpAddress);
private slots: private slots:
void onPluginTimer();
void onNetworkReplyFinished();
void onHeatPumpReachableChanged(); void onHeatPumpReachableChanged();
}; };

View File

@ -106,6 +106,7 @@
DevicePluginCommandLauncher::DevicePluginCommandLauncher() DevicePluginCommandLauncher::DevicePluginCommandLauncher()
{ {
} }
DeviceManager::DeviceSetupStatus DevicePluginCommandLauncher::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginCommandLauncher::setupDevice(Device *device)
@ -137,11 +138,6 @@ DeviceManager::DeviceSetupStatus DevicePluginCommandLauncher::setupDevice(Device
return DeviceManager::DeviceSetupStatusFailure; return DeviceManager::DeviceSetupStatusFailure;
} }
DeviceManager::HardwareResources DevicePluginCommandLauncher::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
DeviceManager::DeviceError DevicePluginCommandLauncher::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginCommandLauncher::executeAction(Device *device, const Action &action)
{ {
// Application // Application

View File

@ -24,6 +24,7 @@
#define DEVICEPLUGINCOMMANDLAUNCHER_H #define DEVICEPLUGINCOMMANDLAUNCHER_H
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include <QProcess> #include <QProcess>
#include <QFileInfo> #include <QFileInfo>
@ -38,7 +39,6 @@ public:
explicit DevicePluginCommandLauncher(); explicit DevicePluginCommandLauncher();
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;

View File

@ -46,6 +46,7 @@
#include "plugin/device.h" #include "plugin/device.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "hardware/radio433/radio433.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -53,11 +54,7 @@
DevicePluginConrad::DevicePluginConrad() DevicePluginConrad::DevicePluginConrad()
{ {
}
DeviceManager::HardwareResources DevicePluginConrad::requiredHardware() const
{
return DeviceManager::HardwareResourceRadio433;
} }
DeviceManager::DeviceSetupStatus DevicePluginConrad::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginConrad::setupDevice(Device *device)
@ -71,6 +68,10 @@ DeviceManager::DeviceSetupStatus DevicePluginConrad::setupDevice(Device *device)
DeviceManager::DeviceError DevicePluginConrad::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginConrad::executeAction(Device *device, const Action &action)
{ {
if (!hardwareManager()->radio433()->available()) {
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
QList<int> rawData; QList<int> rawData;
QByteArray binCode; QByteArray binCode;
@ -119,13 +120,13 @@ DeviceManager::DeviceError DevicePluginConrad::executeAction(Device *device, con
// ======================================= // =======================================
// send data to driver // send data to driver
if(transmitData(delay, rawData, repetitions)){ if(hardwareManager()->radio433()->sendData(delay, rawData, repetitions)){
qCDebug(dcConrad) << "Transmitted successfully" << device->name() << action.actionTypeId(); qCDebug(dcConrad) << "Transmitted successfully" << device->name() << action.actionTypeId();
return DeviceManager::DeviceErrorNoError;
}else{ }else{
qCWarning(dcConrad) << "Could not transmitt" << pluginName() << device->name() << action.actionTypeId(); qCWarning(dcConrad) << "Could not transmitt" << pluginName() << device->name() << action.actionTypeId();
return DeviceManager::DeviceErrorHardwareNotAvailable; return DeviceManager::DeviceErrorHardwareNotAvailable;
} }
return DeviceManager::DeviceErrorNoError;
} }
void DevicePluginConrad::radioData(const QList<int> &rawData) void DevicePluginConrad::radioData(const QList<int> &rawData)

View File

@ -36,9 +36,8 @@ class DevicePluginConrad : public DevicePlugin
public: public:
explicit DevicePluginConrad(); explicit DevicePluginConrad();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void radioData(const QList<int> &rawData) override; void radioData(const QList<int> &rawData);
public slots: public slots:

View File

@ -96,6 +96,8 @@
#include "plugin/device.h" #include "plugin/device.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "hardwaremanager.h"
#include "network/networkaccessmanager.h"
#include <QJsonDocument> #include <QJsonDocument>
#include <QUrlQuery> #include <QUrlQuery>
@ -118,11 +120,6 @@ DevicePluginDateTime::DevicePluginDateTime() :
connect(m_timer, &QTimer::timeout, this, &DevicePluginDateTime::onSecondChanged); connect(m_timer, &QTimer::timeout, this, &DevicePluginDateTime::onSecondChanged);
} }
DeviceManager::HardwareResources DevicePluginDateTime::requiredHardware() const
{
return DeviceManager::HardwareResourceNetworkManager;
}
DeviceManager::DeviceSetupStatus DevicePluginDateTime::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginDateTime::setupDevice(Device *device)
{ {
// check timezone // check timezone
@ -243,28 +240,6 @@ DeviceManager::DeviceError DevicePluginDateTime::executeAction(Device *device, c
return DeviceManager::DeviceErrorNoError; return DeviceManager::DeviceErrorNoError;
} }
void DevicePluginDateTime::networkManagerReplyReady(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (m_locationReplies.contains(reply)) {
m_locationReplies.removeAll(reply);
if (status != 200) {
qCWarning(dcDateTime) << "Http error status for location request:" << status << reply->error();
} else {
processGeoLocationData(reply->readAll());
}
} else if (m_timeReplies.contains(reply)) {
m_timeReplies.removeAll(reply);
if (status != 200) {
qCWarning(dcDateTime) << "Http error status for time request:" << status << reply->error();
} else {
processTimesData(reply->readAll());
}
}
reply->deleteLater();
}
void DevicePluginDateTime::startMonitoringAutoDevices() void DevicePluginDateTime::startMonitoringAutoDevices()
{ {
// foreach (Device *device, myDevices()) { // foreach (Device *device, myDevices()) {
@ -285,9 +260,10 @@ void DevicePluginDateTime::searchGeoLocation()
QNetworkRequest request; QNetworkRequest request;
request.setUrl(QUrl("http://ip-api.com/json")); request.setUrl(QUrl("http://ip-api.com/json"));
qCDebug(dcDateTime) << "Requesting geo location."; qCDebug(dcDateTime()) << "Requesting geo location.";
QNetworkReply *reply = networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginDateTime::onNetworkReplayFinished);
m_locationReplies.append(reply); m_locationReplies.append(reply);
} }
@ -340,7 +316,9 @@ void DevicePluginDateTime::getTimes(const QString &latitude, const QString &long
QNetworkRequest request; QNetworkRequest request;
request.setUrl(url); request.setUrl(url);
QNetworkReply *reply = networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginDateTime::onNetworkReplayFinished);
m_timeReplies.append(reply); m_timeReplies.append(reply);
} }
@ -385,6 +363,30 @@ void DevicePluginDateTime::processTimesData(const QByteArray &data)
updateTimes(); updateTimes();
} }
void DevicePluginDateTime::onNetworkReplayFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (m_locationReplies.contains(reply)) {
m_locationReplies.removeAll(reply);
if (status != 200) {
qCWarning(dcDateTime) << "Http error status for location request:" << status << reply->error();
} else {
processGeoLocationData(reply->readAll());
}
} else if (m_timeReplies.contains(reply)) {
m_timeReplies.removeAll(reply);
if (status != 200) {
qCWarning(dcDateTime) << "Http error status for time request:" << status << reply->error();
} else {
processTimesData(reply->readAll());
}
}
reply->deleteLater();
}
void DevicePluginDateTime::onAlarm() void DevicePluginDateTime::onAlarm()
{ {
Alarm *alarm = static_cast<Alarm *>(sender()); Alarm *alarm = static_cast<Alarm *>(sender());

View File

@ -42,13 +42,11 @@ class DevicePluginDateTime : public DevicePlugin
public: public:
explicit DevicePluginDateTime(); explicit DevicePluginDateTime();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void postSetupDevice(Device *device) override; void postSetupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void startMonitoringAutoDevices() override; void startMonitoringAutoDevices() override;
@ -84,6 +82,7 @@ signals:
void dawn(); void dawn();
private slots: private slots:
void onNetworkReplayFinished();
void onAlarm(); void onAlarm();
void onCountdownTimeout(); void onCountdownTimeout();
void onCountdownRunningChanged(const bool &running); void onCountdownRunningChanged(const bool &running);

34
debian/control vendored
View File

@ -102,21 +102,6 @@ Description: guh.io plugin for denon
This package will install the guh.io plugin for denon This package will install the guh.io plugin for denon
Package: guh-plugin-dollhouse
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
guh-plugins-translations,
Description: guh.io plugin for dollhouse
The guh 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 guh.io plugin for dollhouse
Package: guh-plugin-elgato Package: guh-plugin-elgato
Architecture: any Architecture: any
Depends: ${shlibs:Depends}, Depends: ${shlibs:Depends},
@ -252,21 +237,6 @@ Description: guh.io plugin for lgsmarttv
This package will install the guh.io plugin for lgsmarttv This package will install the guh.io plugin for lgsmarttv
Package: guh-plugin-lircd
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
guh-plugins-translations,
Description: guh.io plugin for lircd
The guh 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 guh.io plugin for lircd
Package: guh-plugin-mailnotification Package: guh-plugin-mailnotification
Architecture: any Architecture: any
Depends: ${shlibs:Depends}, Depends: ${shlibs:Depends},
@ -536,8 +506,7 @@ Description: Plugins for guh IoT server - the default plugin collection
Package: guh-plugins-maker Package: guh-plugins-maker
Section: libs Section: libs
Architecture: all Architecture: all
Depends: guh-plugin-lircd, Depends: guh-plugin-commandlauncher,
guh-plugin-commandlauncher,
guh-plugin-udpcommander, guh-plugin-udpcommander,
guh-plugin-tcpcommander, guh-plugin-tcpcommander,
guh-plugin-genericelements, guh-plugin-genericelements,
@ -557,7 +526,6 @@ Package: guh-plugins-merkurboard
Section: libs Section: libs
Architecture: all Architecture: all
Depends: guh-plugin-osdomotics, Depends: guh-plugin-osdomotics,
guh-plugin-dollhouse,
guh-plugin-plantcare, guh-plugin-plantcare,
guh-plugin-ws2812, guh-plugin-ws2812,
guh-plugin-orderbutton, guh-plugin-orderbutton,

View File

@ -1 +0,0 @@
usr/lib/@DEB_HOST_MULTIARCH@/guh/plugins/libguh_deviceplugindollhouse.so

View File

@ -1 +0,0 @@
usr/lib/@DEB_HOST_MULTIARCH@/guh/plugins/libguh_devicepluginlircd.so

View File

@ -51,9 +51,15 @@ DevicePluginDenon::DevicePluginDenon()
} }
DeviceManager::HardwareResources DevicePluginDenon::requiredHardware() const DevicePluginDenon::~DevicePluginDenon()
{ {
return DeviceManager::HardwareResourceTimer; hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginDenon::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(15);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginDenon::onPluginTimer);
} }
DeviceManager::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device)
@ -96,19 +102,6 @@ void DevicePluginDenon::deviceRemoved(Device *device)
m_denonConnection->deleteLater(); m_denonConnection->deleteLater();
} }
void DevicePluginDenon::guhTimer()
{
if (m_denonConnection.isNull())
return;
if (!m_denonConnection->connected()) {
m_denonConnection->connectDenon();
} else {
m_denonConnection->sendData("PW?\rSI?\rMV?\r");
}
}
DeviceManager::DeviceError DevicePluginDenon::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginDenon::executeAction(Device *device, const Action &action)
{ {
qCDebug(dcDenon) << "Execute action" << device->id() << action.id() << action.params(); qCDebug(dcDenon) << "Execute action" << device->id() << action.id() << action.params();
@ -163,6 +156,18 @@ DeviceManager::DeviceError DevicePluginDenon::executeAction(Device *device, cons
return DeviceManager::DeviceErrorDeviceClassNotFound; return DeviceManager::DeviceErrorDeviceClassNotFound;
} }
void DevicePluginDenon::onPluginTimer()
{
if (m_denonConnection.isNull())
return;
if (!m_denonConnection->connected()) {
m_denonConnection->connectDenon();
} else {
m_denonConnection->sendData("PW?\rSI?\rMV?\r");
}
}
void DevicePluginDenon::onConnectionChanged() void DevicePluginDenon::onConnectionChanged()
{ {
if (!m_device) if (!m_device)

View File

@ -34,6 +34,7 @@
#include <QHostAddress> #include <QHostAddress>
#include <QNetworkReply> #include <QNetworkReply>
#include "plugintimer.h"
#include "denonconnection.h" #include "denonconnection.h"
class DevicePluginDenon : public DevicePlugin class DevicePluginDenon : public DevicePlugin
@ -45,15 +46,15 @@ class DevicePluginDenon : public DevicePlugin
public: public:
explicit DevicePluginDenon(); explicit DevicePluginDenon();
~DevicePluginDenon();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void guhTimer() override;
private: private:
PluginTimer *m_pluginTimer = nullptr;
QPointer<Device> m_device; QPointer<Device> m_device;
QPointer<DenonConnection> m_denonConnection; QPointer<DenonConnection> m_denonConnection;
QList<DenonConnection *> m_asyncSetups; QList<DenonConnection *> m_asyncSetups;
@ -62,6 +63,7 @@ private:
QHash <QNetworkReply *, ActionId> m_asyncActionReplies; QHash <QNetworkReply *, ActionId> m_asyncActionReplies;
private slots: private slots:
void onPluginTimer();
void onConnectionChanged(); void onConnectionChanged();
void onDataReceived(const QByteArray &data); void onDataReceived(const QByteArray &data);
void onSocketError(); void onSocketError();

View File

@ -1,396 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
* *
* This file is part of guh. *
* *
* 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 dollhouse.html
\title Dollhouse
\brief Plugin for a guh demo booth based on 6LoWPAN networking.
\ingroup plugins
\ingroup guh-plugins-merkur
The plugin for the guh-dollhouse demo booth.
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
\quotefile plugins/deviceplugins/dollhouse/deviceplugindollhouse.json
*/
#include "deviceplugindollhouse.h"
#include "plugininfo.h"
#include <QUrlQuery>
DevicePluginDollHouse::DevicePluginDollHouse() :
m_houseReachable(false)
{
m_coap = new Coap(this);
connect(m_coap, SIGNAL(replyFinished(CoapReply*)), this, SLOT(coapReplyFinished(CoapReply*)));
}
DeviceManager::HardwareResources DevicePluginDollHouse::requiredHardware() const
{
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer;
}
DeviceManager::DeviceSetupStatus DevicePluginDollHouse::setupDevice(Device *device)
{
qCDebug(dcDollhouse) << "Setup" << device->name() << device->params();
if (device->deviceClassId() == connectionDeviceClassId) {
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == connectionDeviceClassId) {
qCWarning(dcDollhouse) << "Dollhouse connection allready configured.";
return DeviceManager::DeviceSetupStatusFailure;
}
}
int lookupId = QHostInfo::lookupHost(device->paramValue(rplParamTypeId).toString(), this, SLOT(hostLockupFinished(QHostInfo)));
m_asyncSetup.insert(lookupId, device);
return DeviceManager::DeviceSetupStatusAsync;
} else if (device->deviceClassId() == lightDeviceClassId) {
DollhouseLight *light = new DollhouseLight(this);
light->setName(device->paramValue(nameParamTypeId).toString());
light->setHostAddress(device->paramValue(addressParamTypeId).toString());
light->setConnectionUuid(device->paramValue(connectionUuidParamTypeId).toString());
light->setLightId(device->paramValue(lightIdParamTypeId).toInt());
device->setParentId(DeviceId(light->connectionUuid()));
m_lights.insert(device, light);
return DeviceManager::DeviceSetupStatusSuccess;
}
return DeviceManager::DeviceSetupStatusFailure;
}
void DevicePluginDollHouse::deviceRemoved(Device *device)
{
if (device->deviceClassId() == lightDeviceClassId) {
DollhouseLight *light = m_lights.take(device);
light->deleteLater();
}
m_houseAddress.clear();
m_houseReachable = false;
}
void DevicePluginDollHouse::guhTimer()
{
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == connectionDeviceClassId && m_houseAddress.isNull()) {
scanNodes(device);
}
}
if (!m_houseAddress.isNull()) {
QUrl url;
url.setScheme("coap");
url.setHost(m_houseAddress.toString());
url.setPort(5683);
url.setPath("/a/ws2812");
m_asyncPings.append(m_coap->ping(CoapRequest(url)));
}
}
DeviceManager::DeviceError DevicePluginDollHouse::executeAction(Device *device, const Action &action)
{
if (device->deviceClassId() == lightDeviceClassId) {
if (!device->stateValue(reachableStateTypeId).toBool())
return DeviceManager::DeviceErrorHardwareNotAvailable;
DollhouseLight *light = m_lights.value(device);
// Create URL for action
QUrlQuery query;
query.addQueryItem("number", QString::number(light->lightId()));
QUrl url;
url.setScheme("coap");
url.setHost(device->paramValue(addressParamTypeId).toString());
url.setPath("/a/ws2812");
url.setQuery(query);
if (action.actionTypeId() == colorActionTypeId) {
QColor color = action.param(colorStateParamTypeId).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();
qCDebug(dcDollhouse) << "Sending" << url.toString() << message;
CoapReply *reply = m_coap->post(CoapRequest(url), message);
m_asyncActions.insert(reply, action);
m_asyncActionLights.insert(action.id(), light);
return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == powerActionTypeId) {
QByteArray message;
if (action.param(powerStateParamTypeId).value().toBool()) {
QColor color = light->color().toHsv();
QColor newColor = QColor::fromHsv(color.hue(), color.saturation(), 100 * light->brightness() / 255.0);
message = "color=" + newColor.toRgb().name().remove("#").toUtf8();
} else {
message.append("color=000000");
}
qCDebug(dcDollhouse) << "Sending" << url.toString() << message;
CoapReply *reply = m_coap->post(CoapRequest(url), message);
m_asyncActions.insert(reply, action);
m_asyncActionLights.insert(action.id(), light);
return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == brightnessActionTypeId) {
int brightness = action.param(brightnessStateParamTypeId).value().toInt();
QColor color = light->color().toHsv();
QColor newColor = QColor::fromHsv(color.hue(), color.saturation(), 100 * brightness / 255.0);
QByteArray message = "color=" + newColor.toRgb().name().remove("#").toUtf8();
qCDebug(dcDollhouse) << "Sending" << url.toString() << message;
CoapReply *reply = m_coap->post(CoapRequest(url), message);
m_asyncActions.insert(reply, action);
m_asyncActionLights.insert(action.id(), light);
return DeviceManager::DeviceErrorAsync;
}
}
return DeviceManager::DeviceErrorNoError;
}
void DevicePluginDollHouse::networkManagerReplyReady(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// create user finished
if (m_asyncNodeScan.contains(reply)) {
Device *device = m_asyncNodeScan.take(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcDollhouse) << "Node scan reply HTTP error:" << reply->errorString();
reply->deleteLater();
return;
}
parseNode(device, reply->readAll());
}
reply->deleteLater();
}
void DevicePluginDollHouse::scanNodes(Device *device)
{
QUrl url;
url.setScheme("http");
url.setHost(device->paramValue(rplParamTypeId).toString());
QNetworkReply *reply = networkManagerGet(QNetworkRequest(url));
m_asyncNodeScan.insert(reply, device);
}
void DevicePluginDollHouse::parseNode(Device *device, const QByteArray &data)
{
QList<QByteArray> lines = data.split('\n');
QList<QHostAddress> addresses;
foreach (const QByteArray &line, lines) {
if (line.isEmpty())
continue;
// remove the '/128' from the address
QHostAddress address(QString(data.left(line.length() - 4)));
if (!address.isNull())
addresses.append(address);
}
// int index = data.indexOf("Routes<pre>") + 11;
// int delta = data.indexOf("/128",index);
// QHostAddress houseAddress = QHostAddress(QString(data.mid(index, delta - index)));
if (addresses.isEmpty())
return;
QHostAddress houseAddress = addresses.first();
if (houseAddress != m_houseAddress && !houseAddress.isNull()) {
m_houseAddress = houseAddress;
qCDebug(dcDollhouse) << "Found house at" << m_houseAddress.toString();
if (!m_lights.isEmpty())
return;
QList<DeviceDescriptor> deviceDescriptorList;
for (int i = 0; i < 5; i++) {
DeviceDescriptor descriptor(lightDeviceClassId, "Light", QString::number(i));
ParamList params;
params.append(Param(addressParamTypeId, m_houseAddress.toString()));
params.append(Param(lightIdParamTypeId, i));
params.append(Param(connectionUuidParamTypeId, device->id()));
switch (i) {
case 0:
params.append(Param(nameParamTypeId, "Living room"));
break;
case 1:
params.append(Param(nameParamTypeId, "Kitchen"));
break;
case 2:
params.append(Param(nameParamTypeId, "Under the bed"));
break;
case 3:
params.append(Param(nameParamTypeId, "Bedroom"));
break;
case 4:
params.append(Param(nameParamTypeId, "Dining room"));
break;
default:
params.append(Param(nameParamTypeId, QString("Light %1").arg(QString::number(i))));
break;
}
descriptor.setParams(params);
deviceDescriptorList.append(descriptor);
}
if (!deviceDescriptorList.isEmpty())
emit autoDevicesAppeared(lightDeviceClassId, deviceDescriptorList);
}
}
void DevicePluginDollHouse::hostLockupFinished(const QHostInfo &info)
{
Device *device = m_asyncSetup.value(info.lookupId());
if (!device)
return;
if (info.error() != QHostInfo::NoError) {
qCWarning(dcDollhouse) << "Could not look up host" << info.hostName() << info.errorString();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
}
qCDebug(dcDollhouse) << "Looked up successfully" << info.hostName();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
scanNodes(device);
}
void DevicePluginDollHouse::coapReplyFinished(CoapReply *reply)
{
if (m_asyncPings.contains(reply)) {
m_asyncPings.removeAll(reply);
if (reply->error() != CoapReply::NoError || reply->statusCode() != CoapPdu::Empty) {
if (m_houseReachable) {
qCWarning(dcDollhouse) << "Could not ping Dollhouse:" << reply->errorString();
m_houseReachable = false;
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == lightDeviceClassId) {
device->setStateValue(reachableStateTypeId, m_houseReachable);
}
}
}
} else {
if (!m_houseReachable) {
qCDebug(dcDollhouse) << "Dollhouse reachable";
m_houseReachable = true;
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == lightDeviceClassId) {
device->setStateValue(reachableStateTypeId, m_houseReachable);
}
}
}
}
} else if (m_asyncActions.contains(reply)) {
Action action = m_asyncActions.take(reply);
DollhouseLight *light = m_asyncActionLights.take(action.id());
if (reply->error() != CoapReply::NoError) {
qCWarning(dcDollhouse) << "Got action response with error" << reply->errorString();
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorHardwareFailure);
reply->deleteLater();
return;
}
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcDollhouse) << "Got action response with status code" << reply;
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorHardwareFailure);
reply->deleteLater();
return;
}
emit actionExecutionFinished(action.id(), DeviceManager::DeviceErrorNoError);
// Set the states
if (action.actionTypeId() == powerActionTypeId) {
bool power = action.param(powerStateParamTypeId).value().toBool();
light->setPower(power);
m_lights.key(light)->setStateValue(powerStateTypeId, power);
} else if (action.actionTypeId() == colorActionTypeId) {
if (!light->power()) {
light->setPower(true);
m_lights.key(light)->setStateValue(powerStateTypeId, true);
}
QColor color = action.param(colorStateParamTypeId).value().value<QColor>();
light->setColor(color);
m_lights.key(light)->setStateValue(colorStateTypeId, color);
} else if (action.actionTypeId() == brightnessActionTypeId) {
if (!light->power()) {
light->setPower(true);
m_lights.key(light)->setStateValue(powerStateTypeId, true);
}
int brightness = action.param(brightnessStateParamTypeId).value().toInt();
light->setBrightness(brightness);
m_lights.key(light)->setStateValue(brightnessStateTypeId, brightness);
}
}
reply->deleteLater();
}

View File

@ -1,76 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
* *
* This file is part of guh. *
* *
* 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 DEVICEPLUGINDOLLHOUSE_H
#define DEVICEPLUGINDOLLHOUSE_H
#include "plugin/deviceplugin.h"
#include "devicemanager.h"
#include "coap/coap.h"
#include "dollhouselight.h"
#include <QHash>
class DevicePluginDollHouse : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "deviceplugindollhouse.json")
Q_INTERFACES(DevicePlugin)
public:
DevicePluginDollHouse();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void guhTimer() override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
private:
Coap *m_coap;
QHash<int, Device *> m_asyncSetup;
QHash<QNetworkReply *, Device *> m_asyncNodeScan;
QHash<CoapReply *, Action> m_asyncActions;
QHash<ActionId, DollhouseLight *> m_asyncActionLights;
QList<CoapReply *> m_asyncPings;
QHostAddress m_houseAddress;
bool m_houseReachable;
QHash<Device *, DollhouseLight *> m_lights;
void scanNodes(Device *device);
void parseNode(Device *device, const QByteArray &data);
private slots:
void hostLockupFinished(const QHostInfo &info);
void coapReplyFinished(CoapReply *reply);
};
#endif // DEVICEPLUGINDOLLHOUSE_H

View File

@ -1,126 +0,0 @@
{
"name": "Smart Dollhouse",
"idName": "Dollhouse",
"id": "ee62716c-64b5-4ec5-a877-9a8d9c1042cb",
"vendors": [
{
"name": "guh",
"idName": "guh",
"id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
"deviceClasses": [
{
"name": "Dollhouse Connection",
"idName": "connection",
"id": "44e12a1c-9711-4780-9913-53bb38264e1e",
"createMethods": ["user"],
"interfaces": ["gateway"],
"basicTags": [
"Device",
"Gateway"
],
"paramTypes": [
{
"id": "2015e286-4268-4a12-912f-7d70bf2d0bab",
"idName": "rpl",
"name": "RPL address",
"type": "QString",
"inputType": "TextLine",
"defaultValue": "fdaa:e9b8:d03a::ff:fe00:1"
}
]
},
{
"name": "Dollhouse Light",
"idName": "light",
"id": "b4dd5f10-36d4-4232-867a-6d3b04a08bad",
"createMethods": ["auto"],
"criticalStateTypeId": "93c539b4-50d8-431e-8be4-5ebba89452b7",
"primaryActionTypeId": "f6ac30a0-77b8-4f1f-8c44-4c2e6d542663",
"interfaces": ["colorlight"],
"basicTags": [
"Device",
"Lighting"
],
"paramTypes": [
{
"id": "49d3ae89-d76d-4e4c-b1ad-67f5c8f96e52",
"idName": "name",
"name": "name",
"type": "QString",
"defaultValue": "Dollhouse Light"
},
{
"id": "37d5d2fa-dea2-4007-99b1-a1300025c709",
"idName": "address",
"name": "address",
"type": "QString"
},
{
"id": "c843c179-ab02-4aa8-a228-fdc8d9558f1d",
"idName": "lightId",
"name": "light id",
"type": "int",
"defaultValue": 0,
"readOnly": true
},
{
"id": "2bf1d5d5-1f40-4dca-9acd-2909016e4a2b",
"idName": "connectionUuid",
"name": "connection uuid",
"type": "QString",
"inputType": "TextLine",
"readOnly": true
}
],
"stateTypes": [
{
"id": "e4885a73-9fe1-48ca-b773-aeb93f34cd54",
"idName": "color",
"name": "color",
"eventTypeName": "color changed",
"actionTypeName": "Set color",
"type": "QColor",
"defaultValue": "#fff30a",
"ruleRelevant": false,
"eventRuleRelevant": false,
"writable": true
},
{
"id": "e78c9136-c10a-45c9-b6bc-2d937f09cdec",
"idName": "brightness",
"name": "brightness",
"eventTypeName": "brightness changed",
"actionTypeName": "Set brightness",
"type": "int",
"unit": "Percentage",
"minValue": 0,
"maxValue": 100,
"defaultValue": 100,
"ruleRelevant": false,
"eventRuleRelevant": false,
"writable": true
},
{
"id": "f6ac30a0-77b8-4f1f-8c44-4c2e6d542663",
"idName": "power",
"name": "power",
"eventTypeName": "power changed",
"actionTypeName": "Set power",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "93c539b4-50d8-431e-8be4-5ebba89452b7",
"idName": "reachable",
"name": "reachable",
"eventTypeName": "reachable changed",
"type": "bool",
"defaultValue": false
}
]
}
]
}
]
}

View File

@ -1,15 +0,0 @@
TRANSLATIONS = translations/en_US.ts \
translations/de_DE.ts
# Note: include after the TRANSLATIONS definition
include(../plugins.pri)
TARGET = $$qtLibraryTarget(guh_deviceplugindollhouse)
SOURCES += \
deviceplugindollhouse.cpp \
dollhouselight.cpp
HEADERS += \
deviceplugindollhouse.h \
dollhouselight.h

View File

@ -1,103 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
* *
* This file is part of guh. *
* *
* 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "dollhouselight.h"
DollhouseLight::DollhouseLight(QObject *parent) :
QObject(parent),
m_color(QColor("#fff30a")),
m_brightness(100),
m_power(false)
{
}
QString DollhouseLight::name() const
{
return m_name;
}
void DollhouseLight::setName(const QString &name)
{
m_name = name;
}
QString DollhouseLight::connectionUuid() const
{
return m_connectionUuid;
}
void DollhouseLight::setConnectionUuid(const QString &connectionUuid)
{
m_connectionUuid = connectionUuid;
}
QString DollhouseLight::hostAddress() const
{
return m_hostAddress;
}
void DollhouseLight::setHostAddress(const QString &address)
{
m_hostAddress = address;
}
int DollhouseLight::lightId() const
{
return m_lightId;
}
void DollhouseLight::setLightId(const int &lightId)
{
m_lightId = lightId;
}
QColor DollhouseLight::color() const
{
return m_color;
}
void DollhouseLight::setColor(const QColor &color)
{
m_color = color;
}
int DollhouseLight::brightness() const
{
return m_brightness;
}
void DollhouseLight::setBrightness(const int &brightness)
{
m_brightness = brightness;
}
bool DollhouseLight::power() const
{
return m_power;
}
void DollhouseLight::setPower(const bool &power)
{
m_power = power;
}

View File

@ -1,69 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
* *
* This file is part of guh. *
* *
* 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 DOLLHOUSELIGHT_H
#define DOLLHOUSELIGHT_H
#include <QObject>
#include <QColor>
class DollhouseLight : public QObject
{
Q_OBJECT
public:
explicit DollhouseLight(QObject *parent = 0);
QString name() const;
void setName(const QString &name);
QString connectionUuid() const;
void setConnectionUuid(const QString &connectionUuid);
QString hostAddress() const;
void setHostAddress(const QString &address);
int lightId() const;
void setLightId(const int &lightId);
// properties
QColor color() const;
void setColor(const QColor &color);
int brightness() const;
void setBrightness(const int &brightness);
bool power() const;
void setPower(const bool &power);
private:
QString m_name;
QString m_connectionUuid;
QString m_hostAddress;
int m_lightId;
QColor m_color;
int m_brightness;
bool m_power;
};
#endif // DOLLHOUSELIGHT_H

View File

@ -43,6 +43,8 @@
#include "devicepluginelro.h" #include "devicepluginelro.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "hardware/radio433/radio433.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -51,13 +53,10 @@ DevicePluginElro::DevicePluginElro()
{ {
} }
DeviceManager::HardwareResources DevicePluginElro::requiredHardware() const
{
return DeviceManager::HardwareResourceRadio433;
}
DeviceManager::DeviceError DevicePluginElro::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginElro::executeAction(Device *device, const Action &action)
{ {
if (!hardwareManager()->isAvailable(HardwareResource::TypeRadio433))
return DeviceManager::DeviceErrorHardwareNotAvailable;
if (action.actionTypeId() != powerActionTypeId) if (action.actionTypeId() != powerActionTypeId)
return DeviceManager::DeviceErrorActionTypeNotFound; return DeviceManager::DeviceErrorActionTypeNotFound;
@ -146,13 +145,14 @@ DeviceManager::DeviceError DevicePluginElro::executeAction(Device *device, const
} }
// send data to hardware resource // send data to hardware resource
if (transmitData(delay, rawData)) { if (hardwareManager()->radio433()->sendData(delay, rawData, 10)) {
qCDebug(dcElro) << "Transmitted" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool(); qCDebug(dcElro) << "Transmitted" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool();
return DeviceManager::DeviceErrorNoError;
} else { } else {
qCWarning(dcElro) << "Could not transmitt" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool(); qCWarning(dcElro) << "Could not transmitt" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool();
return DeviceManager::DeviceErrorHardwareNotAvailable; return DeviceManager::DeviceErrorHardwareNotAvailable;
} }
return DeviceManager::DeviceErrorNoError;
} }
void DevicePluginElro::radioData(const QList<int> &rawData) void DevicePluginElro::radioData(const QList<int> &rawData)

View File

@ -35,8 +35,7 @@ class DevicePluginElro : public DevicePlugin
public: public:
explicit DevicePluginElro(); explicit DevicePluginElro();
DeviceManager::HardwareResources requiredHardware() const override; void radioData(const QList<int> &rawData);
void radioData(const QList<int> &rawData) override;
public slots: public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;

View File

@ -73,14 +73,21 @@
DevicePluginEQ3::DevicePluginEQ3() DevicePluginEQ3::DevicePluginEQ3()
{ {
m_cubeDiscovery = new MaxCubeDiscovery(this);
connect(m_cubeDiscovery,SIGNAL(cubesDetected(QList<MaxCube*>)),this,SLOT(discoveryDone(QList<MaxCube*>)));
} }
DeviceManager::HardwareResources DevicePluginEQ3::requiredHardware() const DevicePluginEQ3::~DevicePluginEQ3()
{ {
return DeviceManager::HardwareResourceTimer; hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginEQ3::init()
{
m_cubeDiscovery = new MaxCubeDiscovery(this);
connect(m_cubeDiscovery, &MaxCubeDiscovery::cubesDetected, this, &DevicePluginEQ3::discoveryDone);
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginEQ3::onPluginTimer);
} }
DeviceManager::DeviceError DevicePluginEQ3::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) DeviceManager::DeviceError DevicePluginEQ3::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
@ -145,15 +152,6 @@ void DevicePluginEQ3::deviceRemoved(Device *device)
cube->deleteLater(); cube->deleteLater();
} }
void DevicePluginEQ3::guhTimer()
{
foreach (MaxCube *cube, m_cubes.keys()){
if(cube->isConnected() && cube->isInitialized()){
cube->refresh();
}
}
}
DeviceManager::DeviceError DevicePluginEQ3::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginEQ3::executeAction(Device *device, const Action &action)
{ {
if(device->deviceClassId() == wallThermostateDeviceClassId || device->deviceClassId() == radiatorThermostateDeviceClassId){ if(device->deviceClassId() == wallThermostateDeviceClassId || device->deviceClassId() == radiatorThermostateDeviceClassId){
@ -182,6 +180,15 @@ DeviceManager::DeviceError DevicePluginEQ3::executeAction(Device *device, const
return DeviceManager::DeviceErrorActionTypeNotFound; return DeviceManager::DeviceErrorActionTypeNotFound;
} }
void DevicePluginEQ3::onPluginTimer()
{
foreach (MaxCube *cube, m_cubes.keys()){
if(cube->isConnected() && cube->isInitialized()){
cube->refresh();
}
}
}
void DevicePluginEQ3::cubeConnectionStatusChanged(const bool &connected) void DevicePluginEQ3::cubeConnectionStatusChanged(const bool &connected)
{ {
if(connected){ if(connected){

View File

@ -25,6 +25,7 @@
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "maxcubediscovery.h" #include "maxcubediscovery.h"
#include "plugintimer.h"
#include <QHostAddress> #include <QHostAddress>
@ -39,25 +40,27 @@ class DevicePluginEQ3: public DevicePlugin
public: public:
explicit DevicePluginEQ3(); explicit DevicePluginEQ3();
~DevicePluginEQ3();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
void startMonitoringAutoDevices() override; void startMonitoringAutoDevices() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void guhTimer() override;
private: private:
PluginTimer *m_pluginTimer = nullptr;
QList<Param> m_config; QList<Param> m_config;
MaxCubeDiscovery *m_cubeDiscovery; MaxCubeDiscovery *m_cubeDiscovery = nullptr;
QHash<MaxCube*, Device*> m_cubes; QHash<MaxCube *, Device *> m_cubes;
public slots: public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action); DeviceManager::DeviceError executeAction(Device *device, const Action &action);
private slots: private slots:
void onPluginTimer();
void cubeConnectionStatusChanged(const bool &connected); void cubeConnectionStatusChanged(const bool &connected);
void discoveryDone(const QList<MaxCube *> &cubeList); void discoveryDone(const QList<MaxCube *> &cubeList);
void commandActionFinished(const bool &succeeded, const ActionId &actionId); void commandActionFinished(const bool &succeeded, const ActionId &actionId);

View File

@ -62,11 +62,6 @@ DevicePluginGenericElements::DevicePluginGenericElements()
{ {
} }
DeviceManager::HardwareResources DevicePluginGenericElements::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
DeviceManager::DeviceSetupStatus DevicePluginGenericElements::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginGenericElements::setupDevice(Device *device)
{ {
// Toggle Button // Toggle Button

View File

@ -34,11 +34,8 @@ class DevicePluginGenericElements : public DevicePlugin
public: public:
explicit DevicePluginGenericElements(); explicit DevicePluginGenericElements();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
public slots: public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;

View File

@ -211,11 +211,6 @@ DeviceManager::DeviceError DevicePluginGpio::discoverDevices(const DeviceClassId
return DeviceManager::DeviceErrorVendorNotFound; return DeviceManager::DeviceErrorVendorNotFound;
} }
DeviceManager::HardwareResources DevicePluginGpio::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
void DevicePluginGpio::deviceRemoved(Device *device) void DevicePluginGpio::deviceRemoved(Device *device)
{ {
if (m_gpioDevices.values().contains(device)) { if (m_gpioDevices.values().contains(device)) {

View File

@ -41,7 +41,6 @@ public:
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::HardwareResources requiredHardware() const override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;

View File

@ -6,7 +6,6 @@ PLUGIN_DIRS = \
networkdetector \ networkdetector \
conrad \ conrad \
openweathermap \ openweathermap \
lircd \
wakeonlan \ wakeonlan \
mailnotification \ mailnotification \
philipshue \ philipshue \
@ -21,17 +20,16 @@ PLUGIN_DIRS = \
udpcommander \ udpcommander \
tcpcommander \ tcpcommander \
kodi \ kodi \
elgato \ #elgato \
awattar \ awattar \
netatmo \ netatmo \
dollhouse \
plantcare \ plantcare \
osdomotics \ osdomotics \
ws2812 \ ws2812 \
orderbutton \ orderbutton \
denon \ denon \
avahimonitor \ avahimonitor \
senic \ #senic \
gpio \ gpio \

View File

@ -44,6 +44,7 @@
#include "plugin/device.h" #include "plugin/device.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "hardware/radio433/radio433.h"
#include "plugininfo.h" #include "plugininfo.h"
#include <QDebug> #include <QDebug>
@ -51,15 +52,15 @@
DevicePluginIntertechno::DevicePluginIntertechno() DevicePluginIntertechno::DevicePluginIntertechno()
{ {
} }
DeviceManager::HardwareResources DevicePluginIntertechno::requiredHardware() const
{
return DeviceManager::HardwareResourceRadio433;
}
DeviceManager::DeviceError DevicePluginIntertechno::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginIntertechno::executeAction(Device *device, const Action &action)
{ {
if (!hardwareManager()->isAvailable(HardwareResource::TypeRadio433))
return DeviceManager::DeviceErrorHardwareNotAvailable;
QList<int> rawData; QList<int> rawData;
QByteArray binCode; QByteArray binCode;
@ -175,13 +176,13 @@ DeviceManager::DeviceError DevicePluginIntertechno::executeAction(Device *device
// ======================================= // =======================================
// send data to hardware resource // send data to hardware resource
if (transmitData(delay, rawData)) { if (hardwareManager()->radio433()->sendData(delay, rawData, 10)) {
qCDebug(dcIntertechno) << "transmitted" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool(); qCDebug(dcIntertechno) << "transmitted" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool();
return DeviceManager::DeviceErrorNoError;
} else { } else {
qCWarning(dcIntertechno) << "could not transmitt" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool(); qCWarning(dcIntertechno) << "could not transmitt" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool();
return DeviceManager::DeviceErrorHardwareNotAvailable; return DeviceManager::DeviceErrorHardwareNotAvailable;
} }
return DeviceManager::DeviceErrorNoError;
} }
void DevicePluginIntertechno::radioData(const QList<int> &rawData) void DevicePluginIntertechno::radioData(const QList<int> &rawData)

View File

@ -35,8 +35,7 @@ class DevicePluginIntertechno : public DevicePlugin
public: public:
explicit DevicePluginIntertechno(); explicit DevicePluginIntertechno();
DeviceManager::HardwareResources requiredHardware() const override; void radioData(const QList<int> &rawData);
void radioData(const QList<int> &rawData) override;
public slots: public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;

View File

@ -64,6 +64,7 @@
#include "devicepluginkodi.h" #include "devicepluginkodi.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/upnp/upnpdiscovery.h"
DevicePluginKodi::DevicePluginKodi() DevicePluginKodi::DevicePluginKodi()
{ {
@ -79,12 +80,18 @@ DevicePluginKodi::DevicePluginKodi()
// qCWarning(dcKodi) << "could not read" << file.fileName(); // qCWarning(dcKodi) << "could not read" << file.fileName();
// return; // return;
// } // }
// m_logo = guhLogoByteArray; // m_logo = guhLogoByteArray;
} }
DeviceManager::HardwareResources DevicePluginKodi::requiredHardware() const DevicePluginKodi::~DevicePluginKodi()
{ {
return DeviceManager::HardwareResourceTimer | DeviceManager::HardwareResourceUpnpDisovery; hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginKodi::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginKodi::onPluginTimer);
} }
DeviceManager::DeviceSetupStatus DevicePluginKodi::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginKodi::setupDevice(Device *device)
@ -117,59 +124,18 @@ void DevicePluginKodi::deviceRemoved(Device *device)
kodi->deleteLater(); kodi->deleteLater();
} }
void DevicePluginKodi::guhTimer()
{
foreach (Kodi *kodi, m_kodis.keys()) {
if (!kodi->connected()) {
kodi->connectKodi();
continue;
} else {
// no need for polling information, notifications do the job
//kodi->update();
}
}
}
DeviceManager::DeviceError DevicePluginKodi::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) DeviceManager::DeviceError DevicePluginKodi::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{ {
Q_UNUSED(params) Q_UNUSED(params)
Q_UNUSED(deviceClassId) Q_UNUSED(deviceClassId)
qCDebug(dcKodi) << "Start UPnP search"; qCDebug(dcKodi) << "Start UPnP search";
upnpDiscover(); UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices();
connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginKodi::onUpnpDiscoveryFinished);
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
void DevicePluginKodi::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList)
{
QList<DeviceDescriptor> deviceDescriptors;
foreach (const UpnpDeviceDescriptor &upnpDescriptor, upnpDeviceDescriptorList) {
if (upnpDescriptor.modelName().contains("Kodi")) {
// check if we allready found the kodi on this ip
bool alreadyAdded = false;
foreach (const DeviceDescriptor dDescriptor, deviceDescriptors) {
if (dDescriptor.params().paramValue(ipParamTypeId).toString() == upnpDescriptor.hostAddress().toString()) {
alreadyAdded = true;
break;
}
}
if (alreadyAdded)
continue;
qCDebug(dcKodi) << upnpDescriptor;
DeviceDescriptor deviceDescriptor(kodiDeviceClassId, "Kodi - Media Center", upnpDescriptor.hostAddress().toString());
ParamList params;
params.append(Param(nameParamTypeId, upnpDescriptor.friendlyName()));
params.append(Param(ipParamTypeId, upnpDescriptor.hostAddress().toString()));
params.append(Param(portParamTypeId, 9090));
deviceDescriptor.setParams(params);
deviceDescriptors.append(deviceDescriptor);
}
}
emit devicesDiscovered(kodiDeviceClassId, deviceDescriptors);
}
DeviceManager::DeviceError DevicePluginKodi::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginKodi::executeAction(Device *device, const Action &action)
{ {
if (device->deviceClassId() == kodiDeviceClassId) { if (device->deviceClassId() == kodiDeviceClassId) {
@ -207,6 +173,53 @@ DeviceManager::DeviceError DevicePluginKodi::executeAction(Device *device, const
return DeviceManager::DeviceErrorDeviceClassNotFound; return DeviceManager::DeviceErrorDeviceClassNotFound;
} }
void DevicePluginKodi::onPluginTimer()
{
foreach (Kodi *kodi, m_kodis.keys()) {
if (!kodi->connected()) {
kodi->connectKodi();
continue;
}
}
}
void DevicePluginKodi::onUpnpDiscoveryFinished()
{
qCDebug(dcKodi()) << "Upnp discovery finished";
UpnpDiscoveryReply *reply = static_cast<UpnpDiscoveryReply *>(sender());
if (reply->error() != UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNoError) {
qCWarning(dcKodi()) << "Upnp discovery error" << reply->error();
}
reply->deleteLater();
QList<DeviceDescriptor> deviceDescriptors;
foreach (const UpnpDeviceDescriptor &upnpDescriptor, reply->deviceDescriptors()) {
if (upnpDescriptor.modelName().contains("Kodi")) {
// check if we allready found the kodi on this ip
bool alreadyAdded = false;
foreach (const DeviceDescriptor dDescriptor, deviceDescriptors) {
if (dDescriptor.params().paramValue(ipParamTypeId).toString() == upnpDescriptor.hostAddress().toString()) {
alreadyAdded = true;
break;
}
}
if (alreadyAdded)
continue;
qCDebug(dcKodi) << upnpDescriptor;
DeviceDescriptor deviceDescriptor(kodiDeviceClassId, "Kodi - Media Center", upnpDescriptor.hostAddress().toString());
ParamList params;
params.append(Param(nameParamTypeId, upnpDescriptor.friendlyName()));
params.append(Param(ipParamTypeId, upnpDescriptor.hostAddress().toString()));
params.append(Param(portParamTypeId, 9090));
deviceDescriptor.setParams(params);
deviceDescriptors.append(deviceDescriptor);
}
}
emit devicesDiscovered(kodiDeviceClassId, deviceDescriptors);
}
void DevicePluginKodi::onConnectionChanged() void DevicePluginKodi::onConnectionChanged()
{ {
Kodi *kodi = static_cast<Kodi *>(sender()); Kodi *kodi = static_cast<Kodi *>(sender());

View File

@ -24,6 +24,7 @@
#define DEVICEPLUGINKODI_H #define DEVICEPLUGINKODI_H
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "plugintimer.h"
#include "kodi.h" #include "kodi.h"
#include <QHash> #include <QHash>
@ -38,23 +39,22 @@ class DevicePluginKodi : public DevicePlugin
public: public:
explicit DevicePluginKodi(); explicit DevicePluginKodi();
~DevicePluginKodi();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void guhTimer() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private: private:
PluginTimer *m_pluginTimer;
QHash<Kodi *, Device *> m_kodis; QHash<Kodi *, Device *> m_kodis;
QList<Kodi *> m_asyncSetups; QList<Kodi *> m_asyncSetups;
private slots: private slots:
void onPluginTimer();
void onUpnpDiscoveryFinished();
void onConnectionChanged(); void onConnectionChanged();
void onStateChanged(); void onStateChanged();
void onActionExecuted(const ActionId &actionId, const bool &success); void onActionExecuted(const ActionId &actionId, const bool &success);

View File

@ -49,6 +49,7 @@
#include "devicepluginleynew.h" #include "devicepluginleynew.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "hardware/radio433/radio433.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -64,13 +65,11 @@ DeviceManager::DeviceSetupStatus DevicePluginLeynew::setupDevice(Device *device)
return DeviceManager::DeviceSetupStatusSuccess; return DeviceManager::DeviceSetupStatusSuccess;
} }
DeviceManager::HardwareResources DevicePluginLeynew::requiredHardware() const
{
return DeviceManager::HardwareResourceRadio433;
}
DeviceManager::DeviceError DevicePluginLeynew::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginLeynew::executeAction(Device *device, const Action &action)
{ {
if (!hardwareManager()->radio433()->available()) {
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
if (device->deviceClassId() != rfControllerDeviceClassId) { if (device->deviceClassId() != rfControllerDeviceClassId) {
return DeviceManager::DeviceErrorDeviceClassNotFound; return DeviceManager::DeviceErrorDeviceClassNotFound;
@ -170,11 +169,11 @@ DeviceManager::DeviceError DevicePluginLeynew::executeAction(Device *device, con
// ======================================= // =======================================
// send data to hardware resource // send data to hardware resource
if(transmitData(delay, rawData, repetitions)){ if(hardwareManager()->radio433()->sendData(delay, rawData, repetitions)){
qCDebug(dcLeynew) << "Transmitted" << pluginName() << device->name() << action.id(); qCDebug(dcLeynew) << "Transmitted" << pluginName() << device->name() << action.id();
return DeviceManager::DeviceErrorNoError;
}else{ }else{
qCWarning(dcLeynew) << "Could not transmitt" << pluginName() << device->name() << action.id(); qCWarning(dcLeynew) << "Could not transmitt" << pluginName() << device->name() << action.id();
return DeviceManager::DeviceErrorHardwareNotAvailable; return DeviceManager::DeviceErrorHardwareNotAvailable;
} }
return DeviceManager::DeviceErrorNoError;
} }

View File

@ -36,7 +36,6 @@ public:
explicit DevicePluginLeynew(); explicit DevicePluginLeynew();
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::HardwareResources requiredHardware() const override;
public slots: public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;

View File

@ -45,6 +45,9 @@
#include "plugin/device.h" #include "plugin/device.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h"
#include "hardwaremanager.h"
#include <QDebug> #include <QDebug>
@ -52,22 +55,25 @@ DevicePluginLgSmartTv::DevicePluginLgSmartTv()
{ {
} }
DeviceManager::HardwareResources DevicePluginLgSmartTv::requiredHardware() const DevicePluginLgSmartTv::~DevicePluginLgSmartTv()
{ {
return DeviceManager::HardwareResourceTimer | hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
DeviceManager::HardwareResourceUpnpDisovery | }
DeviceManager::HardwareResourceNetworkManager;
void DevicePluginLgSmartTv::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(15);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginLgSmartTv::onPluginTimer);
} }
DeviceManager::DeviceError DevicePluginLgSmartTv::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) DeviceManager::DeviceError DevicePluginLgSmartTv::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{ {
Q_UNUSED(params) Q_UNUSED(params)
Q_UNUSED(deviceClassId)
if(deviceClassId != lgSmartTvDeviceClassId){ qCDebug(dcLgSmartTv()) << "Start discovering";
return DeviceManager::DeviceErrorDeviceClassNotFound; UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("udap:rootservice","UDAP/2.0");
} connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginLgSmartTv::onUpnpDiscoveryFinished);
qCDebug(dcLgSmartTv) << "Start discovering";
upnpDiscover("udap:rootservice","UDAP/2.0");
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
@ -121,10 +127,206 @@ void DevicePluginLgSmartTv::deviceRemoved(Device *device)
delete tvDevice; delete tvDevice;
} }
void DevicePluginLgSmartTv::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) DeviceManager::DeviceError DevicePluginLgSmartTv::executeAction(Device *device, const Action &action)
{ {
TvDevice * tvDevice = m_tvList.key(device);
if (!tvDevice->reachable()) {
qCWarning(dcLgSmartTv) << "Device not reachable";
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
if (action.actionTypeId() == commandVolumeUpActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::VolUp);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandVolumeDownActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::VolDown);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandMuteActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Mute);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandChannelUpActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ChannelUp);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandChannelDownActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ChannelDown);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandPowerOffActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Power);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandArrowUpActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Up);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandArrowDownActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Down);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandArrowLeftActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Left);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandArrowRightActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Right);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandOkActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Ok);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandBackActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Back);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandHomeActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Home);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandInputSourceActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ExternalInput);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandExitActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Exit);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandInfoActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Info);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandMyAppsActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::MyApps);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandProgramListActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ProgramList);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_asyncActions.insert(reply, action.id());
} else {
return DeviceManager::DeviceErrorActionTypeNotFound;
}
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::DeviceError DevicePluginLgSmartTv::displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor)
{
Q_UNUSED(pairingTransactionId)
QHostAddress host = QHostAddress(deviceDescriptor.params().paramValue(hostAddressParamTypeId).toString());
int port = deviceDescriptor.params().paramValue(portParamTypeId).toInt();
QPair<QNetworkRequest, QByteArray> request = TvDevice::createDisplayKeyRequest(host, port);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_showPinReply.append(reply);
return DeviceManager::DeviceErrorNoError;
}
DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret)
{
Q_UNUSED(deviceClassId)
QHostAddress host = QHostAddress(params.paramValue(hostAddressParamTypeId).toString());
int port = params.paramValue(portParamTypeId).toInt();
QPair<QNetworkRequest, QByteArray> request = TvDevice::createPairingRequest(host, port, secret);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_setupPairingTv.insert(reply, pairingTransactionId);
m_tvKeys.insert(params.paramValue(uuidParamTypeId).toString(), secret);
return DeviceManager::DeviceSetupStatusAsync;
}
void DevicePluginLgSmartTv::pairTvDevice(Device *device, const bool &setup)
{
QHostAddress host = QHostAddress(device->paramValue(hostAddressParamTypeId).toString());
int port = device->paramValue(portParamTypeId).toInt();
QString key = device->paramValue(keyParamTypeId).toString();
QPair<QNetworkRequest, QByteArray> request = TvDevice::createPairingRequest(host, port, key);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
if (setup) {
m_asyncSetup.insert(reply, device);
} else {
m_pairRequests.insert(reply, device);
}
}
void DevicePluginLgSmartTv::unpairTvDevice(Device *device)
{
QHostAddress host = QHostAddress(device->paramValue(hostAddressParamTypeId).toString());
int port = device->paramValue(portParamTypeId).toInt();
QPair<QNetworkRequest, QByteArray> request = TvDevice::createEndPairingRequest(host, port);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_deleteTv.append(reply);
}
void DevicePluginLgSmartTv::refreshTv(Device *device)
{
TvDevice *tv = m_tvList.key(device);
// check volume information
QNetworkReply *volumeReply = hardwareManager()->networkManager()->get(tv->createVolumeInformationRequest());
connect(volumeReply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_volumeInfoRequests.insert(volumeReply, device);
// check channel information
QNetworkReply *channelReply = hardwareManager()->networkManager()->get(tv->createChannelInformationRequest());
connect(channelReply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_channelInfoRequests.insert(channelReply, device);
}
void DevicePluginLgSmartTv::onPluginTimer()
{
foreach (Device *device, m_tvList.values()) {
TvDevice *tv = m_tvList.key(device);
if (tv->paired()) {
refreshTv(device);
} else {
pairTvDevice(device);
}
}
}
void DevicePluginLgSmartTv::onUpnpDiscoveryFinished()
{
qCDebug(dcLgSmartTv()) << "Upnp discovery finished";
UpnpDiscoveryReply *reply = static_cast<UpnpDiscoveryReply *>(sender());
if (reply->error() != UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNoError) {
qCWarning(dcLgSmartTv()) << "Upnp discovery error" << reply->error();
}
reply->deleteLater();
QList<DeviceDescriptor> deviceDescriptors; QList<DeviceDescriptor> deviceDescriptors;
foreach (UpnpDeviceDescriptor upnpDeviceDescriptor, upnpDeviceDescriptorList) { foreach (UpnpDeviceDescriptor upnpDeviceDescriptor, reply->deviceDescriptors()) {
if (!upnpDeviceDescriptor.friendlyName().contains("LG") || !upnpDeviceDescriptor.deviceType().contains("TV")) if (!upnpDeviceDescriptor.friendlyName().contains("LG") || !upnpDeviceDescriptor.deviceType().contains("TV"))
continue; continue;
qCDebug(dcLgSmartTv) << upnpDeviceDescriptor; qCDebug(dcLgSmartTv) << upnpDeviceDescriptor;
@ -140,125 +342,13 @@ void DevicePluginLgSmartTv::upnpDiscoveryFinished(const QList<UpnpDeviceDescript
deviceDescriptors.append(descriptor); deviceDescriptors.append(descriptor);
} }
emit devicesDiscovered(lgSmartTvDeviceClassId, deviceDescriptors); emit devicesDiscovered(lgSmartTvDeviceClassId, deviceDescriptors);
} }
DeviceManager::DeviceError DevicePluginLgSmartTv::executeAction(Device *device, const Action &action) void DevicePluginLgSmartTv::onNetworkManagerReplyFinished()
{ {
TvDevice * tvDevice = m_tvList.key(device); QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
if (!tvDevice->reachable()) {
qCWarning(dcLgSmartTv) << "Device not reachable";
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
if (action.actionTypeId() == commandVolumeUpActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::VolUp);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandVolumeDownActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::VolDown);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandMuteActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Mute);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandChannelUpActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ChannelUp);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandChannelDownActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ChannelDown);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandPowerOffActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Power);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandArrowUpActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Up);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandArrowDownActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Down);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandArrowLeftActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Left);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandArrowRightActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Right);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandOkActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Ok);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandBackActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Back);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandHomeActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Home);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandInputSourceActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ExternalInput);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandExitActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Exit);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandInfoActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Info);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandMyAppsActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::MyApps);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else if(action.actionTypeId() == commandProgramListActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ProgramList);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_asyncActions.insert(reply, action.id());
} else {
return DeviceManager::DeviceErrorActionTypeNotFound;
}
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::DeviceError DevicePluginLgSmartTv::displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor)
{
Q_UNUSED(pairingTransactionId)
QHostAddress host = QHostAddress(deviceDescriptor.params().paramValue(hostAddressParamTypeId).toString());
int port = deviceDescriptor.params().paramValue(portParamTypeId).toInt();
QPair<QNetworkRequest, QByteArray> request = TvDevice::createDisplayKeyRequest(host, port);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_showPinReply.append(reply);
return DeviceManager::DeviceErrorNoError;
}
DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret)
{
Q_UNUSED(deviceClassId)
QHostAddress host = QHostAddress(params.paramValue(hostAddressParamTypeId).toString());
int port = params.paramValue(portParamTypeId).toInt();
QPair<QNetworkRequest, QByteArray> request = TvDevice::createPairingRequest(host, port, secret);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_setupPairingTv.insert(reply, pairingTransactionId);
m_tvKeys.insert(params.paramValue(uuidParamTypeId).toString(), secret);
return DeviceManager::DeviceSetupStatusAsync;
}
void DevicePluginLgSmartTv::networkManagerReplyReady(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (m_showPinReply.contains(reply)) { if (m_showPinReply.contains(reply)) {
@ -274,7 +364,8 @@ void DevicePluginLgSmartTv::networkManagerReplyReady(QNetworkReply *reply)
} else { } else {
// End pairing before calling setupDevice, which will always try to pair // End pairing before calling setupDevice, which will always try to pair
QPair<QNetworkRequest, QByteArray> request = TvDevice::createEndPairingRequest(reply->request().url()); QPair<QNetworkRequest, QByteArray> request = TvDevice::createEndPairingRequest(reply->request().url());
QNetworkReply *reply = networkManagerPost(request.first, request.second); QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished);
m_setupEndPairingTv.insert(reply, pairingTransactionId); m_setupEndPairingTv.insert(reply, pairingTransactionId);
} }
} else if (m_setupEndPairingTv.keys().contains(reply)) { } else if (m_setupEndPairingTv.keys().contains(reply)) {
@ -337,54 +428,6 @@ void DevicePluginLgSmartTv::networkManagerReplyReady(QNetworkReply *reply)
reply->deleteLater(); reply->deleteLater();
} }
void DevicePluginLgSmartTv::guhTimer()
{
foreach (Device *device, m_tvList.values()) {
TvDevice *tv = m_tvList.key(device);
if (tv->paired()) {
refreshTv(device);
} else {
pairTvDevice(device);
}
}
}
void DevicePluginLgSmartTv::pairTvDevice(Device *device, const bool &setup)
{
QHostAddress host = QHostAddress(device->paramValue(hostAddressParamTypeId).toString());
int port = device->paramValue(portParamTypeId).toInt();
QString key = device->paramValue(keyParamTypeId).toString();
QPair<QNetworkRequest, QByteArray> request = TvDevice::createPairingRequest(host, port, key);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
if (setup) {
m_asyncSetup.insert(reply, device);
} else {
m_pairRequests.insert(reply, device);
}
}
void DevicePluginLgSmartTv::unpairTvDevice(Device *device)
{
QHostAddress host = QHostAddress(device->paramValue(hostAddressParamTypeId).toString());
int port = device->paramValue(portParamTypeId).toInt();
QPair<QNetworkRequest, QByteArray> request = TvDevice::createEndPairingRequest(host, port);
QNetworkReply *reply = networkManagerPost(request.first, request.second);
m_deleteTv.append(reply);
}
void DevicePluginLgSmartTv::refreshTv(Device *device)
{
TvDevice *tv = m_tvList.key(device);
// check volume information
QNetworkReply *volumeReply = networkManagerGet(tv->createVolumeInformationRequest());
m_volumeInfoRequests.insert(volumeReply, device);
// check channel information
QNetworkReply *channelReply = networkManagerGet(tv->createChannelInformationRequest());
m_channelInfoRequests.insert(channelReply, device);
}
void DevicePluginLgSmartTv::stateChanged() void DevicePluginLgSmartTv::stateChanged()
{ {
TvDevice *tvDevice = static_cast<TvDevice*>(sender()); TvDevice *tvDevice = static_cast<TvDevice*>(sender());

View File

@ -23,8 +23,9 @@
#ifndef DEVICEPLUGINLGSMARTTV_H #ifndef DEVICEPLUGINLGSMARTTV_H
#define DEVICEPLUGINLGSMARTTV_H #define DEVICEPLUGINLGSMARTTV_H
#include "plugin/deviceplugin.h"
#include "tvdevice.h" #include "tvdevice.h"
#include "plugintimer.h"
#include "plugin/deviceplugin.h"
#include "network/upnp/upnpdevicedescriptor.h" #include "network/upnp/upnpdevicedescriptor.h"
class DevicePluginLgSmartTv : public DevicePlugin class DevicePluginLgSmartTv : public DevicePlugin
@ -36,23 +37,19 @@ class DevicePluginLgSmartTv : public DevicePlugin
public: public:
explicit DevicePluginLgSmartTv(); explicit DevicePluginLgSmartTv();
~DevicePluginLgSmartTv();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
DeviceManager::DeviceError displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor) override; DeviceManager::DeviceError displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor) override;
DeviceManager::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret) override; DeviceManager::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void guhTimer() override;
private: private:
PluginTimer *m_pluginTimer = nullptr;
QHash<TvDevice *, Device *> m_tvList; QHash<TvDevice *, Device *> m_tvList;
QHash<QString, QString> m_tvKeys; QHash<QString, QString> m_tvKeys;
@ -78,6 +75,9 @@ private:
void refreshTv(Device *device); void refreshTv(Device *device);
private slots: private slots:
void onPluginTimer();
void onUpnpDiscoveryFinished();
void onNetworkManagerReplyFinished();
void stateChanged(); void stateChanged();
}; };

View File

@ -1,104 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* *
* This file is part of guh. *
* *
* 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 lirc.html
\title LIRC
\brief Plugin for the LIRC infrared daemon.
\ingroup plugins
\ingroup guh-plugins-maker
This plugin allows to interact with \l{http://www.lirc.org/}{LIRC} daemon and controll commonly used remote controls.
If lircd (LIRC daemon) is configured on your system, guh will connect to the lirc daemon and all configured remote
controls of lircd will appear in guh.
\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/lircd/devicepluginlircd.json
*/
#include "devicepluginlircd.h"
#include "plugin/device.h"
#include "devicemanager.h"
#include "plugininfo.h"
#include "lircdclient.h"
#include <QDebug>
#include <QStringList>
DeviceClassId lircdDeviceClassId = DeviceClassId("5c2bc4cd-ba6c-4052-b6cd-1db83323ea22");
EventTypeId LircKeypressEventTypeId = EventTypeId("8711471a-fa0e-410b-b174-dfc3d2aeffb1");
DevicePluginLircd::DevicePluginLircd()
{
m_lircClient = new LircClient(this);
//m_lircClient->connect();
connect(m_lircClient, &LircClient::buttonPressed, this, &DevicePluginLircd::buttonPressed);
}
DeviceManager::HardwareResources DevicePluginLircd::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
void DevicePluginLircd::buttonPressed(const QString &remoteName, const QString &buttonName, int repeat)
{
Device *remote = nullptr;
QList<Device*> configuredRemotes = deviceManager()->findConfiguredDevices(lircdDeviceClassId);
foreach (Device *device, configuredRemotes) {
if (device->paramValue(nameParamTypeId).toString() == remoteName) {
remote = device;
break;
}
}
if (!remote) {
qCWarning(dcLircd) << "Unhandled remote" << remoteName << buttonName;
return;
}
qCDebug(dcLircd) << "found remote" << remoteName << supportedDevices().first().eventTypes().count();
ParamList params;
Param buttonParam(buttonParamTypeId, buttonName);
params.append(buttonParam);
Param repeatParam(repeatParamTypeId, repeat);
params.append(repeatParam);
Event event(LircKeypressEventTypeId, remote->id(), params);
emitEvent(event);
}
//QVariantMap DevicePluginLircd::configuration() const
//{
// return m_config;
//}
//void DevicePluginLircd::setConfiguration(const QVariantMap &configuration)
//{
// m_config = configuration;
//}

View File

@ -1,56 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* *
* This file is part of guh. *
* *
* 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 DEVICEPLUGINLIRCD_H
#define DEVICEPLUGINLIRCD_H
#include "plugin/deviceplugin.h"
#include <QProcess>
class LircClient;
class DevicePluginLircd: public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "devicepluginlircd.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginLircd();
DeviceManager::HardwareResources requiredHardware() const override;
// QVariantMap configuration() const override;
// void setConfiguration(const QVariantMap &configuration) override;
private slots:
void buttonPressed(const QString &remoteName, const QString &buttonName, int repeat);
private:
LircClient *m_lircClient;
// QVariantMap m_config;
};
#endif // DEVICEPLUGINBOLIRCD_H

View File

@ -1,55 +0,0 @@
{
"name": "Lirc receiver",
"idName": "Lircd",
"id": "075f734f-4d76-4ce3-9ef8-34c212285676",
"vendors": [
{
"name": "Lirc",
"idName": "lirc",
"id": "9a53049c-8828-4b87-b3f6-7bc7708196cd",
"deviceClasses": [
{
"id": "5c2bc4cd-ba6c-4052-b6cd-1db83323ea22",
"idName": "irReceiver",
"name": "IR receiver",
"basicTags": [
"Service",
"Actuator",
"Multimedia"
],
"createMethods": ["user"],
"paramTypes": [
{
"id": "06704d73-66d1-486b-bc0b-0346534983a1",
"idName": "name",
"name": "remoteName",
"type": "QString",
"inputType": "TextLine"
}
],
"eventTypes": [
{
"id": "8711471a-fa0e-410b-b174-dfc3d2aeffb1",
"idName": "buttonPressed",
"name": "button pressed",
"paramTypes": [
{
"id": "a6344673-17f5-4a37-b59e-f342a2877909",
"idName": "button",
"name": "button",
"type": "QString"
},
{
"id": "a98d9348-1154-45c6-a163-c9f0477be626",
"idName": "repeat",
"name": "repeat",
"type": "int"
}
]
}
]
}
]
}
]
}

View File

@ -1,20 +0,0 @@
TRANSLATIONS = translations/en_US.ts \
translations/de_DE.ts
# Note: include after the TRANSLATIONS definition
include(../plugins.pri)
TARGET = $$qtLibraryTarget(guh_devicepluginlircd)
QT += network
SOURCES += \
devicepluginlircd.cpp \
lircdclient.cpp \
HEADERS += \
devicepluginlircd.h \
lircdclient.h \

View File

@ -1,95 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* *
* This file is part of guh. *
* *
* 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "lircdclient.h"
#include "extern-plugininfo.h"
#include <QDebug>
#include <QLocalSocket>
LircClient::LircClient(QObject *parent) :
QObject(parent)
{
m_socket = new QLocalSocket(this);
QObject::connect(m_socket, &QLocalSocket::readyRead, this, &LircClient::readyRead);
}
bool LircClient::connect()
{
m_socket->connectToServer("/var/run/lirc/lircd", QIODevice::ReadWrite);
if (!m_socket->isOpen()) {
qCWarning(dcLircd) << "--> Lirc daemon NOT available.";
return false;
}
m_socket->write("LIST\n");
qCDebug(dcLircd) << "--> Lirc daemon available.";
return true;
}
void LircClient::readyRead()
{
qCDebug(dcLircd) << "got data" << m_socket->readAll();
bool inBlock = false;
while (m_socket->canReadLine()) {
QByteArray line = m_socket->readLine().trimmed();
qCDebug(dcLircd) << "got line:" << line;
if (line == "BEGIN") {
inBlock = true;
continue;
}
if (line == "LIST") {
if (m_socket->readLine().trimmed() == "SUCCESS") {
readRemotes();
} else {
qCWarning(dcLircd) << "Error reading remotes from Lircd";
}
continue;
}
if ( line == "END") {
inBlock = false;
continue;
}
if (!inBlock) {
QList<QByteArray> parts = line.split(' ');
if (parts.count() != 4) {
qCWarning(dcLircd) << "Don't understand IR command. ignoring...";
continue;
}
qCDebug(dcLircd) << "emitting buttonpress";
emit buttonPressed(QString(parts.at(3)), QString(parts.at(2)), parts.at(1).toInt());
}
}
}
void LircClient::readRemotes()
{
m_socket->readLine(); // IGNORE DATA
int remoteCount = m_socket->readLine().trimmed().toInt();
qCDebug(dcLircd) << "found" << remoteCount << "lirc remotes";
for (int i = 0; i < remoteCount; i++) {
QByteArray line = m_socket->readLine().trimmed();
m_remotes.append(line);
}
}

View File

@ -1,53 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* *
* This file is part of guh. *
* *
* 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 LIRCCLIENT_H
#define LIRCCLIENT_H
#include <QObject>
#include <QLocalSocket>
#include <QStringList>
class LircClient : public QObject
{
Q_OBJECT
public:
explicit LircClient(QObject *parent = 0);
bool connect();
signals:
void buttonPressed(const QString &remoteName, const QString &buttonName, int repeat);
private slots:
void readyRead();
private:
void readRemotes();
private:
QLocalSocket *m_socket;
QStringList m_remotes;
};
#endif // LIRCCLIENT_H

View File

@ -164,11 +164,6 @@ DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Devic
return DeviceManager::DeviceSetupStatusFailure; return DeviceManager::DeviceSetupStatusFailure;
} }
DeviceManager::HardwareResources DevicePluginMailNotification::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
DeviceManager::DeviceError DevicePluginMailNotification::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginMailNotification::executeAction(Device *device, const Action &action)
{ {
if(action.actionTypeId() == sendMailActionTypeId) { if(action.actionTypeId() == sendMailActionTypeId) {

View File

@ -38,7 +38,6 @@ public:
~DevicePluginMailNotification(); ~DevicePluginMailNotification();
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;

View File

@ -42,6 +42,7 @@
#include "devicepluginnetatmo.h" #include "devicepluginnetatmo.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/networkaccessmanager.h"
#include <QDebug> #include <QDebug>
#include <QUrlQuery> #include <QUrlQuery>
@ -52,9 +53,15 @@ DevicePluginNetatmo::DevicePluginNetatmo()
} }
DeviceManager::HardwareResources DevicePluginNetatmo::requiredHardware() const DevicePluginNetatmo::~DevicePluginNetatmo()
{ {
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer; hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginNetatmo::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(30);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginNetatmo::onPluginTimer);
} }
DeviceManager::DeviceSetupStatus DevicePluginNetatmo::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginNetatmo::setupDevice(Device *device)
@ -119,49 +126,6 @@ void DevicePluginNetatmo::deviceRemoved(Device *device)
} }
} }
void DevicePluginNetatmo::networkManagerReplyReady(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// update values request
if (m_refreshRequest.keys().contains(reply)) {
Device *device = m_refreshRequest.take(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcNetatmo) << "Device list reply HTTP error:" << status << reply->errorString();
device->setStateValue(availableStateTypeId, false);
reply->deleteLater();
return;
}
// check JSON file
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcNetatmo) << "Device list reply JSON error:" << error.errorString();
reply->deleteLater();
return;
}
//qCDebug(dcNetatmo) << jsonDoc.toJson();
processRefreshData(jsonDoc.toVariant().toMap(), device->id().toString());
}
reply->deleteLater();
}
void DevicePluginNetatmo::guhTimer()
{
foreach (OAuth2 *authentication, m_authentications.keys()) {
if (authentication->authenticated()) {
refreshData(m_authentications.value(authentication), authentication->token());
} else {
authentication->startAuthentication();
}
}
}
DeviceManager::DeviceError DevicePluginNetatmo::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginNetatmo::executeAction(Device *device, const Action &action)
{ {
Q_UNUSED(device) Q_UNUSED(device)
@ -178,7 +142,9 @@ void DevicePluginNetatmo::refreshData(Device *device, const QString &token)
QUrl url("https://api.netatmo.com/api/devicelist"); QUrl url("https://api.netatmo.com/api/devicelist");
url.setQuery(query); url.setQuery(query);
QNetworkReply *reply = networkManagerGet(QNetworkRequest(url)); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginNetatmo::onNetworkReplyFinished);
m_refreshRequest.insert(reply, device); m_refreshRequest.insert(reply, device);
} }
@ -267,6 +233,50 @@ Device *DevicePluginNetatmo::findOutdoorDevice(const QString &macAddress)
return 0; return 0;
} }
void DevicePluginNetatmo::onPluginTimer()
{
foreach (OAuth2 *authentication, m_authentications.keys()) {
if (authentication->authenticated()) {
refreshData(m_authentications.value(authentication), authentication->token());
} else {
authentication->startAuthentication();
}
}
}
void DevicePluginNetatmo::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// update values request
if (m_refreshRequest.keys().contains(reply)) {
Device *device = m_refreshRequest.take(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcNetatmo) << "Device list reply HTTP error:" << status << reply->errorString();
device->setStateValue(availableStateTypeId, false);
reply->deleteLater();
return;
}
// check JSON file
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcNetatmo) << "Device list reply JSON error:" << error.errorString();
reply->deleteLater();
return;
}
//qCDebug(dcNetatmo) << jsonDoc.toJson();
processRefreshData(jsonDoc.toVariant().toMap(), device->id().toString());
}
reply->deleteLater();
}
void DevicePluginNetatmo::onAuthenticationChanged() void DevicePluginNetatmo::onAuthenticationChanged()
{ {
OAuth2 *authentication = static_cast<OAuth2 *>(sender()); OAuth2 *authentication = static_cast<OAuth2 *>(sender());

View File

@ -23,6 +23,7 @@
#ifndef DEVICEPLUGINNETATMO_H #ifndef DEVICEPLUGINNETATMO_H
#define DEVICEPLUGINNETATMO_H #define DEVICEPLUGINNETATMO_H
#include "plugintimer.h"
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "network/oauth2.h" #include "network/oauth2.h"
#include "netatmobasestation.h" #include "netatmobasestation.h"
@ -39,18 +40,17 @@ class DevicePluginNetatmo : public DevicePlugin
public: public:
explicit DevicePluginNetatmo(); explicit DevicePluginNetatmo();
~DevicePluginNetatmo();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void guhTimer() override;
public slots: public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private: private:
PluginTimer *m_pluginTimer;
QList<Device *> m_asyncSetups; QList<Device *> m_asyncSetups;
QHash<OAuth2 *, Device *> m_authentications; QHash<OAuth2 *, Device *> m_authentications;
@ -66,6 +66,8 @@ private:
Device *findOutdoorDevice(const QString &macAddress); Device *findOutdoorDevice(const QString &macAddress);
private slots: private slots:
void onPluginTimer();
void onNetworkReplyFinished();
void onAuthenticationChanged(); void onAuthenticationChanged();
void onIndoorStatesChanged(); void onIndoorStatesChanged();
void onOutdoorStatesChanged(); void onOutdoorStatesChanged();

View File

@ -61,11 +61,19 @@ DevicePluginNetworkDetector::DevicePluginNetworkDetector()
DevicePluginNetworkDetector::~DevicePluginNetworkDetector() DevicePluginNetworkDetector::~DevicePluginNetworkDetector()
{ {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
if (m_discovery->isRunning()) { if (m_discovery->isRunning()) {
m_discovery->abort(); m_discovery->abort();
} }
} }
void DevicePluginNetworkDetector::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginNetworkDetector::onPluginTimer);
}
DeviceManager::DeviceSetupStatus DevicePluginNetworkDetector::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginNetworkDetector::setupDevice(Device *device)
{ {
qCDebug(dcNetworkDetector()) << "Setup" << device->name() << device->params(); qCDebug(dcNetworkDetector()) << "Setup" << device->name() << device->params();
@ -81,7 +89,6 @@ DeviceManager::DeviceError DevicePluginNetworkDetector::discoverDevices(const De
{ {
Q_UNUSED(params) Q_UNUSED(params)
if (deviceClassId != networkDeviceClassId) if (deviceClassId != networkDeviceClassId)
return DeviceManager::DeviceErrorDeviceClassNotFound; return DeviceManager::DeviceErrorDeviceClassNotFound;
@ -95,11 +102,6 @@ DeviceManager::DeviceError DevicePluginNetworkDetector::discoverDevices(const De
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
DeviceManager::HardwareResources DevicePluginNetworkDetector::requiredHardware() const
{
return DeviceManager::HardwareResourceTimer;
}
void DevicePluginNetworkDetector::deviceRemoved(Device *device) void DevicePluginNetworkDetector::deviceRemoved(Device *device)
{ {
DeviceMonitor *monitor = m_monitors.key(device); DeviceMonitor *monitor = m_monitors.key(device);
@ -107,7 +109,7 @@ void DevicePluginNetworkDetector::deviceRemoved(Device *device)
delete monitor; delete monitor;
} }
void DevicePluginNetworkDetector::guhTimer() void DevicePluginNetworkDetector::onPluginTimer()
{ {
foreach (DeviceMonitor *monitor, m_monitors.keys()) { foreach (DeviceMonitor *monitor, m_monitors.keys()) {
monitor->update(); monitor->update();

View File

@ -27,6 +27,7 @@
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "host.h" #include "host.h"
#include "discovery.h" #include "discovery.h"
#include "plugintimer.h"
#include "devicemonitor.h" #include "devicemonitor.h"
#include <QProcess> #include <QProcess>
@ -44,19 +45,23 @@ public:
explicit DevicePluginNetworkDetector(); explicit DevicePluginNetworkDetector();
~DevicePluginNetworkDetector(); ~DevicePluginNetworkDetector();
void init() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::HardwareResources requiredHardware() const override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void guhTimer() override;
private slots: private slots:
void discoveryFinished(const QList<Host> &hosts); void discoveryFinished(const QList<Host> &hosts);
void deviceReachableChanged(bool reachable); void deviceReachableChanged(bool reachable);
void deviceAddressChanged(const QString &address); void deviceAddressChanged(const QString &address);
void onPluginTimer();
private: private:
PluginTimer *m_pluginTimer = nullptr;
Discovery *m_discovery = nullptr; Discovery *m_discovery = nullptr;
QHash<DeviceMonitor*, Device*> m_monitors; QHash<DeviceMonitor*, Device*> m_monitors;
}; };

View File

@ -48,7 +48,6 @@
*/ */
#include "devicepluginopenweathermap.h" #include "devicepluginopenweathermap.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
@ -66,12 +65,17 @@ DevicePluginOpenweathermap::DevicePluginOpenweathermap()
// max 50000 calls/day // max 50000 calls/day
m_apiKey = "c1b9d5584bb740804871583f6c62744f"; m_apiKey = "c1b9d5584bb740804871583f6c62744f";
// update every 15 minutes }
m_timer = new QTimer(this);
m_timer->setSingleShot(false);
m_timer->setInterval(900000);
connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout())); DevicePluginOpenweathermap::~DevicePluginOpenweathermap()
{
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginOpenweathermap::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(900);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginOpenweathermap::onPluginTimer);
} }
DeviceManager::DeviceError DevicePluginOpenweathermap::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) DeviceManager::DeviceError DevicePluginOpenweathermap::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
@ -96,19 +100,11 @@ DeviceManager::DeviceSetupStatus DevicePluginOpenweathermap::setupDevice(Device
if (device->deviceClassId() != openweathermapDeviceClassId) if (device->deviceClassId() != openweathermapDeviceClassId)
return DeviceManager::DeviceSetupStatusFailure; return DeviceManager::DeviceSetupStatusFailure;
if (!m_timer->isActive())
m_timer->start();
update(device); update(device);
return DeviceManager::DeviceSetupStatusSuccess; return DeviceManager::DeviceSetupStatusSuccess;
} }
DeviceManager::HardwareResources DevicePluginOpenweathermap::requiredHardware() const
{
return DeviceManager::HardwareResourceNetworkManager;
}
DeviceManager::DeviceError DevicePluginOpenweathermap::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginOpenweathermap::executeAction(Device *device, const Action &action)
{ {
if(action.actionTypeId() == refreshWeatherActionTypeId){ if(action.actionTypeId() == refreshWeatherActionTypeId){
@ -128,13 +124,12 @@ void DevicePluginOpenweathermap::deviceRemoved(Device *device)
reply->deleteLater(); reply->deleteLater();
} }
} }
if (myDevices().isEmpty())
m_timer->stop();
} }
void DevicePluginOpenweathermap::networkManagerReplyReady(QNetworkReply *reply) void DevicePluginOpenweathermap::networkManagerReplyReady()
{ {
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
if (reply->error()) { if (reply->error()) {
qCWarning(dcOpenWeatherMap) << "OpenWeatherMap reply error: " << reply->errorString(); qCWarning(dcOpenWeatherMap) << "OpenWeatherMap reply error: " << reply->errorString();
reply->deleteLater(); reply->deleteLater();
@ -163,6 +158,7 @@ void DevicePluginOpenweathermap::networkManagerReplyReady(QNetworkReply *reply)
void DevicePluginOpenweathermap::update(Device *device) void DevicePluginOpenweathermap::update(Device *device)
{ {
qCDebug(dcOpenWeatherMap()) << "Refresh data for" << device->name();
QUrl url("http://api.openweathermap.org/data/2.5/weather"); QUrl url("http://api.openweathermap.org/data/2.5/weather");
QUrlQuery query; QUrlQuery query;
query.addQueryItem("id", device->paramValue(idParamTypeId).toString()); query.addQueryItem("id", device->paramValue(idParamTypeId).toString());
@ -171,13 +167,15 @@ void DevicePluginOpenweathermap::update(Device *device)
query.addQueryItem("appid", m_apiKey); query.addQueryItem("appid", m_apiKey);
url.setQuery(query); url.setQuery(query);
QNetworkReply *reply = networkManagerGet(QNetworkRequest(url)); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady);
m_weatherReplies.insert(reply, device); m_weatherReplies.insert(reply, device);
} }
void DevicePluginOpenweathermap::searchAutodetect() void DevicePluginOpenweathermap::searchAutodetect()
{ {
QNetworkReply *reply = networkManagerGet(QNetworkRequest(QUrl("http://ip-api.com/json"))); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(QUrl("http://ip-api.com/json")));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady);
m_autodetectionReplies.append(reply); m_autodetectionReplies.append(reply);
} }
@ -192,7 +190,8 @@ void DevicePluginOpenweathermap::search(QString searchString)
query.addQueryItem("appid", m_apiKey); query.addQueryItem("appid", m_apiKey);
url.setQuery(query); url.setQuery(query);
QNetworkReply *reply = networkManagerGet(QNetworkRequest(url)); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady);
m_searchReplies.append(reply); m_searchReplies.append(reply);
} }
@ -209,7 +208,8 @@ void DevicePluginOpenweathermap::searchGeoLocation(double lat, double lon)
query.addQueryItem("appid", m_apiKey); query.addQueryItem("appid", m_apiKey);
url.setQuery(query); url.setQuery(query);
QNetworkReply *reply = networkManagerGet(QNetworkRequest(url)); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady);
m_searchGeoReplies.append(reply); m_searchGeoReplies.append(reply);
} }
@ -392,7 +392,7 @@ void DevicePluginOpenweathermap::processWeatherData(const QByteArray &data, Devi
} }
} }
void DevicePluginOpenweathermap::onTimeout() void DevicePluginOpenweathermap::onPluginTimer()
{ {
foreach (Device *device, myDevices()) { foreach (Device *device, myDevices()) {
update(device); update(device);

View File

@ -23,9 +23,12 @@
#ifndef DEVICEPLUGINOPENWEATHERMAP_H #ifndef DEVICEPLUGINOPENWEATHERMAP_H
#define DEVICEPLUGINOPENWEATHERMAP_H #define DEVICEPLUGINOPENWEATHERMAP_H
#include "plugintimer.h"
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "network/networkaccessmanager.h"
#include <QTimer> #include <QTimer>
#include <QHostAddress>
class DevicePluginOpenweathermap : public DevicePlugin class DevicePluginOpenweathermap : public DevicePlugin
{ {
@ -36,17 +39,17 @@ class DevicePluginOpenweathermap : public DevicePlugin
public: public:
explicit DevicePluginOpenweathermap(); explicit DevicePluginOpenweathermap();
~DevicePluginOpenweathermap();
void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
//void guhTimer() override;
private: private:
PluginTimer *m_pluginTimer = nullptr;
QList<QNetworkReply *> m_autodetectionReplies; QList<QNetworkReply *> m_autodetectionReplies;
QList<QNetworkReply *> m_searchReplies; QList<QNetworkReply *> m_searchReplies;
QList<QNetworkReply *> m_searchGeoReplies; QList<QNetworkReply *> m_searchGeoReplies;
@ -59,7 +62,6 @@ private:
double m_longitude; double m_longitude;
double m_latitude; double m_latitude;
QTimer *m_timer;
QString m_apiKey; QString m_apiKey;
void update(Device *device); void update(Device *device);
@ -75,7 +77,8 @@ private:
void processWeatherData(const QByteArray &data, Device *device); void processWeatherData(const QByteArray &data, Device *device);
private slots: private slots:
void onTimeout(); void networkManagerReplyReady();
void onPluginTimer();
}; };

View File

@ -42,16 +42,22 @@
#include "devicepluginorderbutton.h" #include "devicepluginorderbutton.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/networkaccessmanager.h"
DevicePluginOrderButton::DevicePluginOrderButton() DevicePluginOrderButton::DevicePluginOrderButton()
{ {
} }
DeviceManager::HardwareResources DevicePluginOrderButton::requiredHardware() const DevicePluginOrderButton::~DevicePluginOrderButton()
{ {
// We need the NetworkAccessManager for node discovery and the timer for ping requests hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer; }
void DevicePluginOrderButton::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginOrderButton::onPluginTimer);
} }
DeviceManager::DeviceSetupStatus DevicePluginOrderButton::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginOrderButton::setupDevice(Device *device)
@ -96,68 +102,18 @@ DeviceManager::DeviceError DevicePluginOrderButton::discoverDevices(const Device
url.setScheme("http"); url.setScheme("http");
url.setHost(address.toString()); url.setHost(address.toString());
m_asyncNodeScans.insert(networkManagerGet(QNetworkRequest(url)), deviceClassId); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOrderButton::onNetworkReplyFinished);
m_asyncNodeScans.insert(reply, deviceClassId);
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
void DevicePluginOrderButton::networkManagerReplyReady(QNetworkReply *reply)
{
if (m_asyncNodeScans.keys().contains(reply)) {
DeviceClassId deviceClassId = m_asyncNodeScans.take(reply);
// Check HTTP status code
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
qCWarning(dcOrderButton) << "Node scan reply HTTP error:" << reply->errorString();
emit devicesDiscovered(deviceClassId, QList<DeviceDescriptor>());
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
qCDebug(dcOrderButton) << "Node discovery finished:" << endl << data;
QList<DeviceDescriptor> deviceDescriptors;
QList<QByteArray> lines = data.split('\n');
qCDebug(dcOrderButton) << lines;
foreach (const QByteArray &line, lines) {
if (line.isEmpty())
continue;
QHostAddress address(QString(line.left(line.length() - 4)));
if (address.isNull())
continue;
qCDebug(dcOrderButton) << "Found node" << address.toString();
// Create a deviceDescriptor for each found address
DeviceDescriptor descriptor(deviceClassId, "Order Button", address.toString());
ParamList params;
params.append(Param(hostParamTypeId, address.toString()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
// Inform the user which devices were found
emit devicesDiscovered(deviceClassId, deviceDescriptors);
}
// Delete the HTTP reply
reply->deleteLater();
}
void DevicePluginOrderButton::postSetupDevice(Device *device) void DevicePluginOrderButton::postSetupDevice(Device *device)
{ {
// Try to ping the device after a successful setup // Try to ping the device after a successful setup
pingDevice(device); pingDevice(device);
} }
void DevicePluginOrderButton::guhTimer()
{
// Try to ping each device every 10 seconds to make sure it is still reachable
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == orderbuttonDeviceClassId) {
pingDevice(device);
}
}
}
DeviceManager::DeviceError DevicePluginOrderButton::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginOrderButton::executeAction(Device *device, const Action &action)
{ {
if (device->deviceClassId() != orderbuttonDeviceClassId) if (device->deviceClassId() != orderbuttonDeviceClassId)
@ -360,6 +316,60 @@ Device *DevicePluginOrderButton::findDevice(const QHostAddress &address)
return NULL; return NULL;
} }
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(hostParamTypeId, 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) void DevicePluginOrderButton::coapReplyFinished(CoapReply *reply)
{ {
if (m_pingReplies.contains(reply)) { if (m_pingReplies.contains(reply)) {

View File

@ -27,6 +27,7 @@
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "types/action.h" #include "types/action.h"
#include "coap/coap.h" #include "coap/coap.h"
#include "plugintimer.h"
#include <QHash> #include <QHash>
@ -38,19 +39,17 @@ class DevicePluginOrderButton : public DevicePlugin
public: public:
explicit DevicePluginOrderButton(); explicit DevicePluginOrderButton();
~DevicePluginOrderButton();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void postSetupDevice(Device *device) override; void postSetupDevice(Device *device) override;
void guhTimer() override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private: private:
PluginTimer *m_pluginTimer = nullptr;
QPointer<Coap> m_coap; QPointer<Coap> m_coap;
QHash<QNetworkReply *, DeviceClassId> m_asyncNodeScans; QHash<QNetworkReply *, DeviceClassId> m_asyncNodeScans;
QHash<CoapReply *, Device *> m_enableNotification; QHash<CoapReply *, Device *> m_enableNotification;
@ -81,6 +80,8 @@ private:
Device *findDevice(const QHostAddress &address); Device *findDevice(const QHostAddress &address);
private slots: private slots:
void onPluginTimer();
void onNetworkReplyFinished();
void coapReplyFinished(CoapReply *reply); void coapReplyFinished(CoapReply *reply);
void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload); void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload);
}; };

View File

@ -46,21 +46,29 @@
#include "devicepluginosdomotics.h" #include "devicepluginosdomotics.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/networkaccessmanager.h"
DevicePluginOsdomotics::DevicePluginOsdomotics() DevicePluginOsdomotics::DevicePluginOsdomotics()
{ {
m_coap = new Coap(this);
connect(m_coap, SIGNAL(replyFinished(CoapReply*)), this, SLOT(coapReplyFinished(CoapReply*)));
} }
DeviceManager::HardwareResources DevicePluginOsdomotics::requiredHardware() const DevicePluginOsdomotics::~DevicePluginOsdomotics()
{ {
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer; hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginOsdomotics::init()
{
m_coap = new Coap(this);
connect(m_coap, &Coap::replyFinished, this, &DevicePluginOsdomotics::coapReplyFinished);
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginOsdomotics::onPluginTimer);
} }
DeviceManager::DeviceSetupStatus DevicePluginOsdomotics::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginOsdomotics::setupDevice(Device *device)
{ {
if (device->deviceClassId() == rplRouterDeviceClassId) { if (device->deviceClassId() == rplRouterDeviceClassId) {
qCDebug(dcOsdomotics) << "Setup RPL router" << device->paramValue(hostParamTypeId).toString(); qCDebug(dcOsdomotics) << "Setup RPL router" << device->paramValue(hostParamTypeId).toString();
QHostAddress address(device->paramValue(hostParamTypeId).toString()); QHostAddress address(device->paramValue(hostParamTypeId).toString());
@ -74,7 +82,8 @@ DeviceManager::DeviceSetupStatus DevicePluginOsdomotics::setupDevice(Device *dev
url.setScheme("http"); url.setScheme("http");
url.setHost(address.toString()); url.setHost(address.toString());
QNetworkReply *reply = networkManagerGet(QNetworkRequest(url)); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOsdomotics::onNetworkReplyFinished);
m_asyncSetup.insert(reply, device); m_asyncSetup.insert(reply, device);
return DeviceManager::DeviceSetupStatusAsync; return DeviceManager::DeviceSetupStatusAsync;
@ -91,59 +100,11 @@ void DevicePluginOsdomotics::deviceRemoved(Device *device)
Q_UNUSED(device) Q_UNUSED(device)
} }
void DevicePluginOsdomotics::networkManagerReplyReady(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// create user finished
if (m_asyncSetup.contains(reply)) {
Device *device = m_asyncSetup.take(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcOsdomotics) << "Setup reply HTTP error:" << reply->errorString();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
parseNodes(device, data);
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
} else if (m_asyncNodeRescans.contains(reply)) {
Device *device = m_asyncSetup.take(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcOsdomotics) << "Setup reply HTTP error:" << reply->errorString();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
parseNodes(device, data);
}
reply->deleteLater();
}
void DevicePluginOsdomotics::postSetupDevice(Device *device) void DevicePluginOsdomotics::postSetupDevice(Device *device)
{ {
updateNode(device); updateNode(device);
} }
void DevicePluginOsdomotics::guhTimer()
{
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == merkurNodeDeviceClassId) {
updateNode(device);
} else if(device->deviceClassId() == rplRouterDeviceClassId) {
scanNodes(device);
}
}
}
DeviceManager::DeviceError DevicePluginOsdomotics::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginOsdomotics::executeAction(Device *device, const Action &action)
{ {
if (device->deviceClassId() == merkurNodeDeviceClassId) { if (device->deviceClassId() == merkurNodeDeviceClassId) {
@ -183,7 +144,8 @@ void DevicePluginOsdomotics::scanNodes(Device *device)
url.setScheme("http"); url.setScheme("http");
url.setHost(address.toString()); url.setHost(address.toString());
QNetworkReply *reply = networkManagerGet(QNetworkRequest(url)); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOsdomotics::onNetworkReplyFinished);
m_asyncNodeRescans.insert(reply, device); m_asyncNodeRescans.insert(reply, device);
} }
@ -258,6 +220,55 @@ Device *DevicePluginOsdomotics::findDevice(const QHostAddress &address)
return 0; return 0;
} }
void DevicePluginOsdomotics::onPluginTimer()
{
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == merkurNodeDeviceClassId) {
updateNode(device);
} else if(device->deviceClassId() == rplRouterDeviceClassId) {
scanNodes(device);
}
}
}
void DevicePluginOsdomotics::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// create user finished
if (m_asyncSetup.contains(reply)) {
Device *device = m_asyncSetup.take(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcOsdomotics) << "Setup reply HTTP error:" << reply->errorString();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
parseNodes(device, data);
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
} else if (m_asyncNodeRescans.contains(reply)) {
Device *device = m_asyncSetup.take(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcOsdomotics) << "Setup reply HTTP error:" << reply->errorString();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
parseNodes(device, data);
}
reply->deleteLater();
}
void DevicePluginOsdomotics::coapReplyFinished(CoapReply *reply) void DevicePluginOsdomotics::coapReplyFinished(CoapReply *reply)
{ {
qCDebug(dcOsdomotics) << "coap reply finished" << reply; qCDebug(dcOsdomotics) << "coap reply finished" << reply;

View File

@ -29,6 +29,7 @@
#include <QDebug> #include <QDebug>
#include "coap/coap.h" #include "coap/coap.h"
#include "plugintimer.h"
class DevicePluginOsdomotics : public DevicePlugin class DevicePluginOsdomotics : public DevicePlugin
{ {
@ -38,19 +39,17 @@ class DevicePluginOsdomotics : public DevicePlugin
public: public:
explicit DevicePluginOsdomotics(); explicit DevicePluginOsdomotics();
~DevicePluginOsdomotics();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void postSetupDevice(Device *device) override; void postSetupDevice(Device *device) override;
void guhTimer() override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private: private:
Coap *m_coap; PluginTimer *m_pluginTimer = nullptr;
Coap *m_coap = nullptr;
QHash<QNetworkReply *, Device *> m_asyncSetup; QHash<QNetworkReply *, Device *> m_asyncSetup;
QHash<QNetworkReply *, Device *> m_asyncNodeRescans; QHash<QNetworkReply *, Device *> m_asyncNodeRescans;
@ -65,6 +64,8 @@ private:
Device *findDevice(const QHostAddress &address); Device *findDevice(const QHostAddress &address);
private slots: private slots:
void onPluginTimer();
void onNetworkReplyFinished();
void coapReplyFinished(CoapReply *reply); void coapReplyFinished(CoapReply *reply);
}; };

View File

@ -47,6 +47,8 @@
#include "plugin/device.h" #include "plugin/device.h"
#include "types/param.h" #include "types/param.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/upnp/upnpdiscovery.h"
#include "network/upnp/upnpdiscoveryreply.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -55,24 +57,28 @@
DevicePluginPhilipsHue::DevicePluginPhilipsHue() DevicePluginPhilipsHue::DevicePluginPhilipsHue()
{ {
m_timer = new QTimer(this);
m_timer->setSingleShot(false);
m_timer->setInterval(5000);
connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
} }
DeviceManager::HardwareResources DevicePluginPhilipsHue::requiredHardware() const DevicePluginPhilipsHue::~DevicePluginPhilipsHue()
{ {
return DeviceManager::HardwareResourceUpnpDisovery | DeviceManager::HardwareResourceNetworkManager; hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginPhilipsHue::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(5);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginPhilipsHue::onPluginTimer);
} }
DeviceManager::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) DeviceManager::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{ {
Q_UNUSED(deviceClassId)
Q_UNUSED(params) Q_UNUSED(params)
Q_UNUSED(deviceClassId)
UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("libhue:idl");
connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginPhilipsHue::onUpnpDiscoveryFinished);
upnpDiscover("libhue:idl");
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
@ -94,7 +100,6 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev
m_bridges.insert(b, device); m_bridges.insert(b, device);
device->setStateValue(bridgeReachableStateTypeId, true); device->setStateValue(bridgeReachableStateTypeId, true);
discoverBridgeDevices(b); discoverBridgeDevices(b);
m_timer->start();
return DeviceManager::DeviceSetupStatusSuccess; return DeviceManager::DeviceSetupStatusSuccess;
} }
} }
@ -111,7 +116,6 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev
bridge->setZigbeeChannel(device->paramValue(bridgeZigbeeChannelParamTypeId).toInt()); bridge->setZigbeeChannel(device->paramValue(bridgeZigbeeChannelParamTypeId).toInt());
m_bridges.insert(bridge, device); m_bridges.insert(bridge, device);
m_timer->start();
return DeviceManager::DeviceSetupStatusSuccess; return DeviceManager::DeviceSetupStatusSuccess;
} }
@ -213,38 +217,6 @@ void DevicePluginPhilipsHue::deviceRemoved(Device *device)
m_remotes.remove(remote); m_remotes.remove(remote);
remote->deleteLater(); remote->deleteLater();
} }
if (myDevices().isEmpty())
m_timer->stop();
}
void DevicePluginPhilipsHue::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList)
{
if (upnpDeviceDescriptorList.isEmpty()) {
qCDebug(dcPhilipsHue) << "No UPnP device found. Try N-UPNP discovery.";
QNetworkRequest request(QUrl("https://www.meethue.com/api/nupnp"));
QNetworkReply *reply = networkManagerGet(request);
m_discoveryRequests.append(reply);
return;
}
QList<DeviceDescriptor> deviceDescriptors;
foreach (const UpnpDeviceDescriptor &upnpDevice, upnpDeviceDescriptorList) {
if (upnpDevice.modelDescription().contains("Philips")) {
DeviceDescriptor descriptor(hueBridgeDeviceClassId, "Philips Hue Bridge", upnpDevice.hostAddress().toString());
ParamList params;
params.append(Param(bridgeNameParamTypeId, upnpDevice.friendlyName()));
params.append(Param(bridgeHostParamTypeId, upnpDevice.hostAddress().toString()));
params.append(Param(bridgeApiParamTypeId, QString()));
params.append(Param(bridgeMacParamTypeId, QString()));
params.append(Param(bridgeIdParamTypeId, upnpDevice.serialNumber().toLower()));
params.append(Param(bridgeZigbeeChannelParamTypeId, -1));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
}
emit devicesDiscovered(hueBridgeDeviceClassId, deviceDescriptors);
} }
DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret) DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret)
@ -265,15 +237,17 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::confirmPairing(const Pa
QNetworkRequest request(QUrl("http://" + pairingInfo->host().toString() + "/api")); QNetworkRequest request(QUrl("http://" + pairingInfo->host().toString() + "/api"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManagerPost(request, jsonDoc.toJson()); QNetworkReply *reply = hardwareManager()->networkManager()->post(request, jsonDoc.toJson());
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_pairingRequests.insert(reply, pairingInfo); m_pairingRequests.insert(reply, pairingInfo);
return DeviceManager::DeviceSetupStatusAsync; return DeviceManager::DeviceSetupStatusAsync;
} }
void DevicePluginPhilipsHue::networkManagerReplyReady(QNetworkReply *reply) void DevicePluginPhilipsHue::networkManagerReplyReady()
{ {
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// create user finished // create user finished
@ -444,27 +418,39 @@ DeviceManager::DeviceError DevicePluginPhilipsHue::executeAction(Device *device,
if (action.actionTypeId() == huePowerActionTypeId) { if (action.actionTypeId() == huePowerActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(action.param(huePowerStateParamTypeId).value().toBool()); QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(action.param(huePowerStateParamTypeId).value().toBool());
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == hueColorActionTypeId) { } else if (action.actionTypeId() == hueColorActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createSetColorRequest(action.param(hueColorStateParamTypeId).value().value<QColor>()); QPair<QNetworkRequest, QByteArray> request = light->createSetColorRequest(action.param(hueColorStateParamTypeId).value().value<QColor>());
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply,QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == hueBrightnessActionTypeId) { } else if (action.actionTypeId() == hueBrightnessActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createSetBrightnessRequest(percentageToBrightness(action.param(hueBrightnessStateParamTypeId).value().toInt())); QPair<QNetworkRequest, QByteArray> request = light->createSetBrightnessRequest(percentageToBrightness(action.param(hueBrightnessStateParamTypeId).value().toInt()));
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == hueEffectActionTypeId) { } else if (action.actionTypeId() == hueEffectActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createSetEffectRequest(action.param(hueEffectStateParamTypeId).value().toString()); QPair<QNetworkRequest, QByteArray> request = light->createSetEffectRequest(action.param(hueEffectStateParamTypeId).value().toString());
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == hueAlertActionTypeId) { } else if (action.actionTypeId() == hueAlertActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createFlashRequest(action.param(alertParamTypeId).value().toString()); QPair<QNetworkRequest, QByteArray> request = light->createFlashRequest(action.param(alertParamTypeId).value().toString());
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == hueTemperatureActionTypeId) { } else if (action.actionTypeId() == hueTemperatureActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createSetTemperatureRequest(action.param(hueTemperatureStateParamTypeId).value().toInt()); QPair<QNetworkRequest, QByteArray> request = light->createSetTemperatureRequest(action.param(hueTemperatureStateParamTypeId).value().toInt());
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
return DeviceManager::DeviceErrorActionTypeNotFound; return DeviceManager::DeviceErrorActionTypeNotFound;
@ -481,15 +467,21 @@ DeviceManager::DeviceError DevicePluginPhilipsHue::executeAction(Device *device,
if (action.actionTypeId() == huePowerActionTypeId) { if (action.actionTypeId() == huePowerActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(action.param(huePowerStateParamTypeId).value().toBool()); QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(action.param(huePowerStateParamTypeId).value().toBool());
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == hueBrightnessActionTypeId) { } else if (action.actionTypeId() == hueBrightnessActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createSetBrightnessRequest(percentageToBrightness(action.param(hueBrightnessStateParamTypeId).value().toInt())); QPair<QNetworkRequest, QByteArray> request = light->createSetBrightnessRequest(percentageToBrightness(action.param(hueBrightnessStateParamTypeId).value().toInt()));
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == hueAlertActionTypeId) { } else if (action.actionTypeId() == hueAlertActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createFlashRequest(action.param(alertParamTypeId).value().toString()); QPair<QNetworkRequest, QByteArray> request = light->createFlashRequest(action.param(alertParamTypeId).value().toString());
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
return DeviceManager::DeviceErrorActionTypeNotFound; return DeviceManager::DeviceErrorActionTypeNotFound;
@ -507,11 +499,15 @@ DeviceManager::DeviceError DevicePluginPhilipsHue::executeAction(Device *device,
return DeviceManager::DeviceErrorNoError; return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == checkForUpdatesActionTypeId) { } else if (action.actionTypeId() == checkForUpdatesActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = bridge->createCheckUpdatesRequest(); QPair<QNetworkRequest, QByteArray> request = bridge->createCheckUpdatesRequest();
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} else if (action.actionTypeId() == upgradeActionTypeId) { } else if (action.actionTypeId() == upgradeActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = bridge->createUpgradeRequest(); QPair<QNetworkRequest, QByteArray> request = bridge->createUpgradeRequest();
m_asyncActions.insert(networkManagerPut(request.first, request.second),QPair<Device *, ActionId>(device, action.id())); QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
return DeviceManager::DeviceErrorActionTypeNotFound; return DeviceManager::DeviceErrorActionTypeNotFound;
@ -591,21 +587,58 @@ void DevicePluginPhilipsHue::onRemoteButtonEvent(const int &buttonCode)
} }
} }
void DevicePluginPhilipsHue::onTimeout() void DevicePluginPhilipsHue::onPluginTimer()
{ {
foreach (Device *device, m_bridges.values()) { foreach (Device *device, m_bridges.values()) {
refreshBridge(device); refreshBridge(device);
} }
} }
void DevicePluginPhilipsHue::onUpnpDiscoveryFinished()
{
qCDebug(dcPhilipsHue()) << "Upnp discovery finished";
UpnpDiscoveryReply *reply = static_cast<UpnpDiscoveryReply *>(sender());
if (reply->error() != UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNoError) {
qCWarning(dcPhilipsHue()) << "Upnp discovery error" << reply->error();
}
reply->deleteLater();
if (reply->deviceDescriptors().isEmpty()) {
qCDebug(dcPhilipsHue) << "No UPnP device found. Try N-UPNP discovery.";
QNetworkRequest request(QUrl("https://www.meethue.com/api/nupnp"));
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_discoveryRequests.append(reply);
return;
}
QList<DeviceDescriptor> deviceDescriptors;
foreach (const UpnpDeviceDescriptor &upnpDevice, reply->deviceDescriptors()) {
if (upnpDevice.modelDescription().contains("Philips")) {
DeviceDescriptor descriptor(hueBridgeDeviceClassId, "Philips Hue Bridge", upnpDevice.hostAddress().toString());
ParamList params;
params.append(Param(bridgeNameParamTypeId, upnpDevice.friendlyName()));
params.append(Param(bridgeHostParamTypeId, upnpDevice.hostAddress().toString()));
params.append(Param(bridgeApiParamTypeId, QString()));
params.append(Param(bridgeMacParamTypeId, QString()));
params.append(Param(bridgeIdParamTypeId, upnpDevice.serialNumber().toLower()));
params.append(Param(bridgeZigbeeChannelParamTypeId, -1));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
}
emit devicesDiscovered(hueBridgeDeviceClassId, deviceDescriptors);
}
void DevicePluginPhilipsHue::refreshLight(Device *device) void DevicePluginPhilipsHue::refreshLight(Device *device)
{ {
HueLight *light = m_lights.key(device); HueLight *light = m_lights.key(device);
QNetworkRequest request(QUrl("http://" + light->hostAddress().toString() + "/api/" + light->apiKey() + "/lights/" + QString::number(light->id()))); QNetworkRequest request(QUrl("http://" + light->hostAddress().toString() + "/api/" + light->apiKey() + "/lights/" + QString::number(light->id())));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_lightRefreshRequests.insert(reply, device); m_lightRefreshRequests.insert(reply, device);
} }
@ -624,8 +657,8 @@ void DevicePluginPhilipsHue::refreshBridge(Device *device)
QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/config")); QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/config"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_bridgeRefreshRequests.insert(reply, device); m_bridgeRefreshRequests.insert(reply, device);
} }
@ -635,8 +668,8 @@ void DevicePluginPhilipsHue::refreshLights(HueBridge *bridge)
QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/lights")); QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/lights"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_lightsRefreshRequests.insert(reply, device); m_lightsRefreshRequests.insert(reply, device);
} }
@ -646,8 +679,8 @@ void DevicePluginPhilipsHue::refreshSensors(HueBridge *bridge)
QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/sensors")); QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/sensors"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_sensorsRefreshRequests.insert(reply, device); m_sensorsRefreshRequests.insert(reply, device);
} }
@ -657,10 +690,14 @@ void DevicePluginPhilipsHue::discoverBridgeDevices(HueBridge *bridge)
qCDebug(dcPhilipsHue) << "Discover bridge devices" << bridge->hostAddress(); qCDebug(dcPhilipsHue) << "Discover bridge devices" << bridge->hostAddress();
QPair<QNetworkRequest, QByteArray> lightsRequest = bridge->createDiscoverLightsRequest(); QPair<QNetworkRequest, QByteArray> lightsRequest = bridge->createDiscoverLightsRequest();
m_bridgeLightsDiscoveryRequests.insert(networkManagerGet(lightsRequest.first), device); QNetworkReply *lightsReply = hardwareManager()->networkManager()->get(lightsRequest.first);
connect(lightsReply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_bridgeLightsDiscoveryRequests.insert(lightsReply, device);
QPair<QNetworkRequest, QByteArray> sensorsRequest = bridge->createSearchSensorsRequest(); QPair<QNetworkRequest, QByteArray> sensorsRequest = bridge->createSearchSensorsRequest();
m_bridgeSensorsDiscoveryRequests.insert(networkManagerGet(sensorsRequest.first), device); QNetworkReply *reply = hardwareManager()->networkManager()->get(sensorsRequest.first);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_bridgeSensorsDiscoveryRequests.insert(reply, device);
} }
void DevicePluginPhilipsHue::searchNewDevices(HueBridge *bridge) void DevicePluginPhilipsHue::searchNewDevices(HueBridge *bridge)
@ -669,7 +706,9 @@ void DevicePluginPhilipsHue::searchNewDevices(HueBridge *bridge)
qCDebug(dcPhilipsHue) << "Discover bridge devices" << bridge->hostAddress(); qCDebug(dcPhilipsHue) << "Discover bridge devices" << bridge->hostAddress();
QPair<QNetworkRequest, QByteArray> request = bridge->createSearchLightsRequest(); QPair<QNetworkRequest, QByteArray> request = bridge->createSearchLightsRequest();
m_bridgeSearchDevicesRequests.insert(networkManagerPost(request.first, request.second), device); QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_bridgeSearchDevicesRequests.insert(reply, device);
} }
void DevicePluginPhilipsHue::setLightName(Device *device, const QString &name) void DevicePluginPhilipsHue::setLightName(Device *device, const QString &name)
@ -684,7 +723,8 @@ void DevicePluginPhilipsHue::setLightName(Device *device, const QString &name)
"/lights/" + QString::number(light->id()))); "/lights/" + QString::number(light->id())));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManagerPut(request,jsonDoc.toJson()); QNetworkReply *reply = hardwareManager()->networkManager()->put(request,jsonDoc.toJson());
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_lightSetNameRequests.insert(reply, device); m_lightSetNameRequests.insert(reply, device);
} }
@ -1059,8 +1099,8 @@ void DevicePluginPhilipsHue::processPairingResponse(PairingInfo *pairingInfo, co
// Paired successfully, check bridge information // Paired successfully, check bridge information
QNetworkRequest request(QUrl("http://" + pairingInfo->host().toString() + "/api/" + pairingInfo->apiKey() + "/config")); QNetworkRequest request(QUrl("http://" + pairingInfo->host().toString() + "/api/" + pairingInfo->apiKey() + "/config"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManagerGet(request); QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_informationRequests.insert(reply, pairingInfo); m_informationRequests.insert(reply, pairingInfo);
} }

View File

@ -29,6 +29,9 @@
#include "huelight.h" #include "huelight.h"
#include "hueremote.h" #include "hueremote.h"
#include "pairinginfo.h" #include "pairinginfo.h"
#include "plugintimer.h"
#include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h"
class QNetworkReply; class QNetworkReply;
@ -41,19 +44,14 @@ class DevicePluginPhilipsHue: public DevicePlugin
public: public:
explicit DevicePluginPhilipsHue(); explicit DevicePluginPhilipsHue();
~DevicePluginPhilipsHue();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) override;
DeviceManager::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret) override; DeviceManager::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
public slots: public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action); DeviceManager::DeviceError executeAction(Device *device, const Action &action);
@ -61,10 +59,14 @@ private slots:
void lightStateChanged(); void lightStateChanged();
void remoteStateChanged(); void remoteStateChanged();
void onRemoteButtonEvent(const int &buttonCode); void onRemoteButtonEvent(const int &buttonCode);
void onTimeout(); void onPluginTimer();
private slots:
void onUpnpDiscoveryFinished();
void networkManagerReplyReady();
private: private:
QTimer *m_timer; PluginTimer *m_pluginTimer = nullptr;
QHash<QNetworkReply *, PairingInfo *> m_pairingRequests; QHash<QNetworkReply *, PairingInfo *> m_pairingRequests;
QHash<QNetworkReply *, PairingInfo *> m_informationRequests; QHash<QNetworkReply *, PairingInfo *> m_informationRequests;
@ -119,6 +121,7 @@ private:
int brightnessToPercentage(int brightness); int brightnessToPercentage(int brightness);
int percentageToBrightness(int percentage); int percentageToBrightness(int percentage);
}; };
#endif // DEVICEPLUGINBOBLIGHT_H #endif // DEVICEPLUGINBOBLIGHT_H

View File

@ -43,16 +43,22 @@
#include "devicepluginplantcare.h" #include "devicepluginplantcare.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/networkaccessmanager.h"
DevicePluginPlantCare::DevicePluginPlantCare() DevicePluginPlantCare::DevicePluginPlantCare()
{ {
} }
DeviceManager::HardwareResources DevicePluginPlantCare::requiredHardware() const DevicePluginPlantCare::~DevicePluginPlantCare()
{ {
// We need the NetworkAccessManager for node discovery and the timer for ping requests hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer; }
void DevicePluginPlantCare::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginPlantCare::onPluginTimer);
} }
DeviceManager::DeviceSetupStatus DevicePluginPlantCare::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginPlantCare::setupDevice(Device *device)
@ -85,6 +91,12 @@ void DevicePluginPlantCare::deviceRemoved(Device *device)
} }
} }
void DevicePluginPlantCare::postSetupDevice(Device *device)
{
// Try to ping the device after a successful setup
pingDevice(device);
}
DeviceManager::DeviceError DevicePluginPlantCare::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) DeviceManager::DeviceError DevicePluginPlantCare::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{ {
Q_UNUSED(params) Q_UNUSED(params)
@ -97,68 +109,12 @@ DeviceManager::DeviceError DevicePluginPlantCare::discoverDevices(const DeviceCl
url.setScheme("http"); url.setScheme("http");
url.setHost(address.toString()); url.setHost(address.toString());
m_asyncNodeScans.insert(networkManagerGet(QNetworkRequest(url)), deviceClassId); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginPlantCare::onNetworkReplyFinished);
m_asyncNodeScans.insert(reply, deviceClassId);
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
void DevicePluginPlantCare::networkManagerReplyReady(QNetworkReply *reply)
{
if (m_asyncNodeScans.keys().contains(reply)) {
DeviceClassId deviceClassId = m_asyncNodeScans.take(reply);
// Check HTTP status code
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
qCWarning(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(hostParamTypeId, 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::postSetupDevice(Device *device)
{
// Try to ping the device after a successful setup
pingDevice(device);
}
void DevicePluginPlantCare::guhTimer()
{
// 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);
}
}
}
DeviceManager::DeviceError DevicePluginPlantCare::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginPlantCare::executeAction(Device *device, const Action &action)
{ {
if (device->deviceClassId() != plantCareDeviceClassId) if (device->deviceClassId() != plantCareDeviceClassId)
@ -404,6 +360,60 @@ Device *DevicePluginPlantCare::findDevice(const QHostAddress &address)
return NULL; return NULL;
} }
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(hostParamTypeId, 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) void DevicePluginPlantCare::coapReplyFinished(CoapReply *reply)
{ {
if (m_pingReplies.contains(reply)) { if (m_pingReplies.contains(reply)) {

View File

@ -27,6 +27,7 @@
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "types/action.h" #include "types/action.h"
#include "coap/coap.h" #include "coap/coap.h"
#include "plugintimer.h"
#include <QHash> #include <QHash>
@ -38,19 +39,17 @@ class DevicePluginPlantCare : public DevicePlugin
public: public:
explicit DevicePluginPlantCare(); explicit DevicePluginPlantCare();
~DevicePluginPlantCare();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void postSetupDevice(Device *device) override; void postSetupDevice(Device *device) override;
void guhTimer() override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private: private:
PluginTimer *m_pluginTimer = nullptr;
QPointer<Coap> m_coap; QPointer<Coap> m_coap;
QHash<QNetworkReply *, DeviceClassId> m_asyncNodeScans; QHash<QNetworkReply *, DeviceClassId> m_asyncNodeScans;
QHash<CoapReply *, Device *> m_enableNotification; QHash<CoapReply *, Device *> m_enableNotification;
@ -82,6 +81,8 @@ private:
Device *findDevice(const QHostAddress &address); Device *findDevice(const QHostAddress &address);
private slots: private slots:
void onPluginTimer();
void onNetworkReplyFinished();
void coapReplyFinished(CoapReply *reply); void coapReplyFinished(CoapReply *reply);
void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload); void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload);
}; };

View File

@ -26,12 +26,6 @@ DevicePluginTcpCommander::DevicePluginTcpCommander()
{ {
} }
DeviceManager::HardwareResources DevicePluginTcpCommander::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
DeviceManager::DeviceSetupStatus DevicePluginTcpCommander::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginTcpCommander::setupDevice(Device *device)
{ {
if (device->deviceClassId() == tcpOutputDeviceClassId) { if (device->deviceClassId() == tcpOutputDeviceClassId) {

View File

@ -35,7 +35,6 @@ class DevicePluginTcpCommander : public DevicePlugin
public: public:
explicit DevicePluginTcpCommander(); explicit DevicePluginTcpCommander();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;

View File

@ -67,11 +67,6 @@ DevicePluginUdpCommander::DevicePluginUdpCommander()
} }
DeviceManager::HardwareResources DevicePluginUdpCommander::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
DeviceManager::DeviceSetupStatus DevicePluginUdpCommander::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginUdpCommander::setupDevice(Device *device)
{ {
// check port // check port

View File

@ -38,7 +38,6 @@ class DevicePluginUdpCommander : public DevicePlugin
public: public:
explicit DevicePluginUdpCommander(); explicit DevicePluginUdpCommander();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;

View File

@ -49,6 +49,8 @@
#include "devicepluginunitec.h" #include "devicepluginunitec.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "hardwaremanager.h"
#include "hardware/radio433/radio433.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -57,11 +59,6 @@ DevicePluginUnitec::DevicePluginUnitec()
{ {
} }
DeviceManager::HardwareResources DevicePluginUnitec::requiredHardware() const
{
return DeviceManager::HardwareResourceRadio433;
}
DeviceManager::DeviceSetupStatus DevicePluginUnitec::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginUnitec::setupDevice(Device *device)
{ {
if (device->deviceClassId() != switchDeviceClassId) { if (device->deviceClassId() != switchDeviceClassId) {
@ -80,6 +77,9 @@ DeviceManager::DeviceSetupStatus DevicePluginUnitec::setupDevice(Device *device)
DeviceManager::DeviceError DevicePluginUnitec::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginUnitec::executeAction(Device *device, const Action &action)
{ {
if (!hardwareManager()->radio433()->available())
return DeviceManager::DeviceErrorHardwareNotAvailable;
QList<int> rawData; QList<int> rawData;
QByteArray binCode; QByteArray binCode;
@ -127,11 +127,12 @@ DeviceManager::DeviceError DevicePluginUnitec::executeAction(Device *device, con
// ======================================= // =======================================
// send data to hardware resource // send data to hardware resource
if(transmitData(delay, rawData)){ if(hardwareManager()->radio433()->sendData(delay, rawData, 10)){
qCDebug(dcUnitec) << "transmitted" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool(); qCDebug(dcUnitec) << "transmitted" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool();
return DeviceManager::DeviceErrorNoError;
}else{ }else{
qCWarning(dcUnitec) << "could not transmitt" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool(); qCWarning(dcUnitec) << "could not transmitt" << pluginName() << device->name() << "power: " << action.param(powerParamTypeId).value().toBool();
return DeviceManager::DeviceErrorHardwareNotAvailable; return DeviceManager::DeviceErrorHardwareNotAvailable;
} }
return DeviceManager::DeviceErrorNoError;
} }

View File

@ -35,7 +35,6 @@ class DevicePluginUnitec : public DevicePlugin
public: public:
explicit DevicePluginUnitec(); explicit DevicePluginUnitec();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
public slots: public slots:

View File

@ -58,11 +58,6 @@ DevicePluginWakeOnLan::DevicePluginWakeOnLan()
{ {
} }
DeviceManager::HardwareResources DevicePluginWakeOnLan::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
DeviceManager::DeviceError DevicePluginWakeOnLan::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginWakeOnLan::executeAction(Device *device, const Action &action)
{ {
if(action.actionTypeId() == wolActionTypeId){ if(action.actionTypeId() == wolActionTypeId){

View File

@ -37,11 +37,8 @@ class DevicePluginWakeOnLan : public DevicePlugin
public: public:
explicit DevicePluginWakeOnLan(); explicit DevicePluginWakeOnLan();
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private slots: private slots:
void wakeup(QString mac); void wakeup(QString mac);

View File

@ -49,6 +49,8 @@
#include "plugin/device.h" #include "plugin/device.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h"
#include <QDebug> #include <QDebug>
#include <QNetworkReply> #include <QNetworkReply>
@ -61,13 +63,26 @@ DevicePluginWemo::DevicePluginWemo()
{ {
} }
DevicePluginWemo::~DevicePluginWemo()
{
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
}
void DevicePluginWemo::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginWemo::onPluginTimer);
connect(hardwareManager()->upnpDiscovery(), &UpnpDiscovery::upnpNotify, this, &DevicePluginWemo::onUpnpNotifyReceived);
}
DeviceManager::DeviceError DevicePluginWemo::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) DeviceManager::DeviceError DevicePluginWemo::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{ {
Q_UNUSED(params); Q_UNUSED(params);
if (deviceClassId != wemoSwitchDeviceClassId) { Q_UNUSED(deviceClassId)
return DeviceManager::DeviceErrorDeviceClassNotFound;
} UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("upnp:rootdevice");
upnpDiscover("upnp:rootdevice"); connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginWemo::onUpnpDiscoveryFinished);
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
@ -81,11 +96,6 @@ DeviceManager::DeviceSetupStatus DevicePluginWemo::setupDevice(Device *device)
return DeviceManager::DeviceSetupStatusSuccess; return DeviceManager::DeviceSetupStatusSuccess;
} }
DeviceManager::HardwareResources DevicePluginWemo::requiredHardware() const
{
return DeviceManager::HardwareResourceTimer | DeviceManager::HardwareResourceUpnpDisovery | DeviceManager::HardwareResourceNetworkManager;
}
DeviceManager::DeviceError DevicePluginWemo::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginWemo::executeAction(Device *device, const Action &action)
{ {
if (device->deviceClassId() != wemoSwitchDeviceClassId) if (device->deviceClassId() != wemoSwitchDeviceClassId)
@ -128,69 +138,6 @@ void DevicePluginWemo::deviceRemoved(Device *device)
} }
} }
void DevicePluginWemo::networkManagerReplyReady(QNetworkReply *reply)
{
if (m_refreshReplies.contains(reply)) {
QByteArray data = reply->readAll();
Device *device = m_refreshReplies.take(reply);
if (reply->error()) {
// give only error if we don't already know that is unreachable
if (device->stateValue(reachableStateTypeId).toBool()) {
qCWarning(dcWemo) << "WeMo reply error: " << reply->errorString();
}
device->setStateValue(reachableStateTypeId, false);
} else {
processRefreshData(data, device);
}
} else if (m_setPowerReplies.contains(reply)) {
QByteArray data = reply->readAll();
Device *device = m_setPowerReplies.take(reply);
ActionId actionId = m_runningActionExecutions.take(reply);
if (reply->error()) {
// give only error if we don't already know that is unreachable
if (device->stateValue(reachableStateTypeId).toBool()) {
qCWarning(dcWemo) << "WeMo reply error: " << reply->errorString();
}
device->setStateValue(reachableStateTypeId, false);
} else {
processSetPowerData(data, device, actionId);
}
}
reply->deleteLater();
}
void DevicePluginWemo::guhTimer()
{
foreach (Device* device, myDevices()) {
refresh(device);
}
}
void DevicePluginWemo::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList)
{
QList<DeviceDescriptor> deviceDescriptors;
foreach (UpnpDeviceDescriptor upnpDeviceDescriptor, upnpDeviceDescriptorList) {
if (upnpDeviceDescriptor.friendlyName() == "WeMo Switch") {
DeviceDescriptor descriptor(wemoSwitchDeviceClassId, "WemoSwitch", upnpDeviceDescriptor.serialNumber());
ParamList params;
params.append(Param(nameParamTypeId, upnpDeviceDescriptor.friendlyName()));
params.append(Param(hostParamTypeId, upnpDeviceDescriptor.hostAddress().toString()));
params.append(Param(portParamTypeId, upnpDeviceDescriptor.port()));
params.append(Param(serialParamTypeId, upnpDeviceDescriptor.serialNumber()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
}
emit devicesDiscovered(wemoSwitchDeviceClassId, deviceDescriptors);
}
void DevicePluginWemo::upnpNotifyReceived(const QByteArray &notifyData)
{
Q_UNUSED(notifyData);
}
void DevicePluginWemo::refresh(Device *device) void DevicePluginWemo::refresh(Device *device)
{ {
QByteArray getBinarayStateMessage("<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:GetBinaryState xmlns:u=\"urn:Belkin:service:basicevent:1\"><BinaryState>1</BinaryState></u:GetBinaryState></s:Body></s:Envelope>"); QByteArray getBinarayStateMessage("<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:GetBinaryState xmlns:u=\"urn:Belkin:service:basicevent:1\"><BinaryState>1</BinaryState></u:GetBinaryState></s:Body></s:Envelope>");
@ -201,7 +148,8 @@ void DevicePluginWemo::refresh(Device *device)
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("guh")); request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("guh"));
request.setRawHeader("SOAPACTION", "\"urn:Belkin:service:basicevent:1#GetBinaryState\""); request.setRawHeader("SOAPACTION", "\"urn:Belkin:service:basicevent:1#GetBinaryState\"");
QNetworkReply *reply = networkManagerPost(request, getBinarayStateMessage); QNetworkReply *reply = hardwareManager()->networkManager()->post(request, getBinarayStateMessage);
connect(reply, &QNetworkReply::finished, this, &DevicePluginWemo::onNetworkReplyFinished);
m_refreshReplies.insert(reply, device); m_refreshReplies.insert(reply, device);
} }
@ -220,7 +168,8 @@ bool DevicePluginWemo::setPower(Device *device, const bool &power, const ActionI
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("guh")); request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("guh"));
request.setRawHeader("SOAPACTION", "\"urn:Belkin:service:basicevent:1#SetBinaryState\""); request.setRawHeader("SOAPACTION", "\"urn:Belkin:service:basicevent:1#SetBinaryState\"");
QNetworkReply *reply = networkManagerPost(request, setPowerMessage); QNetworkReply *reply = hardwareManager()->networkManager()->post(request, setPowerMessage);
connect(reply, &QNetworkReply::finished, this, &DevicePluginWemo::onNetworkReplyFinished);
m_setPowerReplies.insert(reply, device); m_setPowerReplies.insert(reply, device);
m_runningActionExecutions.insert(reply, actionId); m_runningActionExecutions.insert(reply, actionId);
return true; return true;
@ -251,3 +200,67 @@ void DevicePluginWemo::processSetPowerData(const QByteArray &data, Device *devic
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorHardwareNotAvailable); emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorHardwareNotAvailable);
} }
} }
void DevicePluginWemo::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// check HTTP status code
if (status != 200 || reply->error() != QNetworkReply::NoError) {
qCWarning(dcWemo()) << "Request error:" << status << reply->errorString();
reply->deleteLater();
return;
}
if (m_refreshReplies.contains(reply)) {
QByteArray data = reply->readAll();
Device *device = m_refreshReplies.take(reply);
processRefreshData(data, device);
} else if (m_setPowerReplies.contains(reply)) {
QByteArray data = reply->readAll();
Device *device = m_setPowerReplies.take(reply);
ActionId actionId = m_runningActionExecutions.take(reply);
processSetPowerData(data, device, actionId);
}
reply->deleteLater();
}
void DevicePluginWemo::onPluginTimer()
{
foreach (Device* device, myDevices()) {
refresh(device);
}
}
void DevicePluginWemo::onUpnpDiscoveryFinished()
{
qCDebug(dcWemo()) << "Upnp discovery finished";
UpnpDiscoveryReply *reply = static_cast<UpnpDiscoveryReply *>(sender());
if (reply->error() != UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNoError) {
qCWarning(dcWemo()) << "Upnp discovery error" << reply->error();
}
reply->deleteLater();
QList<DeviceDescriptor> deviceDescriptors;
foreach (const UpnpDeviceDescriptor &upnpDeviceDescriptor, reply->deviceDescriptors()) {
if (upnpDeviceDescriptor.friendlyName() == "WeMo Switch") {
DeviceDescriptor descriptor(wemoSwitchDeviceClassId, "WeMo Switch", upnpDeviceDescriptor.serialNumber());
ParamList params;
params.append(Param(nameParamTypeId, upnpDeviceDescriptor.friendlyName()));
params.append(Param(hostParamTypeId, upnpDeviceDescriptor.hostAddress().toString()));
params.append(Param(portParamTypeId, upnpDeviceDescriptor.port()));
params.append(Param(serialParamTypeId, upnpDeviceDescriptor.serialNumber()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
}
emit devicesDiscovered(wemoSwitchDeviceClassId, deviceDescriptors);
}
void DevicePluginWemo::onUpnpNotifyReceived(const QByteArray &notification)
{
Q_UNUSED(notification)
}

View File

@ -23,6 +23,7 @@
#ifndef DEVICEPLUGINWEMO_H #ifndef DEVICEPLUGINWEMO_H
#define DEVICEPLUGINWEMO_H #define DEVICEPLUGINWEMO_H
#include "plugintimer.h"
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
class DevicePluginWemo : public DevicePlugin class DevicePluginWemo : public DevicePlugin
@ -34,20 +35,16 @@ class DevicePluginWemo : public DevicePlugin
public: public:
explicit DevicePluginWemo(); explicit DevicePluginWemo();
~DevicePluginWemo();
void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void guhTimer() override;
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) override;
void upnpNotifyReceived(const QByteArray &notifyData);
private: private:
PluginTimer *m_pluginTimer = nullptr;
QHash<QNetworkReply *, Device *> m_refreshReplies; QHash<QNetworkReply *, Device *> m_refreshReplies;
QHash<QNetworkReply *, Device *> m_setPowerReplies; QHash<QNetworkReply *, Device *> m_setPowerReplies;
QHash<QNetworkReply *, ActionId> m_runningActionExecutions; QHash<QNetworkReply *, ActionId> m_runningActionExecutions;
@ -58,6 +55,12 @@ private:
void processRefreshData(const QByteArray &data, Device *device); void processRefreshData(const QByteArray &data, Device *device);
void processSetPowerData(const QByteArray &data, Device *device, const ActionId &actionId); void processSetPowerData(const QByteArray &data, Device *device, const ActionId &actionId);
private slots:
void onNetworkReplyFinished();
void onPluginTimer();
void onUpnpDiscoveryFinished();
void onUpnpNotifyReceived(const QByteArray &notification);
}; };
#endif // DEVICEPLUGINWEMO_H #endif // DEVICEPLUGINWEMO_H

View File

@ -44,7 +44,7 @@
#include "devicepluginws2812.h" #include "devicepluginws2812.h"
#include "plugin/device.h" #include "plugin/device.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "network/networkaccessmanager.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -55,10 +55,15 @@ DevicePluginWs2812::DevicePluginWs2812()
} }
DeviceManager::HardwareResources DevicePluginWs2812::requiredHardware() const DevicePluginWs2812::~DevicePluginWs2812()
{ {
// We need the NetworkAccessManager for node discovery and the timer for ping requests hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer; }
void DevicePluginWs2812::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginWs2812::onPluginTimer);
} }
DeviceManager::DeviceSetupStatus DevicePluginWs2812::setupDevice(Device *device) DeviceManager::DeviceSetupStatus DevicePluginWs2812::setupDevice(Device *device)
@ -103,68 +108,18 @@ DeviceManager::DeviceError DevicePluginWs2812::discoverDevices(const DeviceClass
url.setScheme("http"); url.setScheme("http");
url.setHost(address.toString()); url.setHost(address.toString());
m_asyncNodeScans.insert(networkManagerGet(QNetworkRequest(url)), deviceClassId); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginWs2812::onNetworkReplyFinished);
m_asyncNodeScans.insert(reply, deviceClassId);
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
} }
void DevicePluginWs2812::networkManagerReplyReady(QNetworkReply *reply)
{
if (m_asyncNodeScans.keys().contains(reply)) {
DeviceClassId deviceClassId = m_asyncNodeScans.take(reply);
// Check HTTP status code
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
qCWarning(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(hostParamTypeId, 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::postSetupDevice(Device *device) void DevicePluginWs2812::postSetupDevice(Device *device)
{ {
// Try to ping the device after a successful setup // Try to ping the device after a successful setup
pingDevice(device); pingDevice(device);
} }
void DevicePluginWs2812::guhTimer()
{
// 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);
}
}
}
DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, const Action &action)
{ {
if (device->deviceClassId() != ws2812DeviceClassId) if (device->deviceClassId() != ws2812DeviceClassId)
@ -228,7 +183,7 @@ DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, con
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
}else if(action.actionTypeId() == brightnessActionTypeId) { } else if(action.actionTypeId() == brightnessActionTypeId) {
QUrl url; QUrl url;
url.setScheme("coap"); url.setScheme("coap");
@ -255,7 +210,7 @@ DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, con
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
}else if(action.actionTypeId() == maxPixActionTypeId) { } else if(action.actionTypeId() == maxPixActionTypeId) {
QUrl url; QUrl url;
url.setScheme("coap"); url.setScheme("coap");
@ -288,7 +243,7 @@ DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, con
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
}else if(action.actionTypeId() == effectModeActionTypeId) { } else if(action.actionTypeId() == effectModeActionTypeId) {
int effectmode = 0; int effectmode = 0;
@ -304,7 +259,7 @@ DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, con
//TODO switch to enum //TODO switch to enum
if(effectModeString == "Off") { if (effectModeString == "Off") {
effectmode = 0; effectmode = 0;
} else if (effectModeString == "Color On") { } else if (effectModeString == "Color On") {
effectmode = 1; effectmode = 1;
@ -312,17 +267,17 @@ DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, con
effectmode = 2; effectmode = 2;
} else if (effectModeString == "Color Fade") { } else if (effectModeString == "Color Fade") {
effectmode = 3; effectmode = 3;
}else if (effectModeString == "Color Flash") { } else if (effectModeString == "Color Flash") {
effectmode = 4; effectmode = 4;
}else if (effectModeString == "Rainbow Wave") { } else if (effectModeString == "Rainbow Wave") {
effectmode = 5; effectmode = 5;
}else if (effectModeString == "Rainbow Flash") { } else if (effectModeString == "Rainbow Flash") {
effectmode = 6; effectmode = 6;
}else if (effectModeString == "Knight Rider") { } else if (effectModeString == "Knight Rider") {
effectmode = 7; effectmode = 7;
}else if (effectModeString == "Fire") { } else if (effectModeString == "Fire") {
effectmode = 8; effectmode = 8;
}else if (effectModeString == "Tricolore") { } else if (effectModeString == "Tricolore") {
effectmode = 9; effectmode = 9;
} }
@ -330,7 +285,7 @@ DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, con
qCDebug(dcWs2812()) << "Sending" << payload << url.path(); qCDebug(dcWs2812()) << "Sending" << payload << url.path();
CoapReply *reply = m_coap->post(CoapRequest(url), payload); CoapReply *reply = m_coap->post(CoapRequest(url), payload);
if (reply->isFinished() && reply->error() != CoapReply::NoError) { if(reply->isFinished() && reply->error() != CoapReply::NoError) {
qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString(); qCWarning(dcWs2812) << "CoAP reply finished with error" << reply->errorString();
setReachable(device, false); setReachable(device, false);
reply->deleteLater(); reply->deleteLater();
@ -341,7 +296,7 @@ DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, con
m_asyncActions.insert(action.id(), device); m_asyncActions.insert(action.id(), device);
return DeviceManager::DeviceErrorAsync; return DeviceManager::DeviceErrorAsync;
}else if(action.actionTypeId() == tcolor1ActionTypeId || action.actionTypeId() == tcolor2ActionTypeId || action.actionTypeId() == tcolor3ActionTypeId) { } else if(action.actionTypeId() == tcolor1ActionTypeId || action.actionTypeId() == tcolor2ActionTypeId || action.actionTypeId() == tcolor3ActionTypeId) {
QUrl url; QUrl url;
url.setScheme("coap"); url.setScheme("coap");
@ -356,7 +311,7 @@ DeviceManager::DeviceError DevicePluginWs2812::executeAction(Device *device, con
* *
*/ */
if(action.actionTypeId() == tcolor1ActionTypeId){ if(action.actionTypeId() == tcolor1ActionTypeId) {
tColor1 = action.param(tcolor1StateParamTypeId).value().value<QColor>().toRgb(); tColor1 = action.param(tcolor1StateParamTypeId).value().value<QColor>().toRgb();
} else if(action.actionTypeId() == tcolor2ActionTypeId){ } else if(action.actionTypeId() == tcolor2ActionTypeId){
tColor2 = action.param(tcolor2StateParamTypeId).value().value<QColor>().toRgb(); tColor2 = action.param(tcolor2StateParamTypeId).value().value<QColor>().toRgb();
@ -558,6 +513,60 @@ Device *DevicePluginWs2812::findDevice(const QHostAddress &address)
return NULL; return NULL;
} }
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(hostParamTypeId, 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) void DevicePluginWs2812::coapReplyFinished(CoapReply *reply)
{ {
if (m_pingReplies.contains(reply)) { if (m_pingReplies.contains(reply)) {

View File

@ -27,6 +27,7 @@
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
#include "types/action.h" #include "types/action.h"
#include "coap/coap.h" #include "coap/coap.h"
#include "plugintimer.h"
#include <QColor> #include <QColor>
#include <QHash> #include <QHash>
@ -39,20 +40,17 @@ class DevicePluginWs2812 : public DevicePlugin
public: public:
explicit DevicePluginWs2812(); explicit DevicePluginWs2812();
~DevicePluginWs2812();
DeviceManager::HardwareResources requiredHardware() const override; void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void postSetupDevice(Device *device) override; void postSetupDevice(Device *device) override;
void guhTimer() override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private: private:
PluginTimer *m_pluginTimer = nullptr;
QPointer<Coap> m_coap; QPointer<Coap> m_coap;
QHash<QNetworkReply *, DeviceClassId> m_asyncNodeScans; QHash<QNetworkReply *, DeviceClassId> m_asyncNodeScans;
QHash<CoapReply *, Device *> m_enableNotification; QHash<CoapReply *, Device *> m_enableNotification;
@ -91,6 +89,8 @@ private:
QColor tColor3; QColor tColor3;
private slots: private slots:
void onPluginTimer();
void onNetworkReplyFinished();
void coapReplyFinished(CoapReply *reply); void coapReplyFinished(CoapReply *reply);
void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload); void onNotificationReceived(const CoapObserveResource &resource, const int &notificationNumber, const QByteArray &payload);
}; };