added miele plugin

This commit is contained in:
Boernsman 2020-11-27 13:34:35 +01:00
parent cdff51655f
commit 37587e6590
12 changed files with 934 additions and 0 deletions

15
debian/control vendored
View File

@ -494,6 +494,21 @@ Description: nymea.io plugin for a generic MQTT client
This package will install a generic MQTT client plugin for nymea.io
Package: nymea-plugin-miele
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-translations,
Description: nymea.io plugin for Miele appliances
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install an integration plugin for Miele appliances.
Package: nymea-plugin-netatmo
Architecture: any
Depends: ${shlibs:Depends},

1
debian/nymea-plugin-miele.install.in vendored Normal file
View File

@ -0,0 +1 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginmiele.so

5
miele/README.md Normal file
View File

@ -0,0 +1,5 @@
# Miele
## Requirements
## More

View File

@ -0,0 +1,158 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
* 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 "integrationpluginmiele.h"
IntegrationPluginMiele::IntegrationPluginMiele()
{
}
void IntegrationPluginMiele::startPairing(ThingPairingInfo *info)
{
if (info->thingClassId() == mieleAccountThingClassId) {
QByteArray clientKey = configValue(mielePluginCustomClientKeyParamTypeId).toByteArray();
QByteArray clientSecret = configValue(mielePluginCustomClientSecretParamTypeId).toByteArray();
if (clientKey.isEmpty() || clientSecret.isEmpty()) {
clientKey = apiKeyStorage()->requestKey("miele").data("clientKey");
clientSecret = apiKeyStorage()->requestKey("miele").data("clientSecret");
}
if (clientKey.isEmpty() || clientSecret.isEmpty()) {
info->finish(Thing::ThingErrorAuthenticationFailure, tr("Client key and/or seceret is not available."));
return;
}
Miele *miele = new Miele(hardwareManager()->networkManager(), clientKey, clientSecret, this);
QUrl url = miele->getLoginUrl(QUrl("https://127.0.0.1:8888"), scope);
qCDebug(dcMiele()) << "HomeConnect url:" << url;
m_setupHomeConnectConnections.insert(info->thingId(), miele);
info->setOAuthUrl(url);
info->finish(Thing::ThingErrorNoError);
} else {
qCWarning(dMiele()) << "Unhandled pairing metod!";
info->finish(Thing::ThingErrorCreationMethodNotSupported);
}
}
void IntegrationPluginMiele::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret)
{
Q_UNUSED(username);
if (info->thingClassId() == mieleAccountThingClassId) {
qCDebug(dcMiele()) << "Redirect url is" << secret;
QUrl url(secret);
QUrlQuery query(url);
QByteArray authorizationCode = query.queryItemValue("code").toLocal8Bit();
Miele *miele = m_setupMieleConnections.value(info->thingId());
if (!miele) {
qWarning(dcMiele()) << "No Miele connection found for device:" << info->thingName();
m_setupMieleConnections.remove(info->thingId());
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
qCDebug(dcMiele()) << "Authorization code" << authorizationCode;
miele->getAccessTokenFromAuthorizationCode(authorizationCode);
connect(miele, &Miele::receivedRefreshToken, info, [info, this](const QByteArray &refreshToken){
qCDebug(dcMiele()) << "Token:" << refreshToken;
pluginStorage()->beginGroup(info->thingId().toString());
pluginStorage()->setValue("refresh_token", refreshToken);
pluginStorage()->endGroup();
info->finish(Thing::ThingErrorNoError);
});
} else {
Q_ASSERT_X(false, "confirmPairing", QString("Unhandled thingClassId: %1").arg(info->thingClassId().toString()).toUtf8());
}
}
void IntegrationPluginMiele::setupThing(ThingSetupInfo *info)
{
}
void IntegrationPluginMiele::postSetupThing(Thing *thing)
{
if (!m_pluginTimer15min) {
m_pluginTimer15min = hardwareManager()->pluginTimerManager()->registerTimer(60*15);
connect(m_pluginTimer15min, &PluginTimer::timeout, this, [this]() {
Q_FOREACH (Thing *thing, myThings().filterByThingClassId(mieleAccountThingClassId)) {
Miele *miele = m_mieleConnections.value(thing);
if (!miele) {
qWarning(dcMiele()) << "No Miele account found for" << thing->name();
continue;
}
miele->getDevices();
Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) {
QString deviceId = childThing->paramValue(m_idParamTypeIds.value(childThing->thingClassId())).toString();
miele->getDevice(deviceId);
}
}
});
}
}
void IntegrationPluginMiele::executeAction(ThingActionInfo *info)
{
Thing *thing = info->thing();
Action action = info->action();
Miele *miele = m_mieleConnections.value(myThings().findById(thing->parentId()));
if (!miele) {
return info->finish(Thing::ThingErrorHardwareNotAvailable);
}
QString haid = thing->paramValue(m_idParamTypeIds.value(thing->thingClassId())).toString();
if (thing->thingClassId() == ovenThingClassId) {
} else if (thing->thingClassId() == ovenThingClassId) {
} else {
}
}
void IntegrationPluginMiele::thingRemoved(Thing *thing)
{
qCDebug(dcMiele) << "Delete " << thing->name();
if (thing->thingClassId() == mieleAccountThingClassId) {
m_mieleConnections.take(thing)->deleteLater();
}
if (myThings().empty()) {
if (m_pluginTimer15min) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer15min);
m_pluginTimer15min = nullptr;
}
}
}

