Merge PR #202: New Plugin: Air Quality Index

This commit is contained in:
Jenkins nymea 2020-04-14 17:29:25 +02:00
commit 8738bb1073
11 changed files with 1213 additions and 0 deletions

42
aqi/README.md Normal file
View File

@ -0,0 +1,42 @@
# Air Quality Index
This plug-in gets air quality information from http://aqicn.org.
Through the WAN IP address the next nearby sensor station will be discovered.
The geo location can also be set manually.
## Supported Things
* Air Quality Index
* Location discovery
* Manually location set
* Air Quality
* Cautionary statement
* PM2.5 pollution level
* PM10 pollution lebel
* Ozone level
* Nitrogen dioxide level
* Carbon monoxide level
* Sulfur dioxide level
* Temperature
* Humidity
* Pressure
* Wind speed
NOTE: If you encounter that a value stays to zero, it means the sensor station
doesn't support that value.
Besides the air pollution level the plug-in also states a cautionary statement.
Both states can be used to let nymea notify you about the pollution level and
inform you what precautions should be taken.
## Requirments
* Valid "Air Quality Index" API Key
* The package "nymea-plugin-airqualityindex" must be installed
* Internet connection
## More
More about the different Air Quality Levels: https://www.airnow.gov/index.cfm?action=aqibasics.aqi

234
aqi/airqualityindex.cpp Normal file
View File

