Merge PR #202: New Plugin: Air Quality Index
This commit is contained in:
commit
8738bb1073
42
aqi/README.md
Normal file
42
aqi/README.md
Normal 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
234
aqi/airqualityindex.cpp
Normal 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
91
aqi/airqualityindex.h
Normal 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
12
aqi/aqi.pro
Normal file
@ -0,0 +1,12 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT+= network
|
||||
|
||||
SOURCES += \
|
||||
airqualityindex.cpp \
|
||||
integrationpluginaqi.cpp \
|
||||
|
||||
HEADERS += \
|
||||
airqualityindex.h \
|
||||
integrationpluginaqi.h \
|
||||
|
||||
282
aqi/integrationpluginaqi.cpp
Normal file
282
aqi/integrationpluginaqi.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
75
aqi/integrationpluginaqi.h
Normal file
75
aqi/integrationpluginaqi.h
Normal 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
|
||||
171
aqi/integrationpluginaqi.json
Normal file
171
aqi/integrationpluginaqi.json
Normal 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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
287
aqi/translations/57d69b76-4d2d-41ec-bef6-949a79ffbe6b-en_US.ts
Normal file
287
aqi/translations/57d69b76-4d2d-41ec-bef6-949a79ffbe6b-en_US.ts
Normal 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
17
debian/control
vendored
@ -39,6 +39,22 @@ Description: nymea.io plugin for ANEL Elektronik NET-PwrCtrl 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
|
||||
Architecture: any
|
||||
Section: libs
|
||||
@ -960,6 +976,7 @@ Package: nymea-plugins
|
||||
Section: libs
|
||||
Architecture: all
|
||||
Depends: nymea-plugin-anel,
|
||||
nymea-plugin-aqi,
|
||||
nymea-plugin-awattar,
|
||||
nymea-plugin-bose,
|
||||
nymea-plugin-datetime,
|
||||
|
||||
1
debian/nymea-plugin-aqi.install.in
vendored
Normal file
1
debian/nymea-plugin-aqi.install.in
vendored
Normal file
@ -0,0 +1 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginaqi.so
|
||||
@ -2,6 +2,7 @@ TEMPLATE = subdirs
|
||||
|
||||
PLUGIN_DIRS = \
|
||||
anel \
|
||||
aqi \
|
||||
avahimonitor \
|
||||
awattar \
|
||||
boblight \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user