| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2022 Jon Beniston, M7RCE                                        //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify          //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by          //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                  //
 | 
					
						
							|  |  |  | // (at your option) any later version.                                           //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,               //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QDebug>
 | 
					
						
							|  |  |  | #include <QUrl>
 | 
					
						
							|  |  |  | #include <QUrlQuery>
 | 
					
						
							|  |  |  | #include <QNetworkReply>
 | 
					
						
							|  |  |  | #include <QJsonDocument>
 | 
					
						
							|  |  |  | #include <QJsonObject>
 | 
					
						
							|  |  |  | #include <QRegularExpression>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "util/iot/tplink.h"
 | 
					
						
							|  |  |  | #include "util/simpleserializer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const QString TPLinkCommon::m_url = "https://wap.tplinkcloud.com"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TPLinkCommon::TPLinkCommon(const QString& username, const QString &password) : | 
					
						
							|  |  |  |     m_loggedIn(false), | 
					
						
							|  |  |  |     m_outstandingRequest(false), | 
					
						
							|  |  |  |     m_username(username), | 
					
						
							|  |  |  |     m_password(password), | 
					
						
							|  |  |  |     m_networkManager(nullptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TPLinkCommon::login() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QUrl url(m_url); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QNetworkRequest request(url); | 
					
						
							|  |  |  |     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); | 
					
						
							|  |  |  |     QJsonObject params { | 
					
						
							|  |  |  |         {"appType", "Kasa_Android"}, | 
					
						
							|  |  |  |         {"cloudUserName", m_username}, | 
					
						
							|  |  |  |         {"cloudPassword", m_password}, | 
					
						
							|  |  |  |         {"terminalUUID", "9cc4653e-338f-48e4-b8ca-6ed3f67631e4"} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject object { | 
					
						
							|  |  |  |         {"method", "login"}, | 
					
						
							|  |  |  |         {"params", params} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonDocument document; | 
					
						
							|  |  |  |     document.setObject(object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_networkManager->post(request, document.toJson()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TPLinkCommon::handleLoginReply(QNetworkReply* reply, QString &errorMessage) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (reply) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!reply->error()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); | 
					
						
							|  |  |  |             if (document.isObject()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 //qDebug() << "Received " << document;
 | 
					
						
							|  |  |  |                 if (!m_loggedIn) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     QJsonObject obj = document.object(); | 
					
						
							|  |  |  |                     if (obj.contains(QStringLiteral("error_code"))) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         int errorCode = obj.value(QStringLiteral("error_code")).toInt(); | 
					
						
							|  |  |  |                         if (!errorCode) | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             if (obj.contains(QStringLiteral("result"))) | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 QJsonObject result = obj.value(QStringLiteral("result")).toObject(); | 
					
						
							|  |  |  |                                 if (result.contains(QStringLiteral("token"))) | 
					
						
							|  |  |  |                                 { | 
					
						
							|  |  |  |                                     m_loggedIn = true; | 
					
						
							|  |  |  |                                     m_token = result.value(QStringLiteral("token")).toString(); | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                                 else | 
					
						
							|  |  |  |                                 { | 
					
						
							|  |  |  |                                     qDebug() << "TPLinkDevice::handleReply: Object doesn't contain a token: " << result; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                             else | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 qDebug() << "TPLinkDevice::handleReply: Object doesn't contain a result object: " << obj; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         else | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             qDebug() << "TPLinkDevice::handleReply: Non-zero error_code while logging in: " << errorCode; | 
					
						
							|  |  |  |                             if (obj.contains(QStringLiteral("msg"))) | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 QString msg = obj.value(QStringLiteral("msg")).toString(); | 
					
						
							|  |  |  |                                 qDebug() << "TPLinkDevice::handleReply: Error message: " << msg; | 
					
						
							|  |  |  |                                 // Typical msg is "Incorrect email or password"
 | 
					
						
							|  |  |  |                                 errorMessage = QString("TP-Link: Failed to log in. %1").arg(msg); | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                             else | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 errorMessage = QString("TP-Link: Failed to log in. Error code: %1").arg(errorCode); | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         qDebug() << "TPLinkDevice::handleReply: Object doesn't contain an error_code: " << obj; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 qDebug() << "TPLinkDevice::handleReply: Document is not an object: " << document; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             qDebug() << "TPLinkDevice::handleReply: error: " << reply->error(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         reply->deleteLater(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug() << "TPLinkDevice::handleReply: reply is null"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!m_loggedIn && errorMessage.isEmpty()) { | 
					
						
							|  |  |  |         errorMessage = "TP-Link: Failed to log in."; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TPLinkDevice::TPLinkDevice(const QString& username, const QString &password, const QString &deviceId, DeviceDiscoverer::DeviceInfo *info) : | 
					
						
							|  |  |  |     Device(info), | 
					
						
							|  |  |  |     TPLinkCommon(username, password), | 
					
						
							|  |  |  |     m_deviceId(deviceId) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_networkManager = new QNetworkAccessManager(); | 
					
						
							|  |  |  |     QObject::connect( | 
					
						
							|  |  |  |         m_networkManager, | 
					
						
							|  |  |  |         &QNetworkAccessManager::finished, | 
					
						
							|  |  |  |         this, | 
					
						
							|  |  |  |         &TPLinkDevice::handleReply | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     login(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TPLinkDevice::~TPLinkDevice() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QObject::disconnect( | 
					
						
							|  |  |  |         m_networkManager, | 
					
						
							|  |  |  |         &QNetworkAccessManager::finished, | 
					
						
							|  |  |  |         this, | 
					
						
							|  |  |  |         &TPLinkDevice::handleReply | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     delete m_networkManager; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TPLinkDevice::getState() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_loggedIn) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_outstandingRequest = true; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QUrl url(m_url); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QNetworkRequest request(url); | 
					
						
							|  |  |  |     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); | 
					
						
							|  |  |  |     QJsonObject system; | 
					
						
							|  |  |  |     system.insert("get_sysinfo", QJsonValue()); | 
					
						
							|  |  |  |     QJsonObject emeter; | 
					
						
							|  |  |  |     emeter.insert("get_realtime", QJsonValue()); | 
					
						
							|  |  |  |     QJsonObject requestData { | 
					
						
							|  |  |  |         {"system", system}, | 
					
						
							|  |  |  |         {"emeter", emeter} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject params { | 
					
						
							|  |  |  |         {"deviceId", m_deviceId}, | 
					
						
							|  |  |  |         {"requestData", requestData}, | 
					
						
							|  |  |  |         {"token", m_token} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject object { | 
					
						
							|  |  |  |         {"method", "passthrough"}, | 
					
						
							|  |  |  |         {"params", params} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonDocument document; | 
					
						
							|  |  |  |     document.setObject(object); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |     QNetworkReply *reply = m_networkManager->post(request, document.toJson()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     recordGetRequest(reply); | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TPLinkDevice::setState(const QString &controlId, bool state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_loggedIn) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Should we queue these and apply after logged in?
 | 
					
						
							|  |  |  |         qDebug() << "TPLinkDevice::setState: Unable to set state for " << controlId << " to " << state << " as not yet logged in"; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QUrl url(m_url); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QNetworkRequest request(url); | 
					
						
							|  |  |  |     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); | 
					
						
							|  |  |  |     QJsonObject stateObj { | 
					
						
							|  |  |  |         {"state", (int)state} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject system { | 
					
						
							|  |  |  |         {"set_relay_state", stateObj} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject requestData { | 
					
						
							|  |  |  |         {"system", system} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     if (controlId != "switch") { | 
					
						
							|  |  |  |         QJsonArray childIds { | 
					
						
							|  |  |  |             controlId | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         QJsonObject context { | 
					
						
							|  |  |  |             {"child_ids", childIds} | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         requestData.insert("context", QJsonValue(context)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QJsonObject params { | 
					
						
							|  |  |  |         {"deviceId", m_deviceId}, | 
					
						
							|  |  |  |         {"requestData", requestData}, | 
					
						
							|  |  |  |         {"token", m_token} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject object { | 
					
						
							|  |  |  |         {"method", "passthrough"}, | 
					
						
							|  |  |  |         {"params", params} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonDocument document; | 
					
						
							|  |  |  |     document.setObject(object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_networkManager->post(request, document.toJson()); | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     recordSetRequest(controlId); | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TPLinkDevice::handleReply(QNetworkReply* reply) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_loggedIn) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString errorMessage; | 
					
						
							|  |  |  |         TPLinkCommon::handleLoginReply(reply, errorMessage); | 
					
						
							|  |  |  |         if (!errorMessage.isEmpty()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             emit error(errorMessage); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (m_outstandingRequest) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_outstandingRequest = true; | 
					
						
							|  |  |  |             getState(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (reply) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!reply->error()) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |             QByteArray data = reply->readAll(); | 
					
						
							|  |  |  |             QJsonParseError error; | 
					
						
							|  |  |  |             QJsonDocument document = QJsonDocument::fromJson(data, &error); | 
					
						
							|  |  |  |             if (!document.isNull()) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                 if (document.isObject()) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                     //qDebug() << "Received " << document;
 | 
					
						
							|  |  |  |                     QJsonObject obj = document.object(); | 
					
						
							|  |  |  |                     if (obj.contains(QStringLiteral("result"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                     { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                         QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject(); | 
					
						
							|  |  |  |                         QHash<QString, QVariant> status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (resultObj.contains(QStringLiteral("responseData"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                         { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                             QJsonObject responseDataObj = resultObj.value(QStringLiteral("responseData")).toObject(); | 
					
						
							|  |  |  |                             if (responseDataObj.contains(QStringLiteral("system"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                             { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                 QJsonObject systemObj = responseDataObj.value(QStringLiteral("system")).toObject(); | 
					
						
							|  |  |  |                                 if (systemObj.contains(QStringLiteral("get_sysinfo"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                     QJsonObject sysInfoObj = systemObj.value(QStringLiteral("get_sysinfo")).toObject(); | 
					
						
							|  |  |  |                                     if (sysInfoObj.contains(QStringLiteral("child_num"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                     { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                         QJsonArray children = sysInfoObj.value(QStringLiteral("children")).toArray(); | 
					
						
							|  |  |  |                                         for (auto childRef : children) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                         { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                             QJsonObject childObj = childRef.toObject(); | 
					
						
							|  |  |  |                                             if (childObj.contains(QStringLiteral("state")) && childObj.contains(QStringLiteral("id"))) | 
					
						
							|  |  |  |                                             { | 
					
						
							|  |  |  |                                                 QString id = childObj.value(QStringLiteral("id")).toString(); | 
					
						
							|  |  |  |                                                 if (getAfterSet(reply, id)) | 
					
						
							|  |  |  |                                                 { | 
					
						
							|  |  |  |                                                     int state = childObj.value(QStringLiteral("state")).toInt(); | 
					
						
							|  |  |  |                                                     status.insert(id, state); // key should match id in discoverer
 | 
					
						
							|  |  |  |                                                 } | 
					
						
							|  |  |  |                                             } | 
					
						
							|  |  |  |                                         } | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     else if (sysInfoObj.contains(QStringLiteral("relay_state"))) | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         if (getAfterSet(reply, "switch")) | 
					
						
							|  |  |  |                                         { | 
					
						
							|  |  |  |                                             int state = sysInfoObj.value(QStringLiteral("relay_state")).toInt(); | 
					
						
							|  |  |  |                                             status.insert("switch", state); // key should match id in discoverer
 | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                         } | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                             } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                             // KP115 has emeter, but KP105 doesn't
 | 
					
						
							|  |  |  |                             if (responseDataObj.contains(QStringLiteral("emeter"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                             { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                 QJsonObject emeterObj = responseDataObj.value(QStringLiteral("emeter")).toObject(); | 
					
						
							|  |  |  |                                 if (emeterObj.contains(QStringLiteral("get_realtime"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                     QJsonObject realtimeObj = emeterObj.value(QStringLiteral("get_realtime")).toObject(); | 
					
						
							|  |  |  |                                     if (realtimeObj.contains(QStringLiteral("current_ma"))) | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         double current = realtimeObj.value(QStringLiteral("current_ma")).toDouble(); | 
					
						
							|  |  |  |                                         status.insert("current", current / 1000.0); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     if (realtimeObj.contains(QStringLiteral("voltage_mv"))) | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         double voltage = realtimeObj.value(QStringLiteral("voltage_mv")).toDouble(); | 
					
						
							|  |  |  |                                         status.insert("voltage", voltage / 1000.0); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     if (realtimeObj.contains(QStringLiteral("power_mw"))) | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         double power = realtimeObj.value(QStringLiteral("power_mw")).toDouble(); | 
					
						
							|  |  |  |                                         status.insert("power", power / 1000.0); | 
					
						
							|  |  |  |                                     } | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 } | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                         emit deviceUpdated(status); | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                     else if (obj.contains(QStringLiteral("error_code"))) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         // If a device isn't available, we can get:
 | 
					
						
							|  |  |  |                         //    {"error_code":-20002,"msg":"Request timeout"}
 | 
					
						
							|  |  |  |                         //    {"error_code":-20571,"msg":"Device is offline"}
 | 
					
						
							|  |  |  |                         int errorCode = obj.value(QStringLiteral("error_code")).toInt(); | 
					
						
							|  |  |  |                         QString msg = obj.value(QStringLiteral("msg")).toString(); | 
					
						
							|  |  |  |                         qDebug() << "TPLinkDevice::handleReply: Error code: " << errorCode << " " << msg; | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                         emit deviceUnavailable(); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         qDebug() << "TPLinkDevice::handleReply: Object doesn't contain a result or error_code: " << obj; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                     qDebug() << "TPLinkDevice::handleReply: Document is not an object: " << document; | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                 qDebug() << "TPLinkDevice::handleReply: Error parsing JSON: " << error.errorString() << " at offset " << error.offset; | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             qDebug() << "TPLinkDevice::handleReply: error: " << reply->error(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |         removeGetRequest(reply); | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |         reply->deleteLater(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug() << "TPLinkDevice::handleReply: reply is null"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TPLinkDeviceDiscoverer::TPLinkDeviceDiscoverer(const QString& username, const QString &password) : | 
					
						
							|  |  |  |     TPLinkCommon(username, password) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_networkManager = new QNetworkAccessManager(); | 
					
						
							|  |  |  |     QObject::connect( | 
					
						
							|  |  |  |         m_networkManager, | 
					
						
							|  |  |  |         &QNetworkAccessManager::finished, | 
					
						
							|  |  |  |         this, | 
					
						
							|  |  |  |         &TPLinkDeviceDiscoverer::handleReply | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     login(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TPLinkDeviceDiscoverer::~TPLinkDeviceDiscoverer() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QObject::disconnect( | 
					
						
							|  |  |  |         m_networkManager, | 
					
						
							|  |  |  |         &QNetworkAccessManager::finished, | 
					
						
							|  |  |  |         this, | 
					
						
							|  |  |  |         &TPLinkDeviceDiscoverer::handleReply | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     delete m_networkManager; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TPLinkDeviceDiscoverer::getDevices() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_loggedIn) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_outstandingRequest = true; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QUrl url(m_url); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QNetworkRequest request(url); | 
					
						
							|  |  |  |     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); | 
					
						
							|  |  |  |     QJsonObject params { | 
					
						
							|  |  |  |         {"token", m_token} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject object { | 
					
						
							|  |  |  |         {"method", "getDeviceList"}, | 
					
						
							|  |  |  |         {"params", params} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonDocument document; | 
					
						
							|  |  |  |     document.setObject(object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_networkManager->post(request, document.toJson()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TPLinkDeviceDiscoverer::getState(const QString &deviceId) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QUrl url(m_url); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QNetworkRequest request(url); | 
					
						
							|  |  |  |     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); | 
					
						
							|  |  |  |     QJsonObject system; | 
					
						
							|  |  |  |     system.insert("get_sysinfo", QJsonValue()); | 
					
						
							|  |  |  |     QJsonObject emeter; | 
					
						
							|  |  |  |     emeter.insert("get_realtime", QJsonValue()); | 
					
						
							|  |  |  |     QJsonObject requestData { | 
					
						
							|  |  |  |         {"system", system}, | 
					
						
							|  |  |  |         {"emeter", emeter} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject params { | 
					
						
							|  |  |  |         {"deviceId", deviceId}, | 
					
						
							|  |  |  |         {"requestData", requestData}, | 
					
						
							|  |  |  |         {"token", m_token} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonObject object { | 
					
						
							|  |  |  |         {"method", "passthrough"}, | 
					
						
							|  |  |  |         {"params", params} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     QJsonDocument document; | 
					
						
							|  |  |  |     document.setObject(object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_getStateReplies.insert(m_networkManager->post(request, document.toJson()), deviceId); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TPLinkDeviceDiscoverer::handleReply(QNetworkReply* reply) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_loggedIn) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString errorMessage; | 
					
						
							|  |  |  |         TPLinkCommon::handleLoginReply(reply, errorMessage); | 
					
						
							|  |  |  |         if (!errorMessage.isEmpty()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             emit error(errorMessage); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (m_outstandingRequest) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_outstandingRequest = false; | 
					
						
							|  |  |  |             getDevices(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (reply) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!reply->error()) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |             QByteArray data = reply->readAll(); | 
					
						
							|  |  |  |             QJsonParseError error; | 
					
						
							|  |  |  |             QJsonDocument document = QJsonDocument::fromJson(data, &error); | 
					
						
							|  |  |  |             if (!document.isNull()) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                 if (document.isObject()) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                     //qDebug() << "Received " << document;
 | 
					
						
							|  |  |  |                     QJsonObject obj = document.object(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (m_getStateReplies.contains(reply)) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                     { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                         // Reply for getState
 | 
					
						
							|  |  |  |                         m_getStateReplies.remove(reply); | 
					
						
							|  |  |  |                         QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject(); | 
					
						
							|  |  |  |                         if (resultObj.contains(QStringLiteral("responseData"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                         { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                             QJsonObject responseDataObj = resultObj.value(QStringLiteral("responseData")).toObject(); | 
					
						
							|  |  |  |                             if (responseDataObj.contains(QStringLiteral("system"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                             { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                 DeviceInfo info; | 
					
						
							|  |  |  |                                 QJsonObject systemObj = responseDataObj.value(QStringLiteral("system")).toObject(); | 
					
						
							|  |  |  |                                 if (systemObj.contains(QStringLiteral("get_sysinfo"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                     QJsonObject sysInfoObj = systemObj.value(QStringLiteral("get_sysinfo")).toObject(); | 
					
						
							|  |  |  |                                     if (sysInfoObj.contains(QStringLiteral("alias"))) { | 
					
						
							|  |  |  |                                         info.m_name = sysInfoObj.value(QStringLiteral("alias")).toString(); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     if (sysInfoObj.contains(QStringLiteral("model"))) { | 
					
						
							|  |  |  |                                         info.m_model = sysInfoObj.value(QStringLiteral("model")).toString(); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     if (sysInfoObj.contains(QStringLiteral("deviceId"))) { | 
					
						
							|  |  |  |                                         info.m_id = sysInfoObj.value(QStringLiteral("deviceId")).toString(); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     if (sysInfoObj.contains(QStringLiteral("child_num"))) | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         QJsonArray children = sysInfoObj.value(QStringLiteral("children")).toArray(); | 
					
						
							|  |  |  |                                         int child = 1; | 
					
						
							|  |  |  |                                         for (auto childRef : children) | 
					
						
							|  |  |  |                                         { | 
					
						
							|  |  |  |                                             QJsonObject childObj = childRef.toObject(); | 
					
						
							|  |  |  |                                             ControlInfo *controlInfo = new ControlInfo(); | 
					
						
							|  |  |  |                                             controlInfo->m_id = childObj.value(QStringLiteral("id")).toString(); | 
					
						
							|  |  |  |                                             if (childObj.contains(QStringLiteral("alias"))) { | 
					
						
							|  |  |  |                                                 controlInfo->m_name = childObj.value(QStringLiteral("alias")).toString(); | 
					
						
							|  |  |  |                                             } | 
					
						
							|  |  |  |                                             controlInfo->m_type = DeviceDiscoverer::BOOL; | 
					
						
							|  |  |  |                                             info.m_controls.append(controlInfo); | 
					
						
							|  |  |  |                                             child++; | 
					
						
							|  |  |  |                                         } | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     else if (sysInfoObj.contains(QStringLiteral("relay_state"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                     { | 
					
						
							|  |  |  |                                         ControlInfo *controlInfo = new ControlInfo(); | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                         controlInfo->m_id = "switch"; | 
					
						
							|  |  |  |                                         if (sysInfoObj.contains(QStringLiteral("alias"))) { | 
					
						
							|  |  |  |                                             controlInfo->m_name = sysInfoObj.value(QStringLiteral("alias")).toString(); | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                         } | 
					
						
							|  |  |  |                                         controlInfo->m_type = DeviceDiscoverer::BOOL; | 
					
						
							|  |  |  |                                         info.m_controls.append(controlInfo); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                 } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                 else | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                     qDebug() << "TPLinkDeviceDiscoverer::handleReply: get_sysinfo missing"; | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                 // KP115 has energy meter, but KP105 doesn't. KP105 will have emeter object, but without get_realtime sub-object
 | 
					
						
							|  |  |  |                                 if (responseDataObj.contains(QStringLiteral("emeter"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                     QJsonObject emeterObj = responseDataObj.value(QStringLiteral("emeter")).toObject(); | 
					
						
							|  |  |  |                                     if (emeterObj.contains(QStringLiteral("get_realtime"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                     { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                         QJsonObject realtimeObj = emeterObj.value(QStringLiteral("get_realtime")).toObject(); | 
					
						
							|  |  |  |                                         if (realtimeObj.contains(QStringLiteral("current_ma"))) | 
					
						
							|  |  |  |                                         { | 
					
						
							|  |  |  |                                             SensorInfo *currentSensorInfo = new SensorInfo(); | 
					
						
							|  |  |  |                                             currentSensorInfo->m_name = "Current"; | 
					
						
							|  |  |  |                                             currentSensorInfo->m_id = "current"; | 
					
						
							|  |  |  |                                             currentSensorInfo->m_type = DeviceDiscoverer::FLOAT; | 
					
						
							|  |  |  |                                             currentSensorInfo->m_units = "A"; | 
					
						
							|  |  |  |                                             info.m_sensors.append(currentSensorInfo); | 
					
						
							|  |  |  |                                         } | 
					
						
							|  |  |  |                                         if (realtimeObj.contains(QStringLiteral("voltage_mv"))) | 
					
						
							|  |  |  |                                         { | 
					
						
							|  |  |  |                                             SensorInfo *voltageSensorInfo = new SensorInfo(); | 
					
						
							|  |  |  |                                             voltageSensorInfo->m_name = "Voltage"; | 
					
						
							|  |  |  |                                             voltageSensorInfo->m_id = "voltage"; | 
					
						
							|  |  |  |                                             voltageSensorInfo->m_type = DeviceDiscoverer::FLOAT; | 
					
						
							|  |  |  |                                             voltageSensorInfo->m_units = "V"; | 
					
						
							|  |  |  |                                             info.m_sensors.append(voltageSensorInfo); | 
					
						
							|  |  |  |                                         } | 
					
						
							|  |  |  |                                         if (realtimeObj.contains(QStringLiteral("power_mw"))) | 
					
						
							|  |  |  |                                         { | 
					
						
							|  |  |  |                                             SensorInfo *powerSensorInfo = new SensorInfo(); | 
					
						
							|  |  |  |                                             powerSensorInfo->m_name = "Power"; | 
					
						
							|  |  |  |                                             powerSensorInfo->m_id = "power"; | 
					
						
							|  |  |  |                                             powerSensorInfo->m_type = DeviceDiscoverer::FLOAT; | 
					
						
							|  |  |  |                                             powerSensorInfo->m_units = "W"; | 
					
						
							|  |  |  |                                             info.m_sensors.append(powerSensorInfo); | 
					
						
							|  |  |  |                                         } | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                     } | 
					
						
							|  |  |  |                                 } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                 if (info.m_controls.size() > 0) { | 
					
						
							|  |  |  |                                     m_devices.append(info); | 
					
						
							|  |  |  |                                 } else { | 
					
						
							|  |  |  |                                     qDebug() << "TPLinkDeviceDiscoverer::handleReply: No controls in info"; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                             } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                         } | 
					
						
							|  |  |  |                         else | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             qDebug() << "TPLinkDeviceDiscoverer::handleReply: No responseData"; | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                         if (m_getStateReplies.size() == 0) | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             emit deviceList(m_devices); | 
					
						
							|  |  |  |                             m_devices.clear(); | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                     else | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                     { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                         // Reply for getDevice
 | 
					
						
							|  |  |  |                         if (obj.contains(QStringLiteral("result"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                         { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                             QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject(); | 
					
						
							|  |  |  |                             if (resultObj.contains(QStringLiteral("deviceList"))) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                             { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                 QJsonArray deviceArray = resultObj.value(QStringLiteral("deviceList")).toArray(); | 
					
						
							|  |  |  |                                 for (auto deviceRef : deviceArray) | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                                     QJsonObject deviceObj = deviceRef.toObject(); | 
					
						
							|  |  |  |                                     if (deviceObj.contains(QStringLiteral("deviceId")) && deviceObj.contains(QStringLiteral("deviceType"))) | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         // In order to discover what controls and sensors a device has, we need to get sysinfo
 | 
					
						
							|  |  |  |                                         getState(deviceObj.value(QStringLiteral("deviceId")).toString()); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     else | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         qDebug() << "TPLinkDeviceDiscoverer::handleReply: deviceList element doesn't contain a deviceId: " << deviceObj; | 
					
						
							|  |  |  |                                     } | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                                 } | 
					
						
							|  |  |  |                             } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                             else | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 qDebug() << "TPLinkDeviceDiscoverer::handleReply: result doesn't contain a deviceList: " << resultObj; | 
					
						
							|  |  |  |                             } | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                         } | 
					
						
							|  |  |  |                         else | 
					
						
							|  |  |  |                         { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                             qDebug() << "TPLinkDeviceDiscoverer::handleReply: Object doesn't contain a result: " << obj; | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     qDebug() << "TPLinkDeviceDiscoverer::handleReply: Document is not an object: " << document; | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2022-09-16 14:29:55 +01:00
										 |  |  |                 qDebug() << "TPLinkDeviceDiscoverer::handleReply: Error parsing JSON: " << error.errorString() << " at offset " << error.offset; | 
					
						
							| 
									
										
										
										
											2022-09-16 10:01:25 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             qDebug() << "TPLinkDeviceDiscoverer::handleReply: error: " << reply->error(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         reply->deleteLater(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug() << "TPLinkDeviceDiscoverer::handleReply: reply is null"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |