added autodetection using geo-location
This commit is contained in:
parent
9e2f1286b1
commit
511a676507
@ -299,41 +299,46 @@ StateTypeId sunsetStateTypeId = StateTypeId("a1dddc3d-549f-4f20-b78b-be850548f28
|
||||
DevicePluginOpenweathermap::DevicePluginOpenweathermap()
|
||||
{
|
||||
m_openweaher = new OpenWeatherMap(this);
|
||||
connect(m_openweaher, SIGNAL(searchResultReady(QList<QVariantMap>)), this, SLOT(searchResultsReady(QList<QVariantMap>)));
|
||||
connect(m_openweaher, SIGNAL(weatherDataReady(QByteArray)), this, SLOT(weatherDataReady(QByteArray)));
|
||||
connect(m_openweaher, &OpenWeatherMap::searchResultReady, this, &DevicePluginOpenweathermap::searchResultsReady);
|
||||
connect(m_openweaher, &OpenWeatherMap::weatherDataReady, this, &DevicePluginOpenweathermap::weatherDataReady);
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceError, QString> DevicePluginOpenweathermap::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms)
|
||||
{
|
||||
if(deviceClassId == openweathermapDeviceClassId){
|
||||
if(deviceClassId != openweathermapDeviceClassId){
|
||||
return report(DeviceManager::DeviceErrorDeviceClassNotFound);
|
||||
}
|
||||
|
||||
QString location;
|
||||
foreach (const Param ¶m, params) {
|
||||
if (param.name() == "location") {
|
||||
location = param.value().toString();
|
||||
}
|
||||
}
|
||||
qDebug() << "Searching for... " << location;
|
||||
if (location.isEmpty()){
|
||||
m_openweaher->searchAutodetect();
|
||||
}else{
|
||||
m_openweaher->search(location);
|
||||
QString location;
|
||||
foreach (const Param ¶m, params) {
|
||||
if (param.name() == "location") {
|
||||
location = param.value().toString();
|
||||
}
|
||||
}
|
||||
|
||||
// if we have an empty search string, perform an autodetection of the location with the WAN ip...
|
||||
if (location.isEmpty()){
|
||||
m_openweaher->searchAutodetect();
|
||||
return report(DeviceManager::DeviceErrorAsync);
|
||||
}else{
|
||||
return report(DeviceManager::DeviceErrorDeviceClassNotFound);
|
||||
}
|
||||
|
||||
// otherwise search the given string
|
||||
m_openweaher->search(location);
|
||||
return report(DeviceManager::DeviceErrorAsync);
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceSetupStatus, QString> DevicePluginOpenweathermap::setupDevice(Device *device)
|
||||
{
|
||||
foreach (Device *deviceListDevice, deviceManager()->findConfiguredDevices(openweathermapDeviceClassId)) {
|
||||
if(deviceListDevice->paramValue("id").toString() == device->paramValue("id").toString()){
|
||||
return reportDeviceSetup(DeviceManager::DeviceSetupStatusFailure,QString("Location " + device->paramValue("location").toString() + "allready in added"));
|
||||
return reportDeviceSetup(DeviceManager::DeviceSetupStatusFailure,QString("Location " + device->paramValue("location").toString() + " already added."));
|
||||
}
|
||||
}
|
||||
|
||||
m_openweaher->update(device->paramValue("id").toString());
|
||||
device->setName("Weather from OpenWeatherMap (" + device->paramValue("location").toString() + ")");
|
||||
m_openweaher->update(device->paramValue("id").toString(), device->id());
|
||||
|
||||
return reportDeviceSetup(DeviceManager::DeviceSetupStatusSuccess);
|
||||
}
|
||||
@ -345,9 +350,8 @@ DeviceManager::HardwareResources DevicePluginOpenweathermap::requiredHardware()
|
||||
|
||||
QPair<DeviceManager::DeviceError, QString> DevicePluginOpenweathermap::executeAction(Device *device, const Action &action)
|
||||
{
|
||||
qDebug() << "execute action " << updateWeatherActionTypeId.toString();
|
||||
if(action.actionTypeId() == updateWeatherActionTypeId){
|
||||
m_openweaher->update(device->paramValue("id").toString());
|
||||
m_openweaher->update(device->paramValue("id").toString(), device->id());
|
||||
}
|
||||
return report();
|
||||
}
|
||||
@ -355,7 +359,7 @@ QPair<DeviceManager::DeviceError, QString> DevicePluginOpenweathermap::executeAc
|
||||
void DevicePluginOpenweathermap::guhTimer()
|
||||
{
|
||||
foreach (Device *device, deviceManager()->findConfiguredDevices(openweathermapDeviceClassId)) {
|
||||
m_openweaher->update(device->paramValue("id").toString());
|
||||
m_openweaher->update(device->paramValue("id").toString(), device->id());
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,7 +381,7 @@ void DevicePluginOpenweathermap::searchResultsReady(const QList<QVariantMap> &ci
|
||||
emit devicesDiscovered(openweathermapDeviceClassId,retList);
|
||||
}
|
||||
|
||||
void DevicePluginOpenweathermap::weatherDataReady(const QByteArray &data)
|
||||
void DevicePluginOpenweathermap::weatherDataReady(const QByteArray &data, const DeviceId &deviceId)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
@ -390,7 +394,7 @@ void DevicePluginOpenweathermap::weatherDataReady(const QByteArray &data)
|
||||
QVariantMap dataMap = jsonDoc.toVariant().toMap();
|
||||
|
||||
foreach (Device *device, deviceManager()->findConfiguredDevices(openweathermapDeviceClassId)) {
|
||||
if(device->paramValue("id").toString() == dataMap.value("id").toString()){
|
||||
if(device->id() == deviceId){
|
||||
|
||||
if(dataMap.contains("clouds")){
|
||||
int cloudiness = dataMap.value("clouds").toMap().value("all").toInt();
|
||||
|
||||
@ -44,7 +44,7 @@ public:
|
||||
|
||||
private slots:
|
||||
void searchResultsReady(const QList<QVariantMap> &cityList);
|
||||
void weatherDataReady(const QByteArray &data);
|
||||
void weatherDataReady(const QByteArray &data, const DeviceId &deviceId);
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "Openweathermap",
|
||||
"name": "OpenWeatherMap",
|
||||
"id": "bc6af567-2338-41d5-aac1-462dec6e4783",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "Openweathermap",
|
||||
"name": "OpenWeatherMap",
|
||||
"id": "bf1e96f0-9650-4e7c-a56c-916d54d18e7a",
|
||||
"deviceClasses": [
|
||||
{
|
||||
"deviceClassId": "985195aa-17ad-4530-88a4-cdd753d747d7",
|
||||
"name": "Weather from openweathermap",
|
||||
"name": "Weather from OpenWeatherMap",
|
||||
"createMethods": ["discovery"],
|
||||
"discoveryParamTypes": [
|
||||
{
|
||||
@ -33,7 +33,7 @@
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "cfbc6504-d86f-4856-8dfa-97b6fbb385e4",
|
||||
"name": "Update"
|
||||
"name": "update"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
|
||||
@ -24,18 +24,18 @@ OpenWeatherMap::OpenWeatherMap(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_manager = new QNetworkAccessManager(this);
|
||||
|
||||
connect(m_manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
|
||||
connect(m_manager, &QNetworkAccessManager::finished, this, &OpenWeatherMap::replyFinished);
|
||||
}
|
||||
|
||||
void OpenWeatherMap::update(QString id)
|
||||
void OpenWeatherMap::update(QString id, DeviceId deviceId)
|
||||
{
|
||||
m_cityId = id;
|
||||
QString urlString = "http://api.openweathermap.org/data/2.5/weather?id="+ m_cityId + "&mode=json&units=metric";
|
||||
QNetworkRequest weatherRequest;
|
||||
weatherRequest.setUrl(QUrl(urlString));
|
||||
|
||||
m_weatherReply = m_manager->get(weatherRequest);
|
||||
QNetworkReply *weatherReply = m_manager->get(weatherRequest);
|
||||
m_weatherReplys.insert(weatherReply, deviceId);
|
||||
}
|
||||
|
||||
void OpenWeatherMap::searchAutodetect()
|
||||
@ -56,6 +56,16 @@ void OpenWeatherMap::search(QString searchString)
|
||||
m_searchReply = m_manager->get(searchRequest);
|
||||
}
|
||||
|
||||
void OpenWeatherMap::searchGeoLocation(double lat, double lon)
|
||||
{
|
||||
QString urlString = "http://api.openweathermap.org/data/2.5/find?lat=" + QString::number(lat) + "&lon=" + QString::number(lon) + "cnt=5&type=like&units=metric&mode=json";
|
||||
QNetworkRequest searchRequest;
|
||||
searchRequest.setUrl(QUrl(urlString));
|
||||
qDebug() << "search URL " << urlString;
|
||||
|
||||
m_searchGeoReply = m_manager->get(searchRequest);
|
||||
}
|
||||
|
||||
void OpenWeatherMap::processLocationResponse(QByteArray data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
@ -64,26 +74,33 @@ void OpenWeatherMap::processLocationResponse(QByteArray data)
|
||||
if(error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "failed to parse data" << data << ":" << error.errorString();
|
||||
}
|
||||
//qDebug() << jsonDoc.toJson();
|
||||
// qDebug() << jsonDoc.toJson();
|
||||
|
||||
// search by geographic coordinates
|
||||
QVariantMap dataMap = jsonDoc.toVariant().toMap();
|
||||
if(dataMap.contains("countryCode")){
|
||||
m_country = dataMap.value("countryCode").toString();
|
||||
}
|
||||
if(dataMap.contains("city")){
|
||||
search(dataMap.value("city").toString());
|
||||
m_cityName = dataMap.value("city").toString();
|
||||
}
|
||||
if(dataMap.contains("query")){
|
||||
m_wanIp = QHostAddress(dataMap.value("query").toString());
|
||||
}
|
||||
if(dataMap.contains("lon") && dataMap.contains("lat")){
|
||||
qDebug() << "Autodetection of location: " << m_cityName << "(" << m_country << ")" << m_wanIp;
|
||||
searchGeoLocation(dataMap.value("lat").toDouble(),dataMap.value("lon").toDouble());
|
||||
}
|
||||
}
|
||||
|
||||
void OpenWeatherMap::processSearchResponse(QByteArray data)
|
||||
{
|
||||
|
||||
// TODO: return here...remove the rest from here...
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
if(error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "failed to parse data" << data << ":" << error.errorString();
|
||||
}
|
||||
//qDebug() << jsonDoc.toJson();
|
||||
|
||||
QVariantMap dataMap = jsonDoc.toVariant().toMap();
|
||||
qDebug() << "----------------------------------------";
|
||||
@ -110,7 +127,7 @@ void OpenWeatherMap::processSearchResponse(QByteArray data)
|
||||
emit searchResultReady(cityList);
|
||||
}
|
||||
|
||||
void OpenWeatherMap::processSearchLocationResponse(QByteArray data)
|
||||
void OpenWeatherMap::processSearchGeoResponse(QByteArray data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
@ -118,26 +135,40 @@ void OpenWeatherMap::processSearchLocationResponse(QByteArray data)
|
||||
if(error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "failed to parse data" << data << ":" << error.errorString();
|
||||
}
|
||||
|
||||
//qDebug() << jsonDoc.toJson();
|
||||
|
||||
QList<QVariantMap> cityList;
|
||||
QVariantMap dataMap = jsonDoc.toVariant().toMap();
|
||||
qDebug() << "----------------------------------------";
|
||||
qDebug() << "openweathermap search results";
|
||||
qDebug() << "----------------------------------------";
|
||||
QList<QVariantMap> cityList;
|
||||
if(dataMap.contains("list")){
|
||||
QVariantList list = dataMap.value("list").toList();
|
||||
foreach (QVariant key, list) {
|
||||
QVariantMap elemant = key.toMap();
|
||||
qDebug() << elemant.value("name").toString();
|
||||
if(elemant.value("sys").toMap().value("country").toString().isEmpty()){
|
||||
qDebug() << m_country;
|
||||
}else{
|
||||
qDebug() << elemant.value("sys").toMap().value("country").toString();
|
||||
}
|
||||
qDebug() << elemant.value("id").toString();
|
||||
qDebug() << "--------------------------------------";
|
||||
|
||||
QVariantMap city;
|
||||
city.insert("name",elemant.value("name").toString());
|
||||
city.insert("country", elemant.value("sys").toMap().value("country").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());
|
||||
}
|
||||
city.insert("id",elemant.value("id").toString());
|
||||
cityList.append(city);
|
||||
|
||||
m_cityId = elemant.value("id").toString();
|
||||
search(m_cityName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
qDebug() << "----------------------------------------";
|
||||
emit searchResultReady(cityList);
|
||||
}
|
||||
|
||||
void OpenWeatherMap::replyFinished(QNetworkReply *reply)
|
||||
@ -145,31 +176,37 @@ void OpenWeatherMap::replyFinished(QNetworkReply *reply)
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
QByteArray data;
|
||||
|
||||
if(reply == m_locationReply && status == 200){
|
||||
data = reply->readAll();
|
||||
processLocationResponse(data);
|
||||
m_locationReply->deleteLater();
|
||||
return;
|
||||
}
|
||||
if(reply->error() == QNetworkReply::NoError){
|
||||
if(reply == m_locationReply){
|
||||
data = reply->readAll();
|
||||
processLocationResponse(data);
|
||||
delete m_locationReply;
|
||||
return;
|
||||
}
|
||||
|
||||
if(reply == m_searchReply && status == 200){
|
||||
data = reply->readAll();
|
||||
processSearchResponse(data);
|
||||
m_searchReply->deleteLater();
|
||||
return;
|
||||
}
|
||||
if(reply == m_searchReply){
|
||||
data = reply->readAll();
|
||||
processSearchResponse(data);
|
||||
delete m_searchReply;
|
||||
return;
|
||||
}
|
||||
|
||||
if(reply == m_searchLocationReply && status == 200){
|
||||
data = reply->readAll();
|
||||
processSearchLocationResponse(data);
|
||||
m_searchLocationReply->deleteLater();
|
||||
return;
|
||||
}
|
||||
if(reply == m_searchGeoReply){
|
||||
data = reply->readAll();
|
||||
processSearchGeoResponse(data);
|
||||
delete m_searchGeoReply;
|
||||
return;
|
||||
}
|
||||
|
||||
if(reply == m_weatherReply && status == 200){
|
||||
data = reply->readAll();
|
||||
emit weatherDataReady(data);
|
||||
m_weatherReply->deleteLater();
|
||||
return;
|
||||
if(m_weatherReplys.contains(reply)){
|
||||
data = reply->readAll();
|
||||
DeviceId deviceId = m_weatherReplys.value(reply);
|
||||
emit weatherDataReady(data, deviceId);
|
||||
m_weatherReplys.take(reply);
|
||||
delete reply;
|
||||
}
|
||||
}else{
|
||||
qWarning() << "ERROR: OpenWeatherMap reply error code: " << status << reply->errorString();
|
||||
delete reply;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,35 +25,43 @@
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonDocument>
|
||||
#include <QVariantMap>
|
||||
#include <QHostAddress>
|
||||
#include <QUrl>
|
||||
|
||||
#include "plugin/deviceplugin.h"
|
||||
|
||||
class OpenWeatherMap : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OpenWeatherMap(QObject *parent = 0);
|
||||
void update(QString id);
|
||||
void update(QString id, DeviceId deviceId);
|
||||
void searchAutodetect();
|
||||
void search(QString searchString);
|
||||
void searchGeoLocation(double lat, double lon);
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *m_manager;
|
||||
|
||||
QString m_cityName;
|
||||
QString m_country;
|
||||
QString m_cityId;
|
||||
QHostAddress m_wanIp;
|
||||
|
||||
QNetworkReply *m_locationReply;
|
||||
QNetworkReply *m_searchLocationReply;
|
||||
QNetworkReply *m_weatherReply;
|
||||
QNetworkReply *m_searchReply;
|
||||
QNetworkReply *m_searchGeoReply;
|
||||
|
||||
void processLocationResponse(QByteArray data);
|
||||
void processSearchResponse(QByteArray data);
|
||||
void processSearchLocationResponse(QByteArray data);
|
||||
void processSearchGeoResponse(QByteArray data);
|
||||
|
||||
QHash<QNetworkReply*,DeviceId> m_weatherReplys;
|
||||
|
||||
signals:
|
||||
void searchResultReady(const QList<QVariantMap> &cityList);
|
||||
void weatherDataReady(const QByteArray &data);
|
||||
void weatherDataReady(const QByteArray &data, const DeviceId &deviceId);
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user