View File

@ -0,0 +1,103 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
* 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 INTEGRATIONPLUGINMIELE_H
#define INTEGRATIONPLUGINMIELE_H
#include "integrations/integrationplugin.h"
#include "plugintimer.h"
#include "miele.h"
#include <QHash>
#include <QDebug>
class IntegrationPluginMiele : public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginmiele.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginMiele();
void startPairing(ThingPairingInfo *info) override;
void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret) override;
void setupThing(ThingSetupInfo *info) override;
void postSetupThing(Thing *thing) override;
void executeAction(ThingActionInfo *info) override;
void thingRemoved(Thing *thing) override;
void browseThing(BrowseResult *result) override;
void browserItem(BrowserItemResult *result) override;
void executeBrowserItem(BrowserActionInfo *info) override;
private:
PluginTimer *m_pluginTimer15min = nullptr;
QHash<Miele *, ThingSetupInfo *> m_asyncSetup;
QHash<ThingId, Miele *> m_setupMieleConnections;
QHash<Thing *, Miele *> m_mieleConnections;
QHash<QUuid, ThingActionInfo *> m_pendingActions;
QHash<Thing *, QString> m_selectedProgram;
QHash<ThingClassId, ParamTypeId> m_idParamTypeIds;
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIds;
QHash<ThingClassId, StateTypeId> m_doorStateStateTypeIds;
QHash<ThingClassId, StateTypeId> m_localControlStateTypeIds;
QHash<ThingClassId, StateTypeId> m_remoteControlActivationStateTypeIds;
QHash<ThingClassId, StateTypeId> m_remoteStartAllowanceStateTypeIds;
QHash<ThingClassId, StateTypeId> m_operationStateTypeIds;
QHash<ThingClassId, StateTypeId> m_doorStateTypeIds;
QHash<ThingClassId, StateTypeId> m_selectedProgramStateTypeIds;
QHash<ThingClassId, StateTypeId> m_progressStateTypeIds;
QHash<ThingClassId, StateTypeId> m_endTimerStateTypeIds;
QHash<ThingClassId, ActionTypeId> m_startActionTypeIds;
QHash<ThingClassId, ActionTypeId> m_stopActionTypeIds;
QHash<ThingClassId, EventTypeId> m_programFinishedEventTypeIds;
QHash<QString, QString> m_coffeeStrengthTypes;
void parseKey(Thing *thing, const QString &key, const QVariant &value);
void parseSettingKey(Thing *thing, const QString &key, const QVariant &value);
bool checkIfActionIsPossible(ThingActionInfo *info);
private slots:
void onConnectionChanged(bool connected);
void onAuthenticationStatusChanged(bool authenticated);
void onRequestExecuted(QUuid requestId, bool success);
};
#endif // INTEGRATIONPLUGINMIELE_H

View File

@ -0,0 +1,343 @@
{
"id": "d44fad27-668a-4540-9eee-505d0ff13c37",
"name": "miele",
"displayName": "Miele",
"paramTypes": [
{
"id": "6ebf0bdb-012d-4277-9603-2a2e68e23c33",
"name": "customClientKey",
"displayName": "Custom client key",
"defaultValue": "",
"type": "QString"
},
{
"id": "37230edb-22ed-4f1d-8849-7fd72f192d89",
"name": "customClientSecret",
"displayName": "Custom client secret",
"defaultValue": "",
"type": "QString"
}
],
"apiKeys": ["miele"],
"vendors": [
{
"id": "ec1e94c4-d649-4af5-90c2-6c50b1a48e9e",
"name": "miele",
"displayName": "Miele",
"thingClasses": [
{
"id": "bea89711-7f41-4add-ba27-32dd69515c1c",
"name": "miele",
"displayName": "Miele",
"interfaces": ["account"],
"createMethods": ["user"],
"setupMethod": "oauth",
"paramTypes": [
],
"stateTypes": [
{
"id": "89f4554b-fad2-402e-a0f0-6a76b26d10ea",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "b38f3d86-6d54-442c-a0f3-78ece8887d93",
"name": "loggedIn",
"displayName": "Logged in",
"displayNameEvent": "Logged in changed",
"defaultValue": true,
"type": "bool"
},
{
"id": "a5b85688-d319-4f61-8907-7da8a2b16d64",
"name": "userDisplayName",
"displayName": "User name",
"displayNameEvent": "User name changed",
"defaultValue": "",
"type": "QString"
}
]
},
{
"id": "cf542b5e-2903-497c-95a0-042df6535450",
"name": "oven",
"displayName": "Oven",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "1e287843-41dd-49c8-a250-a21ed0e4215c",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "9c2c9360-0a4a-43ff-8d15-9cefa80380ec",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "82c7cba0-63fc-400c-8c47-dbeee47a3459",
"name": "dishwasher",
"displayName": "Dishwasher",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "f61d0fef-b588-4547-a5b6-03dc1622d0c5",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "170a1bb2-7c8f-448e-acdc-61a4537f10ab",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "8af89a1f-c752-4452-a568-d3b987e4667d",
"name": "coffeeMaker",
"displayName": "Coffee Maker",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "438cb528-91f4-481f-9b51-16658fd0a7c8",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "4b999b92-def7-4192-9814-38adf9af14e3",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "ad9bc908-9f61-4cb3-a8df-db003c6bf171",
"name": "dryer",
"displayName": "Dryer",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "3de1300c-766f-4a0b-9bc8-e75aa2402a6a",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "4dfce9b8-940b-49cb-8961-b2504fc2f3a6",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "a03e17fd-8da8-4977-8ac3-c058ada9f547",
"name": "fridge",
"displayName": "Fridge Freezer",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "945c1fa3-c304-4fc5-8c6b-f88f1f08d47a",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "6b066033-a290-459f-b6a1-c63857e6b538",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "58a6feaf-b2f7-48e9-822e-6f9526671f04",
"name": "washer",
"displayName": "Washer",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "2681e31e-cb0a-486f-b5b7-8ae28f7c96f9",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "ba271347-04b6-40a6-86f7-9c260a2fb23f",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "bbc55426-f649-4d32-81fc-cebd8a2b46d0",
"name": "cookTop",
"displayName": "Cook top",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "39f094ee-b672-4d75-b106-a21eeec41a34",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "08b7960c-e244-4956-808f-53ca7e486dd9",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "707e46a5-9ca0-4375-8249-2de19ec669ec",
"name": "hood",
"displayName": "Hood",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "15c3cea9-16c2-4517-ae43-3a9b5f388b82",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "be91bef9-c957-4bb8-9c92-1d2a548e762f",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "5698a1cf-5b3d-4746-a4fe-e4412d2768ab",
"name": "cleaningRobot",
"displayName": "Cleaning robot",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "629ac68f-89a2-41cf-801b-20df9968d204",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "8abe70f4-f49f-4b13-8251-216bea230f04",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "40d31505-d6ae-4c45-a2b2-d652e1b85c80",
"name": "cookProcessor",
"displayName": "Cook processor",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "51750b9f-4fc3-4556-a651-c8efcf07abe7",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "9eee48ba-b2e2-40fe-81b5-3404b655a497",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
}
]
}
]
}

