added autodetection using geo-location

This commit is contained in:
Simon Stürz 2014-10-12 00:30:00 +02:00 committed by Michael Zanetti
parent 9e2f1286b1
commit 511a676507
5 changed files with 119 additions and 70 deletions

View File

@ -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 &params)
{
if(deviceClassId == openweathermapDeviceClassId){
if(deviceClassId != openweathermapDeviceClassId){
return report(DeviceManager::DeviceErrorDeviceClassNotFound);
}
QString location;
foreach (const Param &param, 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 &param, 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();

View File

@ -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:

View File

@ -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": [

View File

@ -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;
}
}

View File

@ -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: