added closable sensor and fixed authentication/connected state
This commit is contained in:
parent
5be1f64faf
commit
baa087e988
@ -1,6 +1,6 @@
|
|||||||
# Home Connect
|
# Home Connect
|
||||||
|
|
||||||
Connects your Home Connect home appliences to nymea.
|
Connects your Home Connect home appliances to nymea.
|
||||||
|
|
||||||
## Supported Things
|
## Supported Things
|
||||||
|
|
||||||
|
|||||||
@ -93,7 +93,7 @@ QUrl HomeConnect::getLoginUrl(const QUrl &redirectUrl, const QString &scope)
|
|||||||
queryParams.addQueryItem("scope", scope);
|
queryParams.addQueryItem("scope", scope);
|
||||||
queryParams.addQueryItem("state", QUuid::createUuid().toString());
|
queryParams.addQueryItem("state", QUuid::createUuid().toString());
|
||||||
queryParams.addQueryItem("nonce", QUuid::createUuid().toString());
|
queryParams.addQueryItem("nonce", QUuid::createUuid().toString());
|
||||||
m_codeChallenge = QUuid::createUuid().toString().remove('{').remove('}').remove("-");
|
m_codeChallenge = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
|
||||||
queryParams.addQueryItem("code_challenge", m_codeChallenge);
|
queryParams.addQueryItem("code_challenge", m_codeChallenge);
|
||||||
queryParams.addQueryItem("code_challenge_method", "plain");
|
queryParams.addQueryItem("code_challenge_method", "plain");
|
||||||
url.setQuery(queryParams);
|
url.setQuery(queryParams);
|
||||||
@ -107,19 +107,28 @@ void HomeConnect::onRefreshTimeout()
|
|||||||
getAccessTokenFromRefreshToken(m_refreshToken);
|
getAccessTokenFromRefreshToken(m_refreshToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HomeConnect::checkStatusCode(int status, const QByteArray &payload)
|
bool HomeConnect::checkStatusCode(QNetworkReply *reply, const QByteArray &rawData)
|
||||||
{
|
{
|
||||||
//TODO emit (dis)connected, (un)authenticated,
|
// Check for the internet connection
|
||||||
QJsonParseError error;
|
if (reply->error() == QNetworkReply::NetworkError::HostNotFoundError ||
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
reply->error() == QNetworkReply::NetworkError::UnknownNetworkError ||
|
||||||
if (error.error != QJsonParseError::NoError) {
|
reply->error() == QNetworkReply::NetworkError::TemporaryNetworkFailureError) {
|
||||||
qCWarning(dcHomeConnect()) << "Received invalide JSON object" << payload;
|
qCWarning(dcHomeConnect()) << "Connection error" << reply->errorString();
|
||||||
qCWarning(dcHomeConnect()) << "Status" << status;
|
setConnected(false);
|
||||||
|
setAuthenticated(false);
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
setConnected(true);
|
||||||
}
|
}
|
||||||
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData, &error);
|
||||||
|
|
||||||
switch (status){
|
switch (status){
|
||||||
case 400:
|
case 200: //The request was successful. Typically returned for successful GET requests.
|
||||||
|
case 204: //The request was successful. Typically returned for successful PUT/DELETE requests with no payload.
|
||||||
|
break;
|
||||||
|
case 400: //Error occurred (e.g. validation error - value is out of range)
|
||||||
if(!jsonDoc.toVariant().toMap().contains("error")) {
|
if(!jsonDoc.toVariant().toMap().contains("error")) {
|
||||||
if(jsonDoc.toVariant().toMap().value("error").toString() == "invalid_client") {
|
if(jsonDoc.toVariant().toMap().value("error").toString() == "invalid_client") {
|
||||||
qWarning(dcHomeConnect()) << "Client token provided doesn’t correspond to client that generated auth code.";
|
qWarning(dcHomeConnect()) << "Client token provided doesn’t correspond to client that generated auth code.";
|
||||||
@ -131,16 +140,54 @@ bool HomeConnect::checkStatusCode(int status, const QByteArray &payload)
|
|||||||
qWarning(dcHomeConnect()) << "Expired authorization code.";
|
qWarning(dcHomeConnect()) << "Expired authorization code.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setAuthenticated(false);
|
||||||
return false;
|
return false;
|
||||||
case 401:
|
case 401:
|
||||||
qWarning(dcHomeConnect()) << "Client does not have permission to use this API.";
|
qWarning(dcHomeConnect()) << "Client does not have permission to use this API.";
|
||||||
|
setAuthenticated(false);
|
||||||
|
return false;
|
||||||
|
case 403:
|
||||||
|
qCWarning(dcHomeConnect()) << "Forbidden, Scope has not been granted or home appliance is not assigned to HC account";
|
||||||
|
setAuthenticated(false);
|
||||||
|
return false;
|
||||||
|
case 404:
|
||||||
|
qCWarning(dcHomeConnect()) << "Not Found. This resource is not available (e.g. no images on washing machine)";
|
||||||
return false;
|
return false;
|
||||||
case 405:
|
case 405:
|
||||||
qWarning(dcHomeConnect()) << "Wrong HTTP method used.";
|
qWarning(dcHomeConnect()) << "Wrong HTTP method used.";
|
||||||
|
setAuthenticated(false);
|
||||||
|
return false;
|
||||||
|
case 408:
|
||||||
|
qCWarning(dcHomeConnect())<< "Request Timeout, API Server failed to produce an answer or has no connection to backend service";
|
||||||
|
return false;
|
||||||
|
case 409:
|
||||||
|
qCWarning(dcHomeConnect()) << "Conflict - Command/Query cannot be executed for the home appliance, the error response contains the error details";
|
||||||
|
qCWarning(dcHomeConnect()) << "Error" << jsonDoc.toVariant().toMap().value("error").toString();
|
||||||
|
return false;
|
||||||
|
case 415:
|
||||||
|
qCWarning(dcHomeConnect())<< "Unsupported Media Type. The request's Content-Type is not supported";
|
||||||
|
return false;
|
||||||
|
case 429:
|
||||||
|
qCWarning(dcHomeConnect())<< "Too Many Requests, the number of requests for a specific endpoint exceeded the quota of the client";
|
||||||
|
return false;
|
||||||
|
case 500:
|
||||||
|
qCWarning(dcHomeConnect())<< "Internal Server Error, in case of a server configuration error or any errors in resource files";
|
||||||
|
return false;
|
||||||
|
case 503:
|
||||||
|
qCWarning(dcHomeConnect())<< "Service Unavailable,if a required backend service is not available";
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qCWarning(dcHomeConnect()) << "Received invalide JSON object" << rawData;
|
||||||
|
qCWarning(dcHomeConnect()) << "Status" << status;
|
||||||
|
setAuthenticated(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAuthenticated(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +195,7 @@ void HomeConnect::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
|
|||||||
{
|
{
|
||||||
if (refreshToken.isEmpty()) {
|
if (refreshToken.isEmpty()) {
|
||||||
qWarning(dcHomeConnect) << "No refresh token given!";
|
qWarning(dcHomeConnect) << "No refresh token given!";
|
||||||
emit authenticationStatusChanged(false);
|
setAuthenticated(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,37 +213,31 @@ void HomeConnect::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
|
|||||||
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](){
|
||||||
|
|
||||||
|
QByteArray rawData = reply->readAll();
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
|
||||||
qWarning(dcHomeConnect()) << "Access token error:" << reply->errorString() << reply->readAll();
|
|
||||||
emit authenticationStatusChanged(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QJsonParseError error;
|
|
||||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
|
||||||
if (error.error != QJsonParseError::NoError) {
|
|
||||||
emit authenticationStatusChanged(false);
|
|
||||||
qCDebug(dcHomeConnect()) << "Received invalide JSON object" << data.toJson();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
QJsonDocument data = QJsonDocument::fromJson(rawData);
|
||||||
|
|
||||||
if(!data.toVariant().toMap().contains("access_token")) {
|
if(!data.toVariant().toMap().contains("access_token")) {
|
||||||
emit authenticationStatusChanged(false);
|
setAuthenticated(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_accessToken = data.toVariant().toMap().value("access_token").toByteArray();
|
m_accessToken = data.toVariant().toMap().value("access_token").toByteArray();
|
||||||
|
|
||||||
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(dcHomeConnect) << "Access token expires at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
|
qCDebug(dcHomeConnect) << "Access token expires int" << expireTime << "s, at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
|
||||||
if (!m_tokenRefreshTimer) {
|
if (!m_tokenRefreshTimer) {
|
||||||
qWarning(dcHomeConnect()) << "Access token refresh timer not initialized";
|
qWarning(dcHomeConnect()) << "Access token refresh timer not initialized";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (expireTime < 20) {
|
||||||
|
qCWarning(dcHomeConnect()) << "Expire time too short";
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_tokenRefreshTimer->start((expireTime - 20) * 1000);
|
m_tokenRefreshTimer->start((expireTime - 20) * 1000);
|
||||||
}
|
}
|
||||||
emit authenticationStatusChanged(true);;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,15 +268,14 @@ void HomeConnect::getAccessTokenFromAuthorizationCode(const QByteArray &authoriz
|
|||||||
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](){
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
QByteArray rawData = reply->readAll();
|
||||||
qWarning(dcHomeConnect()) << reply->errorString() << status << reply->readAll();
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
emit authenticationStatusChanged(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll());
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);
|
||||||
if(!jsonDoc.toVariant().toMap().contains("access_token") || !jsonDoc.toVariant().toMap().contains("refresh_token") ) {
|
if(!jsonDoc.toVariant().toMap().contains("access_token") || !jsonDoc.toVariant().toMap().contains("refresh_token") ) {
|
||||||
emit authenticationStatusChanged(false);
|
setAuthenticated(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_accessToken = jsonDoc.toVariant().toMap().value("access_token").toByteArray();
|
m_accessToken = jsonDoc.toVariant().toMap().value("access_token").toByteArray();
|
||||||
@ -243,15 +283,18 @@ void HomeConnect::getAccessTokenFromAuthorizationCode(const QByteArray &authoriz
|
|||||||
|
|
||||||
if (jsonDoc.toVariant().toMap().contains("expires_in")) {
|
if (jsonDoc.toVariant().toMap().contains("expires_in")) {
|
||||||
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
|
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
|
||||||
qCDebug(dcHomeConnect()) << "Token expires at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
|
qCDebug(dcHomeConnect()) << "Token expires in" << expireTime << "s, at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
|
||||||
if (!m_tokenRefreshTimer) {
|
if (!m_tokenRefreshTimer) {
|
||||||
qWarning(dcHomeConnect()) << "Token refresh timer not initialized";
|
qWarning(dcHomeConnect()) << "Token refresh timer not initialized";
|
||||||
emit authenticationStatusChanged(false);
|
setAuthenticated(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (expireTime < 20) {
|
||||||
|
qCWarning(dcHomeConnect()) << "Expire time too short";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_tokenRefreshTimer->start((expireTime - 20) * 1000);
|
m_tokenRefreshTimer->start((expireTime - 20) * 1000);
|
||||||
}
|
}
|
||||||
emit authenticationStatusChanged(true);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,9 +310,10 @@ void HomeConnect::getHomeAppliances()
|
|||||||
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](){
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
checkStatusCode(status, rawData);
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
||||||
|
|
||||||
QList<HomeAppliance> appliances;
|
QList<HomeAppliance> appliances;
|
||||||
@ -304,9 +348,10 @@ void HomeConnect::getPrograms(const QString &haId)
|
|||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, haId, reply]{
|
connect(reply, &QNetworkReply::finished, this, [this, haId, reply]{
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
checkStatusCode(status, rawData);
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
||||||
QVariantList programList = dataMap.value("programs").toList();
|
QVariantList programList = dataMap.value("programs").toList();
|
||||||
@ -334,9 +379,10 @@ void HomeConnect::getProgramsAvailable(const QString &haId)
|
|||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, haId, reply]{
|
connect(reply, &QNetworkReply::finished, this, [this, haId, reply]{
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
checkStatusCode(status, rawData);
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
||||||
QVariantList programList = dataMap.value("programs").toList();
|
QVariantList programList = dataMap.value("programs").toList();
|
||||||
@ -364,9 +410,10 @@ void HomeConnect::getProgramsActive(const QString &haId)
|
|||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, haId, reply]{
|
connect(reply, &QNetworkReply::finished, this, [this, haId, reply]{
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
checkStatusCode(status, rawData);
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
||||||
QHash<QString, QVariant> options;
|
QHash<QString, QVariant> options;
|
||||||
@ -396,9 +443,10 @@ void HomeConnect::getProgramsSelected(const QString &haId)
|
|||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, haId, reply]{
|
connect(reply, &QNetworkReply::finished, this, [this, haId, reply]{
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
checkStatusCode(status, rawData);
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
||||||
QHash<QString, QVariant> options;
|
QHash<QString, QVariant> options;
|
||||||
@ -428,10 +476,10 @@ void HomeConnect::getProgramsActiveOption(const QString &haId, const QString &op
|
|||||||
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]{
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
checkStatusCode(status, rawData);
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
||||||
qCDebug(dcHomeConnect()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
|
qCDebug(dcHomeConnect()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
|
||||||
});
|
});
|
||||||
@ -638,9 +686,10 @@ void HomeConnect::getStatus(const QString &haid)
|
|||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, haid, reply]{
|
connect(reply, &QNetworkReply::finished, this, [this, haid, reply]{
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
checkStatusCode(status, rawData);
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
||||||
QHash<QString, QVariant> statusList;
|
QHash<QString, QVariant> statusList;
|
||||||
@ -676,9 +725,10 @@ void HomeConnect::getSettings(const QString &haid)
|
|||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, haid, reply]{
|
connect(reply, &QNetworkReply::finished, this, [this, haid, reply]{
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
QByteArray rawData = reply->readAll();
|
QByteArray rawData = reply->readAll();
|
||||||
checkStatusCode(status, rawData);
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap().value("data").toMap();
|
||||||
QVariantList settingsList = dataMap.value("settings").toList();
|
QVariantList settingsList = dataMap.value("settings").toList();
|
||||||
QHash<QString, QVariant> settings;
|
QHash<QString, QVariant> settings;
|
||||||
@ -800,21 +850,35 @@ QUuid HomeConnect::sendCommand(const QString &haid, const QString &command)
|
|||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, commandId, reply]{
|
connect(reply, &QNetworkReply::finished, this, [this, commandId, reply]{
|
||||||
|
|
||||||
//TODO check status
|
QByteArray rawData = reply->readAll();
|
||||||
QJsonParseError error;
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
|
||||||
if (error.error != QJsonParseError::NoError) {
|
|
||||||
qCDebug(dcHomeConnect()) << "Send command: Received invalide JSON object";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qCDebug(dcHomeConnect()) << "Send command" << data.toJson();
|
QVariantMap map = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
||||||
if (data.toVariant().toMap().contains("data")) {
|
qCDebug(dcHomeConnect()) << "Send command" << map;
|
||||||
QVariantMap dataMap = data.toVariant().toMap().value("data").toMap();
|
if (map.contains("data")) {
|
||||||
|
QVariantMap dataMap = map.value("data").toMap();
|
||||||
qCDebug(dcHomeConnect()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
|
qCDebug(dcHomeConnect()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
|
||||||
} else if (data.toVariant().toMap().contains("error")) {
|
} else if (map.contains("error")) {
|
||||||
qCWarning(dcHomeConnect()) << "Send command" << data.toVariant().toMap().value("error").toMap().value("description").toString();
|
qCWarning(dcHomeConnect()) << "Send command" << map.value("error").toMap().value("description").toString();
|
||||||
}
|
}
|
||||||
emit commandExecuted(commandId, true);
|
emit commandExecuted(commandId, true);
|
||||||
});
|
});
|
||||||
return commandId;
|
return commandId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HomeConnect::setAuthenticated(bool state)
|
||||||
|
{
|
||||||
|
if (state != m_authenticated) {
|
||||||
|
m_authenticated = state;
|
||||||
|
emit authenticationStatusChanged(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HomeConnect::setConnected(bool state)
|
||||||
|
{
|
||||||
|
if (state != m_connected) {
|
||||||
|
m_connected = state;
|
||||||
|
emit connectionChanged(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -159,7 +159,13 @@ private:
|
|||||||
NetworkAccessManager *m_networkManager = nullptr;
|
NetworkAccessManager *m_networkManager = nullptr;
|
||||||
QTimer *m_tokenRefreshTimer = nullptr;
|
QTimer *m_tokenRefreshTimer = nullptr;
|
||||||
|
|
||||||
bool checkStatusCode(int status, const QByteArray &payload);
|
void setAuthenticated(bool state);
|
||||||
|
void setConnected(bool state);
|
||||||
|
|
||||||
|
bool m_authenticated = false;
|
||||||
|
bool m_connected = false;
|
||||||
|
|
||||||
|
bool checkStatusCode(QNetworkReply *reply, const QByteArray &rawData);
|
||||||
private slots:
|
private slots:
|
||||||
void onRefreshTimeout();
|
void onRefreshTimeout();
|
||||||
|
|
||||||
|
|||||||
@ -77,11 +77,11 @@ IntegrationPluginHomeConnect::IntegrationPluginHomeConnect()
|
|||||||
m_remoteControlActivationStateTypeIds.insert(dishwasherThingClassId, dishwasherRemoteControlActivationStateStateTypeId);
|
m_remoteControlActivationStateTypeIds.insert(dishwasherThingClassId, dishwasherRemoteControlActivationStateStateTypeId);
|
||||||
m_remoteControlActivationStateTypeIds.insert(washerThingClassId, washerRemoteControlActivationStateStateTypeId);
|
m_remoteControlActivationStateTypeIds.insert(washerThingClassId, washerRemoteControlActivationStateStateTypeId);
|
||||||
|
|
||||||
m_doorStateTypeIds.insert(dishwasherThingClassId, dishwasherDoorStateStateTypeId);
|
m_doorStateTypeIds.insert(dishwasherThingClassId, dishwasherClosedStateTypeId);
|
||||||
m_doorStateTypeIds.insert(washerThingClassId, washerDoorStateStateTypeId);
|
m_doorStateTypeIds.insert(washerThingClassId, washerClosedStateTypeId);
|
||||||
m_doorStateTypeIds.insert(dryerThingClassId, dryerDoorStateStateTypeId);
|
m_doorStateTypeIds.insert(dryerThingClassId, dryerClosedStateTypeId);
|
||||||
m_doorStateTypeIds.insert(ovenThingClassId, ovenDoorStateStateTypeId);
|
m_doorStateTypeIds.insert(ovenThingClassId, ovenClosedStateTypeId);
|
||||||
m_doorStateTypeIds.insert(coffeeMakerThingClassId, coffeeMakerDoorStateStateTypeId);
|
m_doorStateTypeIds.insert(coffeeMakerThingClassId, coffeeMakerClosedStateTypeId);
|
||||||
|
|
||||||
m_operationStateTypeIds.insert(ovenThingClassId, ovenOperationStateStateTypeId);
|
m_operationStateTypeIds.insert(ovenThingClassId, ovenOperationStateStateTypeId);
|
||||||
m_operationStateTypeIds.insert(dryerThingClassId, dryerOperationStateStateTypeId);
|
m_operationStateTypeIds.insert(dryerThingClassId, dryerOperationStateStateTypeId);
|
||||||
@ -140,21 +140,29 @@ IntegrationPluginHomeConnect::IntegrationPluginHomeConnect()
|
|||||||
|
|
||||||
void IntegrationPluginHomeConnect::startPairing(ThingPairingInfo *info)
|
void IntegrationPluginHomeConnect::startPairing(ThingPairingInfo *info)
|
||||||
{
|
{
|
||||||
if (info->thingClassId() == homeConnectConnectionThingClassId) {
|
if (info->thingClassId() == homeConnectAccountThingClassId) {
|
||||||
|
|
||||||
bool simulationMode = configValue(homeConnectPluginSimulationModeParamTypeId).toBool();
|
bool simulationMode = configValue(homeConnectPluginSimulationModeParamTypeId).toBool();
|
||||||
bool controlEnabled = configValue(homeConnectPluginControlEnabledParamTypeId).toBool();
|
bool controlEnabled = configValue(homeConnectPluginControlEnabledParamTypeId).toBool();
|
||||||
QByteArray clientKey = apiKeyStorage()->requestKey("homeconnect").data("clientKey");
|
QByteArray clientKey = configValue(homeConnectPluginCustomClientKeyParamTypeId).toByteArray();
|
||||||
QByteArray clientSecret = apiKeyStorage()->requestKey("homeconnect").data("clientSecret");
|
QByteArray clientSecret = configValue(homeConnectPluginCustomClientSecretParamTypeId).toByteArray();
|
||||||
|
if (clientKey.isEmpty() || clientSecret.isEmpty()) {
|
||||||
|
clientKey = apiKeyStorage()->requestKey("homeconnect").data("clientKey");
|
||||||
|
clientSecret = apiKeyStorage()->requestKey("homeconnect").data("clientSecret");
|
||||||
|
}
|
||||||
|
if (clientKey.isEmpty() || clientSecret.isEmpty()) {
|
||||||
|
info->finish(Thing::ThingErrorAuthenticationFailure, tr("Client key and/or seceret is not available."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
HomeConnect *homeConnect = new HomeConnect(hardwareManager()->networkManager(), clientKey, clientSecret, simulationMode, this);
|
HomeConnect *homeConnect = new HomeConnect(hardwareManager()->networkManager(), clientKey, clientSecret, simulationMode, this);
|
||||||
QString scope = "IdentifyAppliance Monitor Settings Dishwasher Washer Dryer WasherDryer Refrigerator Freezer WineCooler CoffeeMaker Hood CookProcessor";
|
QString scope = "IdentifyAppliance Monitor Settings Dishwasher Washer Dryer WasherDryer Refrigerator Freezer WineCooler CoffeeMaker Hood CookProcessor";
|
||||||
if (controlEnabled)
|
if (controlEnabled)
|
||||||
scope.append(" Control");
|
scope.append(" Control");
|
||||||
QUrl url = homeConnect->getLoginUrl(QUrl("https://127.0.0.1:8888"), scope);
|
QUrl url = homeConnect->getLoginUrl(QUrl("https://127.0.0.1:8888"), scope);
|
||||||
qCDebug(dcHomeConnect()) << "HomeConnect url:" << url;
|
qCDebug(dcHomeConnect()) << "HomeConnect url:" << url;
|
||||||
|
m_setupHomeConnectConnections.insert(info->thingId(), homeConnect);
|
||||||
info->setOAuthUrl(url);
|
info->setOAuthUrl(url);
|
||||||
info->finish(Thing::ThingErrorNoError);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
m_setupHomeConnectConnections.insert(info->thingId(), homeConnect);
|
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcHomeConnect()) << "Unhandled pairing metod!";
|
qCWarning(dcHomeConnect()) << "Unhandled pairing metod!";
|
||||||
info->finish(Thing::ThingErrorCreationMethodNotSupported);
|
info->finish(Thing::ThingErrorCreationMethodNotSupported);
|
||||||
@ -165,7 +173,7 @@ void IntegrationPluginHomeConnect::confirmPairing(ThingPairingInfo *info, const
|
|||||||
{
|
{
|
||||||
Q_UNUSED(username);
|
Q_UNUSED(username);
|
||||||
|
|
||||||
if (info->thingClassId() == homeConnectConnectionThingClassId) {
|
if (info->thingClassId() == homeConnectAccountThingClassId) {
|
||||||
qCDebug(dcHomeConnect()) << "Redirect url is" << secret;
|
qCDebug(dcHomeConnect()) << "Redirect url is" << secret;
|
||||||
QUrl url(secret);
|
QUrl url(secret);
|
||||||
QUrlQuery query(url);
|
QUrlQuery query(url);
|
||||||
@ -175,7 +183,6 @@ void IntegrationPluginHomeConnect::confirmPairing(ThingPairingInfo *info, const
|
|||||||
if (!homeConnect) {
|
if (!homeConnect) {
|
||||||
qWarning(dcHomeConnect()) << "No HomeConnect connection found for device:" << info->thingName();
|
qWarning(dcHomeConnect()) << "No HomeConnect connection found for device:" << info->thingName();
|
||||||
m_setupHomeConnectConnections.remove(info->thingId());
|
m_setupHomeConnectConnections.remove(info->thingId());
|
||||||
homeConnect->deleteLater();
|
|
||||||
info->finish(Thing::ThingErrorHardwareFailure);
|
info->finish(Thing::ThingErrorHardwareFailure);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -211,7 +218,7 @@ void IntegrationPluginHomeConnect::setupThing(ThingSetupInfo *info)
|
|||||||
{
|
{
|
||||||
Thing *thing = info->thing();
|
Thing *thing = info->thing();
|
||||||
|
|
||||||
if (thing->thingClassId() == homeConnectConnectionThingClassId) {
|
if (thing->thingClassId() == homeConnectAccountThingClassId) {
|
||||||
bool simulationMode = configValue(homeConnectPluginSimulationModeParamTypeId).toBool();
|
bool simulationMode = configValue(homeConnectPluginSimulationModeParamTypeId).toBool();
|
||||||
HomeConnect *homeConnect;
|
HomeConnect *homeConnect;
|
||||||
if (m_setupHomeConnectConnections.keys().contains(thing->id())) {
|
if (m_setupHomeConnectConnections.keys().contains(thing->id())) {
|
||||||
@ -225,8 +232,20 @@ void IntegrationPluginHomeConnect::setupThing(ThingSetupInfo *info)
|
|||||||
pluginStorage()->beginGroup(thing->id().toString());
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
QByteArray refreshToken = pluginStorage()->value("refresh_token").toByteArray();
|
QByteArray refreshToken = pluginStorage()->value("refresh_token").toByteArray();
|
||||||
pluginStorage()->endGroup();
|
pluginStorage()->endGroup();
|
||||||
QByteArray clientKey = apiKeyStorage()->requestKey("homeconnect").data("clientKey");
|
if (refreshToken.isEmpty()) {
|
||||||
QByteArray clientSecret = apiKeyStorage()->requestKey("homeconnect").data("clientSecret");
|
info->finish(Thing::ThingErrorAuthenticationFailure, tr("Refresh token is not available."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QByteArray clientKey = configValue(homeConnectPluginCustomClientKeyParamTypeId).toByteArray();
|
||||||
|
QByteArray clientSecret = configValue(homeConnectPluginCustomClientSecretParamTypeId).toByteArray();
|
||||||
|
if (clientKey.isEmpty() || clientSecret.isEmpty()) {
|
||||||
|
clientKey = apiKeyStorage()->requestKey("homeconnect").data("clientKey");
|
||||||
|
clientSecret = apiKeyStorage()->requestKey("homeconnect").data("clientSecret");
|
||||||
|
}
|
||||||
|
if (clientKey.isEmpty() || clientSecret.isEmpty()) {
|
||||||
|
info->finish(Thing::ThingErrorAuthenticationFailure, tr("Client key and/or seceret is not available."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
homeConnect = new HomeConnect(hardwareManager()->networkManager(), clientKey, clientSecret, simulationMode, this);
|
homeConnect = new HomeConnect(hardwareManager()->networkManager(), clientKey, clientSecret, simulationMode, this);
|
||||||
homeConnect->getAccessTokenFromRefreshToken(refreshToken);
|
homeConnect->getAccessTokenFromRefreshToken(refreshToken);
|
||||||
m_asyncSetup.insert(homeConnect, info);
|
m_asyncSetup.insert(homeConnect, info);
|
||||||
@ -269,14 +288,14 @@ void IntegrationPluginHomeConnect::postSetupThing(Thing *thing)
|
|||||||
if (!m_pluginTimer60sec) {
|
if (!m_pluginTimer60sec) {
|
||||||
m_pluginTimer60sec = hardwareManager()->pluginTimerManager()->registerTimer(60);
|
m_pluginTimer60sec = hardwareManager()->pluginTimerManager()->registerTimer(60);
|
||||||
connect(m_pluginTimer60sec, &PluginTimer::timeout, this, [this]() {
|
connect(m_pluginTimer60sec, &PluginTimer::timeout, this, [this]() {
|
||||||
foreach (Thing *thing, myThings().filterByThingClassId(homeConnectConnectionThingClassId)) {
|
Q_FOREACH (Thing *thing, myThings().filterByThingClassId(homeConnectAccountThingClassId)) {
|
||||||
HomeConnect *homeConnect = m_homeConnectConnections.value(thing);
|
HomeConnect *homeConnect = m_homeConnectConnections.value(thing);
|
||||||
if (!homeConnect) {
|
if (!homeConnect) {
|
||||||
qWarning(dcHomeConnect()) << "No HomeConnect account found for" << thing->name();
|
qWarning(dcHomeConnect()) << "No HomeConnect account found for" << thing->name();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
homeConnect->getHomeAppliances();
|
homeConnect->getHomeAppliances();
|
||||||
Q_FOREACH(Thing *childThing, myThings().filterByParentId(thing->id())) {
|
Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) {
|
||||||
QString haId = childThing->paramValue(m_idParamTypeIds.value(childThing->thingClassId())).toString();
|
QString haId = childThing->paramValue(m_idParamTypeIds.value(childThing->thingClassId())).toString();
|
||||||
homeConnect->getStatus(haId);
|
homeConnect->getStatus(haId);
|
||||||
homeConnect->getSettings(haId);
|
homeConnect->getSettings(haId);
|
||||||
@ -286,12 +305,12 @@ void IntegrationPluginHomeConnect::postSetupThing(Thing *thing)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thing->thingClassId() == homeConnectConnectionThingClassId) {
|
if (thing->thingClassId() == homeConnectAccountThingClassId) {
|
||||||
HomeConnect *homeConnect = m_homeConnectConnections.value(thing);
|
HomeConnect *homeConnect = m_homeConnectConnections.value(thing);
|
||||||
homeConnect->getHomeAppliances();
|
homeConnect->getHomeAppliances();
|
||||||
homeConnect->connectEventStream();
|
homeConnect->connectEventStream();
|
||||||
thing->setStateValue(homeConnectConnectionConnectedStateTypeId, true);
|
thing->setStateValue(homeConnectAccountConnectedStateTypeId, true);
|
||||||
thing->setStateValue(homeConnectConnectionLoggedInStateTypeId, true);
|
thing->setStateValue(homeConnectAccountLoggedInStateTypeId, true);
|
||||||
//TBD Set user name
|
//TBD Set user name
|
||||||
} else if ((thing->thingClassId() == dryerThingClassId) ||
|
} else if ((thing->thingClassId() == dryerThingClassId) ||
|
||||||
(thing->thingClassId() == fridgeThingClassId) ||
|
(thing->thingClassId() == fridgeThingClassId) ||
|
||||||
@ -481,7 +500,7 @@ void IntegrationPluginHomeConnect::executeAction(ThingActionInfo *info)
|
|||||||
void IntegrationPluginHomeConnect::thingRemoved(Thing *thing)
|
void IntegrationPluginHomeConnect::thingRemoved(Thing *thing)
|
||||||
{
|
{
|
||||||
qCDebug(dcHomeConnect) << "Delete " << thing->name();
|
qCDebug(dcHomeConnect) << "Delete " << thing->name();
|
||||||
if (thing->thingClassId() == homeConnectConnectionThingClassId) {
|
if (thing->thingClassId() == homeConnectAccountThingClassId) {
|
||||||
m_homeConnectConnections.take(thing)->deleteLater();
|
m_homeConnectConnections.take(thing)->deleteLater();
|
||||||
} else {
|
} else {
|
||||||
m_selectedProgram.remove(thing);
|
m_selectedProgram.remove(thing);
|
||||||
@ -546,7 +565,6 @@ void IntegrationPluginHomeConnect::executeBrowserItem(BrowserActionInfo *info)
|
|||||||
if (!homeConnect)
|
if (!homeConnect)
|
||||||
return;
|
return;
|
||||||
QString haid = thing->paramValue(m_idParamTypeIds.value(thing->thingClassId())).toString();
|
QString haid = thing->paramValue(m_idParamTypeIds.value(thing->thingClassId())).toString();
|
||||||
|
|
||||||
QUuid requestId = homeConnect->selectProgram(haid, info->browserAction().itemId(), QList<HomeConnect::Option> ());
|
QUuid requestId = homeConnect->selectProgram(haid, info->browserAction().itemId(), QList<HomeConnect::Option> ());
|
||||||
m_selectedProgram.insert(thing, info->browserAction().itemId());
|
m_selectedProgram.insert(thing, info->browserAction().itemId());
|
||||||
|
|
||||||
@ -581,8 +599,8 @@ void IntegrationPluginHomeConnect::parseKey(Thing *thing, const QString &key, co
|
|||||||
thing->setStateValue(ovenTargetTemperatureStateTypeId, value);
|
thing->setStateValue(ovenTargetTemperatureStateTypeId, value);
|
||||||
} else if (key == "BSH.Common.Option.Duration") {
|
} else if (key == "BSH.Common.Option.Duration") {
|
||||||
thing->setStateValue(ovenDurationStateTypeId, value);
|
thing->setStateValue(ovenDurationStateTypeId, value);
|
||||||
} else if (key == "Cooking.Oven.Option.FastPreHeat") {
|
//} else if (key == "Cooking.Oven.Option.FastPreHeat") {
|
||||||
} else if (key == "BSH.Common.Option.StartInRelative") {
|
//} else if (key == "BSH.Common.Option.StartInRelative") {
|
||||||
} else if (key == "LaundryCare.Washer.Option.Temperature") {
|
} else if (key == "LaundryCare.Washer.Option.Temperature") {
|
||||||
thing->setStateValue(washerTemperatureStateTypeId, value.toString().split('.').last()); // Cold, 20, 40, 60°C
|
thing->setStateValue(washerTemperatureStateTypeId, value.toString().split('.').last()); // Cold, 20, 40, 60°C
|
||||||
} else if (key == "LaundryCare.Washer.Option.SpinSpeed") {
|
} else if (key == "LaundryCare.Washer.Option.SpinSpeed") {
|
||||||
@ -620,14 +638,13 @@ void IntegrationPluginHomeConnect::parseKey(Thing *thing, const QString &key, co
|
|||||||
qCDebug(dcHomeConnect()) << "Unkown Coffee temperature string" << temperature;
|
qCDebug(dcHomeConnect()) << "Unkown Coffee temperature string" << temperature;
|
||||||
}
|
}
|
||||||
} else if (key == "Cooking.Common.Option.Hood.VentingLevel") {
|
} else if (key == "Cooking.Common.Option.Hood.VentingLevel") {
|
||||||
//TODO
|
thing->setStateValue(hoodVentingLevelStateTypeId, value);
|
||||||
} else if (key == "Cooking.Common.Option.Hood.IntensiveLevel") {
|
//} else if (key == "Cooking.Common.Option.Hood.IntensiveLevel") {
|
||||||
//TODO
|
//} else if (key == "ConsumerProducts.CleaningRobot.Option.ReferenceMapId") {
|
||||||
} else if (key == "ConsumerProducts.CleaningRobot.Option.ReferenceMapId") {
|
//} else if (key == "ConsumerProducts.CleaningRobot.Option.CleaningMode") {
|
||||||
} else if (key == "ConsumerProducts.CleaningRobot.Option.CleaningMode") {
|
|
||||||
|
|
||||||
// Program Progress Changes
|
// Program Progress Changes
|
||||||
} else if (key == "BSH.Common.Option.ElapsedProgramTime") {
|
//} else if (key == "BSH.Common.Option.ElapsedProgramTime") {
|
||||||
} else if (key == "BSH.Common.Option.RemainingProgramTime") {
|
} else if (key == "BSH.Common.Option.RemainingProgramTime") {
|
||||||
QString time = QDateTime::fromMSecsSinceEpoch(QDateTime::currentMSecsSinceEpoch()+(value.toInt()*1000)).time().toString();
|
QString time = QDateTime::fromMSecsSinceEpoch(QDateTime::currentMSecsSinceEpoch()+(value.toInt()*1000)).time().toString();
|
||||||
thing->setStateValue(m_endTimerStateTypeIds.value(thing->thingClassId()), time);
|
thing->setStateValue(m_endTimerStateTypeIds.value(thing->thingClassId()), time);
|
||||||
@ -635,7 +652,7 @@ void IntegrationPluginHomeConnect::parseKey(Thing *thing, const QString &key, co
|
|||||||
if (m_progressStateTypeIds.contains(thing->thingClassId())) {
|
if (m_progressStateTypeIds.contains(thing->thingClassId())) {
|
||||||
thing->setStateValue(m_progressStateTypeIds.value(thing->thingClassId()), value);
|
thing->setStateValue(m_progressStateTypeIds.value(thing->thingClassId()), value);
|
||||||
}
|
}
|
||||||
} else if (key == "ConsumerProducts.CleaningRobot.Option.ProcessPhase") {
|
//} else if (key == "ConsumerProducts.CleaningRobot.Option.ProcessPhase") {
|
||||||
} else if (key == "BSH.Common.Status.OperationState") {
|
} else if (key == "BSH.Common.Status.OperationState") {
|
||||||
if (m_operationStateTypeIds.contains(thing->thingClassId())) {
|
if (m_operationStateTypeIds.contains(thing->thingClassId())) {
|
||||||
QString operationState = value.toString();
|
QString operationState = value.toString();
|
||||||
@ -683,12 +700,11 @@ void IntegrationPluginHomeConnect::parseKey(Thing *thing, const QString &key, co
|
|||||||
if (m_progressStateTypeIds.contains(thing->thingClassId())) {
|
if (m_progressStateTypeIds.contains(thing->thingClassId())) {
|
||||||
thing->setStateValue(m_progressStateTypeIds.value(thing->thingClassId()), 0);
|
thing->setStateValue(m_progressStateTypeIds.value(thing->thingClassId()), 0);
|
||||||
}
|
}
|
||||||
} else if (key == "BSH.Common.Event.AlarmClockElapsed") {
|
//} else if (key == "BSH.Common.Event.AlarmClockElapsed") {
|
||||||
} else if (key == "Cooking.Oven.Event.PreheatFinished") {
|
} else if (key == "Cooking.Oven.Event.PreheatFinished") {
|
||||||
emitEvent(Event(ovenPreheatFinishedEventTypeId, thing->id()));
|
emitEvent(Event(ovenPreheatFinishedEventTypeId, thing->id()));
|
||||||
// Home Appliance State Changes
|
// Home Appliance State Changes
|
||||||
} else if (key == "BSH.Common.Setting.PowerState") {
|
//} else if (key == "BSH.Common.Setting.PowerState") {
|
||||||
//Ignore
|
|
||||||
} else if (key == "BSH.Common.Status.RemoteControlActive") {
|
} else if (key == "BSH.Common.Status.RemoteControlActive") {
|
||||||
if (m_remoteControlActivationStateTypeIds.contains(thing->thingClassId())) {
|
if (m_remoteControlActivationStateTypeIds.contains(thing->thingClassId())) {
|
||||||
thing->setStateValue(m_remoteControlActivationStateTypeIds.value(thing->thingClassId()), value);
|
thing->setStateValue(m_remoteControlActivationStateTypeIds.value(thing->thingClassId()), value);
|
||||||
@ -703,7 +719,7 @@ void IntegrationPluginHomeConnect::parseKey(Thing *thing, const QString &key, co
|
|||||||
}
|
}
|
||||||
} else if (key == "BSH.Common.Status.DoorState") {
|
} else if (key == "BSH.Common.Status.DoorState") {
|
||||||
if (m_doorStateTypeIds.contains(thing->thingClassId())) {
|
if (m_doorStateTypeIds.contains(thing->thingClassId())) {
|
||||||
thing->setStateValue(m_doorStateTypeIds.value(thing->thingClassId()), value.toString().split('.').last());
|
thing->setStateValue(m_doorStateTypeIds.value(thing->thingClassId()), value.toString().split('.').last() != "Open");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Home Appliance Events
|
// Home Appliance Events
|
||||||
@ -736,32 +752,33 @@ void IntegrationPluginHomeConnect::parseKey(Thing *thing, const QString &key, co
|
|||||||
|
|
||||||
void IntegrationPluginHomeConnect::parseSettingKey(Thing *thing, const QString &key, const QVariant &value)
|
void IntegrationPluginHomeConnect::parseSettingKey(Thing *thing, const QString &key, const QVariant &value)
|
||||||
{
|
{
|
||||||
if (key.contains("BSH.Common.Setting.PowerState")) {
|
if (key.contains("Refrigeration.FridgeFreezer.Setting.SetpointTemperatureRefrigerator")) {
|
||||||
} else if (key.contains("BSH.Common.Setting.TemperatureUnit")) {
|
|
||||||
} else if (key.contains("BSH.Common.Setting.LiquidVolumeUnit")) {
|
|
||||||
} else if (key.contains("Refrigeration.FridgeFreezer.Setting.SetpointTemperatureRefrigerator")) {
|
|
||||||
thing->setStateValue(fridgeFridgeTemperatureSettingStateTypeId, value);
|
thing->setStateValue(fridgeFridgeTemperatureSettingStateTypeId, value);
|
||||||
} else if (key.contains("Refrigeration.FridgeFreezer.Setting.SetpointTemperatureFreezer")) {
|
} else if (key.contains("Refrigeration.FridgeFreezer.Setting.SetpointTemperatureFreezer")) {
|
||||||
thing->setStateValue(fridgeFreezerTemperatureStateTypeId, value);
|
thing->setStateValue(fridgeFreezerTemperatureStateTypeId, value);
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.BottleCooler.SetpointTemperature")) {
|
// For future improvements
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.ChillerLeft.SetpointTemperature")) {
|
//} else if (key.contains("BSH.Common.Setting.PowerState")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.ChillerCommon.SetpointTemperature")) {
|
//} else if (key.contains("BSH.Common.Setting.TemperatureUnit")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.ChillerRight.SetpointTemperature")) {
|
//} else if (key.contains("BSH.Common.Setting.LiquidVolumeUnit")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.WineCompartment.SetpointTemperature")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.BottleCooler.SetpointTemperature")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.WineCompartment2.SetpointTemperature")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.ChillerLeft.SetpointTemperature")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.WineCompartment3.SetpointTemperature")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.ChillerCommon.SetpointTemperature")) {
|
||||||
} else if (key.contains("Refrigeration.FridgeFreezer.Setting.SuperModeRefrigerator")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.ChillerRight.SetpointTemperature")) {
|
||||||
} else if (key.contains("Refrigeration.FridgeFreezer.Setting.SuperModeFreezer")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.WineCompartment.SetpointTemperature")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.EcoMode")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.WineCompartment2.SetpointTemperature")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.SabbathMode")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.WineCompartment3.SetpointTemperature")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.VacationMode")) {
|
//} else if (key.contains("Refrigeration.FridgeFreezer.Setting.SuperModeRefrigerator")) {
|
||||||
} else if (key.contains("Refrigeration.Common.Setting.FreshMode")) {
|
//} else if (key.contains("Refrigeration.FridgeFreezer.Setting.SuperModeFreezer")) {
|
||||||
} else if (key.contains("Cooking.Common.Setting.Lighting")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.EcoMode")) {
|
||||||
} else if (key.contains("Cooking.Common.Setting.LightingBrightness")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.SabbathMode")) {
|
||||||
} else if (key.contains("BSH.Common.Setting.AmbientLightEnabled")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.VacationMode")) {
|
||||||
} else if (key.contains("BSH.Common.Setting.AmbientLightBrightness")) {
|
//} else if (key.contains("Refrigeration.Common.Setting.FreshMode")) {
|
||||||
} else if (key.contains("BSH.Common.Setting.AmbientLightColor")) {
|
//} else if (key.contains("Cooking.Common.Setting.Lighting")) {
|
||||||
} else if (key.contains("BSH.Common.Setting.AmbientLightCustomColor")) {
|
//} else if (key.contains("Cooking.Common.Setting.LightingBrightness")) {
|
||||||
|
//} else if (key.contains("BSH.Common.Setting.AmbientLightEnabled")) {
|
||||||
|
//} else if (key.contains("BSH.Common.Setting.AmbientLightBrightness")) {
|
||||||
|
//} else if (key.contains("BSH.Common.Setting.AmbientLightColor")) {
|
||||||
|
//} else if (key.contains("BSH.Common.Setting.AmbientLightCustomColor")) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,7 +788,7 @@ void IntegrationPluginHomeConnect::onConnectionChanged(bool connected)
|
|||||||
Thing *thing = m_homeConnectConnections.key(homeConnect);
|
Thing *thing = m_homeConnectConnections.key(homeConnect);
|
||||||
if (!thing)
|
if (!thing)
|
||||||
return;
|
return;
|
||||||
thing->setStateValue(homeConnectConnectionConnectedStateTypeId, connected);
|
thing->setStateValue(homeConnectAccountConnectedStateTypeId, connected);
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
Q_FOREACH(Thing *child, myThings().filterByParentId(thing->id())) {
|
Q_FOREACH(Thing *child, myThings().filterByParentId(thing->id())) {
|
||||||
child->setStateValue(m_connectedStateTypeIds.value(child->thingClassId()), connected);
|
child->setStateValue(m_connectedStateTypeIds.value(child->thingClassId()), connected);
|
||||||
@ -796,7 +813,7 @@ void IntegrationPluginHomeConnect::onAuthenticationStatusChanged(bool authentica
|
|||||||
if (!thing)
|
if (!thing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
thing->setStateValue(homeConnectConnectionLoggedInStateTypeId, authenticated);
|
thing->setStateValue(homeConnectAccountLoggedInStateTypeId, authenticated);
|
||||||
if (!authenticated) {
|
if (!authenticated) {
|
||||||
//refresh access token needs to be refreshed
|
//refresh access token needs to be refreshed
|
||||||
pluginStorage()->beginGroup(thing->id().toString());
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
|
|||||||
@ -16,6 +16,20 @@
|
|||||||
"displayName": "Control enabled",
|
"displayName": "Control enabled",
|
||||||
"defaultValue": false,
|
"defaultValue": false,
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "19cedaab-b8a0-4cab-80c7-0cae5fce124d",
|
||||||
|
"name": "customClientKey",
|
||||||
|
"displayName": "Custom client key",
|
||||||
|
"defaultValue": "",
|
||||||
|
"type": "QString"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "49b828ab-f495-4332-900b-99a9d37565b1",
|
||||||
|
"name": "customClientSecret",
|
||||||
|
"displayName": "Custom client secret",
|
||||||
|
"defaultValue": "",
|
||||||
|
"type": "QString"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"apiKeys": ["homeconnect"],
|
"apiKeys": ["homeconnect"],
|
||||||
@ -27,8 +41,8 @@
|
|||||||
"thingClasses": [
|
"thingClasses": [
|
||||||
{
|
{
|
||||||
"id": "babc1a39-730a-4516-95bf-ff51a8ce887a",
|
"id": "babc1a39-730a-4516-95bf-ff51a8ce887a",
|
||||||
"name": "homeConnectConnection",
|
"name": "homeConnectAccount",
|
||||||
"displayName": "Home Connect connection",
|
"displayName": "Home Connect account",
|
||||||
"interfaces": ["account"],
|
"interfaces": ["account"],
|
||||||
"createMethods": ["user"],
|
"createMethods": ["user"],
|
||||||
"setupMethod": "oauth",
|
"setupMethod": "oauth",
|
||||||
@ -66,7 +80,7 @@
|
|||||||
"id": "96845b7d-4c20-43a0-a810-ec505df3ee88",
|
"id": "96845b7d-4c20-43a0-a810-ec505df3ee88",
|
||||||
"name": "oven",
|
"name": "oven",
|
||||||
"displayName": "Oven",
|
"displayName": "Oven",
|
||||||
"interfaces": ["connectable"],
|
"interfaces": ["connectable", "closablesensor"],
|
||||||
"createMethods": ["auto"],
|
"createMethods": ["auto"],
|
||||||
"browsable": true,
|
"browsable": true,
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
@ -90,15 +104,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "e892ca9e-5b31-41f5-a568-44474091f0f6",
|
"id": "e892ca9e-5b31-41f5-a568-44474091f0f6",
|
||||||
"name": "doorState",
|
"name": "closed",
|
||||||
"displayName": "Door state",
|
"displayName": "Door closed",
|
||||||
"displayNameEvent": "Door state changed",
|
"displayNameEvent": "Door closed changed",
|
||||||
"defaultValue": "Open",
|
"defaultValue": false,
|
||||||
"type": "QString",
|
"type": "bool"
|
||||||
"possibleValues": [
|
|
||||||
"Open",
|
|
||||||
"Closed"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "c9f9bd33-513f-4834-a504-c2c1611fb4be",
|
"id": "c9f9bd33-513f-4834-a504-c2c1611fb4be",
|
||||||
@ -241,15 +251,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "8cbb3746-7e04-4fc8-93eb-b774b606a057",
|
"id": "8cbb3746-7e04-4fc8-93eb-b774b606a057",
|
||||||
"name": "doorState",
|
"name": "closed",
|
||||||
"displayName": "Door state",
|
"displayName": "Door closed",
|
||||||
"displayNameEvent": "Door state changed",
|
"displayNameEvent": "Door closed changed",
|
||||||
"defaultValue": "Open",
|
"defaultValue": false,
|
||||||
"type": "QString",
|
"type": "bool"
|
||||||
"possibleValues": [
|
|
||||||
"Open",
|
|
||||||
"Closed"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2b45fbfc-d3d7-4dd4-91f8-4a789405246e",
|
"id": "2b45fbfc-d3d7-4dd4-91f8-4a789405246e",
|
||||||
@ -369,15 +375,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "5011efa7-9915-4ecc-b717-6ced369abcb7",
|
"id": "5011efa7-9915-4ecc-b717-6ced369abcb7",
|
||||||
"name": "doorState",
|
"name": "closed",
|
||||||
"displayName": "Door state",
|
"displayName": "Door closed",
|
||||||
"displayNameEvent": "Door state changed",
|
"displayNameEvent": "Door closed changed",
|
||||||
"defaultValue": "Open",
|
"defaultValue": false,
|
||||||
"type": "QString",
|
"type": "bool"
|
||||||
"possibleValues": [
|
|
||||||
"Open",
|
|
||||||
"Closed"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "693fc8d2-d9a9-4109-b8c5-f3d22091500c",
|
"id": "693fc8d2-d9a9-4109-b8c5-f3d22091500c",
|
||||||
@ -540,16 +542,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "81aa609e-69c0-4d5c-98f0-46e6f14c7eaa",
|
"id": "81aa609e-69c0-4d5c-98f0-46e6f14c7eaa",
|
||||||
"name": "doorState",
|
"name": "closed",
|
||||||
"displayName": "Door state",
|
"displayName": "Door closed",
|
||||||
"displayNameEvent": "Door state changed",
|
"displayNameEvent": "Door closed changed",
|
||||||
"defaultValue": "Open",
|
"defaultValue": false,
|
||||||
"type": "QString",
|
"type": "bool"
|
||||||
"possibleValues": [
|
|
||||||
"Open",
|
|
||||||
"Closed",
|
|
||||||
"Locked"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "52fde732-ed14-437e-8fbf-461d2ed19654",
|
"id": "52fde732-ed14-437e-8fbf-461d2ed19654",
|
||||||
@ -682,15 +679,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "99bba70c-5ead-4076-8b71-720a931668a4",
|
"id": "99bba70c-5ead-4076-8b71-720a931668a4",
|
||||||
"name": "doorState",
|
"name": "closed",
|
||||||
"displayName": "Door state",
|
"displayName": "Door closed",
|
||||||
"displayNameEvent": "Door state changed",
|
"displayNameEvent": "Door closed changed",
|
||||||
"defaultValue": "Open",
|
"defaultValue": false,
|
||||||
"type": "QString",
|
"type": "bool"
|
||||||
"possibleValues": [
|
|
||||||
"Open",
|
|
||||||
"Closed"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "bc13977e-0ea1-4804-af00-311ae62c6c06",
|
"id": "bc13977e-0ea1-4804-af00-311ae62c6c06",
|
||||||
@ -785,16 +778,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "99296e86-09bf-4b74-b122-ee82b6bfdb62",
|
"id": "99296e86-09bf-4b74-b122-ee82b6bfdb62",
|
||||||
"name": "doorState",
|
"name": "closed",
|
||||||
"displayName": "Door state",
|
"displayName": "Door closed",
|
||||||
"displayNameEvent": "Door state changed",
|
"displayNameEvent": "Door closed changed",
|
||||||
"defaultValue": "Open",
|
"defaultValue": false,
|
||||||
"type": "QString",
|
"type": "bool"
|
||||||
"possibleValues": [
|
|
||||||
"Open",
|
|
||||||
"Closed",
|
|
||||||
"Locked"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2ad3e2f8-c955-4e1d-b394-1e71a16f03bb",
|
"id": "2ad3e2f8-c955-4e1d-b394-1e71a16f03bb",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user