@ -0,0 +1,234 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "airqualityindex.h"
#include "extern-plugininfo.h"
#include <QNetworkReply>
#include <QUrlQuery>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
AirQualityIndex::AirQualityIndex(NetworkAccessManager *networkAccessManager, const QString &apiKey, QObject *parent) :
QObject(parent),
m_networkAccessManager(networkAccessManager),
m_apiKey(apiKey)
{
}
void AirQualityIndex::setApiKey(const QString &apiKey)
{
m_apiKey = apiKey;
}
QUuid AirQualityIndex::searchByName(const QString &name)
{
if (m_apiKey.isEmpty())
qCWarning(dcAirQualityIndex()) << "API key is not set";
QUuid requestId = QUuid::createUuid();;
QUrl url;
url.setUrl(m_baseUrl);
url.setPath("/search/");
QUrlQuery query;
query.addQueryItem("token", m_apiKey);
query.addQueryItem("keyword", name);
url.setQuery(query);
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("User-Agent", "nymea");
QNetworkReply *reply = m_networkAccessManager->get(request);
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// Check HTTP status code
if (status != 200 || reply->error() != QNetworkReply::NoError) {
if (status == 400) {
qCWarning(dcAirQualityIndex()) << "Request error due to exceeded request quota";
}
requestExecuted(requestId, false);
qCWarning(dcAirQualityIndex()) << "Request error:" << status << reply->errorString();
return;
}
QByteArray rawData = reply->readAll();
qCDebug(dcAirQualityIndex()) << "Search response" << rawData;
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(rawData, &error);
if (error.error != QJsonParseError::NoError) {
emit requestExecuted(requestId, false);
qCWarning(dcAirQualityIndex()) << "Received invalide JSON object";
return;
}
QList<Station> stations;
QVariantList stationList = doc.toVariant().toMap().value("data").toList();
foreach (QVariant stationVariant, stationList) {
Station station;
station.aqi = stationVariant.toMap().value("aqi").toInt();
station.idx = stationVariant.toMap().value("idx").toInt();
station.measurementTime = QTime::fromString(stationVariant.toMap().value("time").toMap().value("s").toString());
station.timezone = stationVariant.toMap().value("time").toMap().value("tz").toString();
station.name = stationVariant.toMap().value("city").toMap().value("name").toString();
station.url = QUrl(stationVariant.toMap().value("city").toMap().value("url").toString());
station.location.latitude = stationVariant.toMap().value("city").toMap().value("geo").toList().first().toDouble();
station.location.longitude = stationVariant.toMap().value("city").toMap().value("geo").toList().last().toDouble();
stations.append(station);
}
if (!stations.isEmpty())
emit stationsReceived(requestId, stations);
requestExecuted(requestId, true);
});
return requestId;
}
QUuid AirQualityIndex::getDataByIp()
{
if (m_apiKey.isEmpty())
qCWarning(dcAirQualityIndex()) << "API key is not set";
QUuid requestId = QUuid::createUuid();;
QUrl url;
url.setUrl(m_baseUrl);
url.setPath("/feed/here/");
QUrlQuery query;
query.addQueryItem("token", m_apiKey);
url.setQuery(query);
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("User-Agent", "nymea");
qCDebug(dcAirQualityIndex()) << "Get data by IP request" << url.toString();
QNetworkReply *reply = m_networkAccessManager->get(request);
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// Check HTTP status code
if (status != 200 || reply->error() != QNetworkReply::NoError) {
if (status == 400) {
qCWarning(dcAirQualityIndex()) << "Request error due to exceeded request quota";
}
requestExecuted(requestId, false);
qCWarning(dcAirQualityIndex()) << "Request error:" << status << reply->errorString();
return;
}
if (!parseData(requestId, reply->readAll()))
requestExecuted(requestId, false);
requestExecuted(requestId, true);
});
return requestId;
}
QUuid AirQualityIndex::getDataByGeolocation(const QString &lat, const QString &lng)
{
if (m_apiKey.isEmpty())
qCWarning(dcAirQualityIndex()) << "API key is not set";
QUuid requestId = QUuid::createUuid();
QUrl url;
url.setUrl(m_baseUrl);
url.setPath("/feed/geo:"+lat+";"+lng+"/");
QUrlQuery query;
query.addQueryItem("token", m_apiKey);
url.setQuery(query);
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("User-Agent", "nymea");
qCDebug(dcAirQualityIndex()) << "Get data by geo location request" << url.toString();
QNetworkReply *reply = m_networkAccessManager->get(request);
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// Check HTTP status code
if (status != 200 || reply->error() != QNetworkReply::NoError) {
if (status == 400) {
qCWarning(dcAirQualityIndex()) << "Request error due to exceeded request quota";
}
requestExecuted(requestId, false);
qCWarning(dcAirQualityIndex()) << "Request error:" << status << reply->errorString();
return;
}
if (!parseData(requestId, reply->readAll()))
requestExecuted(requestId, false);
requestExecuted(requestId, true);
});
return requestId;
}
bool AirQualityIndex::parseData(QUuid requestId, const QByteArray &data)
{
qCDebug(dcAirQualityIndex()) << "Parsing data" << data;
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcAirQualityIndex()) << "Received invalide JSON object";
return false;
}
Station station;
station.aqi = doc.toVariant().toMap().value("data").toMap().value("aqi").toInt();
station.idx = doc.toVariant().toMap().value("data").toMap().value("idx").toInt();
QVariantMap city = doc.toVariant().toMap().value("data").toMap().value("city").toMap();
if (city["geo"].toList().length() == 2) {
station.location.latitude = city["geo"].toList().first().toDouble();
station.location.longitude = city["geo"].toList().last().toDouble();
} else {
qCWarning(dcAirQualityIndex()) << "Parse data: geo location data list error" << city["geo"];
}
station.name = city["name"].toString();
station.url = city["url"].toString();
QVariantMap time = doc.toVariant().toMap().value("data").toMap().value("time").toMap();
station.timezone = time["tz"].toString();
station.measurementTime = QTime::fromString(time["s"].toString());
emit stationsReceived(requestId, QList<Station>() << station);
QVariantMap iaqi = doc.toVariant().toMap().value("data").toMap().value("iaqi").toMap();
AirQualityData aqiData;
aqiData.humidity = iaqi["h"].toMap().value("v").toDouble();
aqiData.pressure = iaqi["p"].toMap().value("v").toDouble();
aqiData.pm25 = iaqi["pm25"].toMap().value("v").toInt();
aqiData.pm10 = iaqi["pm10"].toMap().value("v").toInt();
aqiData.so2 = iaqi["so2"].toMap().value("v").toDouble();
aqiData.no2 = iaqi["no2"].toMap().value("v").toDouble();
aqiData.o3 = iaqi["o3"].toMap().value("v").toDouble();
aqiData.co = iaqi["co"].toMap().value("v").toDouble();
aqiData.temperature = iaqi["t"].toMap().value("v").toDouble();
aqiData.windSpeed = iaqi["w"].toMap().value("v").toDouble();
emit dataReceived(requestId, aqiData);
return true;
}

91
aqi/airqualityindex.h Normal file
View File

@ -0,0 +1,91 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef AIRQUALITYINDEX_H
#define AIRQUALITYINDEX_H
#include "network/networkaccessmanager.h"
#include <QObject>
#include <QUuid>
#include <QTime>
class AirQualityIndex : public QObject
{
Q_OBJECT
public:
struct AirQualityData {
double humidity;
double pressure;
int pm25;
int pm10;
double so2;
double no2;
double o3;
double co;
double temperature;
double windSpeed;
};
struct GeoData {
double latitude;
double longitude;
};
struct Station {
int idx;
int aqi;
QTime measurementTime;
QString timezone;
QString name;
GeoData location;
QUrl url;
};
explicit AirQualityIndex(NetworkAccessManager *networkAccessManager, const QString &apiKey, QObject *parent = nullptr);
void setApiKey(const QString &apiKey);
QUuid searchByName(const QString &name);
QUuid getDataByIp();
QUuid getDataByGeolocation(const QString &lat, const QString &lng);
private:
NetworkAccessManager *m_networkAccessManager;
QString m_baseUrl = "https://api.waqi.info";
QString m_apiKey;
bool parseData(QUuid requestId, const QByteArray &data);
signals:
void stationsReceived(QUuid requestId, QList<Station> stations);
void requestExecuted(QUuid requestId, bool success);
void dataReceived(QUuid requestId, const AirQualityData &data);
};
#endif // AIRQUALITYINDEX_H

