fixed state update
parent
d47214ac14
commit
5c28eaf871
|
|
@ -2,3 +2,13 @@
|
|||
|
||||
Let's you connect to your Tado account. All configured zones will appear in nymea automatically.
|
||||
You will get all relevant data and can set the mode and target temperature.
|
||||
|
||||
## Device Setup
|
||||
|
||||
nymea will connect to your Tado account. After the account is connected all associated devices
|
||||
will appear automatically. The Tado app is required to create a Tado account and connect the
|
||||
devices to it.
|
||||
|
||||
More about Tado:
|
||||
https://www.tado.com
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,30 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* This project may also contain libraries licensed under the open source software license GNU GPL v.3.
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project 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 project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "deviceplugintado.h"
|
||||
#include "devices/device.h"
|
||||
|
|
@ -34,11 +40,6 @@ DevicePluginTado::DevicePluginTado()
|
|||
|
||||
}
|
||||
|
||||
DevicePluginTado::~DevicePluginTado()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DevicePluginTado::startPairing(DevicePairingInfo *info)
|
||||
{
|
||||
info->finish(Device::DeviceErrorNoError, QT_TR_NOOP("Please enter the login credentials."));
|
||||
|
|
@ -53,6 +54,7 @@ void DevicePluginTado::confirmPairing(DevicePairingInfo *info, const QString &us
|
|||
connect(tado, &Tado::homesReceived, this, &DevicePluginTado::onHomesReceived);
|
||||
connect(tado, &Tado::zonesReceived, this, &DevicePluginTado::onZonesReceived);
|
||||
connect(tado, &Tado::zoneStateReceived, this, &DevicePluginTado::onZoneStateReceived);
|
||||
connect(tado, &Tado::overlayReceived, this, &DevicePluginTado::onOverlayReceived);
|
||||
m_unfinishedTadoAccounts.insert(info->deviceId(), tado);
|
||||
m_unfinishedDevicePairings.insert(info->deviceId(), info);
|
||||
tado->getToken(password);
|
||||
|
|
@ -88,6 +90,7 @@ void DevicePluginTado::setupDevice(DeviceSetupInfo *info)
|
|||
connect(tado, &Tado::homesReceived, this, &DevicePluginTado::onHomesReceived);
|
||||
connect(tado, &Tado::zonesReceived, this, &DevicePluginTado::onZonesReceived);
|
||||
connect(tado, &Tado::zoneStateReceived, this, &DevicePluginTado::onZoneStateReceived);
|
||||
connect(tado, &Tado::overlayReceived, this, &DevicePluginTado::onOverlayReceived);
|
||||
tado->getToken(password);
|
||||
m_tadoAccounts.insert(device->id(), tado);
|
||||
m_asyncDeviceSetup.insert(tado, info);
|
||||
|
|
@ -106,9 +109,6 @@ void DevicePluginTado::deviceRemoved(Device *device)
|
|||
if (device->deviceClassId() == tadoConnectionDeviceClassId) {
|
||||
Tado *tado = m_tadoAccounts.take(device->id());
|
||||
tado->deleteLater();
|
||||
|
||||
} else if (device->deviceClassId() == zoneDeviceClassId) {
|
||||
|
||||
}
|
||||
|
||||
if (myDevices().isEmpty() && m_pluginTimer) {
|
||||
|
|
@ -129,7 +129,6 @@ void DevicePluginTado::postSetupDevice(Device *device)
|
|||
device->setStateValue(tadoConnectionUserDisplayNameStateTypeId, tado->username());
|
||||
device->setStateValue(tadoConnectionLoggedInStateTypeId, true);
|
||||
device->setStateValue(tadoConnectionConnectedStateTypeId, true);
|
||||
|
||||
tado->getHomes();
|
||||
|
||||
} else if (device->deviceClassId() == zoneDeviceClassId) {
|
||||
|
|
@ -169,7 +168,8 @@ void DevicePluginTado::executeAction(DeviceActionInfo *info)
|
|||
|
||||
double temperature = action.param(zoneTargetTemperatureActionTargetTemperatureParamTypeId).value().toDouble();
|
||||
if (temperature <= 0) {
|
||||
tado->setOverlay(homeId, zoneId, false, 0);
|
||||
QUuid requestId = tado->setOverlay(homeId, zoneId, false, 0);
|
||||
m_asyncActions.insert(requestId, info);
|
||||
} else {
|
||||
tado->setOverlay(homeId, zoneId, true, temperature);
|
||||
}
|
||||
|
|
@ -210,7 +210,8 @@ void DevicePluginTado::onAuthenticationStatusChanged(bool authenticated)
|
|||
Tado *tado = static_cast<Tado*>(sender());
|
||||
|
||||
if (m_unfinishedTadoAccounts.values().contains(tado) && !authenticated){
|
||||
DeviceId id = m_tadoAccounts.key(tado);
|
||||
DeviceId id = m_unfinishedTadoAccounts.key(tado);
|
||||
m_unfinishedTadoAccounts.remove(id);
|
||||
DevicePairingInfo *info = m_unfinishedDevicePairings.take(id);
|
||||
info->finish(Device::DeviceErrorSetupFailed);
|
||||
}
|
||||
|
|
@ -238,10 +239,6 @@ void DevicePluginTado::onTokenReceived(Tado::Token token)
|
|||
DevicePairingInfo *info = m_unfinishedDevicePairings.take(id);
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
}
|
||||
|
||||
if (m_tadoAccounts.values().contains(tado)) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginTado::onHomesReceived(QList<Tado::Home> homes)
|
||||
|
|
@ -304,8 +301,6 @@ void DevicePluginTado::onZoneStateReceived(const QString &homeId, const QString
|
|||
}
|
||||
|
||||
device->setStateValue(zonePowerStateTypeId, (state.heatingPowerPercentage > 0));
|
||||
|
||||
|
||||
device->setStateValue(zoneConnectedStateTypeId, state.connected);
|
||||
device->setStateValue(zoneTargetTemperatureStateTypeId, state.settingTemperature);
|
||||
device->setStateValue(zoneTemperatureStateTypeId, state.temperature);
|
||||
|
|
@ -313,3 +308,26 @@ void DevicePluginTado::onZoneStateReceived(const QString &homeId, const QString
|
|||
device->setStateValue(zoneWindowOpenStateTypeId, state.windowOpen);
|
||||
device->setStateValue(zoneTadoModeStateTypeId, state.tadoMode);
|
||||
}
|
||||
|
||||
void DevicePluginTado::onOverlayReceived(const QString &homeId, const QString &zoneId, const Tado::Overlay &overlay)
|
||||
{
|
||||
Tado *tado = static_cast<Tado*>(sender());
|
||||
DeviceId parentId = m_tadoAccounts.key(tado);
|
||||
ParamList params;
|
||||
params.append(Param(zoneDeviceHomeIdParamTypeId, homeId));
|
||||
params.append(Param(zoneDeviceZoneIdParamTypeId, zoneId));
|
||||
Device *device = myDevices().filterByParentDeviceId(parentId).findByParams(params);
|
||||
if (!device)
|
||||
return;
|
||||
device->setStateValue(zoneTargetTemperatureStateTypeId, overlay.temperature);
|
||||
|
||||
if (overlay.tadoMode == "MANUAL") {
|
||||
if (overlay.power) {
|
||||
device->setStateValue(zoneModeStateTypeId, "Manual");
|
||||
} else {
|
||||
device->setStateValue(zoneModeStateTypeId, "Off");
|
||||
}
|
||||
} else {
|
||||
device->setStateValue(zoneModeStateTypeId, "Tado");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,30 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2020 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* This project may also contain libraries licensed under the open source software license GNU GPL v.3.
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project 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 project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef DEVICEPLUGINTADO_H
|
||||
#define DEVICEPLUGINTADO_H
|
||||
|
|
@ -39,8 +45,6 @@ class DevicePluginTado : public DevicePlugin
|
|||
|
||||
public:
|
||||
explicit DevicePluginTado();
|
||||
~DevicePluginTado();
|
||||
|
||||
void startPairing(DevicePairingInfo *info) override;
|
||||
void confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret) override;
|
||||
void setupDevice(DeviceSetupInfo *info) override;
|
||||
|
|
@ -55,6 +59,7 @@ private:
|
|||
|
||||
QHash<DeviceId, Tado*> m_tadoAccounts;
|
||||
QHash<Tado *, DeviceSetupInfo *> m_asyncDeviceSetup;
|
||||
QHash<QUuid, DeviceActionInfo *> m_asyncActions;
|
||||
|
||||
private slots:
|
||||
void onPluginTimer();
|
||||
|
|
@ -65,6 +70,7 @@ private slots:
|
|||
void onHomesReceived(QList<Tado::Home> homes);
|
||||
void onZonesReceived(const QString &homeId, QList<Tado::Zone> zones);
|
||||
void onZoneStateReceived(const QString &homeId,const QString &zoneId, Tado::ZoneState sate);
|
||||
void onOverlayReceived(const QString &homeId, const QString &zoneId, const Tado::Overlay &overlay);
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINTADO_H
|
||||
|
|
|
|||
192
tado/tado.cpp
192
tado/tado.cpp
|
|
@ -1,24 +1,30 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* This project may also contain libraries licensed under the open source software license GNU GPL v.3.
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project 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 project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "tado.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
|
@ -72,33 +78,47 @@ void Tado::getToken(const QString &password)
|
|||
if (reply->error() == QNetworkReply::HostNotFoundError) {
|
||||
emit connectionChanged(false);
|
||||
}
|
||||
if (status == 400 || status == 401) {
|
||||
if (status == 401) {
|
||||
emit authenticationStatusChanged(false);
|
||||
}
|
||||
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
emit authenticationStatusChanged(true);
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qDebug(dcTado()) << "Get Token: Recieved invalide JSON object";
|
||||
qDebug(dcTado()) << "Get Token: Received invalide JSON object";
|
||||
return;
|
||||
}
|
||||
Token token;
|
||||
QVariantMap obj = data.toVariant().toMap();
|
||||
token.accesToken = obj["access_token"].toString();
|
||||
m_accessToken = token.accesToken;
|
||||
token.tokenType = obj["token_type"].toString();
|
||||
token.refreshToken = obj["refresh_token"].toString();
|
||||
m_refreshToken = token.refreshToken;
|
||||
token.expires = obj["expires_in"].toInt();
|
||||
m_refreshTimer->start((token.expires - 10)*1000);
|
||||
token.scope = obj["scope"].toString();
|
||||
token.jti = obj["jti"].toString();
|
||||
emit tokenReceived(token);
|
||||
if (data.isObject()) {
|
||||
Token token;
|
||||
QVariantMap obj = data.toVariant().toMap();
|
||||
if (obj.contains("access_token")) {
|
||||
token.accesToken = obj["access_token"].toString();
|
||||
m_accessToken = token.accesToken;
|
||||
} else {
|
||||
qCWarning(dcTado()) << "Received response doesnt contain an access token";
|
||||
}
|
||||
|
||||
token.tokenType = obj["token_type"].toString();
|
||||
token.refreshToken = obj["refresh_token"].toString();
|
||||
m_refreshToken = token.refreshToken;
|
||||
if (obj.contains("expires_in")) {
|
||||
token.expires = obj["expires_in"].toInt();
|
||||
m_refreshTimer->start((token.expires - 10)*1000);
|
||||
} else {
|
||||
qCWarning(dcTado()) << "Received response doesn't contain an expire time";
|
||||
}
|
||||
token.scope = obj["scope"].toString();
|
||||
token.jti = obj["jti"].toString();
|
||||
emit authenticationStatusChanged(true);
|
||||
emit tokenReceived(token);
|
||||
} else {
|
||||
qCWarning(dcTado()) << "Received response isn't an object" << data.toJson();
|
||||
emit authenticationStatusChanged(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -119,12 +139,14 @@ void Tado::getHomes()
|
|||
if (reply->error() == QNetworkReply::HostNotFoundError) {
|
||||
emit connectionChanged(false);
|
||||
}
|
||||
if (status == 400 || status == 401) {
|
||||
if (status == 401) {
|
||||
emit authenticationStatusChanged(false);
|
||||
}
|
||||
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
emit authenticationStatusChanged(true);
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
|
|
@ -163,12 +185,14 @@ void Tado::getZones(const QString &homeId)
|
|||
if (reply->error() == QNetworkReply::HostNotFoundError) {
|
||||
emit connectionChanged(false);
|
||||
}
|
||||
if (status == 400 || status == 401) {
|
||||
if (status == 401) {
|
||||
emit authenticationStatusChanged(false);
|
||||
}
|
||||
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
emit authenticationStatusChanged(true);
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
|
|
@ -207,19 +231,24 @@ void Tado::getZoneState(const QString &homeId, const QString &zoneId)
|
|||
if (reply->error() == QNetworkReply::HostNotFoundError) {
|
||||
emit connectionChanged(false);
|
||||
}
|
||||
if (status == 400 || status == 401) {
|
||||
if (status == 401) {
|
||||
emit authenticationStatusChanged(false);
|
||||
}
|
||||
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
emit connectionChanged(true);
|
||||
emit authenticationStatusChanged(true);
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qDebug(dcTado()) << "Get Token: Recieved invalide JSON object";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug(dcTado()) << "Get zone stat" << data;
|
||||
ZoneState state;
|
||||
QVariantMap map = data.toVariant().toMap();
|
||||
state.tadoMode = map["tadoMode"].toString();
|
||||
|
|
@ -244,8 +273,9 @@ void Tado::getZoneState(const QString &homeId, const QString &zoneId)
|
|||
state.overlayIsSet = true;
|
||||
QVariantMap overlayMap = map["overlay"].toMap();
|
||||
state.overlayType = map["overlayType"].toString();
|
||||
state.overlaySettingPower = (overlayMap["settings"].toMap().value("power").toString() == "ON");
|
||||
state.overlaySettingTemperature = overlayMap["settings"].toMap().value("temperature").toDouble();
|
||||
qCDebug(dcTado()) << "Overlay power" << overlayMap["setting"].toMap().value("power").toString() << overlayMap["setting"].toMap().value("temperature").toDouble();
|
||||
state.overlaySettingPower = (overlayMap["setting"].toMap().value("power").toString() == "ON");
|
||||
state.overlaySettingTemperature = overlayMap["setting"].toMap().value("temperature").toDouble();
|
||||
} else {
|
||||
state.overlayIsSet = false;
|
||||
}
|
||||
|
|
@ -253,26 +283,13 @@ void Tado::getZoneState(const QString &homeId, const QString &zoneId)
|
|||
});
|
||||
}
|
||||
|
||||
void Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power, double targetTemperature)
|
||||
QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power, double targetTemperature)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/overlay"));
|
||||
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8");
|
||||
request.setRawHeader("Authorization", "Bearer " + m_accessToken.toLocal8Bit());
|
||||
/*QJsonDocument doc;
|
||||
QJsonObject obj;
|
||||
QJsonObject setting;
|
||||
setting.insert("power", "ON");
|
||||
QJsonObject temperature;
|
||||
temperature.insert("celsius", targetTemperature);
|
||||
//temperature.insert("fahrenheit", (targetTemperature * (9.0/5.0)) + 32.0);
|
||||
setting.insert("type", "HEATING");
|
||||
setting.insert("temperature", temperature);
|
||||
obj.insert("setting", setting);
|
||||
QJsonObject termination;
|
||||
termination.insert("type", "MANUAL");
|
||||
obj.insert("termination", termination);
|
||||
doc.setObject(obj);*/
|
||||
|
||||
QByteArray body;
|
||||
QByteArray powerString;
|
||||
|
|
@ -282,23 +299,30 @@ void Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power,
|
|||
powerString = "OFF";
|
||||
|
||||
body.append("{\"setting\":{\"type\":\"HEATING\",\"power\":\""+ powerString + "\",\"temperature\":{\"celsius\":" + QVariant(targetTemperature).toByteArray() + "}},\"termination\":{\"type\":\"MANUAL\"}}");
|
||||
qCDebug(dcTado()) << "Sending request" << body;
|
||||
QNetworkReply *reply = m_networkManager->put(request, body);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, this] {
|
||||
connect(reply, &QNetworkReply::finished, this, [homeId, zoneId, requestId, reply, this] {
|
||||
reply->deleteLater();
|
||||
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
// Check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
emit requestExecuted(requestId, false);
|
||||
if (reply->error() == QNetworkReply::HostNotFoundError) {
|
||||
emit connectionChanged(false);
|
||||
}
|
||||
if (status == 400 || status == 401) {
|
||||
if (status == 401) { //Unauthorized
|
||||
emit authenticationStatusChanged(false);
|
||||
} else if (status == 422) { //Unprocessable Entity
|
||||
qCWarning(dcTado()) << "Unprocessable Entity, probably a value out of range";
|
||||
} else {
|
||||
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||
}
|
||||
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit authenticationStatusChanged(true);
|
||||
emit connectionChanged(true);
|
||||
emit requestExecuted(requestId, true);
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
|
|
@ -307,32 +331,72 @@ void Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power,
|
|||
return;
|
||||
}
|
||||
QVariantMap map = data.toVariant().toMap();
|
||||
qCDebug(dcTado()) << map["type"].toString();
|
||||
|
||||
Overlay overlay;
|
||||
QVariantMap settingsMap = map["setting"].toMap();
|
||||
overlay.zoneType = settingsMap["type"].toString();
|
||||
overlay.power = (settingsMap["power"].toString() == "ON");
|
||||
overlay.temperature = settingsMap["temperature"].toMap().value("celsius").toDouble();
|
||||
QVariantMap terminationMap = map["termination"].toMap();
|
||||
overlay.terminationType = terminationMap["type"].toString();
|
||||
|
||||
overlay.tadoMode = map["type"].toString();
|
||||
emit overlayReceived(homeId, zoneId, overlay);
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
void Tado::deleteOverlay(const QString &homeId, const QString &zoneId)
|
||||
QUuid Tado::deleteOverlay(const QString &homeId, const QString &zoneId)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/overlay"));
|
||||
request.setRawHeader("Authorization", "Bearer " + m_accessToken.toLocal8Bit());
|
||||
QNetworkReply *reply = m_networkManager->deleteResource(request);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, this] {
|
||||
connect(reply, &QNetworkReply::finished, this, [homeId, zoneId, requestId, reply, this] {
|
||||
reply->deleteLater();
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
// Check HTTP status code
|
||||
if (status < 200 || status > 210 || reply->error() != QNetworkReply::NoError) {
|
||||
emit requestExecuted(requestId ,false);
|
||||
if (reply->error() == QNetworkReply::HostNotFoundError) {
|
||||
emit connectionChanged(false);
|
||||
}
|
||||
if (status == 400 || status == 401) {
|
||||
if (status == 401) { //Unauthorized
|
||||
emit authenticationStatusChanged(false);
|
||||
} else if (status == 422) { //Unprocessable Entity
|
||||
qCWarning(dcTado()) << "Unprocessable Entity, probably a value out of range";
|
||||
} else {
|
||||
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||
}
|
||||
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit authenticationStatusChanged(true);
|
||||
emit connectionChanged(true);
|
||||
emit requestExecuted(requestId, true);
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qDebug(dcTado()) << "Get Token: Recieved invalide JSON object";
|
||||
return;
|
||||
}
|
||||
QVariantMap map = data.toVariant().toMap();
|
||||
|
||||
Overlay overlay;
|
||||
QVariantMap settingsMap = map["setting"].toMap();
|
||||
overlay.zoneType = settingsMap["type"].toString();
|
||||
overlay.power = (settingsMap["power"].toString() == "ON");
|
||||
overlay.temperature = settingsMap["temperature"].toMap().value("celsius").toDouble();
|
||||
QVariantMap terminationMap = map["termination"].toMap();
|
||||
overlay.terminationType = terminationMap["type"].toString();
|
||||
|
||||
overlay.tadoMode = map["type"].toString();
|
||||
emit overlayReceived(homeId, zoneId, overlay);
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
void Tado::onRefreshTimer()
|
||||
|
|
|
|||
66
tado/tado.h
66
tado/tado.h
|
|
@ -1,24 +1,30 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* This project may also contain libraries licensed under the open source software license GNU GPL v.3.
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project 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 project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TADO_H
|
||||
#define TADO_H
|
||||
|
|
@ -28,6 +34,7 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
|
||||
class Tado : public QObject
|
||||
{
|
||||
|
|
@ -48,6 +55,15 @@ public:
|
|||
QString type;
|
||||
};
|
||||
|
||||
struct Overlay {
|
||||
bool power;
|
||||
double temperature;
|
||||
QString zoneType;
|
||||
QString terminationType;
|
||||
QString tadoMode;
|
||||
};
|
||||
|
||||
|
||||
struct ZoneState {
|
||||
bool connected;
|
||||
bool power;
|
||||
|
|
@ -81,8 +97,8 @@ public:
|
|||
void getZones(const QString &homeId);
|
||||
void getZoneState(const QString &homeId, const QString &zoneId);
|
||||
|
||||
void setOverlay(const QString &homeId, const QString &zoneId, bool power, double targetTemperature);
|
||||
void deleteOverlay(const QString &homeId, const QString &zoneId);
|
||||
QUuid setOverlay(const QString &homeId, const QString &zoneId, bool power, double targetTemperature);
|
||||
QUuid deleteOverlay(const QString &homeId, const QString &zoneId);
|
||||
|
||||
private:
|
||||
QByteArray m_baseAuthorizationUrl = "https://auth.tado.com/oauth/token";
|
||||
|
|
@ -99,12 +115,14 @@ private:
|
|||
signals:
|
||||
void connectionChanged(bool connected);
|
||||
void authenticationStatusChanged(bool authenticated);
|
||||
void requestExecuted(QUuid requestId, bool success);
|
||||
|
||||
void tokenReceived(Token token);
|
||||
|
||||
void homesReceived(QList<Home> homes);
|
||||
void zonesReceived(const QString &homeId, QList<Zone> zones);
|
||||
void zoneStateReceived(const QString &homeId,const QString &zoneId, ZoneState sate);
|
||||
void overlayReceived(const QString &homeId, const QString &zoneId, const Overlay &overlay);
|
||||
|
||||
private slots:
|
||||
void onRefreshTimer();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue