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);
}
Device::DeviceError DevicePluginOpenweathermap::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
void DevicePluginOpenweathermap::discoverDevices(DeviceDiscoveryInfo *info)
{
if (deviceClassId != openweathermapDeviceClassId) {
return Device::DeviceErrorDeviceClassNotFound;
}
QString location = params.paramValue(openweathermapDiscoveryLocationParamTypeId).toString();
QString location = info->params().paramValue(openweathermapDiscoveryLocationParamTypeId).toString();
// if we have an empty search string, perform an autodetection of the location with the WAN ip...
if (location.isEmpty()){
searchAutodetect();
searchAutodetect(info);
} else {
search(location);
search(location, info);
}
return Device::DeviceErrorAsync;
}
Device::DeviceSetupStatus DevicePluginOpenweathermap::setupDevice(Device *device)
void DevicePluginOpenweathermap::setupDevice(DeviceSetupInfo *info)
{
if (device->deviceClassId() != openweathermapDeviceClassId)
return Device::DeviceSetupStatusFailure;
update(device);
return Device::DeviceSetupStatusSuccess;
update(info->device());
info->finish(Device::DeviceErrorNoError);
}
Device::DeviceError DevicePluginOpenweathermap::executeAction(Device *device, const Action &action)
void DevicePluginOpenweathermap::executeAction(DeviceActionInfo *info)
{
if(action.actionTypeId() == openweathermapRefreshWeatherActionTypeId){
update(device);
return Device::DeviceErrorNoError;
}
return Device::DeviceErrorActionTypeNotFound;
update(info->device());
info->finish(Device::DeviceErrorNoError);
}
void DevicePluginOpenweathermap::deviceRemoved(Device *device)
@ -119,19 +107,7 @@ void DevicePluginOpenweathermap::networkManagerReplyReady()
return;
}
if (m_autodetectionReplies.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)) {
if (m_weatherReplies.contains(reply)) {
QByteArray data = reply->readAll();
Device* device = m_weatherReplies.take(reply);
processWeatherData(data, device);
@ -155,14 +131,49 @@ void DevicePluginOpenweathermap::update(Device *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")));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady);
m_autodetectionReplies.append(reply);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
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");
QUrlQuery query;
@ -174,11 +185,43 @@ void DevicePluginOpenweathermap::search(QString searchString)
url.setQuery(query);
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady);
m_searchReplies.append(reply);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
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");
QUrlQuery query;
@ -192,109 +235,46 @@ void DevicePluginOpenweathermap::searchGeoLocation(double lat, double lon)
url.setQuery(query);
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &DevicePluginOpenweathermap::networkManagerReplyReady);
m_searchGeoReplies.append(reply);
}
void DevicePluginOpenweathermap::processAutodetectResponse(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;
}
// 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);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, info, [this, info, reply, country](){
if (reply->error()) {
qCWarning(dcOpenWeatherMap) << "OpenWeatherMap reply error: " << reply->errorString();
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Error searching for weather stations in current location."));
return;
}
}
processSearchResults(cityList);
}
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
void DevicePluginOpenweathermap::processGeoSearchResponse(QByteArray data)
{
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;
}
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());
if(elemant.value("sys").toMap().value("country").toString().isEmpty()){
city.insert("country",m_country);
}else{
city.insert("country", elemant.value("sys").toMap().value("country").toString());
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());
if(elemant.value("sys").toMap().value("country").toString().isEmpty()){
city.insert("country",country);
}else{
city.insert("country", elemant.value("sys").toMap().value("country").toString());
}
city.insert("id",elemant.value("id").toString());
cityList.append(city);
}
city.insert("id",elemant.value("id").toString());
cityList.append(city);
}
}
processSearchResults(cityList);
processSearchResults(cityList, info);
});
}
void DevicePluginOpenweathermap::processSearchResults(const QList<QVariantMap> &cityList)
void DevicePluginOpenweathermap::processSearchResults(const QList<QVariantMap> &cityList, DeviceDiscoveryInfo *info)
{
QList<DeviceDescriptor> retList;
foreach (QVariantMap element, cityList) {
DeviceDescriptor descriptor(openweathermapDeviceClassId, element.value("name").toString(), element.value("country").toString());
ParamList params;
@ -311,9 +291,9 @@ void DevicePluginOpenweathermap::processSearchResults(const QList<QVariantMap> &
break;
}
}
retList.append(descriptor);
info->addDeviceDescriptor(descriptor);
}
emit devicesDiscovered(openweathermapDeviceClassId, retList);
info->finish(Device::DeviceErrorNoError);
}
void DevicePluginOpenweathermap::processWeatherData(const QByteArray &data, Device *device)

View File

@ -42,38 +42,28 @@ public:
~DevicePluginOpenweathermap();
void init() override;
Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
Device::DeviceSetupStatus setupDevice(Device *device) override;
Device::DeviceError executeAction(Device *device, const Action &action) override;
void discoverDevices(DeviceDiscoveryInfo *info) override;
void setupDevice(DeviceSetupInfo *info) override;
void executeAction(DeviceActionInfo *info) override;
void deviceRemoved(Device *device) override;
private:
PluginTimer *m_pluginTimer = nullptr;
QList<QNetworkReply *> m_autodetectionReplies;
QList<QNetworkReply *> m_searchReplies;
QList<QNetworkReply *> m_searchGeoReplies;
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;
void update(Device *device);
void searchAutodetect();
void search(QString searchString);
void searchGeoLocation(double lat, double lon);
void searchAutodetect(DeviceDiscoveryInfo *info);
void search(QString searchString, DeviceDiscoveryInfo *info);
void searchGeoLocation(double lat, double lon, const QString &country, DeviceDiscoveryInfo *info);
void processAutodetectResponse(QByteArray data);
void processSearchResponse(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);
private slots: