Update openweathermap plugin

This commit is contained in:
Michael Zanetti 2019-09-19 01:30:00 +02:00
parent d7ccba9f43
commit 313a38da5a
2 changed files with 126 additions and 156 deletions

View File

@ -61,40 +61,28 @@ void DevicePluginOpenweathermap::init()
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginOpenweathermap::onPluginTimer); connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginOpenweathermap::onPluginTimer);
} }
Device::DeviceError DevicePluginOpenweathermap::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) void DevicePluginOpenweathermap::discoverDevices(DeviceDiscoveryInfo *info)
{ {
if (deviceClassId != openweathermapDeviceClassId) { QString location = info->params().paramValue(openweathermapDiscoveryLocationParamTypeId).toString();
return Device::DeviceErrorDeviceClassNotFound;
}
QString location = params.paramValue(openweathermapDiscoveryLocationParamTypeId).toString();
// if we have an empty search string, perform an autodetection of the location with the WAN ip... // if we have an empty search string, perform an autodetection of the location with the WAN ip...
if (location.isEmpty()){ if (location.isEmpty()){
searchAutodetect(); searchAutodetect(info);
} else { } else {
search(location); search(location, info);
} }
return Device::DeviceErrorAsync;
} }
Device::DeviceSetupStatus DevicePluginOpenweathermap::setupDevice(Device *device) void DevicePluginOpenweathermap::setupDevice(DeviceSetupInfo *info)
{ {
if (device->deviceClassId() != openweathermapDeviceClassId) update(info->device());
return Device::DeviceSetupStatusFailure; info->finish(Device::DeviceErrorNoError);
update(device);
return Device::DeviceSetupStatusSuccess;
} }
Device::DeviceError DevicePluginOpenweathermap::executeAction(Device *device, const Action &action) void DevicePluginOpenweathermap::executeAction(DeviceActionInfo *info)
{ {
if(action.actionTypeId() == openweathermapRefreshWeatherActionTypeId){ update(info->device());
update(device); info->finish(Device::DeviceErrorNoError);
return Device::DeviceErrorNoError;
}
return Device::DeviceErrorActionTypeNotFound;
} }
void DevicePluginOpenweathermap::deviceRemoved(Device *device) void DevicePluginOpenweathermap::deviceRemoved(Device *device)
@ -119,19 +107,7 @@ void DevicePluginOpenweathermap::networkManagerReplyReady()
return; return;
} }
if (m_autodetectionReplies.contains(reply)) { if (m_weatherReplies.contains(reply)) {
QByteArray data = reply->readAll();
m_autodetectionReplies.removeOne(reply);
processAutodetectResponse(data);
} else if (m_searchReplies.contains(reply)) {
QByteArray data = reply->readAll();
m_searchReplies.removeOne(reply);
processSearchResponse(data);
} else if (m_searchGeoReplies.contains(reply)) {
QByteArray data = reply->readAll();
m_searchGeoReplies.removeOne(reply);
processGeoSearchResponse(data);
} else if (m_weatherReplies.contains(reply)) {
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
Device* device = m_weatherReplies.take(reply); Device* device = m_weatherReplies.take(reply);
processWeatherData(data, device); processWeatherData(data, device);
@ -155,14 +131,49 @@ void DevicePluginOpenweathermap::update(Device *device)
m_weatherReplies.insert(reply, device); m_weatherReplies.insert(reply, device);
} }
void DevicePluginOpenweathermap::searchAutodetect() void DevicePluginOpenweathermap::searchAutodetect(DeviceDiscoveryInfo *info)
{ {
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(QUrl("http://ip-api.com/json"))); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(QUrl("http://ip-api.com/json")));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
m_autodetectionReplies.append(reply); connect(reply, &QNetworkReply::finished, info, [this, info, reply](){
if (reply->error()) {
qCWarning(dcOpenWeatherMap) << "OpenWeatherMap reply error: " << reply->errorString();
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Error detecting current location."));
return;
}
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if(error.error != QJsonParseError::NoError) {
qCWarning(dcOpenWeatherMap) << "failed to parse data" << data << ":" << error.errorString();
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Received unexpected data detecting current location."));
return;
}
// search by geographic coordinates
QVariantMap dataMap = jsonDoc.toVariant().toMap();
QString country = dataMap.value("countryCode").toString();
QString cityName = dataMap.value("city").toString();
QHostAddress wanIp = QHostAddress(dataMap.value("query").toString());
double longitude = dataMap.value("lon").toDouble();
double latitude = dataMap.value("lat").toDouble();
qCDebug(dcOpenWeatherMap) << "----------------------------------------";
qCDebug(dcOpenWeatherMap) << "Autodetection of location: ";
qCDebug(dcOpenWeatherMap) << "----------------------------------------";
qCDebug(dcOpenWeatherMap) << " name:" << cityName;
qCDebug(dcOpenWeatherMap) << " country:" << country;
qCDebug(dcOpenWeatherMap) << " WAN IP:" << wanIp.toString();
qCDebug(dcOpenWeatherMap) << " latitude:" << latitude;
qCDebug(dcOpenWeatherMap) << " longitude:" << longitude;
qCDebug(dcOpenWeatherMap) << "----------------------------------------";
searchGeoLocation(latitude, longitude, country, info);
});
} }
void DevicePluginOpenweathermap::search(QString searchString) void DevicePluginOpenweathermap::search(QString searchString, DeviceDiscoveryInfo *info)
{ {
QUrl url("http://api.openweathermap.org/data/2.5/find"); QUrl url("http://api.openweathermap.org/data/2.5/find");
QUrlQuery query; QUrlQuery query;
@ -174,11 +185,43 @@ void DevicePluginOpenweathermap::search(QString searchString)
url.setQuery(query); url.setQuery(query);
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url)); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
m_searchReplies.append(reply);
connect(reply, &QNetworkReply::finished, info, [this, info, reply](){
if (reply->error()) {
qCWarning(dcOpenWeatherMap) << "OpenWeatherMap reply error: " << reply->errorString();
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Error searching for weather stations."));
return;
}
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if(error.error != QJsonParseError::NoError) {
qCWarning(dcOpenWeatherMap) << "failed to parse data" << data << ":" << error.errorString();
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Received unexpected data while searching for weather stations."));
return;
}
QVariantMap dataMap = jsonDoc.toVariant().toMap();
QList<QVariantMap> cityList;
if (dataMap.contains("list")) {
QVariantList list = dataMap.value("list").toList();
foreach (QVariant key, list) {
QVariantMap elemant = key.toMap();
QVariantMap city;
city.insert("name",elemant.value("name").toString());
city.insert("country", elemant.value("sys").toMap().value("country").toString());
city.insert("id",elemant.value("id").toString());
cityList.append(city);
}
}
processSearchResults(cityList, info);
});
} }
void DevicePluginOpenweathermap::searchGeoLocation(double lat, double lon) void DevicePluginOpenweathermap::searchGeoLocation(double lat, double lon, const QString &country, DeviceDiscoveryInfo *info)
{ {
QUrl url("http://api.openweathermap.org/data/2.5/find"); QUrl url("http://api.openweathermap.org/data/2.5/find");
QUrlQuery query; QUrlQuery query;
@ -192,109 +235,46 @@ void DevicePluginOpenweathermap::searchGeoLocation(double lat, double lon)
url.setQuery(query); url.setQuery(query);
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url)); QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
m_searchGeoReplies.append(reply); connect(reply, &QNetworkReply::finished, info, [this, info, reply, country](){
} if (reply->error()) {
qCWarning(dcOpenWeatherMap) << "OpenWeatherMap reply error: " << reply->errorString();
void DevicePluginOpenweathermap::processAutodetectResponse(QByteArray data) info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Error searching for weather stations in current location."));
{ return;
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if(error.error != QJsonParseError::NoError) {
qCWarning(dcOpenWeatherMap) << "failed to parse data" << data << ":" << error.errorString();
emit devicesDiscovered(openweathermapDeviceClassId, QList<DeviceDescriptor>());
return;
}
// search by geographic coordinates
QVariantMap dataMap = jsonDoc.toVariant().toMap();
if (dataMap.contains("countryCode")) {
m_country = dataMap.value("countryCode").toString();
}
if (dataMap.contains("city")) {
m_cityName = dataMap.value("city").toString();
}
if (dataMap.contains("query")) {
m_wanIp = QHostAddress(dataMap.value("query").toString());
}
if (dataMap.contains("lon") && dataMap.contains("lat")) {
m_longitude = dataMap.value("lon").toDouble();
m_latitude = dataMap.value("lat").toDouble();
qCDebug(dcOpenWeatherMap) << "----------------------------------------";
qCDebug(dcOpenWeatherMap) << "Autodetection of location: ";
qCDebug(dcOpenWeatherMap) << "----------------------------------------";
qCDebug(dcOpenWeatherMap) << " name:" << m_cityName;
qCDebug(dcOpenWeatherMap) << " country:" << m_country;
qCDebug(dcOpenWeatherMap) << " WAN IP:" << m_wanIp.toString();
qCDebug(dcOpenWeatherMap) << " latitude:" << m_latitude;
qCDebug(dcOpenWeatherMap) << " longitude:" << m_longitude;
qCDebug(dcOpenWeatherMap) << "----------------------------------------";
searchGeoLocation(m_latitude, m_longitude);
}
}
void DevicePluginOpenweathermap::processSearchResponse(QByteArray data)
{
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if(error.error != QJsonParseError::NoError) {
qCWarning(dcOpenWeatherMap) << "failed to parse data" << data << ":" << error.errorString();
emit devicesDiscovered(openweathermapDeviceClassId, QList<DeviceDescriptor>());
return;
}
QVariantMap dataMap = jsonDoc.toVariant().toMap();
QList<QVariantMap> cityList;
if (dataMap.contains("list")) {
QVariantList list = dataMap.value("list").toList();
foreach (QVariant key, list) {
QVariantMap elemant = key.toMap();
QVariantMap city;
city.insert("name",elemant.value("name").toString());
city.insert("country", elemant.value("sys").toMap().value("country").toString());
city.insert("id",elemant.value("id").toString());
cityList.append(city);
} }
} QByteArray data = reply->readAll();
processSearchResults(cityList); QJsonParseError error;
} QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
void DevicePluginOpenweathermap::processGeoSearchResponse(QByteArray data) if(error.error != QJsonParseError::NoError) {
{ qCWarning(dcOpenWeatherMap) << "failed to parse data" << data << ":" << error.errorString();
QJsonParseError error; info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Received unexpected data while searching for weather stations."));
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); return;
}
if(error.error != QJsonParseError::NoError) { QVariantMap dataMap = jsonDoc.toVariant().toMap();
qCWarning(dcOpenWeatherMap) << "failed to parse data" << data << ":" << error.errorString(); QList<QVariantMap> cityList;
emit devicesDiscovered(openweathermapDeviceClassId, QList<DeviceDescriptor>()); if (dataMap.contains("list")) {
return; QVariantList list = dataMap.value("list").toList();
} foreach (QVariant key, list) {
QVariantMap elemant = key.toMap();
QVariantMap dataMap = jsonDoc.toVariant().toMap(); QVariantMap city;
QList<QVariantMap> cityList; city.insert("name",elemant.value("name").toString());
if (dataMap.contains("list")) { if(elemant.value("sys").toMap().value("country").toString().isEmpty()){
QVariantList list = dataMap.value("list").toList(); city.insert("country",country);
foreach (QVariant key, list) { }else{
QVariantMap elemant = key.toMap(); city.insert("country", elemant.value("sys").toMap().value("country").toString());
QVariantMap city; }
city.insert("name",elemant.value("name").toString()); city.insert("id",elemant.value("id").toString());
if(elemant.value("sys").toMap().value("country").toString().isEmpty()){ cityList.append(city);
city.insert("country",m_country);
}else{
city.insert("country", elemant.value("sys").toMap().value("country").toString());
} }
city.insert("id",elemant.value("id").toString());
cityList.append(city);
} }
} processSearchResults(cityList, info);
processSearchResults(cityList); });
} }
void DevicePluginOpenweathermap::processSearchResults(const QList<QVariantMap> &cityList) void DevicePluginOpenweathermap::processSearchResults(const QList<QVariantMap> &cityList, DeviceDiscoveryInfo *info)
{ {
QList<DeviceDescriptor> retList;
foreach (QVariantMap element, cityList) { foreach (QVariantMap element, cityList) {
DeviceDescriptor descriptor(openweathermapDeviceClassId, element.value("name").toString(), element.value("country").toString()); DeviceDescriptor descriptor(openweathermapDeviceClassId, element.value("name").toString(), element.value("country").toString());
ParamList params; ParamList params;
@ -311,9 +291,9 @@ void DevicePluginOpenweathermap::processSearchResults(const QList<QVariantMap> &
break; break;
} }
} }
retList.append(descriptor); info->addDeviceDescriptor(descriptor);
} }
emit devicesDiscovered(openweathermapDeviceClassId, retList); info->finish(Device::DeviceErrorNoError);
} }
void DevicePluginOpenweathermap::processWeatherData(const QByteArray &data, Device *device) void DevicePluginOpenweathermap::processWeatherData(const QByteArray &data, Device *device)