12
aqi/aqi.pro Normal file
View File

@ -0,0 +1,12 @@
include(../plugins.pri)
QT+= network
SOURCES += \
airqualityindex.cpp \
integrationpluginaqi.cpp \
HEADERS += \
airqualityindex.h \
integrationpluginaqi.h \

View File

@ -0,0 +1,282 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "integrationpluginaqi.h"
#include "plugininfo.h"
#include <QNetworkAccessManager>
IntegrationPluginAqi::IntegrationPluginAqi()
{
}
void IntegrationPluginAqi::startPairing(ThingPairingInfo *info)
{
NetworkAccessManager *network = hardwareManager()->networkManager();
QNetworkReply *reply = network->get(QNetworkRequest(QUrl("https://api.waqi.info")));
connect(reply, &QNetworkReply::finished, this, [reply, info] {
reply->deleteLater();
if (reply->error() == QNetworkReply::NetworkError::HostNotFoundError) {
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Air quality index server is not reachable."));
} else {
info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter your API token for Air Quality Index"));
}
});
}
void IntegrationPluginAqi::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret)
{
Q_UNUSED(username)
QNetworkRequest request(QUrl("https://api.waqi.info/feed/here/?token="+secret));
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, info, [this, reply, info, secret](){
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// check HTTP status code
if (status != 200) {
//: Error setting up device with invalid token
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("This token is not valid."));
return;
}
pluginStorage()->beginGroup(info->thingId().toString());
pluginStorage()->setValue("apiKey", secret);
pluginStorage()->endGroup();
info->finish(Thing::ThingErrorNoError);
});
}
void IntegrationPluginAqi::discoverThings(ThingDiscoveryInfo *info)
{
if (!m_aqiConnection) {
QString apiKey = "74d31bb5ad9bcdeaed48097418b55188cb56d450"; //temporary key for discovery
m_aqiConnection = new AirQualityIndex(hardwareManager()->networkManager(), apiKey, this);
connect(m_aqiConnection, &AirQualityIndex::requestExecuted, this, &IntegrationPluginAqi::onRequestExecuted);
connect(m_aqiConnection, &AirQualityIndex::dataReceived, this, &IntegrationPluginAqi::onAirQualityDataReceived);
connect(m_aqiConnection, &AirQualityIndex::stationsReceived, this, &IntegrationPluginAqi::onAirQualityStationsReceived);
connect(info, &ThingDiscoveryInfo::aborted, [this] {
if (myThings().filterByThingClassId(airQualityIndexThingClassId).isEmpty()) {
m_aqiConnection->deleteLater();
m_aqiConnection = nullptr;
}
});
} else {
qCDebug(dcAirQualityIndex()) << "AQI connection alread created";
}
QUuid requestId = m_aqiConnection->getDataByIp();
m_asyncDiscovery.insert(requestId, info);
connect(info, &ThingDiscoveryInfo::aborted, [=] {m_asyncDiscovery.remove(requestId);});
}
void IntegrationPluginAqi::setupThing(ThingSetupInfo *info)
{
if (info->thing()->thingClassId() == airQualityIndexThingClassId) {
if (!m_aqiConnection) {
pluginStorage()->beginGroup(info->thing()->id().toString());
QString apiKey = pluginStorage()->value("apiKey").toString();
pluginStorage()->endGroup();
m_aqiConnection = new AirQualityIndex(hardwareManager()->networkManager(), apiKey, this);
connect(m_aqiConnection, &AirQualityIndex::requestExecuted, this, &IntegrationPluginAqi::onRequestExecuted);
connect(m_aqiConnection, &AirQualityIndex::dataReceived, this, &IntegrationPluginAqi::onAirQualityDataReceived);
connect(m_aqiConnection, &AirQualityIndex::stationsReceived, this, &IntegrationPluginAqi::onAirQualityStationsReceived);
QString longitude = info->thing()->paramValue(airQualityIndexThingLongitudeParamTypeId).toString();
QString latitude = info->thing()->paramValue(airQualityIndexThingLatitudeParamTypeId).toString();
QUuid requestId = m_aqiConnection->getDataByGeolocation(latitude, longitude);
m_asyncSetups.insert(requestId, info);
connect(info, &ThingSetupInfo::aborted, [requestId, this] {
m_asyncSetups.remove(requestId);
if (myThings().filterByThingClassId(airQualityIndexThingClassId).isEmpty()) {
m_aqiConnection->deleteLater();
m_aqiConnection = nullptr;
}
});
} else {
// An AQI connection might be setup because of an discovery request
// or because there is already another thing using the connection
// In any case the API key is being updated to avoid using the discovery key.
pluginStorage()->beginGroup(info->thing()->id().toString());
QString apiKey = pluginStorage()->value("apiKey").toString();
pluginStorage()->endGroup();
m_aqiConnection->setApiKey(apiKey);
info->finish(Thing::ThingErrorNoError);
}
} else {
qCWarning(dcAirQualityIndex()) << "setupThing - thing class id not found" << info->thing()->thingClassId();
info->finish(Thing::ThingErrorSetupFailed);
}
}
void IntegrationPluginAqi::postSetupThing(Thing *thing)
{
if (thing->thingClassId() == airQualityIndexThingClassId) {
if (!m_aqiConnection) {
qCWarning(dcAirQualityIndex()) << "Air quality connection not initialized";
return;
}
QString longitude = thing->paramValue(airQualityIndexThingLongitudeParamTypeId).toString();
QString latitude = thing->paramValue(airQualityIndexThingLatitudeParamTypeId).toString();
QUuid requestId = m_aqiConnection->getDataByGeolocation(latitude, longitude);
m_asyncRequests.insert(requestId, thing->id());
}
if(!m_pluginTimer) {
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(60);
connect(m_pluginTimer, &PluginTimer::timeout, this, &IntegrationPluginAqi::onPluginTimer);
}
}
void IntegrationPluginAqi::thingRemoved(Thing *thing)
{
Q_UNUSED(thing)
if (myThings().empty()) {
if (m_pluginTimer) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
m_pluginTimer = nullptr; }
if (m_aqiConnection) {
m_aqiConnection->deleteLater();
m_aqiConnection = nullptr;
}
}
}
void IntegrationPluginAqi::onAirQualityDataReceived(QUuid requestId, AirQualityIndex::AirQualityData data)
{
qCDebug(dcAirQualityIndex()) << "Air Quality data received, request id:" << requestId << "is an async request:" << m_asyncRequests.contains(requestId);
if (m_asyncSetups.contains(requestId)) {
ThingSetupInfo *info = m_asyncSetups.value(requestId);
return info->finish(Thing::ThingErrorNoError);
}
if (m_asyncRequests.contains(requestId)) {
Thing * thing = myThings().findById(m_asyncRequests.take(requestId));
if (!thing)
return;
thing->setStateValue(airQualityIndexConnectedStateTypeId, true);
thing->setStateValue(airQualityIndexCoStateTypeId, data.co);
thing->setStateValue(airQualityIndexHumidityStateTypeId, data.humidity);
thing->setStateValue(airQualityIndexTemperatureStateTypeId, data.temperature);
thing->setStateValue(airQualityIndexPressureStateTypeId, data.pressure);
thing->setStateValue(airQualityIndexO3StateTypeId, data.o3);
thing->setStateValue(airQualityIndexNo2StateTypeId, data.no2);
thing->setStateValue(airQualityIndexSo2StateTypeId, data.so2);
thing->setStateValue(airQualityIndexPm10StateTypeId, data.pm10);
thing->setStateValue(airQualityIndexPm25StateTypeId, data.pm25);
thing->setStateValue(airQualityIndexWindSpeedStateTypeId, data.windSpeed);
if (data.pm25 <= 50.00) {
thing->setStateValue(airQualityIndexAirQualityStateTypeId, "Good");
thing->setStateValue(airQualityIndexCautionaryStatementStateTypeId, tr("None"));
} else if ((data.pm25 > 50.00) && (data.pm25 <= 100.00)) {
thing->setStateValue(airQualityIndexAirQualityStateTypeId, "Moderate");
thing->setStateValue(airQualityIndexCautionaryStatementStateTypeId, tr("Active children and adults, and people with respiratory disease, such as asthma, should limit prolonged outdoor exertion."));
} else if ((data.pm25 > 100.00) && (data.pm25 <= 150.00)) {
thing->setStateValue(airQualityIndexAirQualityStateTypeId, "Unhealthy for Sensitive Groups");
thing->setStateValue(airQualityIndexCautionaryStatementStateTypeId, tr("Active children and adults, and people with respiratory disease, such as asthma, should limit prolonged outdoor exertion."));
} else if ((data.pm25 > 150.00) && (data.pm25 <= 200.00)) {
thing->setStateValue(airQualityIndexAirQualityStateTypeId, "Unhealthy");
thing->setStateValue(airQualityIndexCautionaryStatementStateTypeId, tr("Active children and adults, and people with respiratory disease, such as asthma, should avoid prolonged outdoor exertion; everyone else, especially children, should limit prolonged outdoor exertion"));
} else if ((data.pm25 > 200.00) && (data.pm25 <= 300.00)) {
thing->setStateValue(airQualityIndexAirQualityStateTypeId, "Very Unhealthy");
thing->setStateValue(airQualityIndexCautionaryStatementStateTypeId, tr("Active children and adults, and people with respiratory disease, such as asthma, should avoid all outdoor exertion; everyone else, especially children, should limit outdoor exertion."));
} else {
thing->setStateValue(airQualityIndexAirQualityStateTypeId, "Hazardous");
thing->setStateValue(airQualityIndexCautionaryStatementStateTypeId, tr("Everyone should avoid all outdoor exertion"));
}
}
}
void IntegrationPluginAqi::onAirQualityStationsReceived(QUuid requestId, QList<AirQualityIndex::Station> stations)
{
qCDebug(dcAirQualityIndex()) << "Air Quality Stations received, request id:" << requestId << "is an async request:" << m_asyncRequests.contains(requestId);
if (m_asyncDiscovery.contains(requestId)) {
ThingDiscoveryInfo *info = m_asyncDiscovery.take(requestId);
foreach(AirQualityIndex::Station station, stations) {
ThingDescriptor descriptor(airQualityIndexThingClassId, station.name, "Air Quality Index Station");
ParamList params;
params << Param(airQualityIndexThingLatitudeParamTypeId, station.location.latitude);
params << Param(airQualityIndexThingLongitudeParamTypeId, station.location.longitude);
descriptor.setParams(params);
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
}
if (m_asyncRequests.contains(requestId)) {
Thing * thing = myThings().findById(m_asyncRequests.value(requestId));
if (!thing) {
qCWarning(dcAirQualityIndex()) << "Can't find thing, associated to this async request";
return;
}
if (stations.length() != 0) {
thing->setStateValue(airQualityIndexStationNameStateTypeId, stations.first().name);
}
}
}
void IntegrationPluginAqi::onPluginTimer()
{
if (!m_aqiConnection)
return;
foreach (Thing *thing, myThings().filterByThingClassId(airQualityIndexThingClassId)) {
QString longitude = thing->paramValue(airQualityIndexThingLongitudeParamTypeId).toString();
QString latitude = thing->paramValue(airQualityIndexThingLatitudeParamTypeId).toString();
QUuid requestId = m_aqiConnection->getDataByGeolocation(latitude, longitude);
m_asyncRequests.insert(requestId, thing->id());
}
}
void IntegrationPluginAqi::onRequestExecuted(QUuid requestId, bool success)
{
qCDebug(dcAirQualityIndex()) << "Request executd, requestId:" << requestId << "Success:" << success << "is an async request:" << m_asyncRequests.contains(requestId);
if (m_asyncRequests.contains(requestId)) {
Thing *thing = myThings().findById(m_asyncRequests.value(requestId));
thing->setStateValue(airQualityIndexConnectedStateTypeId, success);
if (!success) {
qCWarning(dcAirQualityIndex()) << "Request failed, removing request from async request list";
}
m_asyncRequests.remove(requestId);
}
}

View File

@ -0,0 +1,75 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef INTEGRATIONPLUGINAQI_H
#define INTEGRATIONPLUGINAQI_H
#include "plugintimer.h"
#include "integrations/integrationplugin.h"
#include "network/networkaccessmanager.h"
#include "airqualityindex.h"
#include <QTimer>
#include <QUrl>
#include <QHostAddress>
class IntegrationPluginAqi : public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginaqi.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginAqi();
void startPairing(ThingPairingInfo *info) override;
void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret) override;
void discoverThings(ThingDiscoveryInfo *info) override;
void setupThing(ThingSetupInfo *info) override;
void thingRemoved(Thing *thing) override;
void postSetupThing(Thing *thing) override;
private:
PluginTimer *m_pluginTimer = nullptr;
AirQualityIndex *m_aqiConnection = nullptr;
QHash<QUuid, ThingDiscoveryInfo *> m_asyncDiscovery;
QHash<QUuid, ThingSetupInfo *> m_asyncSetups;
QHash<QUuid, ThingId> m_asyncRequests;
private slots:
void onPluginTimer();
void onRequestExecuted(QUuid requestId, bool success);
void onAirQualityDataReceived(QUuid requestId, AirQualityIndex::AirQualityData data);
void onAirQualityStationsReceived(QUuid requestId, QList<AirQualityIndex::Station> stations);
};
#endif // INTEGRATIONPLUGINAQI_H

View File

@ -0,0 +1,171 @@
{
"name": "AirQualityIndex",
"displayName": "AirQualityIndex",
"id": "57d69b76-4d2d-41ec-bef6-949a79ffbe6b",
"vendors": [
{
"name": "airQualityIndex",
"displayName": "Air Quality Index",
"id": "6c8e2ded-0a33-4e77-b76c-ea02168741ec",
"thingClasses": [
{
"id": "23ea32c9-38b0-4155-bacc-3afa8c09f6ee",
"name": "airQualityIndex",
"displayName": "Air quality index",
"interfaces": ["windspeedsensor", "humiditysensor", "pressuresensor", "temperaturesensor", "connectable"],
"createMethods": ["discovery", "user"],
"setupMethod": "displaypin",
"paramTypes": [
{
"id": "afd5803b-6c98-44d7-9f4a-45e91cfb062e",
"name": "latitude",
"displayName": "Latitude",
"type": "QString",
"inputType": "TextLine"
},
{
"id": "4800d78e-a367-41f7-9bf6-7c81d40ce19a",
"name": "longitude",
"displayName": "Longitude",
"type": "QString",
"inputType": "TextLine"
}
],
"stateTypes": [
{
"id": "7b9135cd-2461-4d33-b2b3-3dc600983895",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "33a3329a-4117-4488-aa18-91c76056ed6e",
"name": "airQuality",
"displayName": "Air quality",
"displayNameEvent": "Air quality changed",
"type": "QString",
"possibleValues": [
"Good",
"Moderate",
"Unhealthy for Sensitive Groups",
"Unhealthy",
"Very unhealthy",
"Hazardous"
],
"defaultValue": "Good"
},
{
"id": "cfece671-4e88-4c49-9456-e3f8f7c79ab3",
"name": "cautionaryStatement",
"displayName": "Cautionary statement",
"displayNameEvent": "Cautionary statement changed",
"type": "QString",
"defaultValue": "-"
},
{
"id": "8385f3d5-62f7-482e-927c-b5d61a70d607",
"name": "stationName",
"displayName": "Station name",
"displayNameEvent": "Station name changed",
"type": "QString",
"defaultValue": "Undefined"
},
{
"id": "bc8c4c83-d229-4be4-8732-bc4f2390f399",
"name": "pm25",
"displayName": "Fine particles pollution level (PM2.5)",
"displayNameEvent": "Fine particles pollution level (PM2.5) changed",
"type": "int",
"defaultValue": 0
},
{
"id": "24b41ec4-e26b-4dfb-b52c-8e2b1bbdafc6",
"name": "pm10",
"displayName": "Coarse dust particles pollution level (PM10)",
"displayNameEvent": "Coarse dust particles pollution level (PM10) changed",
"type": "int",
"defaultValue": 0
},
{
"id": "4e88526d-009f-4820-9a84-09b3646d23c9",
"name": "o3",
"displayName": "Ozone level (O3)",
"displayNameEvent": "Ozone level (O3) changed",
"unit": "",
"type": "double",
"defaultValue": 0
},
{
"id": "6ed6c505-f36e-44c4-a982-f395b04e539b",
"name": "no2",
"displayName": "Nitrogen Dioxide level (NO2)",
"displayNameEvent": "Nitrogen Dioxide level (NO2) changed",
"unit": "",
"type": "double",
"defaultValue": 0
},
{
"id": "54ac72f3-6444-46a8-a43d-210c2a6fbfb5",
"name": "co",
"displayName": "Carbon monoxide level (CO)",
"displayNameEvent": "Carbon monoxide level (CO) changed",
"unit": "",
"type": "double",
"defaultValue": 0
},
{
"id": "f3a05e65-a9b3-48fd-be43-688d4c293cc9",
"name": "so2",
"displayName": "Sulfur dioxide level (SO2)",
"displayNameEvent": "Sulfur dioxide level (SO2) changed",
"unit": "",
"type": "double",
"defaultValue": 0
},
{
"id": "94219802-0a82-4761-99b3-c6b6dfc096db",
"name": "temperature",
"displayName": "Temperature",
"displayNameEvent": "Temperature changed",
"unit": "DegreeCelsius",
"type": "double",
"defaultValue": 0
},
{
"id": "4fc45fca-25ab-45a0-b862-817eea1f51e3",
"name": "humidity",
"displayName": "Humidity",
"displayNameEvent": "Humidity changed",
"unit": "Percentage",
"type": "double",
"maxValue": 100,
"minValue": 0,
"defaultValue": 0
},
{
"id": "5f799040-08f8-44d1-aa0a-4cab7caad839",
"name": "pressure",
"displayName": "Pressure",
"displayNameEvent": "Pressure changed",
"unit": "MilliBar",
"type": "double",
"defaultValue": 0
},
{
"id": "c4366608-2511-428b-964e-2ad9e37f8f3c",
"name": "windSpeed",
"displayName": "Wind speed",
"displayNameEvent": "Wind speed changed",
"unit": "MeterPerSecond",
"type": "double",
"defaultValue": 0
}
]
}
]
}
]
}