13
miele/meta.json Normal file
View File

@ -0,0 +1,13 @@
{
"title": "Miele",
"tagline": "Connect to Miele appliances.",
"icon": "miele.png",
"stability": "consumer",
"offline": false,
"technologies": [
"network"
],
"categories": [
"online-service"
]
}

133
miele/miele.cpp Normal file
View File

@ -0,0 +1,133 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
* 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 "miele.h"
#include "extern-plugininfo.h"
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>
#include <QJsonObject>
#include <QUrlQuery>
void Miele::getDevices()
{
}
QUuid Miele::processAction(const QString &deviceId, Miele::ProcessAction action)
{
QJsonDocument doc;
QJsonObject object;
object.insert("processAction", action);
doc.setObject(object);
return putAction(deviceId, doc);
}
QUuid Miele::setPower(const QString &deviceId, bool power)
{
QJsonDocument doc;
QJsonObject object;
if (power) {
object.insert("powerOn", true);
} else {
object.insert("powerOff", true);
}
doc.setObject(object);
return putAction(deviceId, doc);
}
QUuid Miele::setDeviceName(const QString &deviceId, const QString &deviceName)
{
QJsonDocument doc;
QJsonObject object;
object.insert("description", deviceName);
doc.setObject(object);
return putAction(deviceId, doc);
}
QUuid Miele::setLight(const QString &deviceId, bool power)
{
QJsonDocument doc;
QJsonObject object;
if (power) {
object.insert("light", 1);
} else {
object.insert("light", 2);
}
doc.setObject(object);
return putAction(deviceId, doc);
}
QUuid Miele::setTargetTemperature(const QString &deviceId, int zone, int targetTemperature)
{
QJsonDocument doc;
QJsonObject object;
QJsonObject temperatureObj;
temperatureObj.insert("zone", zone);
temperatureObj.insert("value", targetTemperature);
object.insert("targetTemperature", temperatureObj);
doc.setObject(object);
return putAction(deviceId, doc);
}
QUuid Miele::putAction(const QString &deviceId, const QJsonDocument &action)
{
QUuid commandId = QUuid::createUuid();
QUrl url = m_apiUrl;
url.setPath("/v1/devices/"+deviceId+"/actions");
url.setQuery("language=en");
QNetworkRequest request(url);
request.setRawHeader("Authorization", "Bearer "+m_accessToken);
// request.setRawHeader("Accept-Language", "en-US");
request.setRawHeader("accept", "application/json; charset=utf-8");
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_networkManager->put(request, action.toJson());
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, this, [this, commandId, reply]{
QByteArray rawData = reply->readAll();
if (!checkStatusCode(reply, rawData)) {
return;
}
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
qCDebug(dcMiele()) << "Send command" << map;
if (map.contains("data")) {
QVariantMap dataMap = map.value("data").toMap();
qCDebug(dcMiele()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
} else if (map.contains("error")) {
qCWarning(dcMiele()) << "Send command" << map.value("error").toMap().value("description").toString();
}
emit commandExecuted(commandId, true);
});
return commandId;
}

139
miele/miele.h Normal file
View File

@ -0,0 +1,139 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
* 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 MIELE_H
#define MIELE_H
#include <QObject>
#include <QTimer>
#include <QUuid>
#include <QJsonDocument>
#include "network/networkaccessmanager.h"
class Miele : public QObject
{
Q_OBJECT
public:
enum ProcessAction {
ProcessActionsStart = 0,
ProcessActionsStop,
ProcessActionsPause,
ProcessActionsStarSuperfreezing,
ProcessActionsStopSuperfreezing,
ProcessActionsStartSupercooling,
ProcessActionsStopSupercooling
};
enum Mode {
ModeNormal,
ModeSabbath
};
enum Color {
ColorWhite,
ColorBlue,
ColorRed,
ColorYellow,
ColorOrange,
ColorGreen,
ColorPink,
ColorPurple,
ColorTurquoise
};
enum Status {
StatusOff = 1,
StatusOn = 2,
StatusProgrammed = 3,
StatusProgrammedWaitingToStart = 4,
StatusRunnin = 5,
StatusPause = 6,
StatusEndProgrammed = 7,
StatusFailure = 8,
StatusProgrammInterrupted = 9,
StatusIdle = 10,
StatusRinseHold = 11,
StatusService = 12,
StatusSuperfreezing = 13,
StatusSupercooling = 14,
StatusSuperheating = 15,
StatusSupercoolingSuperfreezing = 146,
StatusNotConnected = 255
};
Miele(NetworkAccessManager *networkmanager, const QByteArray &clientKey, const QByteArray &clientSecret, bool simulationMode = false, QObject *parent = nullptr);
QByteArray accessToken();
QByteArray refreshToken();
void setSimulationMode(bool simulation);
QUrl getLoginUrl(const QUrl &redirectUrl, const QString &scope);
void getAccessTokenFromRefreshToken(const QByteArray &refreshToken);
void getAccessTokenFromAuthorizationCode(const QByteArray &authorizationCode);
// INFORMATION
void getDevices();
void getDevice(const QString &deviceId);
// ACTION
void getActions(const QString &deviceId); //The GET action is used to request a device to send the currently supported actions
QUuid processAction(const QString &deviceId, ProcessAction action);
QUuid setPower(const QString &deviceId, bool power);
QUuid setDeviceName(const QString &deviceId, const QString &deviceName);
QUuid setLight(const QString &deviceId, bool power);
QUuid setTargetTemperature(const QString &deviceId, int zone, int targetTemperature);
QUuid setColors(const QString &deviceId, Color color);
QUuid setModes(const QString &deviceId, Mode mode);
QUuid setVentilationStep(const QString &deviceId, int step);
QUuid setStartTime();
// EVENTS
void getAllEvents();
private:
NetworkAccessManager *m_networkManager = nullptr;
QUuid putAction(const QString &deviceId, const QJsonDocument &action); //
QUrl m_authorizationUrl = QUrl("https://api.mcs3.miele.com/thirdparty/login/");
QUrl m_tokenUrl = QUrl("https://api.mcs3.miele.com/thirdparty/token/");
QUrl m_apiUrl = QUrl("https://api.mcs3.miele.com/");
bool checkStatusCode(QNetworkReply *reply, const QByteArray &rawData);
signals:
void connectionChanged(bool connected);
void authenticationStatusChanged(bool authenticated);
void receivedRefreshToken(const QByteArray &refreshToken);
void receivedAccessToken(const QByteArray &accessToken);
void commandExecuted(const QUuid &commandId, bool success);
};
#endif // MIELE

11
miele/miele.pro Normal file
View File

@ -0,0 +1,11 @@
include(../plugins.pri)
QT += network
SOURCES += \
integrationpluginmiele.cpp \
miele.cpp \
HEADERS += \
integrationpluginmiele.h \
miele.h \

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>IntegrationPluginMiele</name>
<message>
<location filename="../integrationpluginmiele.cpp" line="49"/>
<source>Client key and/or seceret is not available.</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -33,6 +33,7 @@ PLUGIN_DIRS = \
lifx \
mailnotification \
mqttclient \
miele \
nanoleaf \
netatmo \
networkdetector \