mirror of https://github.com/nymea/nymea.git
parent
550f8a29f4
commit
2693b1c8bd
|
|
@ -20,3 +20,4 @@ usr/lib/guh/plugins/libguh_devicepluginudpcommander.so
|
|||
usr/lib/guh/plugins/libguh_devicepluginkodi.so
|
||||
usr/lib/guh/plugins/libguh_devicepluginelgato.so
|
||||
usr/lib/guh/plugins/libguh_devicepluginawattar.so
|
||||
usr/lib/guh/plugins/libguh_devicepluginnetatmo.so
|
||||
|
|
|
|||
|
|
@ -257,12 +257,16 @@
|
|||
\li 36
|
||||
\li The value of the \l{Param} has unit \tt {[\%]} \unicode{0x2192} percentage.
|
||||
\row
|
||||
\li Types::UnitEuro
|
||||
\li Types::UnitPartsPerMillion
|
||||
\li 37
|
||||
\li The value of the \l{Param} has unit \tt {[ppm]} \unicode{0x2192} parts per million.
|
||||
\row
|
||||
\li Types::UnitEuro
|
||||
\li 38
|
||||
\li The value of the \l{Param} has unit \tt {[€]} \unicode{0x2192} euro.
|
||||
\row
|
||||
\li Types::UnitDollar
|
||||
\li 38
|
||||
\li 39
|
||||
\li The value of the \l{Param} has unit \tt {[\$]} \unicode{0x2192} dollar.
|
||||
\endtable
|
||||
|
||||
|
|
|
|||
2
guh.pri
2
guh.pri
|
|
@ -2,7 +2,7 @@
|
|||
GUH_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"')
|
||||
|
||||
# define protocol versions
|
||||
JSON_PROTOCOL_VERSION=31
|
||||
JSON_PROTOCOL_VERSION=32
|
||||
REST_API_VERSION=1
|
||||
|
||||
DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" \
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@ contains(DEFINES, BLUETOOTH_LE) {
|
|||
bluetooth/bluetoothlowenergydevice.h \
|
||||
}
|
||||
|
||||
SOURCES += plugin/device.cpp \
|
||||
SOURCES += devicemanager.cpp \
|
||||
loggingcategories.cpp \
|
||||
guhsettings.cpp \
|
||||
plugin/device.cpp \
|
||||
plugin/deviceclass.cpp \
|
||||
plugin/deviceplugin.cpp \
|
||||
plugin/devicedescriptor.cpp \
|
||||
devicemanager.cpp \
|
||||
hardware/gpio.cpp \
|
||||
hardware/gpiomonitor.cpp \
|
||||
hardware/radio433/radio433.cpp \
|
||||
|
|
@ -31,6 +33,8 @@ SOURCES += plugin/device.cpp \
|
|||
network/upnpdiscovery/upnpdevice.cpp \
|
||||
network/upnpdiscovery/upnpdevicedescriptor.cpp \
|
||||
network/upnpdiscovery/upnpdiscoveryrequest.cpp \
|
||||
network/networkmanager.cpp \
|
||||
network/oauth2.cpp \
|
||||
types/action.cpp \
|
||||
types/actiontype.cpp \
|
||||
types/state.cpp \
|
||||
|
|
@ -45,14 +49,15 @@ SOURCES += plugin/device.cpp \
|
|||
types/ruleaction.cpp \
|
||||
types/ruleactionparam.cpp \
|
||||
types/statedescriptor.cpp \
|
||||
loggingcategories.cpp \
|
||||
guhsettings.cpp \
|
||||
|
||||
HEADERS += plugin/device.h \
|
||||
HEADERS += devicemanager.h \
|
||||
typeutils.h \
|
||||
loggingcategories.h \
|
||||
guhsettings.h \
|
||||
plugin/device.h \
|
||||
plugin/deviceclass.h \
|
||||
plugin/deviceplugin.h \
|
||||
plugin/devicedescriptor.h \
|
||||
devicemanager.h \
|
||||
hardware/gpio.h \
|
||||
hardware/gpiomonitor.h \
|
||||
hardware/radio433/radio433.h \
|
||||
|
|
@ -63,6 +68,8 @@ HEADERS += plugin/device.h \
|
|||
network/upnpdiscovery/upnpdevice.h \
|
||||
network/upnpdiscovery/upnpdevicedescriptor.h \
|
||||
network/upnpdiscovery/upnpdiscoveryrequest.h \
|
||||
network/networkmanager.h \
|
||||
network/oauth2.h \
|
||||
types/action.h \
|
||||
types/actiontype.h \
|
||||
types/state.h \
|
||||
|
|
@ -77,9 +84,6 @@ HEADERS += plugin/device.h \
|
|||
types/ruleaction.h \
|
||||
types/ruleactionparam.h \
|
||||
types/statedescriptor.h \
|
||||
typeutils.h \
|
||||
loggingcategories.h \
|
||||
guhsettings.h \
|
||||
|
||||
|
||||
# install files for libguh-dev
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@ Q_LOGGING_CATEGORY(dcDeviceManager, "DeviceManager")
|
|||
Q_LOGGING_CATEGORY(dcRuleEngine, "RuleEngine")
|
||||
Q_LOGGING_CATEGORY(dcHardware, "Hardware")
|
||||
Q_LOGGING_CATEGORY(dcConnection, "Connection")
|
||||
Q_LOGGING_CATEGORY(dcLogEngine, "LogEngine")
|
||||
Q_LOGGING_CATEGORY(dcTcpServer, "TcpServer")
|
||||
Q_LOGGING_CATEGORY(dcWebServer, "WebServer")
|
||||
Q_LOGGING_CATEGORY(dcWebSocketServer, "WebSocketServer")
|
||||
Q_LOGGING_CATEGORY(dcJsonRpc, "JsonRpc")
|
||||
Q_LOGGING_CATEGORY(dcRest, "Rest")
|
||||
Q_LOGGING_CATEGORY(dcLogEngine, "LogEngine")
|
||||
Q_LOGGING_CATEGORY(dcWebSocketServer, "WebSocketServer")
|
||||
Q_LOGGING_CATEGORY(dcOAuth2, "OAuth2")
|
||||
|
|
|
|||
|
|
@ -29,11 +29,12 @@ Q_DECLARE_LOGGING_CATEGORY(dcDeviceManager)
|
|||
Q_DECLARE_LOGGING_CATEGORY(dcRuleEngine)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcHardware)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcConnection)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcJsonRpc)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcRest)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcLogEngine)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcTcpServer)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcWebServer)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServer)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcJsonRpc)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcRest)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcOAuth2)
|
||||
|
||||
#endif // LOGGINGCATEGORYS_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "oauth2.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QNetworkRequest>
|
||||
#include <QJsonDocument>
|
||||
|
||||
OAuth2::OAuth2(QString clientId, QString clientSecret, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_clientId(clientId),
|
||||
m_clientSecret(clientSecret),
|
||||
m_authenticated(false)
|
||||
{
|
||||
m_networkManager = new QNetworkAccessManager(this);
|
||||
connect(m_networkManager, &QNetworkAccessManager::finished, this, &OAuth2::replyFinished);
|
||||
|
||||
m_timer = new QTimer(this);
|
||||
m_timer->setSingleShot(false);
|
||||
|
||||
connect(m_timer, &QTimer::timeout, this, &OAuth2::refreshTimeout);
|
||||
}
|
||||
|
||||
QUrl OAuth2::url() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
void OAuth2::setUrl(const QUrl &url)
|
||||
{
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
QUrlQuery OAuth2::query() const
|
||||
{
|
||||
return m_query;
|
||||
}
|
||||
|
||||
void OAuth2::setQuery(const QUrlQuery &query)
|
||||
{
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
QString OAuth2::username() const
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
|
||||
void OAuth2::setUsername(const QString &username)
|
||||
{
|
||||
m_username = username;
|
||||
}
|
||||
|
||||
QString OAuth2::password() const
|
||||
{
|
||||
return m_password;
|
||||
}
|
||||
|
||||
void OAuth2::setPassword(const QString &password)
|
||||
{
|
||||
m_password = password;
|
||||
}
|
||||
|
||||
QString OAuth2::clientId() const
|
||||
{
|
||||
return m_clientId;
|
||||
}
|
||||
|
||||
void OAuth2::setClientId(const QString &clientId)
|
||||
{
|
||||
m_clientId = clientId;
|
||||
}
|
||||
|
||||
QString OAuth2::clientSecret() const
|
||||
{
|
||||
return m_clientSecret;
|
||||
}
|
||||
|
||||
void OAuth2::setClientSecret(const QString clientSecret)
|
||||
{
|
||||
m_clientSecret = clientSecret;
|
||||
}
|
||||
|
||||
QString OAuth2::scope() const
|
||||
{
|
||||
return m_scope;
|
||||
}
|
||||
|
||||
void OAuth2::setScope(const QString &scope)
|
||||
{
|
||||
m_scope = scope;
|
||||
}
|
||||
|
||||
QString OAuth2::token() const
|
||||
{
|
||||
return m_token;
|
||||
}
|
||||
|
||||
bool OAuth2::authenticated() const
|
||||
{
|
||||
return m_authenticated;
|
||||
}
|
||||
|
||||
void OAuth2::startAuthentication()
|
||||
{
|
||||
qCDebug(dcOAuth2) << "Start authentication" << m_username;
|
||||
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("grant_type", "password");
|
||||
query.addQueryItem("client_id", m_clientId);
|
||||
query.addQueryItem("client_secret", m_clientSecret);
|
||||
query.addQueryItem("username", m_username);
|
||||
query.addQueryItem("password", m_password);
|
||||
query.addQueryItem("scope", m_scope);
|
||||
setQuery(query);
|
||||
|
||||
QNetworkRequest request(m_url);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
m_tokenRequests.append(m_networkManager->post(request, m_query.toString().toUtf8()));
|
||||
}
|
||||
|
||||
void OAuth2::setAuthenticated(const bool &authenticated)
|
||||
{
|
||||
if (authenticated) {
|
||||
qCDebug(dcOAuth2) << "Authenticated successfully" << m_username;
|
||||
} else {
|
||||
qCWarning(dcOAuth2) << "Authentication failed" << m_username;
|
||||
}
|
||||
m_authenticated = authenticated;
|
||||
emit authenticationChanged();
|
||||
}
|
||||
|
||||
void OAuth2::setToken(const QString &token)
|
||||
{
|
||||
m_token = token;
|
||||
emit tokenChanged();
|
||||
}
|
||||
|
||||
void OAuth2::replyFinished(QNetworkReply *reply)
|
||||
{
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
// token request
|
||||
if (m_tokenRequests.contains(reply)) {
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
m_tokenRequests.removeAll(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200) {
|
||||
qCWarning(dcOAuth2) << "Request token reply HTTP error:" << status << reply->errorString();
|
||||
qCWarning(dcOAuth2) << data;
|
||||
setAuthenticated(false);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// check JSON
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcOAuth2) << "Request token reply JSON error:" << error.errorString();
|
||||
setAuthenticated(false);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jsonDoc.toVariant().toMap().contains("access_token")) {
|
||||
qCWarning(dcOAuth2) << "Could not get access token" << jsonDoc.toJson();
|
||||
setAuthenticated(false);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
setToken(jsonDoc.toVariant().toMap().value("access_token").toString());
|
||||
setAuthenticated(true);
|
||||
|
||||
if (jsonDoc.toVariant().toMap().contains("expires_in") && jsonDoc.toVariant().toMap().contains("refresh_token")) {
|
||||
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
|
||||
m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toString();
|
||||
qCDebug(dcOAuth2) << "Token will be refreshed in" << expireTime << "[s]";
|
||||
m_timer->start((expireTime - 20) * 1000);
|
||||
}
|
||||
|
||||
} else if (m_refreshTokenRequests.contains(reply)) {
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
m_refreshTokenRequests.removeAll(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200) {
|
||||
qCWarning(dcOAuth2) << "Refresh token reply HTTP error:" << status << reply->errorString();
|
||||
qCWarning(dcOAuth2) << data;
|
||||
setAuthenticated(false);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// check JSON
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcOAuth2) << "Refresh token reply JSON error:" << error.errorString();
|
||||
setAuthenticated(false);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jsonDoc.toVariant().toMap().contains("access_token")) {
|
||||
qCWarning(dcOAuth2) << "Could not get access token after refresh" << jsonDoc.toJson();
|
||||
setAuthenticated(false);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
setToken(jsonDoc.toVariant().toMap().value("access_token").toString());
|
||||
qCDebug(dcOAuth2) << "Token refreshed successfully";
|
||||
|
||||
if (jsonDoc.toVariant().toMap().contains("expires_in") && jsonDoc.toVariant().toMap().contains("refresh_token")) {
|
||||
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
|
||||
m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toString();
|
||||
qCDebug(dcOAuth2) << "Token will be refreshed in" << expireTime << "[s]";
|
||||
m_timer->start((expireTime - 20) * 1000);
|
||||
}
|
||||
|
||||
if (!authenticated())
|
||||
setAuthenticated(true);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void OAuth2::refreshTimeout()
|
||||
{
|
||||
qCDebug(dcOAuth2) << "Refresh authentication token for" << m_username;
|
||||
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("grant_type", "refresh_token");
|
||||
query.addQueryItem("refresh_token", m_refreshToken);
|
||||
query.addQueryItem("client_id", m_clientId);
|
||||
query.addQueryItem("client_secret", m_clientSecret);
|
||||
|
||||
QNetworkRequest request(m_url);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
m_refreshTokenRequests.append(m_networkManager->post(request, query.toString().toUtf8()));
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef OAUTH2_H
|
||||
#define OAUTH2_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QUrlQuery>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
// OAuth 2.0 - Resource Owner Password Credentials Grant: http://tools.ietf.org/html/rfc6749#section-4.3
|
||||
|
||||
class OAuth2 : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OAuth2(QString clientId, QString clientSecret, QObject *parent = 0);
|
||||
|
||||
QUrl url() const;
|
||||
void setUrl(const QUrl &url);
|
||||
|
||||
QUrlQuery query() const;
|
||||
void setQuery(const QUrlQuery &query);
|
||||
|
||||
QString username() const;
|
||||
void setUsername(const QString &username);
|
||||
|
||||
QString password() const;
|
||||
void setPassword(const QString &password);
|
||||
|
||||
QString clientId() const;
|
||||
void setClientId(const QString &clientId);
|
||||
|
||||
QString clientSecret() const;
|
||||
void setClientSecret(const QString clientSecret);
|
||||
|
||||
QString scope() const;
|
||||
void setScope(const QString &scope);
|
||||
|
||||
QString token() const;
|
||||
|
||||
bool authenticated() const;
|
||||
|
||||
void startAuthentication();
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QTimer *m_timer;
|
||||
QList<QNetworkReply *> m_tokenRequests;
|
||||
QList<QNetworkReply *> m_refreshTokenRequests;
|
||||
|
||||
QUrl m_url;
|
||||
QUrlQuery m_query;
|
||||
QString m_username;
|
||||
QString m_password;
|
||||
QString m_clientId;
|
||||
QString m_clientSecret;
|
||||
QString m_scope;
|
||||
|
||||
QString m_token;
|
||||
QString m_refreshToken;
|
||||
|
||||
bool m_authenticated;
|
||||
|
||||
void setAuthenticated(const bool &authenticated);
|
||||
void setToken(const QString &token);
|
||||
|
||||
private slots:
|
||||
void replyFinished(QNetworkReply *reply);
|
||||
void refreshTimeout();
|
||||
|
||||
signals:
|
||||
void authenticationChanged();
|
||||
void tokenChanged();
|
||||
|
||||
};
|
||||
|
||||
#endif // OAUTH2_H
|
||||
|
|
@ -760,6 +760,8 @@ Types::Unit DevicePlugin::unitStringToUnit(const QString &unitString) const
|
|||
return Types::UnitEuroPerMegaWattHour;
|
||||
} else if (unitString == "Percentage") {
|
||||
return Types::UnitPercentage;
|
||||
} else if (unitString == "PartsPerMillion") {
|
||||
return Types::UnitPartsPerMillion;
|
||||
} else if (unitString == "Euro") {
|
||||
return Types::UnitEuro;
|
||||
} else if (unitString == "Dollar") {
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ public:
|
|||
UnitKiloWattHour,
|
||||
UnitEuroPerMegaWattHour,
|
||||
UnitPercentage,
|
||||
UnitPartsPerMillion,
|
||||
UnitEuro,
|
||||
UnitDollar
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
\note If a \l{StateType} has the parameter \tt{"writable": {...}}, an \l{ActionType} with the same uuid and \l{ParamType}{ParamTypes}
|
||||
will be created automatically.
|
||||
|
||||
\quotefile plugins/deviceplugins/udpcommander/devicepluginawattar.json
|
||||
\quotefile plugins/deviceplugins/awattar/devicepluginawattar.json
|
||||
*/
|
||||
|
||||
#include "devicepluginawattar.h"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ SUBDIRS += elro \
|
|||
kodi \
|
||||
elgato \
|
||||
awattar \
|
||||
netatmo \
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "Elgato",
|
||||
"id": "c5c03ad4-bfdb-444a-8eca-2c234c46cc27",
|
||||
"idName": "Elgato",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "Elgato",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,218 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*!
|
||||
\page netatmo.html
|
||||
\title netatmo
|
||||
|
||||
\ingroup plugins
|
||||
\ingroup network
|
||||
|
||||
This plugin allows to receive data from you netatmo weather station.
|
||||
|
||||
\chapter Plugin properties
|
||||
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
|
||||
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
|
||||
|
||||
Each \l{DeviceClass} has a list of \l{ParamType}{paramTypes}, \l{ActionType}{actionTypes}, \l{StateType}{stateTypes}
|
||||
and \l{EventType}{eventTypes}. The \l{DeviceClass::CreateMethod}{createMethods} parameter describes how the \l{Device}
|
||||
will be created in the system. A device can have more than one \l{DeviceClass::CreateMethod}{CreateMethod}.
|
||||
The \l{DeviceClass::SetupMethod}{setupMethod} describes the setup method of the \l{Device}.
|
||||
The detailed implementation of each \l{DeviceClass} can be found in the source code.
|
||||
|
||||
\note If a \l{StateType} has the parameter \tt{"writable": {...}}, an \l{ActionType} with the same uuid and \l{ParamType}{ParamTypes}
|
||||
will be created automatically.
|
||||
|
||||
\quotefile plugins/deviceplugins/netatmo/devicepluginnetatmo.json
|
||||
*/
|
||||
|
||||
#include "devicepluginnetatmo.h"
|
||||
#include "plugin/device.h"
|
||||
#include "plugininfo.h"
|
||||
|
||||
#include <QUrlQuery>
|
||||
#include <QJsonDocument>
|
||||
|
||||
DevicePluginNetatmo::DevicePluginNetatmo()
|
||||
{
|
||||
}
|
||||
|
||||
DeviceManager::HardwareResources DevicePluginNetatmo::requiredHardware() const
|
||||
{
|
||||
return DeviceManager::HardwareResourceNetworkManager | DeviceManager::HardwareResourceTimer;
|
||||
}
|
||||
|
||||
DeviceManager::DeviceSetupStatus DevicePluginNetatmo::setupDevice(Device *device)
|
||||
{
|
||||
if (device->deviceClassId() == connectionDeviceClassId) {
|
||||
qCDebug(dcNetatmo) << "Setup netatmo connection";
|
||||
|
||||
OAuth2 *authentication = new OAuth2("561c015d49c75f0d1cce6e13", "GuvKkdtu7JQlPD47qTTepRR9hQ0CUPAj4Tae3Ohcq", this);
|
||||
authentication->setUrl(QUrl("https://api.netatmo.net/oauth2/token"));
|
||||
authentication->setUsername(device->paramValue("username").toString());
|
||||
authentication->setPassword(device->paramValue("password").toString());
|
||||
authentication->setScope("read_station read_thermostat write_thermostat");
|
||||
|
||||
m_authentications.insert(authentication, device);
|
||||
m_asyncSetups.append(device);
|
||||
connect(authentication, &OAuth2::authenticationChanged, this, &DevicePluginNetatmo::onAuthenticationChanged);
|
||||
|
||||
authentication->startAuthentication();
|
||||
return DeviceManager::DeviceSetupStatusAsync;
|
||||
|
||||
} else if (device->deviceClassId() == indoorDeviceClassId) {
|
||||
qCDebug(dcNetatmo) << "Setup netatmo indoor base station" << device->params();
|
||||
NetatmoBaseStation *indoor = new NetatmoBaseStation(device->paramValue("name").toString(),
|
||||
device->paramValue("mac address").toString(),
|
||||
device->paramValue("connection id").toString(), this);
|
||||
|
||||
connect(indoor, &NetatmoBaseStation::statesChanged, this, &DevicePluginNetatmo::onIndoorStatesChanged);
|
||||
|
||||
return DeviceManager::DeviceSetupStatusSuccess;
|
||||
}
|
||||
|
||||
return DeviceManager::DeviceSetupStatusFailure;
|
||||
}
|
||||
|
||||
void DevicePluginNetatmo::deviceRemoved(Device *device)
|
||||
{
|
||||
OAuth2 * authentication = m_authentications.key(device);
|
||||
m_authentications.remove(authentication);
|
||||
authentication->deleteLater();
|
||||
}
|
||||
|
||||
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();
|
||||
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
|
||||
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();
|
||||
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcNetatmo) << jsonDoc.toJson();
|
||||
processRefreshData(jsonDoc.toVariant().toMap(), device->id().toString());
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void DevicePluginNetatmo::guhTimer()
|
||||
{
|
||||
foreach (Device *device, myDevices()) {
|
||||
if (device->deviceClassId() == connectionDeviceClassId) {
|
||||
OAuth2 *authentication = m_authentications.key(device);
|
||||
// TODO: check if authenticated
|
||||
refreshData(device, authentication->token());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginNetatmo::refreshData(Device *device, const QString &token)
|
||||
{
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("access_token", token);
|
||||
|
||||
QUrl url("https://api.netatmo.com/api/devicelist");
|
||||
url.setQuery(query);
|
||||
|
||||
QNetworkReply *reply = networkManagerGet(QNetworkRequest(url));
|
||||
m_refreshRequest.insert(reply, device);
|
||||
}
|
||||
|
||||
void DevicePluginNetatmo::processRefreshData(const QVariantMap &data, const QString &connectionId)
|
||||
{
|
||||
if (data.contains("body")) {
|
||||
if (data.value("body").toMap().contains("devices")) {
|
||||
QVariantList deviceList = data.value("body").toMap().value("devices").toList();
|
||||
//QVariantList modulesList = data.value("body").toMap().value("modules").toList();
|
||||
|
||||
// check devices
|
||||
foreach (QVariant deviceVariant, deviceList) {
|
||||
QVariantMap deviceMap = deviceVariant.toMap();
|
||||
// we support currently only NAMain devices
|
||||
if (deviceMap.value("type").toString() == "NAMain") {
|
||||
NetatmoBaseStation *indoor = findIndoorDevice(deviceMap.value("_id").toString());
|
||||
// check if we have to create the device (auto)
|
||||
if (!indoor) {
|
||||
DeviceDescriptor descriptor(indoorDeviceClassId, "Indoor Station", deviceMap.value("station_name").toString());
|
||||
ParamList params;
|
||||
params.append(Param("name", deviceMap.value("station_name").toString()));
|
||||
params.append(Param("mac address", deviceMap.value("_id").toString()));
|
||||
params.append(Param("connection id", connectionId));
|
||||
descriptor.setParams(params);
|
||||
emit autoDevicesAppeared(indoorDeviceClassId, QList<DeviceDescriptor>() << descriptor);
|
||||
} else {
|
||||
indoor->updateStates(deviceMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NetatmoBaseStation *DevicePluginNetatmo::findIndoorDevice(const QString &macAddress)
|
||||
{
|
||||
foreach (NetatmoBaseStation *bs, m_indoorDevices.keys()) {
|
||||
if (bs->macAddress() == macAddress) {
|
||||
return bs;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DevicePluginNetatmo::onAuthenticationChanged()
|
||||
{
|
||||
OAuth2 *authentication = static_cast<OAuth2 *>(sender());
|
||||
Device *device = m_authentications.value(authentication);
|
||||
|
||||
// check if this is was a setup athentication
|
||||
if (m_asyncSetups.contains(device)) {
|
||||
m_asyncSetups.removeAll(device);
|
||||
if (authentication->authenticated()) {
|
||||
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
|
||||
refreshData(device, authentication->token());
|
||||
} else {
|
||||
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
|
||||
m_authentications.remove(authentication);
|
||||
authentication->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef DEVICEPLUGINNETATMO_H
|
||||
#define DEVICEPLUGINNETATMO_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
#include "plugin/deviceplugin.h"
|
||||
#include "network/oauth2.h"
|
||||
#include "netatmobasestation.h"
|
||||
|
||||
class DevicePluginNetatmo : public DevicePlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "devicepluginnetatmo.json")
|
||||
Q_INTERFACES(DevicePlugin)
|
||||
|
||||
public:
|
||||
explicit DevicePluginNetatmo();
|
||||
|
||||
DeviceManager::HardwareResources requiredHardware() const override;
|
||||
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
|
||||
void deviceRemoved(Device *device) override;
|
||||
void networkManagerReplyReady(QNetworkReply *reply) override;
|
||||
|
||||
void guhTimer() override;
|
||||
|
||||
private:
|
||||
QList<Device *> m_asyncSetups;
|
||||
|
||||
QHash<OAuth2 *, Device *> m_authentications;
|
||||
QHash<NetatmoBaseStation *, Device *> m_indoorDevices;
|
||||
|
||||
QHash<QNetworkReply *, Device *> m_refreshRequest;
|
||||
|
||||
void refreshData(Device *device, const QString &token);
|
||||
void processRefreshData(const QVariantMap &data, const QString &connectionId);
|
||||
|
||||
NetatmoBaseStation *findIndoorDevice(const QString &macAddress);
|
||||
|
||||
private slots:
|
||||
void onAuthenticationChanged();
|
||||
void onIndoorStatesChanged();
|
||||
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINNETATMO_H
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
{
|
||||
"name": "Netatmo",
|
||||
"idName": "Netatmo",
|
||||
"id": "3af70774-4b43-46fe-96a4-22108d4efb1b",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "Netatmo",
|
||||
"idName": "netatmo",
|
||||
"id": "31828f6f-c63d-4d44-b2b1-d0f70b3ce933",
|
||||
"deviceClasses": [
|
||||
{
|
||||
"deviceClassId": "728d5a67-27a3-400e-b83c-2765f5196f69",
|
||||
"name": "Netatmo Connection",
|
||||
"idName": "connection",
|
||||
"createMethods": ["user"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"name": "username",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine"
|
||||
},
|
||||
{
|
||||
"name": "password",
|
||||
"type": "QString",
|
||||
"inputType": "Password"
|
||||
}
|
||||
],
|
||||
"stateType": [
|
||||
{
|
||||
"id": "2f79bc1d-27ed-480a-b583-728363c83ea6",
|
||||
"idName": "available",
|
||||
"name": "available",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"deviceClassId": "d79d373c-c992-4d75-bd01-a0f8ab346ac5",
|
||||
"name": "Indoor Station",
|
||||
"idName": "indoor",
|
||||
"createMethods": ["auto"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"name": "mac address",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"name": "connection id",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"readOnly": true
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "50da9f6b-c350-401c-a72e-2e4036f3975d",
|
||||
"idName": "updateTime",
|
||||
"name": "last update",
|
||||
"unit": "UnixTime",
|
||||
"type": "int",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "3cb25538-e463-40ae-92f9-8f34f0c06b92",
|
||||
"idName": "temperature",
|
||||
"name": "temperature",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "ae8bb713-8805-4efd-89a1-bca44a1f1690",
|
||||
"idName": "temperatureMin",
|
||||
"name": "temperature minimum",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "dd30507e-037b-4c74-bcca-e04b94c7c5fe",
|
||||
"idName": "temperatureMax",
|
||||
"name": "temperature maximum",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "e2db5f01-196a-48d1-8874-6b8cbfe0d8c9",
|
||||
"idName": "humidity",
|
||||
"name": "humidity",
|
||||
"unit": "Percentage",
|
||||
"type": "int",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "03b0a7b7-987d-4d3b-b3f0-21d9f92ad326",
|
||||
"idName": "pressure",
|
||||
"name": "pressure",
|
||||
"unit": "MilliBar",
|
||||
"type": "double",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "906cea9d-1daf-4e9c-90b9-e40f43052a34",
|
||||
"idName": "noise",
|
||||
"name": "noise",
|
||||
"unit": "Dezibel",
|
||||
"type": "int",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "e5710bd1-79fa-4bd4-9052-8416aae909b9",
|
||||
"idName": "co2",
|
||||
"name": "co2",
|
||||
"unit": "PartsPerMillion",
|
||||
"type": "int",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "6ea906d4-5740-454d-a730-6fdb9fa0d624",
|
||||
"idName": "wifiStrength",
|
||||
"name": "wifi signal strength",
|
||||
"unit": "Percentage",
|
||||
"type": "int",
|
||||
"defaultValue": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
include(../../plugins.pri)
|
||||
|
||||
TARGET = $$qtLibraryTarget(guh_devicepluginnetatmo)
|
||||
|
||||
SOURCES += \
|
||||
devicepluginnetatmo.cpp \
|
||||
netatmobasestation.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginnetatmo.h \
|
||||
netatmobasestation.h
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "netatmobasestation.h"
|
||||
|
||||
NetatmoBaseStation::NetatmoBaseStation(const QString &name, const QString &macAddress, const QString &connectionId, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_name(name),
|
||||
m_macAddress(macAddress),
|
||||
m_connectionId(connectionId)
|
||||
{
|
||||
}
|
||||
|
||||
QString NetatmoBaseStation::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
QString NetatmoBaseStation::macAddress() const
|
||||
{
|
||||
return m_macAddress;
|
||||
}
|
||||
|
||||
QString NetatmoBaseStation::connectionId() const
|
||||
{
|
||||
return m_connectionId;
|
||||
}
|
||||
|
||||
int NetatmoBaseStation::lastUpdate() const
|
||||
{
|
||||
return m_lastUpdate;
|
||||
}
|
||||
|
||||
double NetatmoBaseStation::temperature() const
|
||||
{
|
||||
return m_temperature;
|
||||
}
|
||||
|
||||
double NetatmoBaseStation::minTemperature() const
|
||||
{
|
||||
return m_minTemperature;
|
||||
}
|
||||
|
||||
double NetatmoBaseStation::maxTemperature() const
|
||||
{
|
||||
return m_maxTemperature;
|
||||
}
|
||||
|
||||
double NetatmoBaseStation::pressure() const
|
||||
{
|
||||
return m_pressure;
|
||||
}
|
||||
|
||||
int NetatmoBaseStation::humidity() const
|
||||
{
|
||||
return m_humidity;
|
||||
}
|
||||
|
||||
int NetatmoBaseStation::noise() const
|
||||
{
|
||||
return m_noise;
|
||||
}
|
||||
|
||||
int NetatmoBaseStation::co2() const
|
||||
{
|
||||
return m_co2;
|
||||
}
|
||||
|
||||
int NetatmoBaseStation::wifiStrength() const
|
||||
{
|
||||
return m_wifiStrength;
|
||||
}
|
||||
|
||||
void NetatmoBaseStation::updateStates(const QVariantMap &data)
|
||||
{
|
||||
Q_UNUSED(data)
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef NETATMOBASESTATION_H
|
||||
#define NETATMOBASESTATION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class NetatmoBaseStation : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NetatmoBaseStation(const QString &name, const QString &macAddress, const QString &connectionId, QObject *parent = 0);
|
||||
|
||||
// Params
|
||||
QString name() const;
|
||||
QString macAddress() const;
|
||||
QString connectionId() const;
|
||||
|
||||
// States
|
||||
int lastUpdate() const;
|
||||
double temperature() const;
|
||||
double minTemperature() const;
|
||||
double maxTemperature() const;
|
||||
double pressure() const;
|
||||
int humidity() const;
|
||||
int noise() const;
|
||||
int co2() const;
|
||||
int wifiStrength() const;
|
||||
|
||||
void updateStates(const QVariantMap &data);
|
||||
|
||||
private:
|
||||
// Params
|
||||
QString m_name;
|
||||
QString m_macAddress;
|
||||
QString m_connectionId;
|
||||
|
||||
// States
|
||||
int m_lastUpdate;
|
||||
double m_temperature;
|
||||
double m_minTemperature;
|
||||
double m_maxTemperature;
|
||||
double m_pressure;
|
||||
int m_humidity;
|
||||
int m_noise;
|
||||
int m_co2;
|
||||
int m_wifiStrength;
|
||||
|
||||
signals:
|
||||
void statesChanged();
|
||||
};
|
||||
|
||||
#endif // NETATMOBASESTATION_H
|
||||
|
|
@ -61,14 +61,15 @@ int main(int argc, char *argv[])
|
|||
s_loggingFilters.insert("Warnings", true);
|
||||
s_loggingFilters.insert("DeviceManager", true);
|
||||
s_loggingFilters.insert("RuleEngine", true);
|
||||
s_loggingFilters.insert("Hardware", false);
|
||||
s_loggingFilters.insert("Connection", true);
|
||||
s_loggingFilters.insert("LogEngine", false);
|
||||
s_loggingFilters.insert("TcpServer", false);
|
||||
s_loggingFilters.insert("WebServer", true);
|
||||
s_loggingFilters.insert("WebSocketServer", false);
|
||||
s_loggingFilters.insert("JsonRpc", false);
|
||||
s_loggingFilters.insert("Rest", true);
|
||||
s_loggingFilters.insert("Hardware", false);
|
||||
s_loggingFilters.insert("LogEngine", false);
|
||||
s_loggingFilters.insert("OAuth2", false);
|
||||
|
||||
QHash<QString, bool> loggingFiltersPlugins;
|
||||
foreach (const QJsonObject &pluginMetadata, DeviceManager::pluginsMetadata()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue