fix pump reachable bug

fix readding bug
pull/135/head
Simon Stürz 2016-03-12 14:47:11 +01:00 committed by Michael Zanetti
parent 8f461ca2d6
commit 334576f882
5 changed files with 112 additions and 205 deletions

View File

@ -78,9 +78,7 @@
#include <QJsonDocument>
#include <QSslConfiguration>
DevicePluginAwattar::DevicePluginAwattar() :
m_device(0),
m_setupRetry(0)
DevicePluginAwattar::DevicePluginAwattar()
{
}
@ -102,20 +100,19 @@ DeviceManager::DeviceSetupStatus DevicePluginAwattar::setupDevice(Device *device
m_token = device->paramValue("token").toString();
m_userUuid = device->paramValue("user uuid").toString();
connectionTest();
return DeviceManager::DeviceSetupStatusSuccess;
}
return DeviceManager::DeviceSetupStatusAsync;
void DevicePluginAwattar::postSetupDevice(Device *device)
{
Q_UNUSED(device)
guhTimer();
}
void DevicePluginAwattar::deviceRemoved(Device *device)
{
Q_UNUSED(device)
foreach (HeatPump *pump, m_heatPumps) {
qCDebug(dcAwattar) << "Delete pump" << pump->address().toString();
pump->deleteLater();
}
qDeleteAll(m_heatPumps);
m_device = 0;
}
@ -123,54 +120,13 @@ void DevicePluginAwattar::networkManagerReplyReady(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (m_asyncSetup.contains(reply)) {
m_asyncSetup.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Setup reply HTTP error:" << status << reply->errorString();
if (m_setupRetry == 3) {
emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusFailure);
m_setupRetry = 0;
reply->deleteLater();
return;
} else {
m_setupRetry++;
reply->deleteLater();
// retry in 1 sec
qCWarning(dcAwattar) << "Retry to connect" << m_setupRetry << "/ 3";
QTimer::singleShot(2000, this, SLOT(connectionTest()));
return;
}
}
// check JSON file
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcAwattar) << "Setup reply JSON error:" << error.errorString();
emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusFailure);
reply->deleteLater();
return;
}
Q_UNUSED(jsonDoc)
emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusSuccess);
// get data
searchHeatPumps();
updateData();
} else if (m_updatePrice.contains(reply)) {
if (m_updatePrice.contains(reply)) {
m_updatePrice.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Update reply HTTP error:" << status << reply->errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
@ -180,6 +136,7 @@ void DevicePluginAwattar::networkManagerReplyReady(QNetworkReply *reply)
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcAwattar) << "Update reply JSON error:" << error.errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
@ -190,12 +147,12 @@ void DevicePluginAwattar::networkManagerReplyReady(QNetworkReply *reply)
m_updateUserData.append(requestUserData(m_token, m_userUuid));
} else if (m_updateUserData.contains(reply)) {
m_updateUserData.removeAll(reply);
// check HTTP status code
if (status != 200) {
qCWarning(dcAwattar) << "Update user data reply HTTP error:" << status << reply->errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
@ -205,14 +162,15 @@ void DevicePluginAwattar::networkManagerReplyReady(QNetworkReply *reply)
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcAwattar) << "Update user data reply JSON error:" << error.errorString();
setOnlineStatus(false);
reply->deleteLater();
return;
}
setOnlineStatus(true);
processUserData(jsonDoc.toVariant().toMap());
} else if (m_searchPumpReplies.contains(reply)) {
m_searchPumpReplies.removeAll(reply);
// check HTTP status code
@ -230,7 +188,7 @@ void DevicePluginAwattar::networkManagerReplyReady(QNetworkReply *reply)
void DevicePluginAwattar::guhTimer()
{
if (!m_device)
if (m_device.isNull())
return;
updateData();
@ -239,7 +197,7 @@ void DevicePluginAwattar::guhTimer()
DeviceManager::DeviceError DevicePluginAwattar::executeAction(Device *device, const Action &action)
{
if (!m_device || m_device != device)
if (m_device.isNull() || m_device != device)
return DeviceManager::DeviceErrorHardwareNotAvailable;
if (action.actionTypeId() == sgSyncModeActionTypeId) {
@ -276,9 +234,50 @@ DeviceManager::DeviceError DevicePluginAwattar::executeAction(Device *device, co
return DeviceManager::DeviceErrorActionTypeNotFound;
}
QNetworkReply *DevicePluginAwattar::requestPriceData(const QString &token)
{
QByteArray data = QString(token + ":").toUtf8().toBase64();
QString header = "Basic " + data;
QNetworkRequest request(QUrl("https://api.awattar.com/v1/marketdata"));
request.setRawHeader("Authorization", header.toLocal8Bit());
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
return networkManagerGet(request);
}
QNetworkReply *DevicePluginAwattar::requestUserData(const QString &token, const QString &userId)
{
QByteArray data = QString(token + ":").toUtf8().toBase64();
QString header = "Basic " + data;
QNetworkRequest request(QUrl(QString("https://api.awattar.com/v1/devices/%1/actuators").arg(userId)));
request.setRawHeader("Authorization", header.toLocal8Bit());
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
return networkManagerGet(request);
}
void DevicePluginAwattar::updateData()
{
m_updatePrice.append(requestPriceData(m_token));
}
void DevicePluginAwattar::searchHeatPumps()
{
QHostAddress rplAddress = QHostAddress(configuration().paramValue("RPL address").toString());
if (rplAddress.isNull()) {
qCWarning(dcAwattar) << "Invalid RPL address" << configuration().paramValue("RPL address").toString();
return;
}
QNetworkRequest request(QUrl(QString("http://[%1]").arg(rplAddress.toString())));
QNetworkReply *reply = networkManagerGet(request);
m_searchPumpReplies.append(reply);
}
void DevicePluginAwattar::processPriceData(const QVariantMap &data)
{
if (!m_device)
if (m_device.isNull())
return;
QVariantList dataElements = data.value("data").toList();
@ -343,7 +342,7 @@ void DevicePluginAwattar::processPriceData(const QVariantMap &data)
void DevicePluginAwattar::processUserData(const QVariantMap &data)
{
if (!m_device)
if (m_device.isNull())
return;
QVariantList dataElements = data.value("data").toList();
@ -384,66 +383,22 @@ void DevicePluginAwattar::processPumpSearchData(const QByteArray &data)
// remove the '/128' from the address
QHostAddress pumpAddress(QString(data.left(line.length() - 4)));
if (!pumpAddress.isNull()) {
if (pumpAddress.isNull())
continue;
// check if we already created this heat pump
if (heatPumpExists(pumpAddress))
continue;
qCDebug(dcAwattar) << "Found heat pump at" << pumpAddress.toString();
HeatPump *pump = new HeatPump(pumpAddress, this);
connect(pump, SIGNAL(reachableChanged()), this, SLOT(onHeatPumpReachableChanged()));
m_heatPumps.append(pump);
} else {
// check if we already created this heat pump
if (heatPumpExists(pumpAddress)) {
qCWarning(dcAwattar) << "Could not read pump address" << line;
continue;
}
qCDebug(dcAwattar) << "New heat pump found at" << pumpAddress.toString();
QPointer<HeatPump> pump = new HeatPump(pumpAddress, this);
connect(pump, &HeatPump::reachableChanged, this, &DevicePluginAwattar::onHeatPumpReachableChanged);
m_heatPumps.append(pump);
}
}
QNetworkReply *DevicePluginAwattar::requestPriceData(const QString &token)
{
QByteArray data = QString(token + ":").toUtf8().toBase64();
QString header = "Basic " + data;
QNetworkRequest request(QUrl("https://api.awattar.com/v1/marketdata"));
request.setRawHeader("Authorization", header.toLocal8Bit());
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
return networkManagerGet(request);
}
QNetworkReply *DevicePluginAwattar::requestUserData(const QString &token, const QString &userId)
{
QByteArray data = QString(token + ":").toUtf8().toBase64();
QString header = "Basic " + data;
QNetworkRequest request(QUrl(QString("https://api.awattar.com/v1/devices/%1/actuators").arg(userId)));
request.setRawHeader("Authorization", header.toLocal8Bit());
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
return networkManagerGet(request);
}
void DevicePluginAwattar::updateData()
{
m_updatePrice.append(requestPriceData(m_token));
}
void DevicePluginAwattar::searchHeatPumps()
{
QHostAddress rplAddress = QHostAddress(configuration().paramValue("RPL address").toString());
if (rplAddress.isNull()) {
qCWarning(dcAwattar) << "Invalid RPL address" << configuration().paramValue("RPL address").toString();
return;
}
QNetworkRequest request(QUrl(QString("http://[%1]").arg(rplAddress.toString())));
QNetworkReply *reply = networkManagerGet(request);
m_searchPumpReplies.append(reply);
}
void DevicePluginAwattar::setSgMode(const int &sgMode)
{
switch (sgMode) {
@ -465,15 +420,24 @@ void DevicePluginAwattar::setSgMode(const int &sgMode)
}
foreach (HeatPump *pump, m_heatPumps) {
if (pump->reachable()) {
pump->setSgMode(sgMode);
}
pump->setSgMode(sgMode);
}
}
void DevicePluginAwattar::setOnlineStatus(const bool &online)
{
if (m_device.isNull())
return;
m_device->setStateValue(onlineStateTypeId, online);
}
bool DevicePluginAwattar::heatPumpExists(const QHostAddress &pumpAddress)
{
foreach (HeatPump *pump, m_heatPumps) {
foreach (QPointer<HeatPump> pump, m_heatPumps) {
if (pump.isNull())
continue;
if (pump->address() == pumpAddress) {
return true;
}
@ -481,11 +445,6 @@ bool DevicePluginAwattar::heatPumpExists(const QHostAddress &pumpAddress)
return false;
}
void DevicePluginAwattar::connectionTest()
{
m_asyncSetup.append(requestUserData(m_token, m_userUuid));
}
void DevicePluginAwattar::onHeatPumpReachableChanged()
{
HeatPump *pump = static_cast<HeatPump *>(sender());
@ -501,7 +460,7 @@ void DevicePluginAwattar::onHeatPumpReachableChanged()
}
}
foreach (Device *device, myDevices()) {
device->setStateValue(reachableStateTypeId, reachable);
}
if (m_device)
m_device->setStateValue(reachableStateTypeId, reachable);
}

View File

@ -27,6 +27,7 @@
#include <QHash>
#include <QDebug>
#include <QTimer>
#include <QPointer>
class DevicePluginAwattar : public DevicePlugin
{
@ -39,33 +40,27 @@ public:
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void postSetupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void networkManagerReplyReady(QNetworkReply *reply) override;
void guhTimer() override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private:
Device *m_device;
QList<HeatPump *> m_heatPumps;
QPointer<Device> m_device;
QList<QPointer<HeatPump> > m_heatPumps;
QList<QNetworkReply *> m_asyncSetup;
QList<QNetworkReply *> m_searchPumpReplies;
QList<QNetworkReply *> m_updatePrice;
QList<QNetworkReply *> m_updateUserData;
QList<QPointer<QNetworkReply> > m_searchPumpReplies;
QList<QPointer<QNetworkReply> > m_updatePrice;
QList<QPointer<QNetworkReply> > m_updateUserData;
QString m_token;
QString m_userUuid;
int m_setupRetry;
int m_autoSgMode;
int m_manualSgMode;
void processPriceData(const QVariantMap &data);
void processUserData(const QVariantMap &data);
void processPumpSearchData(const QByteArray &data);
QNetworkReply *requestPriceData(const QString& token);
QNetworkReply *requestUserData(const QString& token, const QString &userId);
@ -73,12 +68,15 @@ private:
void updateData();
void searchHeatPumps();
void setSgMode(const int &sgMode);
void processPriceData(const QVariantMap &data);
void processUserData(const QVariantMap &data);
void processPumpSearchData(const QByteArray &data);
void setSgMode(const int &sgMode);
void setOnlineStatus(const bool &online);
bool heatPumpExists(const QHostAddress &pumpAddress);
private slots:
void connectionTest();
void onHeatPumpReachableChanged();
};

View File

@ -88,6 +88,13 @@
"unit": "EuroCentPerKiloWattHour",
"defaultValue": 0
},
{
"id": "470b9b88-17f3-42e3-9250-cc181984eafe",
"idName": "online",
"name": "online",
"type": "bool",
"defaultValue": false
},
{
"id": "1c9d139a-6618-4a39-bc83-37f80942017d",
"idName": "reachable",

View File

@ -30,7 +30,6 @@ HeatPump::HeatPump(QHostAddress address, QObject *parent) :
m_sgMode(0)
{
m_coap = new Coap(this);
connect(m_coap, SIGNAL(replyFinished(CoapReply*)), this, SLOT(onReplyFinished(CoapReply*)));
QUrl url;
@ -63,6 +62,7 @@ void HeatPump::setSgMode(const int &sgMode)
if (m_sgMode != sgMode) {
m_sgMode = sgMode;
qCDebug(dcAwattar) << "Setting sg-mode to" << sgMode;
// Note: always try to set sg-mode, to make sure the pump is still reachable (like a ping)
}
QUrl url;
@ -75,6 +75,7 @@ void HeatPump::setSgMode(const int &sgMode)
CoapReply *reply = m_coap->post(CoapRequest(url), payload);
if (reply->error() != CoapReply::NoError) {
qCWarning(dcAwattar()) << "Could not set sg mode" << reply->errorString();
setReachable(false);
reply->deleteLater();
return;
}
@ -82,33 +83,12 @@ void HeatPump::setSgMode(const int &sgMode)
m_sgModeReplies.append(reply);
}
void HeatPump::setLed(const bool &power)
{
QUrl url;
url.setScheme("coap");
url.setHost(m_address.toString());
url.setPath("/a/led");
QByteArray data;
if (power) {
data = QString("mode=1").toUtf8();
} else {
data = QString("mode=0").toUtf8();
}
CoapReply *reply = m_coap->post(CoapRequest(url), data);
if (reply->error() != CoapReply::NoError) {
qCWarning(dcAwattar()) << "Could not set led" << reply->errorString();
reply->deleteLater();
return;
}
m_ledReplies.append(reply);
}
void HeatPump::setReachable(const bool &reachable)
{
m_reachable = reachable;
emit reachableChanged();
if (m_reachable != reachable) {
m_reachable = reachable;
emit reachableChanged();
}
}
void HeatPump::onReplyFinished(CoapReply *reply)
@ -125,6 +105,7 @@ void HeatPump::onReplyFinished(CoapReply *reply)
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcAwattar()) << "Resource discovery status code:" << reply;
setReachable(false);
reply->deleteLater();
return;
}
@ -149,6 +130,7 @@ void HeatPump::onReplyFinished(CoapReply *reply)
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcAwattar()) << "Set sg-mode status code error:" << reply;
setReachable(false);
reply->deleteLater();
return;
}
@ -156,42 +138,6 @@ void HeatPump::onReplyFinished(CoapReply *reply)
if (!reachable())
qCDebug(dcAwattar) << "Set sg-mode successfully.";
} else if (m_ledReplies.contains(reply)) {
m_ledReplies.removeAll(reply);
if (reply->error() != CoapReply::NoError) {
if (reachable())
qCWarning(dcAwattar()) << "CoAP set led power reply error" << reply->errorString();
setReachable(false);
reply->deleteLater();
return;
}
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcAwattar()) << "Set LED status code error:" << reply;
reply->deleteLater();
return;
}
qCDebug(dcAwattar) << "Set led power successfully.";
} else {
// unhandled reply
if (reply->error() != CoapReply::NoError) {
qCWarning(dcAwattar()) << "CoAP reply error" << reply->errorString();
setReachable(false);
reply->deleteLater();
return;
}
if (reply->statusCode() != CoapPdu::Content) {
qCWarning(dcAwattar()) << "Unknown reply" << reply;
reply->deleteLater();
return;
}
qCDebug(dcAwattar) << reply;
}
// the reply had no error until now, so make sure the resource is reachable

View File

@ -39,8 +39,6 @@ public:
bool reachable() const;
void setSgMode(const int &sgMode);
void setLed(const bool &power);
private:
QHostAddress m_address;
bool m_reachable;
@ -50,7 +48,6 @@ private:
QList<CoapReply *> m_discoverReplies;
QList<CoapReply *> m_sgModeReplies;
QList<CoapReply *> m_ledReplies;
void setReachable(const bool &reachable);