View File

@ -0,0 +1,287 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AirQualityIndex</name>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="67"/>
<source>Air Quality Index</source>
<extracomment>The name of the vendor ({6c8e2ded-0a33-4e77-b76c-ea02168741ec})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="70"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="73"/>
<source>Air quality</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: airQuality, ID: {33a3329a-4117-4488-aa18-91c76056ed6e})
----------
The name of the StateType ({33a3329a-4117-4488-aa18-91c76056ed6e}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="76"/>
<source>Air quality changed</source>
<extracomment>The name of the EventType ({33a3329a-4117-4488-aa18-91c76056ed6e}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="79"/>
<source>Air quality index</source>
<extracomment>The name of the ThingClass ({23ea32c9-38b0-4155-bacc-3afa8c09f6ee})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="82"/>
<source>AirQualityIndex</source>
<extracomment>The name of the plugin AirQualityIndex ({57d69b76-4d2d-41ec-bef6-949a79ffbe6b})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="85"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="88"/>
<source>Carbon monoxide level (CO)</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: co, ID: {54ac72f3-6444-46a8-a43d-210c2a6fbfb5})
----------
The name of the StateType ({54ac72f3-6444-46a8-a43d-210c2a6fbfb5}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="91"/>
<source>Carbon monoxide level (CO) changed</source>
<extracomment>The name of the EventType ({54ac72f3-6444-46a8-a43d-210c2a6fbfb5}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="94"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="97"/>
<source>Cautionary statement</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: cautionaryStatement, ID: {cfece671-4e88-4c49-9456-e3f8f7c79ab3})
----------
The name of the StateType ({cfece671-4e88-4c49-9456-e3f8f7c79ab3}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="100"/>
<source>Cautionary statement changed</source>
<extracomment>The name of the EventType ({cfece671-4e88-4c49-9456-e3f8f7c79ab3}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="103"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="106"/>
<source>Coarse dust particles pollution level (PM10)</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: pm10, ID: {24b41ec4-e26b-4dfb-b52c-8e2b1bbdafc6})
----------
The name of the StateType ({24b41ec4-e26b-4dfb-b52c-8e2b1bbdafc6}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="109"/>
<source>Coarse dust particles pollution level (PM10) changed</source>
<extracomment>The name of the EventType ({24b41ec4-e26b-4dfb-b52c-8e2b1bbdafc6}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="112"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="115"/>
<source>Connected</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: connected, ID: {7b9135cd-2461-4d33-b2b3-3dc600983895})
----------
The name of the StateType ({7b9135cd-2461-4d33-b2b3-3dc600983895}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="118"/>
<source>Connected changed</source>
<extracomment>The name of the EventType ({7b9135cd-2461-4d33-b2b3-3dc600983895}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="121"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="124"/>
<source>Fine particles pollution level (PM2.5)</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: pm25, ID: {bc8c4c83-d229-4be4-8732-bc4f2390f399})
----------
The name of the StateType ({bc8c4c83-d229-4be4-8732-bc4f2390f399}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="127"/>
<source>Fine particles pollution level (PM2.5) changed</source>
<extracomment>The name of the EventType ({bc8c4c83-d229-4be4-8732-bc4f2390f399}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="130"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="133"/>
<source>Humidity</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: humidity, ID: {4fc45fca-25ab-45a0-b862-817eea1f51e3})
----------
The name of the StateType ({4fc45fca-25ab-45a0-b862-817eea1f51e3}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="136"/>
<source>Humidity changed</source>
<extracomment>The name of the EventType ({4fc45fca-25ab-45a0-b862-817eea1f51e3}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="139"/>
<source>Latitude</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, Type: thing, ID: {afd5803b-6c98-44d7-9f4a-45e91cfb062e})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="142"/>
<source>Longitude</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, Type: thing, ID: {4800d78e-a367-41f7-9bf6-7c81d40ce19a})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="145"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="148"/>
<source>Nitrogen Dioxide level (NO2)</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: no2, ID: {6ed6c505-f36e-44c4-a982-f395b04e539b})
----------
The name of the StateType ({6ed6c505-f36e-44c4-a982-f395b04e539b}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="151"/>
<source>Nitrogen Dioxide level (NO2) changed</source>
<extracomment>The name of the EventType ({6ed6c505-f36e-44c4-a982-f395b04e539b}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="154"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="157"/>
<source>Ozone level (O3)</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: o3, ID: {4e88526d-009f-4820-9a84-09b3646d23c9})
----------
The name of the StateType ({4e88526d-009f-4820-9a84-09b3646d23c9}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="160"/>
<source>Ozone level (O3) changed</source>
<extracomment>The name of the EventType ({4e88526d-009f-4820-9a84-09b3646d23c9}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="163"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="166"/>
<source>Pressure</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: pressure, ID: {5f799040-08f8-44d1-aa0a-4cab7caad839})
----------
The name of the StateType ({5f799040-08f8-44d1-aa0a-4cab7caad839}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="169"/>
<source>Pressure changed</source>
<extracomment>The name of the EventType ({5f799040-08f8-44d1-aa0a-4cab7caad839}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="172"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="175"/>
<source>Station name</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: stationName, ID: {8385f3d5-62f7-482e-927c-b5d61a70d607})
----------
The name of the StateType ({8385f3d5-62f7-482e-927c-b5d61a70d607}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="178"/>
<source>Station name changed</source>
<extracomment>The name of the EventType ({8385f3d5-62f7-482e-927c-b5d61a70d607}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="181"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="184"/>
<source>Sulfur dioxide level (SO2)</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: so2, ID: {f3a05e65-a9b3-48fd-be43-688d4c293cc9})
----------
The name of the StateType ({f3a05e65-a9b3-48fd-be43-688d4c293cc9}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="187"/>
<source>Sulfur dioxide level (SO2) changed</source>
<extracomment>The name of the EventType ({f3a05e65-a9b3-48fd-be43-688d4c293cc9}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="190"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="193"/>
<source>Temperature</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: temperature, ID: {94219802-0a82-4761-99b3-c6b6dfc096db})
----------
The name of the StateType ({94219802-0a82-4761-99b3-c6b6dfc096db}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="196"/>
<source>Temperature changed</source>
<extracomment>The name of the EventType ({94219802-0a82-4761-99b3-c6b6dfc096db}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="199"/>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="202"/>
<source>Wind speed</source>
<extracomment>The name of the ParamType (ThingClass: airQualityIndex, EventType: windSpeed, ID: {c4366608-2511-428b-964e-2ad9e37f8f3c})
----------
The name of the StateType ({c4366608-2511-428b-964e-2ad9e37f8f3c}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-Desktop-Debug/aqi/plugininfo.h" line="205"/>
<source>Wind speed changed</source>
<extracomment>The name of the EventType ({c4366608-2511-428b-964e-2ad9e37f8f3c}) of ThingClass airQualityIndex</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>IntegrationPluginAqi</name>
<message>
<location filename="../integrationpluginaqi.cpp" line="43"/>
<source>Please enter your API token for Air Quality Index</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginaqi.cpp" line="60"/>
<source>This token is not valid.</source>
<extracomment>Error setting up device with invalid token</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginaqi.cpp" line="193"/>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginaqi.cpp" line="196"/>
<location filename="../integrationpluginaqi.cpp" line="199"/>
<source>Active children and adults, and people with respiratory disease, such as asthma, should limit prolonged outdoor exertion.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginaqi.cpp" line="202"/>
<source>Active children and adults, and people with respiratory disease, such as asthma, should avoid prolonged outdoor exertion; everyone else, especially children, should limit prolonged outdoor exertion</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginaqi.cpp" line="205"/>
<source>Active children and adults, and people with respiratory disease, such as asthma, should avoid all outdoor exertion; everyone else, especially children, should limit outdoor exertion.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginaqi.cpp" line="208"/>
<source>Everyone should avoid all outdoor exertion</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

17
debian/control vendored
View File

@ -39,6 +39,22 @@ Description: nymea.io plugin for ANEL Elektronik NET-PwrCtrl power sockets
network controlled power sockets. network controlled power sockets.
Package: nymea-plugin-aqi
Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-translations,
Description: nymea.io plugin to fetch the air quaility index from http://aqicn.org
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for the air quality index
Package: nymea-plugin-avahimonitor Package: nymea-plugin-avahimonitor
Architecture: any Architecture: any
Section: libs Section: libs
@ -960,6 +976,7 @@ Package: nymea-plugins
Section: libs Section: libs
Architecture: all Architecture: all
Depends: nymea-plugin-anel, Depends: nymea-plugin-anel,
nymea-plugin-aqi,
nymea-plugin-awattar, nymea-plugin-awattar,
nymea-plugin-bose, nymea-plugin-bose,
nymea-plugin-datetime, nymea-plugin-datetime,

1
debian/nymea-plugin-aqi.install.in vendored Normal file
View File

@ -0,0 +1 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginaqi.so

View File

@ -2,6 +2,7 @@ TEMPLATE = subdirs
PLUGIN_DIRS = \ PLUGIN_DIRS = \
anel \ anel \
aqi \
avahimonitor \ avahimonitor \
awattar \ awattar \
boblight \ boblight \