mirror of https://github.com/f4exb/sdrangel.git
IoT Devices: Add protection against out-of-date state
This commit is contained in:
parent
ffa17d3a2d
commit
ce5837a392
|
@ -154,6 +154,35 @@ void Device::setState(const QString &controlId, const QString &state)
|
||||||
qDebug() << "Device::setState: " << getProtocol() << " doesn't support QString. Can't set " << controlId << " to " << state;
|
qDebug() << "Device::setState: " << getProtocol() << " doesn't support QString. Can't set " << controlId << " to " << state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device::recordGetRequest(void *ptr)
|
||||||
|
{
|
||||||
|
m_getRequests.insert(ptr, QDateTime::currentDateTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::removeGetRequest(void *ptr)
|
||||||
|
{
|
||||||
|
m_getRequests.remove(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::recordSetRequest(const QString &id, int guardMS)
|
||||||
|
{
|
||||||
|
m_setRequests.insert(id, QDateTime::currentDateTime().addMSecs(guardMS));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::getAfterSet(void *ptr, const QString &id)
|
||||||
|
{
|
||||||
|
if (m_getRequests.contains(ptr) && m_setRequests.contains(id))
|
||||||
|
{
|
||||||
|
QDateTime getTime = m_getRequests.value(ptr);
|
||||||
|
QDateTime setTime = m_setRequests.value(id);
|
||||||
|
return getTime > setTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const QStringList DeviceDiscoverer::m_typeStrings = {
|
const QStringList DeviceDiscoverer::m_typeStrings = {
|
||||||
"Auto",
|
"Auto",
|
||||||
"Boolean",
|
"Boolean",
|
||||||
|
|
|
@ -139,6 +139,14 @@ signals:
|
||||||
protected:
|
protected:
|
||||||
DeviceDiscoverer::DeviceInfo m_info;
|
DeviceDiscoverer::DeviceInfo m_info;
|
||||||
|
|
||||||
|
QHash<void *, QDateTime> m_getRequests; // These data and functions help prevent using stale data from slow getStates
|
||||||
|
QHash<QString, QDateTime> m_setRequests;
|
||||||
|
|
||||||
|
void recordGetRequest(void *ptr);
|
||||||
|
void removeGetRequest(void *ptr);
|
||||||
|
void recordSetRequest(const QString &id, int guardMS=0);
|
||||||
|
bool getAfterSet(void *ptr, const QString &id);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INCLUDE_DEVICE_H */
|
#endif /* INCLUDE_DEVICE_H */
|
||||||
|
|
|
@ -65,7 +65,8 @@ void HomeAssistantDevice::getState()
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
request.setRawHeader("Authorization", "Bearer " + m_apiKey.toLocal8Bit());
|
request.setRawHeader("Authorization", "Bearer " + m_apiKey.toLocal8Bit());
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
m_networkManager->get(request);
|
QNetworkReply *reply = m_networkManager->get(request);
|
||||||
|
recordGetRequest(reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +85,10 @@ void HomeAssistantDevice::setState(const QString &controlId, bool state)
|
||||||
document.setObject(object);
|
document.setObject(object);
|
||||||
|
|
||||||
m_networkManager->post(request, document.toJson());
|
m_networkManager->post(request, document.toJson());
|
||||||
|
|
||||||
|
// 750ms guard, to try to avoid toggling of widget, while state updates on server
|
||||||
|
// Perhaps should be a setting
|
||||||
|
recordSetRequest(controlId, 750);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HomeAssistantDevice::handleReply(QNetworkReply* reply)
|
void HomeAssistantDevice::handleReply(QNetworkReply* reply)
|
||||||
|
@ -92,44 +97,54 @@ void HomeAssistantDevice::handleReply(QNetworkReply* reply)
|
||||||
{
|
{
|
||||||
if (!reply->error())
|
if (!reply->error())
|
||||||
{
|
{
|
||||||
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
QByteArray data = reply->readAll();
|
||||||
//qDebug() << "Received " << document;
|
QJsonParseError error;
|
||||||
if (document.isObject())
|
QJsonDocument document = QJsonDocument::fromJson(data, &error);
|
||||||
|
if (!document.isNull())
|
||||||
{
|
{
|
||||||
QHash<QString, QVariant> status;
|
//qDebug() << "Received " << document;
|
||||||
QJsonObject obj = document.object();
|
// POSTs to /api/services return an array, GETs from /api/states return an object
|
||||||
|
if (document.isObject())
|
||||||
if (obj.contains(QStringLiteral("entity_id")) && obj.contains(QStringLiteral("state")))
|
|
||||||
{
|
{
|
||||||
QString entityId = obj.value(QStringLiteral("entity_id")).toString();
|
QJsonObject obj = document.object();
|
||||||
QString state = obj.value(QStringLiteral("state")).toString();
|
|
||||||
bool dOk;
|
if (obj.contains(QStringLiteral("entity_id")) && obj.contains(QStringLiteral("state")))
|
||||||
bool iOk;
|
{
|
||||||
int i = state.toInt(&iOk);
|
QString entityId = obj.value(QStringLiteral("entity_id")).toString();
|
||||||
double d = state.toDouble(&dOk);
|
if (getAfterSet(reply, entityId))
|
||||||
if ((state == "on") || (state == "playing")) {
|
{
|
||||||
status.insert(entityId, 1);
|
QHash<QString, QVariant> status;
|
||||||
} else if ((state == "off") || (state == "paused")) {
|
QString state = obj.value(QStringLiteral("state")).toString();
|
||||||
status.insert(entityId, 0);
|
bool dOk;
|
||||||
} else if (iOk) {
|
bool iOk;
|
||||||
status.insert(entityId, i);
|
int i = state.toInt(&iOk);
|
||||||
} else if (dOk) {
|
double d = state.toDouble(&dOk);
|
||||||
status.insert(entityId, d);
|
if ((state == "on") || (state == "playing")) {
|
||||||
} else {
|
status.insert(entityId, 1);
|
||||||
status.insert(entityId, state);
|
} else if ((state == "off") || (state == "paused")) {
|
||||||
|
status.insert(entityId, 0);
|
||||||
|
} else if (iOk) {
|
||||||
|
status.insert(entityId, i);
|
||||||
|
} else if (dOk) {
|
||||||
|
status.insert(entityId, d);
|
||||||
|
} else {
|
||||||
|
status.insert(entityId, state);
|
||||||
|
}
|
||||||
|
emit deviceUpdated(status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emit deviceUpdated(status);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "HomeAssistantDevice::handleReply: Document is not an object: " << document;
|
qDebug() << "HomeAssistantDevice::handleReply: Error parsing JSON: " << error.errorString() << " at offset " << error.offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "HomeAssistantDevice::handleReply: error: " << reply->error();
|
qDebug() << "HomeAssistantDevice::handleReply: error: " << reply->error();
|
||||||
}
|
}
|
||||||
|
removeGetRequest(reply);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -294,7 +309,7 @@ void HomeAssistantDeviceDiscoverer::handleReply(QNetworkReply* reply)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "HomeAssistantDeviceDiscoverer::handleReply: Error parson JSON: " << error.errorString() << " at offset " << error.offset;
|
qDebug() << "HomeAssistantDeviceDiscoverer::handleReply: Error parsing JSON: " << error.errorString() << " at offset " << error.offset;
|
||||||
}
|
}
|
||||||
emit deviceList(devices);
|
emit deviceList(devices);
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,9 @@ void TPLinkDevice::getState()
|
||||||
QJsonDocument document;
|
QJsonDocument document;
|
||||||
document.setObject(object);
|
document.setObject(object);
|
||||||
|
|
||||||
m_networkManager->post(request, document.toJson());
|
QNetworkReply *reply = m_networkManager->post(request, document.toJson());
|
||||||
|
|
||||||
|
recordGetRequest(reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TPLinkDevice::setState(const QString &controlId, bool state)
|
void TPLinkDevice::setState(const QString &controlId, bool state)
|
||||||
|
@ -242,6 +244,8 @@ void TPLinkDevice::setState(const QString &controlId, bool state)
|
||||||
document.setObject(object);
|
document.setObject(object);
|
||||||
|
|
||||||
m_networkManager->post(request, document.toJson());
|
m_networkManager->post(request, document.toJson());
|
||||||
|
|
||||||
|
recordSetRequest(controlId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TPLinkDevice::handleReply(QNetworkReply* reply)
|
void TPLinkDevice::handleReply(QNetworkReply* reply)
|
||||||
|
@ -264,99 +268,115 @@ void TPLinkDevice::handleReply(QNetworkReply* reply)
|
||||||
{
|
{
|
||||||
if (!reply->error())
|
if (!reply->error())
|
||||||
{
|
{
|
||||||
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
QByteArray data = reply->readAll();
|
||||||
if (document.isObject())
|
QJsonParseError error;
|
||||||
|
QJsonDocument document = QJsonDocument::fromJson(data, &error);
|
||||||
|
if (!document.isNull())
|
||||||
{
|
{
|
||||||
//qDebug() << "Received " << document;
|
if (document.isObject())
|
||||||
QJsonObject obj = document.object();
|
|
||||||
if (obj.contains(QStringLiteral("result")))
|
|
||||||
{
|
{
|
||||||
QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject();
|
//qDebug() << "Received " << document;
|
||||||
QHash<QString, QVariant> status;
|
QJsonObject obj = document.object();
|
||||||
|
if (obj.contains(QStringLiteral("result")))
|
||||||
if (resultObj.contains(QStringLiteral("responseData")))
|
|
||||||
{
|
{
|
||||||
QJsonObject responseDataObj = resultObj.value(QStringLiteral("responseData")).toObject();
|
QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject();
|
||||||
if (responseDataObj.contains(QStringLiteral("system")))
|
QHash<QString, QVariant> status;
|
||||||
|
|
||||||
|
if (resultObj.contains(QStringLiteral("responseData")))
|
||||||
{
|
{
|
||||||
QJsonObject systemObj = responseDataObj.value(QStringLiteral("system")).toObject();
|
QJsonObject responseDataObj = resultObj.value(QStringLiteral("responseData")).toObject();
|
||||||
if (systemObj.contains(QStringLiteral("get_sysinfo")))
|
if (responseDataObj.contains(QStringLiteral("system")))
|
||||||
{
|
{
|
||||||
QJsonObject sysInfoObj = systemObj.value(QStringLiteral("get_sysinfo")).toObject();
|
QJsonObject systemObj = responseDataObj.value(QStringLiteral("system")).toObject();
|
||||||
if (sysInfoObj.contains(QStringLiteral("child_num")))
|
if (systemObj.contains(QStringLiteral("get_sysinfo")))
|
||||||
{
|
{
|
||||||
QJsonArray children = sysInfoObj.value(QStringLiteral("children")).toArray();
|
QJsonObject sysInfoObj = systemObj.value(QStringLiteral("get_sysinfo")).toObject();
|
||||||
for (auto childRef : children)
|
if (sysInfoObj.contains(QStringLiteral("child_num")))
|
||||||
{
|
{
|
||||||
QJsonObject childObj = childRef.toObject();
|
QJsonArray children = sysInfoObj.value(QStringLiteral("children")).toArray();
|
||||||
if (childObj.contains(QStringLiteral("state")) && childObj.contains(QStringLiteral("id")))
|
for (auto childRef : children)
|
||||||
{
|
{
|
||||||
int state = childObj.value(QStringLiteral("state")).toInt();
|
QJsonObject childObj = childRef.toObject();
|
||||||
QString id = childObj.value(QStringLiteral("id")).toString();
|
if (childObj.contains(QStringLiteral("state")) && childObj.contains(QStringLiteral("id")))
|
||||||
status.insert(id, state); // key should match id in discoverer
|
{
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sysInfoObj.contains(QStringLiteral("relay_state")))
|
|
||||||
{
|
|
||||||
int state = sysInfoObj.value(QStringLiteral("relay_state")).toInt();
|
|
||||||
status.insert("switch", state); // key should match id in discoverer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
// KP115 has emeter, but KP105 doesn't
|
||||||
// KP115 has emeter, but KP105 doesn't
|
if (responseDataObj.contains(QStringLiteral("emeter")))
|
||||||
if (responseDataObj.contains(QStringLiteral("emeter")))
|
|
||||||
{
|
|
||||||
QJsonObject emeterObj = responseDataObj.value(QStringLiteral("emeter")).toObject();
|
|
||||||
if (emeterObj.contains(QStringLiteral("get_realtime")))
|
|
||||||
{
|
{
|
||||||
QJsonObject realtimeObj = emeterObj.value(QStringLiteral("get_realtime")).toObject();
|
QJsonObject emeterObj = responseDataObj.value(QStringLiteral("emeter")).toObject();
|
||||||
if (realtimeObj.contains(QStringLiteral("current_ma")))
|
if (emeterObj.contains(QStringLiteral("get_realtime")))
|
||||||
{
|
{
|
||||||
double current = realtimeObj.value(QStringLiteral("current_ma")).toDouble();
|
QJsonObject realtimeObj = emeterObj.value(QStringLiteral("get_realtime")).toObject();
|
||||||
status.insert("current", current / 1000.0);
|
if (realtimeObj.contains(QStringLiteral("current_ma")))
|
||||||
}
|
{
|
||||||
if (realtimeObj.contains(QStringLiteral("voltage_mv")))
|
double current = realtimeObj.value(QStringLiteral("current_ma")).toDouble();
|
||||||
{
|
status.insert("current", current / 1000.0);
|
||||||
double voltage = realtimeObj.value(QStringLiteral("voltage_mv")).toDouble();
|
}
|
||||||
status.insert("voltage", voltage / 1000.0);
|
if (realtimeObj.contains(QStringLiteral("voltage_mv")))
|
||||||
}
|
{
|
||||||
if (realtimeObj.contains(QStringLiteral("power_mw")))
|
double voltage = realtimeObj.value(QStringLiteral("voltage_mv")).toDouble();
|
||||||
{
|
status.insert("voltage", voltage / 1000.0);
|
||||||
double power = realtimeObj.value(QStringLiteral("power_mw")).toDouble();
|
}
|
||||||
status.insert("power", power / 1000.0);
|
if (realtimeObj.contains(QStringLiteral("power_mw")))
|
||||||
|
{
|
||||||
|
double power = realtimeObj.value(QStringLiteral("power_mw")).toDouble();
|
||||||
|
status.insert("power", power / 1000.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit deviceUpdated(status);
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
emit deviceUpdated(status);
|
emit deviceUnavailable();
|
||||||
}
|
}
|
||||||
else if (obj.contains(QStringLiteral("error_code")))
|
else
|
||||||
{
|
{
|
||||||
// If a device isn't available, we can get:
|
qDebug() << "TPLinkDevice::handleReply: Object doesn't contain a result or error_code: " << obj;
|
||||||
// {"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;
|
|
||||||
|
|
||||||
emit deviceUnavailable();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "TPLinkDevice::handleReply: Object doesn't contain a result or error_code: " << obj;
|
qDebug() << "TPLinkDevice::handleReply: Document is not an object: " << document;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "TPLinkDevice::handleReply: Document is not an object: " << document;
|
qDebug() << "TPLinkDevice::handleReply: Error parsing JSON: " << error.errorString() << " at offset " << error.offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "TPLinkDevice::handleReply: error: " << reply->error();
|
qDebug() << "TPLinkDevice::handleReply: error: " << reply->error();
|
||||||
}
|
}
|
||||||
|
removeGetRequest(reply);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -462,161 +482,170 @@ void TPLinkDeviceDiscoverer::handleReply(QNetworkReply* reply)
|
||||||
{
|
{
|
||||||
if (!reply->error())
|
if (!reply->error())
|
||||||
{
|
{
|
||||||
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
QByteArray data = reply->readAll();
|
||||||
if (document.isObject())
|
QJsonParseError error;
|
||||||
|
QJsonDocument document = QJsonDocument::fromJson(data, &error);
|
||||||
|
if (!document.isNull())
|
||||||
{
|
{
|
||||||
//qDebug() << "Received " << document;
|
if (document.isObject())
|
||||||
QJsonObject obj = document.object();
|
|
||||||
|
|
||||||
if (m_getStateReplies.contains(reply))
|
|
||||||
{
|
{
|
||||||
// Reply for getState
|
//qDebug() << "Received " << document;
|
||||||
m_getStateReplies.remove(reply);
|
QJsonObject obj = document.object();
|
||||||
QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject();
|
|
||||||
if (resultObj.contains(QStringLiteral("responseData")))
|
if (m_getStateReplies.contains(reply))
|
||||||
{
|
{
|
||||||
QJsonObject responseDataObj = resultObj.value(QStringLiteral("responseData")).toObject();
|
// Reply for getState
|
||||||
if (responseDataObj.contains(QStringLiteral("system")))
|
m_getStateReplies.remove(reply);
|
||||||
|
QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject();
|
||||||
|
if (resultObj.contains(QStringLiteral("responseData")))
|
||||||
{
|
{
|
||||||
DeviceInfo info;
|
QJsonObject responseDataObj = resultObj.value(QStringLiteral("responseData")).toObject();
|
||||||
QJsonObject systemObj = responseDataObj.value(QStringLiteral("system")).toObject();
|
if (responseDataObj.contains(QStringLiteral("system")))
|
||||||
if (systemObj.contains(QStringLiteral("get_sysinfo")))
|
|
||||||
{
|
{
|
||||||
QJsonObject sysInfoObj = systemObj.value(QStringLiteral("get_sysinfo")).toObject();
|
DeviceInfo info;
|
||||||
if (sysInfoObj.contains(QStringLiteral("alias"))) {
|
QJsonObject systemObj = responseDataObj.value(QStringLiteral("system")).toObject();
|
||||||
info.m_name = sysInfoObj.value(QStringLiteral("alias")).toString();
|
if (systemObj.contains(QStringLiteral("get_sysinfo")))
|
||||||
}
|
|
||||||
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();
|
QJsonObject sysInfoObj = systemObj.value(QStringLiteral("get_sysinfo")).toObject();
|
||||||
int child = 1;
|
if (sysInfoObj.contains(QStringLiteral("alias"))) {
|
||||||
for (auto childRef : children)
|
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")))
|
||||||
{
|
{
|
||||||
QJsonObject childObj = childRef.toObject();
|
|
||||||
ControlInfo *controlInfo = new ControlInfo();
|
ControlInfo *controlInfo = new ControlInfo();
|
||||||
controlInfo->m_id = childObj.value(QStringLiteral("id")).toString();
|
controlInfo->m_id = "switch";
|
||||||
if (childObj.contains(QStringLiteral("alias"))) {
|
if (sysInfoObj.contains(QStringLiteral("alias"))) {
|
||||||
controlInfo->m_name = childObj.value(QStringLiteral("alias")).toString();
|
controlInfo->m_name = sysInfoObj.value(QStringLiteral("alias")).toString();
|
||||||
}
|
}
|
||||||
controlInfo->m_type = DeviceDiscoverer::BOOL;
|
controlInfo->m_type = DeviceDiscoverer::BOOL;
|
||||||
info.m_controls.append(controlInfo);
|
info.m_controls.append(controlInfo);
|
||||||
child++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sysInfoObj.contains(QStringLiteral("relay_state")))
|
|
||||||
{
|
|
||||||
ControlInfo *controlInfo = new ControlInfo();
|
|
||||||
controlInfo->m_id = "switch";
|
|
||||||
if (sysInfoObj.contains(QStringLiteral("alias"))) {
|
|
||||||
controlInfo->m_name = sysInfoObj.value(QStringLiteral("alias")).toString();
|
|
||||||
}
|
|
||||||
controlInfo->m_type = DeviceDiscoverer::BOOL;
|
|
||||||
info.m_controls.append(controlInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qDebug() << "TPLinkDeviceDiscoverer::handleReply: get_sysinfo missing";
|
|
||||||
}
|
|
||||||
// KP115 has energy meter, but KP105 doesn't. KP105 will have emeter object, but without get_realtime sub-object
|
|
||||||
if (responseDataObj.contains(QStringLiteral("emeter")))
|
|
||||||
{
|
|
||||||
QJsonObject emeterObj = responseDataObj.value(QStringLiteral("emeter")).toObject();
|
|
||||||
if (emeterObj.contains(QStringLiteral("get_realtime")))
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (info.m_controls.size() > 0) {
|
|
||||||
m_devices.append(info);
|
|
||||||
} else {
|
|
||||||
qDebug() << "TPLinkDeviceDiscoverer::handleReply: No controls in info";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qDebug() << "TPLinkDeviceDiscoverer::handleReply: No responseData";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_getStateReplies.size() == 0)
|
|
||||||
{
|
|
||||||
emit deviceList(m_devices);
|
|
||||||
m_devices.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Reply for getDevice
|
|
||||||
if (obj.contains(QStringLiteral("result")))
|
|
||||||
{
|
|
||||||
QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject();
|
|
||||||
if (resultObj.contains(QStringLiteral("deviceList")))
|
|
||||||
{
|
|
||||||
QJsonArray deviceArray = resultObj.value(QStringLiteral("deviceList")).toArray();
|
|
||||||
for (auto deviceRef : deviceArray)
|
|
||||||
{
|
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "TPLinkDeviceDiscoverer::handleReply: deviceList element doesn't contain a deviceId: " << deviceObj;
|
qDebug() << "TPLinkDeviceDiscoverer::handleReply: get_sysinfo missing";
|
||||||
}
|
}
|
||||||
|
// KP115 has energy meter, but KP105 doesn't. KP105 will have emeter object, but without get_realtime sub-object
|
||||||
|
if (responseDataObj.contains(QStringLiteral("emeter")))
|
||||||
|
{
|
||||||
|
QJsonObject emeterObj = responseDataObj.value(QStringLiteral("emeter")).toObject();
|
||||||
|
if (emeterObj.contains(QStringLiteral("get_realtime")))
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (info.m_controls.size() > 0) {
|
||||||
|
m_devices.append(info);
|
||||||
|
} else {
|
||||||
|
qDebug() << "TPLinkDeviceDiscoverer::handleReply: No controls in info";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "TPLinkDeviceDiscoverer::handleReply: result doesn't contain a deviceList: " << resultObj;
|
qDebug() << "TPLinkDeviceDiscoverer::handleReply: No responseData";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_getStateReplies.size() == 0)
|
||||||
|
{
|
||||||
|
emit deviceList(m_devices);
|
||||||
|
m_devices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "TPLinkDeviceDiscoverer::handleReply: Object doesn't contain a result: " << obj;
|
// Reply for getDevice
|
||||||
|
if (obj.contains(QStringLiteral("result")))
|
||||||
|
{
|
||||||
|
QJsonObject resultObj = obj.value(QStringLiteral("result")).toObject();
|
||||||
|
if (resultObj.contains(QStringLiteral("deviceList")))
|
||||||
|
{
|
||||||
|
QJsonArray deviceArray = resultObj.value(QStringLiteral("deviceList")).toArray();
|
||||||
|
for (auto deviceRef : deviceArray)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "TPLinkDeviceDiscoverer::handleReply: result doesn't contain a deviceList: " << resultObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "TPLinkDeviceDiscoverer::handleReply: Object doesn't contain a result: " << obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "TPLinkDeviceDiscoverer::handleReply: Document is not an object: " << document;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "TPLinkDeviceDiscoverer::handleReply: Document is not an object: " << document;
|
qDebug() << "TPLinkDeviceDiscoverer::handleReply: Error parsing JSON: " << error.errorString() << " at offset " << error.offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue