mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-08-05 03:33:51 +02:00
POC of fridge thing.
Fixed authentication (refresh token needs to be saved again when refreshing access token).
This commit is contained in:
parent
ef95857664
commit
7d2de6f268
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "integrationpluginmiele.h"
|
#include "integrationpluginmiele.h"
|
||||||
#include "plugininfo.h"
|
#include "plugininfo.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
@ -56,6 +57,14 @@ IntegrationPluginMiele::IntegrationPluginMiele()
|
|||||||
m_connectedStateTypeIds.insert(cookTopThingClassId, cookTopConnectedStateTypeId);
|
m_connectedStateTypeIds.insert(cookTopThingClassId, cookTopConnectedStateTypeId);
|
||||||
m_connectedStateTypeIds.insert(cleaningRobotThingClassId, cleaningRobotConnectedStateTypeId);
|
m_connectedStateTypeIds.insert(cleaningRobotThingClassId, cleaningRobotConnectedStateTypeId);
|
||||||
m_connectedStateTypeIds.insert(hoodThingClassId, hoodConnectedStateTypeId);
|
m_connectedStateTypeIds.insert(hoodThingClassId, hoodConnectedStateTypeId);
|
||||||
|
|
||||||
|
m_mieleDeviceTypeLabelToThingClassId.insert("oven", ovenThingClassId);
|
||||||
|
m_mieleDeviceTypeLabelToThingClassId.insert("washing machine", washerThingClassId);
|
||||||
|
m_mieleDeviceTypeLabelToThingClassId.insert("dish washer", dishwasherThingClassId);
|
||||||
|
m_mieleDeviceTypeLabelToThingClassId.insert("coffee system", coffeeMakerThingClassId);
|
||||||
|
m_mieleDeviceTypeLabelToThingClassId.insert("tumber dryer", dryerThingClassId);
|
||||||
|
m_mieleDeviceTypeLabelToThingClassId.insert("refrigerator", fridgeThingClassId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginMiele::startPairing(ThingPairingInfo *info)
|
void IntegrationPluginMiele::startPairing(ThingPairingInfo *info)
|
||||||
@ -148,7 +157,15 @@ void IntegrationPluginMiele::setupThing(ThingSetupInfo *info)
|
|||||||
m_mieleConnections.insert(info->thing(), miele);
|
m_mieleConnections.insert(info->thing(), miele);
|
||||||
info->finish(Thing::ThingErrorNoError);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
});
|
});
|
||||||
|
connect(miele, &Miele::receivedRefreshToken, info, [info, thing, this](const QByteArray &refreshToken){
|
||||||
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
|
pluginStorage()->setValue("refresh_token", refreshToken);
|
||||||
|
pluginStorage()->endGroup();
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
});
|
||||||
connect(info, &ThingSetupInfo::aborted, miele, &Miele::deleteLater);
|
connect(info, &ThingSetupInfo::aborted, miele, &Miele::deleteLater);
|
||||||
|
connect(miele, &Miele::devicesFound, this, &IntegrationPluginMiele::onDevicesFound);
|
||||||
|
connect(miele, &Miele::deviceStateReceived, this, &IntegrationPluginMiele::onDeviceStateReceived);
|
||||||
}
|
}
|
||||||
} else if (m_idParamTypeIds.contains(thing->thingClassId())) {
|
} else if (m_idParamTypeIds.contains(thing->thingClassId())) {
|
||||||
Thing *parentThing = myThings().findById(thing->parentId());
|
Thing *parentThing = myThings().findById(thing->parentId());
|
||||||
@ -172,7 +189,7 @@ void IntegrationPluginMiele::postSetupThing(Thing *thing)
|
|||||||
qCDebug(dcMiele()) << "Post setup thing" << thing->name();
|
qCDebug(dcMiele()) << "Post setup thing" << thing->name();
|
||||||
if (!m_pluginTimer15min) {
|
if (!m_pluginTimer15min) {
|
||||||
qCDebug(dcMiele()) << "Registering plugin timer";
|
qCDebug(dcMiele()) << "Registering plugin timer";
|
||||||
m_pluginTimer15min = hardwareManager()->pluginTimerManager()->registerTimer(60*15);
|
m_pluginTimer15min = hardwareManager()->pluginTimerManager()->registerTimer(60 * 1);
|
||||||
connect(m_pluginTimer15min, &PluginTimer::timeout, this, [this]() {
|
connect(m_pluginTimer15min, &PluginTimer::timeout, this, [this]() {
|
||||||
qCDebug(dcMiele()) << "Plugin timer triggered";
|
qCDebug(dcMiele()) << "Plugin timer triggered";
|
||||||
Q_FOREACH (Thing *thing, myThings().filterByThingClassId(mieleAccountThingClassId)) {
|
Q_FOREACH (Thing *thing, myThings().filterByThingClassId(mieleAccountThingClassId)) {
|
||||||
@ -181,10 +198,10 @@ void IntegrationPluginMiele::postSetupThing(Thing *thing)
|
|||||||
qWarning(dcMiele()) << "No Miele account found for" << thing->name();
|
qWarning(dcMiele()) << "No Miele account found for" << thing->name();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
miele->getDevices();
|
miele->getDevicesShort();
|
||||||
Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) {
|
Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) {
|
||||||
QString deviceId = childThing->paramValue(m_idParamTypeIds.value(childThing->thingClassId())).toString();
|
QString deviceId = childThing->paramValue(m_idParamTypeIds.value(childThing->thingClassId())).toString();
|
||||||
miele->getDevice(deviceId);
|
miele->getDeviceState(deviceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -192,7 +209,7 @@ void IntegrationPluginMiele::postSetupThing(Thing *thing)
|
|||||||
|
|
||||||
if (thing->thingClassId() == mieleAccountThingClassId) {
|
if (thing->thingClassId() == mieleAccountThingClassId) {
|
||||||
Miele *miele = m_mieleConnections.value(thing);
|
Miele *miele = m_mieleConnections.value(thing);
|
||||||
miele->getDevices();
|
miele->getDevicesShort();
|
||||||
//miele->connectEventStream();
|
//miele->connectEventStream();
|
||||||
thing->setStateValue(mieleAccountConnectedStateTypeId, true);
|
thing->setStateValue(mieleAccountConnectedStateTypeId, true);
|
||||||
thing->setStateValue(mieleAccountLoggedInStateTypeId, true);
|
thing->setStateValue(mieleAccountLoggedInStateTypeId, true);
|
||||||
@ -206,7 +223,7 @@ void IntegrationPluginMiele::postSetupThing(Thing *thing)
|
|||||||
if (!miele) {
|
if (!miele) {
|
||||||
qCWarning(dcMiele()) << "Could not find HomeConnect connection for thing" << thing->name();
|
qCWarning(dcMiele()) << "Could not find HomeConnect connection for thing" << thing->name();
|
||||||
} else {
|
} else {
|
||||||
miele->getDevice(deviceId);
|
miele->getDeviceState(deviceId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||||
@ -221,10 +238,17 @@ void IntegrationPluginMiele::executeAction(ThingActionInfo *info)
|
|||||||
if (!miele) {
|
if (!miele) {
|
||||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||||
}
|
}
|
||||||
QString haid = thing->paramValue(m_idParamTypeIds.value(thing->thingClassId())).toString();
|
QString deviceId = thing->paramValue(m_idParamTypeIds.value(thing->thingClassId())).toString();
|
||||||
|
|
||||||
if (thing->thingClassId() == ovenThingClassId) {
|
|
||||||
|
|
||||||
|
if (thing->thingClassId() == fridgeThingClassId) {
|
||||||
|
if (action.actionTypeId() == fridgeTargetTemperatureActionTypeId) {
|
||||||
|
double targetTemp = action.param(fridgeTargetTemperatureActionTargetTemperatureParamTypeId).value().toDouble();
|
||||||
|
int iTargetTemp = floor(targetTemp);
|
||||||
|
qCDebug(dcMiele()) << "Setting fridge temp: " << iTargetTemp;
|
||||||
|
miele->setTargetTemperature(deviceId, 1, iTargetTemp);
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
thing->setStateValue(fridgeTargetTemperatureStateTypeId, iTargetTemp);
|
||||||
|
}
|
||||||
} else if (thing->thingClassId() == ovenThingClassId) {
|
} else if (thing->thingClassId() == ovenThingClassId) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -327,4 +351,86 @@ void IntegrationPluginMiele::onRequestExecuted(QUuid requestId, bool success)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginMiele::onDevicesFound(QList<Miele::DeviceShort> devices)
|
||||||
|
{
|
||||||
|
qCDebug(dcMiele()) << "Found " << devices.size() << " devices";
|
||||||
|
Miele *miele = static_cast<Miele*>(sender());
|
||||||
|
|
||||||
|
if(m_mieleConnections.values().contains(miele)) {
|
||||||
|
Thing *parentDevice = myThings().findById(m_mieleConnections.key(miele)->id());
|
||||||
|
qCDebug(dcMiele()) << devices.size() << " devices received for prent: " << parentDevice->id();
|
||||||
|
|
||||||
|
ThingDescriptors descriptors;
|
||||||
|
foreach(Miele::DeviceShort ds, devices) {
|
||||||
|
qCDebug(dcMiele()) << "Setting up device: " << ds.type << " " << ds.name << " " << ds.state;
|
||||||
|
if (!m_mieleDeviceTypeLabelToThingClassId.contains(ds.type.toLower())) {
|
||||||
|
qCDebug(dcMiele()) << "Device type [" << ds.type << "] is not supported!";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ThingClassId deviceClassId = m_mieleDeviceTypeLabelToThingClassId.value(ds.type.toLower());
|
||||||
|
ThingDescriptor descriptor(deviceClassId, ds.name, "Appliance type: " + ds.type, parentDevice->id());
|
||||||
|
ParamList params;
|
||||||
|
params.append(Param(m_idParamTypeIds.value(deviceClassId), ds.fabNumber));
|
||||||
|
if (myThings().findByParams(params)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
descriptor.setParams(params);
|
||||||
|
descriptors.append(descriptor);
|
||||||
|
}
|
||||||
|
emit autoThingsAppeared(descriptors);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// TODO: improve debug message
|
||||||
|
qCWarning(dcMiele()) << "Miele connection not linked to a thingId";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IntegrationPluginMiele::onDeviceStateReceived(const QString &deviceId, const QVariantMap &deviceState)
|
||||||
|
{
|
||||||
|
Miele *miele = static_cast<Miele*>(sender());
|
||||||
|
if (!m_mieleConnections.values().contains(miele)) {
|
||||||
|
qCWarning(dcMiele()) << "Can't find Miele connection!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thing *parentDevice = myThings().findById(m_mieleConnections.key(miele)->id());
|
||||||
|
if (!parentDevice) {
|
||||||
|
qCWarning(dcMiele()) << "Can't find parent thing!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(Thing *thing, myThings().filterByParentId(parentDevice->id())) {
|
||||||
|
if (thing->paramValue(m_idParamTypeIds.value(thing->thingClassId())).toString() == deviceId) {
|
||||||
|
qCDebug(dcMiele()) << "Received state for: " << thing->name();
|
||||||
|
setThingState(thing, deviceState);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginMiele::setThingState(Thing *thing, const QVariantMap &state)
|
||||||
|
{
|
||||||
|
qCDebug(dcMiele()) << "Setting device state: " << thing->name();
|
||||||
|
if (thing->thingClassId() == fridgeThingClassId) {
|
||||||
|
qCDebug(dcMiele()) << "Setting state for fridge!";
|
||||||
|
|
||||||
|
bool connected = state.value("status").toMap().value("value_raw").toInt() == Miele::StatusNotConnected
|
||||||
|
? false
|
||||||
|
: true;
|
||||||
|
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), connected);
|
||||||
|
|
||||||
|
// Fridges should have only one temperature zone
|
||||||
|
QVariant fridgeTempZone = state.value("temperature").toList().first();
|
||||||
|
double fridgeTemp = fridgeTempZone.toMap().value("value_raw").toDouble();
|
||||||
|
thing->setStateValue(fridgeTemperatureStateTypeId, fridgeTemp / 100);
|
||||||
|
|
||||||
|
QVariant fridgeTargetTempZone = state.value("targetTemperature").toList().first();
|
||||||
|
double fridgeTargetTemp = fridgeTargetTempZone.toMap().value("value_raw").toDouble();
|
||||||
|
thing->setStateValue(fridgeTargetTemperatureStateTypeId, fridgeTargetTemp / 100);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qCWarning(dcMiele()) << "Device " << thing->name() << " is not yet supported!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -67,13 +67,18 @@ private:
|
|||||||
QHash<ThingClassId, ParamTypeId> m_idParamTypeIds;
|
QHash<ThingClassId, ParamTypeId> m_idParamTypeIds;
|
||||||
|
|
||||||
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIds;
|
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIds;
|
||||||
|
QHash<QString, ThingClassId> m_mieleDeviceTypeLabelToThingClassId;
|
||||||
|
|
||||||
Miele *createMieleConnection();
|
Miele *createMieleConnection();
|
||||||
|
void setThingState(Thing *thing, const QVariantMap &state);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onConnectionChanged(bool connected);
|
void onConnectionChanged(bool connected);
|
||||||
void onAuthenticationStatusChanged(bool authenticated);
|
void onAuthenticationStatusChanged(bool authenticated);
|
||||||
void onRequestExecuted(QUuid requestId, bool success);
|
void onRequestExecuted(QUuid requestId, bool success);
|
||||||
|
|
||||||
|
void onDevicesFound(QList<Miele::DeviceShort> devices);
|
||||||
|
void onDeviceStateReceived(const QString &deviceId, const QVariantMap &deviceState);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INTEGRATIONPLUGINMIELE_H
|
#endif // INTEGRATIONPLUGINMIELE_H
|
||||||
|
|||||||
@ -178,7 +178,7 @@
|
|||||||
"id": "a03e17fd-8da8-4977-8ac3-c058ada9f547",
|
"id": "a03e17fd-8da8-4977-8ac3-c058ada9f547",
|
||||||
"name": "fridge",
|
"name": "fridge",
|
||||||
"displayName": "Fridge Freezer",
|
"displayName": "Fridge Freezer",
|
||||||
"interfaces": ["connectable"],
|
"interfaces": ["thermostat", "connectable"],
|
||||||
"createMethods": ["auto"],
|
"createMethods": ["auto"],
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
@ -198,6 +198,42 @@
|
|||||||
"defaultValue": true,
|
"defaultValue": true,
|
||||||
"cached": false,
|
"cached": false,
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ef656321-e2c8-4339-be18-aa3cdb53dea6",
|
||||||
|
"name": "temperature",
|
||||||
|
"displayName": "Temperature",
|
||||||
|
"displayNameEvent": "Temperature changed",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"type": "double",
|
||||||
|
"minValue": "0",
|
||||||
|
"maxValue": "10",
|
||||||
|
"unit": "DegreeCelsius"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ebac99f4-cb89-4813-9b21-a9c6bf5209d5",
|
||||||
|
"name": "targetTemperature",
|
||||||
|
"displayName": "Temperature Setting",
|
||||||
|
"displayNameEvent": "Temperature setting changed",
|
||||||
|
"displayNameAction": "Set target temperature",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"type": "double",
|
||||||
|
"minValue": "0",
|
||||||
|
"maxValue": "10",
|
||||||
|
"unit": "DegreeCelsius",
|
||||||
|
"writable": true,
|
||||||
|
"ioType": "analogInput"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "60a46368-febc-4cff-bbfb-99064dbb93a9",
|
||||||
|
"name": "power",
|
||||||
|
"displayName": "On/off",
|
||||||
|
"displayNameEvent": "Turned on/off",
|
||||||
|
"displayNameAction": "Turn on/off",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false,
|
||||||
|
"writable": true,
|
||||||
|
"ioType": "digitalInput"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
|
|
||||||
@ -93,6 +94,10 @@ void Miele::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//delete me
|
||||||
|
qCDebug(dcMiele()) << "Refresh token is not empty: " << refreshToken;
|
||||||
|
qCDebug(dcMiele()) << "Client: " << m_clientId << " secret: " << m_clientSecret;
|
||||||
|
|
||||||
QUrl url(m_tokenUrl);
|
QUrl url(m_tokenUrl);
|
||||||
QUrlQuery query;
|
QUrlQuery query;
|
||||||
query.clear();
|
query.clear();
|
||||||
@ -106,7 +111,7 @@ void Miele::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
|
|||||||
|
|
||||||
QNetworkReply *reply = m_networkManager->post(request, query.toString().toUtf8());
|
QNetworkReply *reply = m_networkManager->post(request, query.toString().toUtf8());
|
||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, reply](){
|
connect(reply, &QNetworkReply::finished, this, [this, reply, refreshToken](){
|
||||||
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
if (!checkStatusCode(reply, rawData)) {
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
@ -114,13 +119,16 @@ void Miele::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
|
|||||||
}
|
}
|
||||||
QJsonDocument data = QJsonDocument::fromJson(rawData);
|
QJsonDocument data = QJsonDocument::fromJson(rawData);
|
||||||
|
|
||||||
if(!data.toVariant().toMap().contains("access_token")) {
|
if(!data.toVariant().toMap().contains("access_token") || !data.toVariant().toMap().contains("refresh_token")) {
|
||||||
setAuthenticated(false);
|
setAuthenticated(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_accessToken = data.toVariant().toMap().value("access_token").toByteArray();
|
m_accessToken = data.toVariant().toMap().value("access_token").toByteArray();
|
||||||
emit receivedAccessToken(m_accessToken);
|
emit receivedAccessToken(m_accessToken);
|
||||||
|
|
||||||
|
m_refreshToken = data.toVariant().toMap().value("refresh_token").toByteArray();
|
||||||
|
emit receivedRefreshToken(m_refreshToken);
|
||||||
|
|
||||||
if (data.toVariant().toMap().contains("expires_in")) {
|
if (data.toVariant().toMap().contains("expires_in")) {
|
||||||
int expireTime = data.toVariant().toMap().value("expires_in").toInt();
|
int expireTime = data.toVariant().toMap().value("expires_in").toInt();
|
||||||
qCDebug(dcMiele) << "Access token expires int" << expireTime << "s, at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
|
qCDebug(dcMiele) << "Access token expires int" << expireTime << "s, at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
|
||||||
@ -145,7 +153,7 @@ void Miele::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC
|
|||||||
query.clear();
|
query.clear();
|
||||||
query.addQueryItem("client_id", m_clientId);
|
query.addQueryItem("client_id", m_clientId);
|
||||||
query.addQueryItem("client_secret", m_clientSecret);
|
query.addQueryItem("client_secret", m_clientSecret);
|
||||||
//query.addQueryItem("vg", "de-DE");
|
query.addQueryItem("vg", "de-DE");
|
||||||
query.addQueryItem("redirect_uri", m_redirectUri);
|
query.addQueryItem("redirect_uri", m_redirectUri);
|
||||||
query.addQueryItem("grant_type", "authorization_code");
|
query.addQueryItem("grant_type", "authorization_code");
|
||||||
query.addQueryItem("code", authorizationCode);
|
query.addQueryItem("code", authorizationCode);
|
||||||
@ -169,7 +177,7 @@ void Miele::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC
|
|||||||
}
|
}
|
||||||
m_accessToken = jsonDoc.toVariant().toMap().value("access_token").toByteArray();
|
m_accessToken = jsonDoc.toVariant().toMap().value("access_token").toByteArray();
|
||||||
receivedAccessToken(m_accessToken);
|
receivedAccessToken(m_accessToken);
|
||||||
m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toByteArray();
|
m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toByteArray();
|
||||||
receivedRefreshToken(m_refreshToken);
|
receivedRefreshToken(m_refreshToken);
|
||||||
|
|
||||||
if (jsonDoc.toVariant().toMap().contains("expires_in")) {
|
if (jsonDoc.toVariant().toMap().contains("expires_in")) {
|
||||||
@ -180,7 +188,7 @@ void Miele::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC
|
|||||||
qCWarning(dcMiele()) << "Expire time too short";
|
qCWarning(dcMiele()) << "Expire time too short";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_accessTokenExpireTime = QDateTime::currentMSecsSinceEpoch() + (expireTime-(m_refreshInterval*1000));
|
m_accessTokenExpireTime = QDateTime::currentMSecsSinceEpoch() + (expireTime-(m_refreshInterval*1000));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -207,8 +215,7 @@ void Miele::getDevices()
|
|||||||
if (!checkStatusCode(reply, rawData)) {
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
||||||
qCDebug(dcMiele()) << "Get devices" << map;
|
|
||||||
if (map.contains("data")) {
|
if (map.contains("data")) {
|
||||||
QVariantMap dataMap = map.value("data").toMap();
|
QVariantMap dataMap = map.value("data").toMap();
|
||||||
qCDebug(dcMiele()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
|
qCDebug(dcMiele()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
|
||||||
@ -218,11 +225,48 @@ void Miele::getDevices()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Miele::getDevicesShort()
|
||||||
|
{
|
||||||
|
qCDebug(dcMiele()) << "Get devices short";
|
||||||
|
QUrl url = m_apiUrl;
|
||||||
|
url.setPath("/v1/short/devices");
|
||||||
|
url.setQuery("language=en");
|
||||||
|
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
request.setRawHeader("Authorization", "Bearer "+m_accessToken);
|
||||||
|
request.setRawHeader("accept", "application/json; charset=utf-8");
|
||||||
|
|
||||||
|
qCDebug(dcMiele()) << "Sending GET request" << request.url() << request.rawHeader("Authorization");
|
||||||
|
QNetworkReply *reply = m_networkManager->get(request);
|
||||||
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, reply] {
|
||||||
|
|
||||||
|
QByteArray rawData = reply->readAll();
|
||||||
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList devices = QJsonDocument::fromJson(rawData).toVariant().toList();
|
||||||
|
QList<DeviceShort> foundDevices;
|
||||||
|
foreach (QVariant device, devices) {
|
||||||
|
QVariantMap deviceObj = device.toMap();
|
||||||
|
qCDebug(dcMiele()) << "Got device: " << deviceObj;
|
||||||
|
DeviceShort ds;
|
||||||
|
ds.fabNumber = deviceObj["fabNumber"].toString();
|
||||||
|
ds.name = deviceObj["deviceName"].toString();
|
||||||
|
ds.state = deviceObj["state"].toString();
|
||||||
|
ds.type = deviceObj["type"].toString();
|
||||||
|
foundDevices.append(ds);
|
||||||
|
}
|
||||||
|
emit devicesFound(foundDevices);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Miele::getDevice(const QString &deviceId)
|
void Miele::getDevice(const QString &deviceId)
|
||||||
{
|
{
|
||||||
qCDebug(dcMiele()) << "Get device" << deviceId;
|
qCDebug(dcMiele()) << "Get device" << deviceId;
|
||||||
QUrl url = m_apiUrl;
|
QUrl url = m_apiUrl;
|
||||||
url.setPath("/v1/devices/"+deviceId);
|
url.setPath("/v1/devices/" + deviceId);
|
||||||
url.setQuery("language=en");
|
url.setQuery("language=en");
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
@ -238,7 +282,31 @@ void Miele::getDevice(const QString &deviceId)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
||||||
qCDebug(dcMiele()) << "Get device" << map;
|
qCDebug(dcMiele()) << "Got device: " << map;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Miele::getDeviceState(const QString &deviceId) {
|
||||||
|
qCDebug(dcMiele()) << "Get device state for: " << deviceId;
|
||||||
|
QUrl url = m_apiUrl;
|
||||||
|
url.setPath("/v1/devices/" + deviceId + "/state");
|
||||||
|
url.setQuery("language=en");
|
||||||
|
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
request.setRawHeader("Authorization", "Bearer "+m_accessToken);
|
||||||
|
request.setRawHeader("accept", "application/json; charset=utf-8");
|
||||||
|
|
||||||
|
QNetworkReply *reply = m_networkManager->get(request);
|
||||||
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, reply, deviceId]{
|
||||||
|
|
||||||
|
QByteArray rawData = reply->readAll();
|
||||||
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
||||||
|
qCDebug(dcMiele()) << "Got device state for: " << deviceId;
|
||||||
|
emit deviceStateReceived(deviceId, map);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,11 +366,14 @@ QUuid Miele::setTargetTemperature(const QString &deviceId, int zone, int targetT
|
|||||||
{
|
{
|
||||||
QJsonDocument doc;
|
QJsonDocument doc;
|
||||||
QJsonObject object;
|
QJsonObject object;
|
||||||
|
|
||||||
QJsonObject temperatureObj;
|
QJsonObject temperatureObj;
|
||||||
temperatureObj.insert("zone", zone);
|
temperatureObj.insert("zone", zone);
|
||||||
temperatureObj.insert("value", targetTemperature);
|
temperatureObj.insert("value", targetTemperature);
|
||||||
object.insert("targetTemperature", temperatureObj);
|
QJsonArray tempZones;
|
||||||
doc.setObject(object);
|
tempZones.push_front(temperatureObj);
|
||||||
|
object.insert("targetTemperature", tempZones);
|
||||||
|
doc.setObject(object);
|
||||||
return putAction(deviceId, doc);
|
return putAction(deviceId, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,6 +562,7 @@ bool Miele::checkStatusCode(QNetworkReply *reply, const QByteArray &rawData)
|
|||||||
if (error.error != QJsonParseError::NoError) {
|
if (error.error != QJsonParseError::NoError) {
|
||||||
qCWarning(dcMiele()) << "Received invalide JSON object" << rawData;
|
qCWarning(dcMiele()) << "Received invalide JSON object" << rawData;
|
||||||
qCWarning(dcMiele()) << "Status" << status;
|
qCWarning(dcMiele()) << "Status" << status;
|
||||||
|
qCWarning(dcMiele()) << "Error" << error.errorString();
|
||||||
setAuthenticated(false);
|
setAuthenticated(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,6 +90,14 @@ public:
|
|||||||
StatusNotConnected = 255
|
StatusNotConnected = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DeviceShort {
|
||||||
|
QString details;
|
||||||
|
QString name;
|
||||||
|
QString fabNumber;
|
||||||
|
QString state;
|
||||||
|
QString type;
|
||||||
|
};
|
||||||
|
|
||||||
Miele(NetworkAccessManager *networkmanager, const QByteArray &clientId, const QByteArray &clientSecret, const QString &language = "en", QObject *parent = nullptr);
|
Miele(NetworkAccessManager *networkmanager, const QByteArray &clientId, const QByteArray &clientSecret, const QString &language = "en", QObject *parent = nullptr);
|
||||||
QByteArray accessToken();
|
QByteArray accessToken();
|
||||||
QByteArray refreshToken();
|
QByteArray refreshToken();
|
||||||
@ -101,7 +109,9 @@ public:
|
|||||||
|
|
||||||
// INFORMATION
|
// INFORMATION
|
||||||
void getDevices();
|
void getDevices();
|
||||||
|
void getDevicesShort();
|
||||||
void getDevice(const QString &deviceId);
|
void getDevice(const QString &deviceId);
|
||||||
|
void getDeviceState(const QString &deviceId);
|
||||||
|
|
||||||
// ACTION
|
// ACTION
|
||||||
void getActions(const QString &deviceId); //The GET action is used to request a device to send the currently supported actions
|
void getActions(const QString &deviceId); //The GET action is used to request a device to send the currently supported actions
|
||||||
@ -150,6 +160,8 @@ signals:
|
|||||||
void receivedRefreshToken(const QByteArray &refreshToken);
|
void receivedRefreshToken(const QByteArray &refreshToken);
|
||||||
void receivedAccessToken(const QByteArray &accessToken);
|
void receivedAccessToken(const QByteArray &accessToken);
|
||||||
void commandExecuted(const QUuid &commandId, bool success);
|
void commandExecuted(const QUuid &commandId, bool success);
|
||||||
|
void devicesFound(QList<DeviceShort> devices);
|
||||||
|
void deviceStateReceived(const QString &deviceId, const QVariantMap &deviceState);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onRefreshTimeout();
|
void onRefreshTimeout();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user