View File

@ -42,38 +42,28 @@ public:
~DevicePluginOpenweathermap(); ~DevicePluginOpenweathermap();
void init() override; void init() override;
Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; void discoverDevices(DeviceDiscoveryInfo *info) override;
Device::DeviceSetupStatus setupDevice(Device *device) override; void setupDevice(DeviceSetupInfo *info) override;
Device::DeviceError executeAction(Device *device, const Action &action) override; void executeAction(DeviceActionInfo *info) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
private: private:
PluginTimer *m_pluginTimer = nullptr; PluginTimer *m_pluginTimer = nullptr;
QList<QNetworkReply *> m_autodetectionReplies;
QList<QNetworkReply *> m_searchReplies;
QList<QNetworkReply *> m_searchGeoReplies;
QHash<QNetworkReply *, Device *> m_weatherReplies; QHash<QNetworkReply *, Device *> m_weatherReplies;
// Autodetection data
QHostAddress m_wanIp;
QString m_country;
QString m_cityName;
double m_longitude;
double m_latitude;
QString m_apiKey; QString m_apiKey;
void update(Device *device); void update(Device *device);
void searchAutodetect(); void searchAutodetect(DeviceDiscoveryInfo *info);
void search(QString searchString); void search(QString searchString, DeviceDiscoveryInfo *info);
void searchGeoLocation(double lat, double lon); void searchGeoLocation(double lat, double lon, const QString &country, DeviceDiscoveryInfo *info);
void processAutodetectResponse(QByteArray data); void processAutodetectResponse(QByteArray data);
void processSearchResponse(QByteArray data); void processSearchResponse(QByteArray data);
void processGeoSearchResponse(QByteArray data); void processGeoSearchResponse(QByteArray data);
void processSearchResults(const QList<QVariantMap> &cityList); void processSearchResults(const QList<QVariantMap> &cityList, DeviceDiscoveryInfo *info);
void processWeatherData(const QByteArray &data, Device *device); void processWeatherData(const QByteArray &data, Device *device);
private slots: private slots: