From e194b3af8390e8d83872fd5c8fbb2eafd3191b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 14 Oct 2015 22:56:57 +0200 Subject: [PATCH] add netatmo outdoor module --- libguh/devicemanager.cpp | 7 +- libguh/plugin/deviceplugin.h | 3 +- .../netatmo/devicepluginnetatmo.cpp | 127 +++++++++++++++--- .../netatmo/devicepluginnetatmo.h | 16 ++- .../netatmo/devicepluginnetatmo.json | 101 +++++++++++++- plugins/deviceplugins/netatmo/netatmo.pro | 6 +- .../netatmo/netatmobasestation.cpp | 32 ++++- .../netatmo/netatmobasestation.h | 1 + .../netatmo/netatmooutdoormodule.cpp | 125 +++++++++++++++++ .../netatmo/netatmooutdoormodule.h | 68 ++++++++++ 10 files changed, 453 insertions(+), 33 deletions(-) create mode 100644 plugins/deviceplugins/netatmo/netatmooutdoormodule.cpp create mode 100644 plugins/deviceplugins/netatmo/netatmooutdoormodule.h diff --git a/libguh/devicemanager.cpp b/libguh/devicemanager.cpp index 1b9ea48a..add42aba 100644 --- a/libguh/devicemanager.cpp +++ b/libguh/devicemanager.cpp @@ -806,7 +806,10 @@ void DeviceManager::loadPlugins() } QPluginLoader loader(fi.absoluteFilePath()); - DevicePlugin *pluginIface = qobject_cast(loader.instance()); + DevicePlugin *pluginIface = qobject_cast(loader.instance()); + if (!pluginIface) + qCWarning(dcDeviceManager) << "Could not load plugin interface of" << entry; + if (verifyPluginMetadata(loader.metaData().value("MetaData").toObject()) && pluginIface) { pluginIface->initPlugin(loader.metaData().value("MetaData").toObject(), this); qCDebug(dcDeviceManager) << "*** Loaded plugin" << pluginIface->pluginName(); @@ -1218,7 +1221,7 @@ bool DeviceManager::verifyPluginMetadata(const QJsonObject &data) requiredFields << "name" << "id" << "vendors"; foreach (const QString &field, requiredFields) { - if (!data.contains("name")) { + if (!data.contains(field)) { qCWarning(dcDeviceManager) << "Error loading plugin. Incomplete metadata. Missing field:" << field; qCWarning(dcDeviceManager) << data; return false; diff --git a/libguh/plugin/deviceplugin.h b/libguh/plugin/deviceplugin.h index 624d0e30..bbc3062e 100644 --- a/libguh/plugin/deviceplugin.h +++ b/libguh/plugin/deviceplugin.h @@ -137,6 +137,7 @@ private: friend class DeviceManager; }; + Q_DECLARE_INTERFACE(DevicePlugin, "guru.guh.DevicePlugin") -#endif +#endif // DEVICEPLUGIN_H diff --git a/plugins/deviceplugins/netatmo/devicepluginnetatmo.cpp b/plugins/deviceplugins/netatmo/devicepluginnetatmo.cpp index a4ff7ddc..bdf6ad1a 100644 --- a/plugins/deviceplugins/netatmo/devicepluginnetatmo.cpp +++ b/plugins/deviceplugins/netatmo/devicepluginnetatmo.cpp @@ -47,6 +47,7 @@ #include "plugin/device.h" #include "plugininfo.h" +#include #include #include @@ -83,19 +84,31 @@ DeviceManager::DeviceSetupStatus DevicePluginNetatmo::setupDevice(Device *device device->paramValue("mac address").toString(), device->paramValue("connection id").toString(), this); - connect(indoor, &NetatmoBaseStation::statesChanged, this, &DevicePluginNetatmo::onIndoorStatesChanged); + m_indoorDevices.insert(indoor, device); + connect(indoor, SIGNAL(statesChanged()), this, SLOT(onIndoorStatesChanged())); + + return DeviceManager::DeviceSetupStatusSuccess; + } else if (device->deviceClassId() == outdoorDeviceClassId) { + qCDebug(dcNetatmo) << "Setup netatmo outdoor module" << device->params(); + NetatmoOutdoorModule *outdoor = new NetatmoOutdoorModule(device->paramValue("name").toString(), + device->paramValue("mac address").toString(), + device->paramValue("connection id").toString(), this); + + m_outdoorDevices.insert(outdoor, device); + connect(outdoor, SIGNAL(statesChanged()), this, SLOT(onOutdoorStatesChanged())); return DeviceManager::DeviceSetupStatusSuccess; } - return DeviceManager::DeviceSetupStatusFailure; } void DevicePluginNetatmo::deviceRemoved(Device *device) { - OAuth2 * authentication = m_authentications.key(device); - m_authentications.remove(authentication); - authentication->deleteLater(); + if (device->deviceClassId() == connectionDeviceClassId) { + OAuth2 * authentication = m_authentications.key(device); + m_authentications.remove(authentication); + authentication->deleteLater(); + } } void DevicePluginNetatmo::networkManagerReplyReady(QNetworkReply *reply) @@ -137,11 +150,21 @@ void DevicePluginNetatmo::guhTimer() if (device->deviceClassId() == connectionDeviceClassId) { OAuth2 *authentication = m_authentications.key(device); // TODO: check if authenticated - refreshData(device, authentication->token()); + if (authentication->authenticated()) { + refreshData(device, authentication->token()); + } } } } +DeviceManager::DeviceError DevicePluginNetatmo::executeAction(Device *device, const Action &action) +{ + Q_UNUSED(device) + Q_UNUSED(action) + + return DeviceManager::DeviceErrorNoError; +} + void DevicePluginNetatmo::refreshData(Device *device, const QString &token) { QUrlQuery query; @@ -157,18 +180,18 @@ void DevicePluginNetatmo::refreshData(Device *device, const QString &token) void DevicePluginNetatmo::processRefreshData(const QVariantMap &data, const QString &connectionId) { if (data.contains("body")) { + + // check devices if (data.value("body").toMap().contains("devices")) { QVariantList deviceList = data.value("body").toMap().value("devices").toList(); - //QVariantList modulesList = data.value("body").toMap().value("modules").toList(); - // check devices foreach (QVariant deviceVariant, deviceList) { QVariantMap deviceMap = deviceVariant.toMap(); // we support currently only NAMain devices if (deviceMap.value("type").toString() == "NAMain") { - NetatmoBaseStation *indoor = findIndoorDevice(deviceMap.value("_id").toString()); + Device *indoorDevice = findIndoorDevice(deviceMap.value("_id").toString()); // check if we have to create the device (auto) - if (!indoor) { + if (!indoorDevice) { DeviceDescriptor descriptor(indoorDeviceClassId, "Indoor Station", deviceMap.value("station_name").toString()); ParamList params; params.append(Param("name", deviceMap.value("station_name").toString())); @@ -177,7 +200,36 @@ void DevicePluginNetatmo::processRefreshData(const QVariantMap &data, const QStr descriptor.setParams(params); emit autoDevicesAppeared(indoorDeviceClassId, QList() << descriptor); } else { - indoor->updateStates(deviceMap); + if (m_indoorDevices.values().contains(indoorDevice)) { + m_indoorDevices.key(indoorDevice)->updateStates(deviceMap); + } + } + } + } + } + + // check modules + if (data.value("body").toMap().contains("modules")) { + QVariantList modulesList = data.value("body").toMap().value("modules").toList(); + // check devices + foreach (QVariant moduleVariant, modulesList) { + QVariantMap moduleMap = moduleVariant.toMap(); + // we support currently only NAModule1 + if (moduleMap.value("type").toString() == "NAModule1") { + Device *outdoorDevice = findOutdoorDevice(moduleMap.value("_id").toString()); + // check if we have to create the device (auto) + if (!outdoorDevice) { + DeviceDescriptor descriptor(outdoorDeviceClassId, "Outdoor Module", moduleMap.value("module_name").toString()); + ParamList params; + params.append(Param("name", moduleMap.value("module_name").toString())); + params.append(Param("mac address", moduleMap.value("_id").toString())); + params.append(Param("connection id", connectionId)); + descriptor.setParams(params); + emit autoDevicesAppeared(outdoorDeviceClassId, QList() << descriptor); + } else { + if (m_outdoorDevices.values().contains(outdoorDevice)) { + m_outdoorDevices.key(outdoorDevice)->updateStates(moduleMap); + } } } } @@ -185,12 +237,25 @@ void DevicePluginNetatmo::processRefreshData(const QVariantMap &data, const QStr } } - -NetatmoBaseStation *DevicePluginNetatmo::findIndoorDevice(const QString &macAddress) +Device *DevicePluginNetatmo::findIndoorDevice(const QString &macAddress) { - foreach (NetatmoBaseStation *bs, m_indoorDevices.keys()) { - if (bs->macAddress() == macAddress) { - return bs; + foreach (Device *device, myDevices()) { + if (device->deviceClassId() == indoorDeviceClassId) { + if (device->paramValue("mac address").toString() == macAddress) { + return device; + } + } + } + return 0; +} + +Device *DevicePluginNetatmo::findOutdoorDevice(const QString &macAddress) +{ + foreach (Device *device, myDevices()) { + if (device->deviceClassId() == outdoorDeviceClassId) { + if (device->paramValue("mac address").toString() == macAddress) { + return device; + } } } return 0; @@ -215,4 +280,34 @@ void DevicePluginNetatmo::onAuthenticationChanged() } } +void DevicePluginNetatmo::onIndoorStatesChanged() +{ + NetatmoBaseStation *indoor = static_cast(sender()); + Device *device = m_indoorDevices.value(indoor); + + device->setStateValue(updateTimeStateTypeId, indoor->lastUpdate()); + device->setStateValue(temperatureStateTypeId, indoor->temperature()); + device->setStateValue(temperatureMinStateTypeId, indoor->minTemperature()); + device->setStateValue(temperatureMaxStateTypeId, indoor->maxTemperature()); + device->setStateValue(pressureStateTypeId, indoor->pressure()); + device->setStateValue(humidityStateTypeId, indoor->humidity()); + device->setStateValue(co2StateTypeId, indoor->co2()); + device->setStateValue(noiseStateTypeId, indoor->noise()); + device->setStateValue(wifiStrengthStateTypeId, indoor->wifiStrength()); +} + +void DevicePluginNetatmo::onOutdoorStatesChanged() +{ + NetatmoOutdoorModule *outdoor = static_cast(sender()); + Device *device = m_outdoorDevices.value(outdoor); + + device->setStateValue(updateTimeStateTypeId, outdoor->lastUpdate()); + device->setStateValue(temperatureStateTypeId, outdoor->temperature()); + device->setStateValue(temperatureMinStateTypeId, outdoor->minTemperature()); + device->setStateValue(temperatureMaxStateTypeId, outdoor->maxTemperature()); + device->setStateValue(humidityStateTypeId, outdoor->humidity()); + device->setStateValue(signalStrengthStateTypeId, outdoor->signalStrength()); + device->setStateValue(batteryStateTypeId, outdoor->battery()); +} + diff --git a/plugins/deviceplugins/netatmo/devicepluginnetatmo.h b/plugins/deviceplugins/netatmo/devicepluginnetatmo.h index 170969a0..f71c9e6c 100644 --- a/plugins/deviceplugins/netatmo/devicepluginnetatmo.h +++ b/plugins/deviceplugins/netatmo/devicepluginnetatmo.h @@ -21,13 +21,13 @@ #ifndef DEVICEPLUGINNETATMO_H #define DEVICEPLUGINNETATMO_H -#include -#include -#include - #include "plugin/deviceplugin.h" #include "network/oauth2.h" #include "netatmobasestation.h" +#include "netatmooutdoormodule.h" + +#include +#include class DevicePluginNetatmo : public DevicePlugin { @@ -45,22 +45,28 @@ public: void guhTimer() override; +public slots: + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; + private: QList m_asyncSetups; QHash m_authentications; QHash m_indoorDevices; + QHash m_outdoorDevices; QHash m_refreshRequest; void refreshData(Device *device, const QString &token); void processRefreshData(const QVariantMap &data, const QString &connectionId); - NetatmoBaseStation *findIndoorDevice(const QString &macAddress); + Device *findIndoorDevice(const QString &macAddress); + Device *findOutdoorDevice(const QString &macAddress); private slots: void onAuthenticationChanged(); void onIndoorStatesChanged(); + void onOutdoorStatesChanged(); }; diff --git a/plugins/deviceplugins/netatmo/devicepluginnetatmo.json b/plugins/deviceplugins/netatmo/devicepluginnetatmo.json index 6d7c15c3..7201aa4b 100644 --- a/plugins/deviceplugins/netatmo/devicepluginnetatmo.json +++ b/plugins/deviceplugins/netatmo/devicepluginnetatmo.json @@ -1,19 +1,24 @@ { "name": "Netatmo", "idName": "Netatmo", - "id": "3af70774-4b43-46fe-96a4-22108d4efb1b", + "id": "69d14951-0c02-4877-bcef-dffdf48b7ccb", "vendors": [ { "name": "Netatmo", "idName": "netatmo", - "id": "31828f6f-c63d-4d44-b2b1-d0f70b3ce933", + "id": "4b46b4ed-5ec9-4aa4-afc3-92d3f80e6351", "deviceClasses": [ { "deviceClassId": "728d5a67-27a3-400e-b83c-2765f5196f69", - "name": "Netatmo Connection", "idName": "connection", + "name": "Netatmo Connection", "createMethods": ["user"], "paramTypes": [ + { + "name": "name", + "type": "QString", + "inputType": "TextLine" + }, { "name": "username", "type": "QString", @@ -25,7 +30,7 @@ "inputType": "Password" } ], - "stateType": [ + "stateTypes": [ { "id": "2f79bc1d-27ed-480a-b583-728363c83ea6", "idName": "available", @@ -36,9 +41,9 @@ ] }, { - "deviceClassId": "d79d373c-c992-4d75-bd01-a0f8ab346ac5", - "name": "Indoor Station", + "deviceClassId": "1c809049-04f2-4710-99f5-6ed379a2934f", "idName": "indoor", + "name": "Indoor Station", "createMethods": ["auto"], "paramTypes": [ { @@ -134,6 +139,90 @@ "defaultValue": 0 } ] + }, + { + "deviceClassId": "6cc01d62-7317-4ec4-8ac4-a4cab762c179", + "idName": "outdoor", + "name": "Outdoor Station", + "createMethods": ["auto"], + "paramTypes": [ + { + "name": "name", + "type": "QString", + "inputType": "TextLine", + "readOnly": true + }, + { + "name": "mac address", + "type": "QString", + "inputType": "TextLine", + "readOnly": true + }, + { + "name": "basestation id", + "type": "QString", + "inputType": "TextLine", + "readOnly": true + } + ], + "stateTypes": [ + { + "id": "50da9f6b-c350-401c-a72e-2e4036f3975d", + "idName": "updateTime", + "name": "last update", + "unit": "UnixTime", + "type": "int", + "defaultValue": 0 + }, + { + "id": "3cb25538-e463-40ae-92f9-8f34f0c06b92", + "idName": "temperature", + "name": "temperature", + "unit": "DegreeCelsius", + "type": "double", + "defaultValue": 0 + }, + { + "id": "ae8bb713-8805-4efd-89a1-bca44a1f1690", + "idName": "temperatureMin", + "name": "temperature minimum", + "unit": "DegreeCelsius", + "type": "double", + "defaultValue": 0 + }, + { + "id": "dd30507e-037b-4c74-bcca-e04b94c7c5fe", + "idName": "temperatureMax", + "name": "temperature maximum", + "unit": "DegreeCelsius", + "type": "double", + "defaultValue": 0 + }, + { + "id": "e2db5f01-196a-48d1-8874-6b8cbfe0d8c9", + "idName": "humidity", + "name": "humidity", + "unit": "Percentage", + "type": "int", + "defaultValue": 0 + }, + { + "id": "0faa3d08-9004-46fb-a5aa-a59b75e454cc", + "idName": "signalStrength", + "name": "signal strength", + "unit": "Percentage", + "type": "int", + "defaultValue": 0 + }, + { + "id": "15d8fae1-ba47-42e1-994d-530e8017c965", + "idName": "battery", + "name": "battery", + "unit": "Percentage", + "type": "int", + "defaultValue": 0 + } + ] } ] } diff --git a/plugins/deviceplugins/netatmo/netatmo.pro b/plugins/deviceplugins/netatmo/netatmo.pro index 38fa38f4..14f07da6 100644 --- a/plugins/deviceplugins/netatmo/netatmo.pro +++ b/plugins/deviceplugins/netatmo/netatmo.pro @@ -4,10 +4,12 @@ TARGET = $$qtLibraryTarget(guh_devicepluginnetatmo) SOURCES += \ devicepluginnetatmo.cpp \ - netatmobasestation.cpp + netatmobasestation.cpp \ + netatmooutdoormodule.cpp HEADERS += \ devicepluginnetatmo.h \ - netatmobasestation.h + netatmobasestation.h \ + netatmooutdoormodule.h diff --git a/plugins/deviceplugins/netatmo/netatmobasestation.cpp b/plugins/deviceplugins/netatmo/netatmobasestation.cpp index a6dffc5d..12049518 100644 --- a/plugins/deviceplugins/netatmo/netatmobasestation.cpp +++ b/plugins/deviceplugins/netatmo/netatmobasestation.cpp @@ -20,6 +20,8 @@ #include "netatmobasestation.h" +#include + NetatmoBaseStation::NetatmoBaseStation(const QString &name, const QString &macAddress, const QString &connectionId, QObject *parent) : QObject(parent), m_name(name), @@ -90,5 +92,33 @@ int NetatmoBaseStation::wifiStrength() const void NetatmoBaseStation::updateStates(const QVariantMap &data) { - Q_UNUSED(data) + // check data timestamp + if (data.contains("last_status_store")) { + m_lastUpdate = data.value("last_status_store").toInt(); + } + + // update dashboard data + if (data.contains("dashboard_data")) { + QVariantMap measurments = data.value("dashboard_data").toMap(); + m_pressure = measurments.value("AbsolutePressure").toDouble(); + m_humidity = measurments.value("Humidity").toInt(); + m_noise = measurments.value("Noise").toInt(); + m_temperature = measurments.value("Temperature").toDouble(); + m_minTemperature = measurments.value("min_temp").toDouble(); + m_maxTemperature = measurments.value("max_temp").toDouble(); + m_co2 = measurments.value("CO2").toInt(); + } + // update wifi signal strength + if (data.contains("wifi_status")) { + int wifiStrength = data.value("wifi_status").toInt(); + if (wifiStrength <= 56) { + m_wifiStrength = 100; + } else if (wifiStrength >= 86) { + m_wifiStrength = 0; + } else { + int delta = 30 - (wifiStrength - 56); + m_wifiStrength = qRound(100.0 * delta / 30.0); + } + } + emit statesChanged(); } diff --git a/plugins/deviceplugins/netatmo/netatmobasestation.h b/plugins/deviceplugins/netatmo/netatmobasestation.h index 6be01157..fc3d8be7 100644 --- a/plugins/deviceplugins/netatmo/netatmobasestation.h +++ b/plugins/deviceplugins/netatmo/netatmobasestation.h @@ -67,6 +67,7 @@ private: signals: void statesChanged(); + }; #endif // NETATMOBASESTATION_H diff --git a/plugins/deviceplugins/netatmo/netatmooutdoormodule.cpp b/plugins/deviceplugins/netatmo/netatmooutdoormodule.cpp new file mode 100644 index 00000000..70fd7882 --- /dev/null +++ b/plugins/deviceplugins/netatmo/netatmooutdoormodule.cpp @@ -0,0 +1,125 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "netatmooutdoormodule.h" + +#include + +NetatmoOutdoorModule::NetatmoOutdoorModule(const QString &name, const QString &macAddress, const QString &connectionId, QObject *parent) : + QObject(parent), + m_name(name), + m_macAddress(macAddress), + m_connectionId(connectionId) +{ +} + +QString NetatmoOutdoorModule::name() const +{ + return m_name; +} + +QString NetatmoOutdoorModule::macAddress() const +{ + return m_macAddress; +} + +QString NetatmoOutdoorModule::connectionId() const +{ + return m_connectionId; +} + +int NetatmoOutdoorModule::lastUpdate() const +{ + return m_lastUpdate; +} + +int NetatmoOutdoorModule::humidity() const +{ + return m_humidity; +} + +double NetatmoOutdoorModule::temperature() const +{ + return m_temperature; +} + +double NetatmoOutdoorModule::minTemperature() const +{ + return m_minTemperature; +} + +double NetatmoOutdoorModule::maxTemperature() const +{ + return m_maxTemperature; +} + +int NetatmoOutdoorModule::signalStrength() const +{ + return m_signalStrength; +} + +int NetatmoOutdoorModule::battery() const +{ + return m_battery; +} + +void NetatmoOutdoorModule::updateStates(const QVariantMap &data) +{ + // check data timestamp + if (data.contains("last_message")) { + m_lastUpdate = data.value("last_message").toInt(); + } + + // update dashboard data + if (data.contains("dashboard_data")) { + QVariantMap measurments = data.value("dashboard_data").toMap(); + m_humidity = measurments.value("Humidity").toInt(); + m_temperature = measurments.value("Temperature").toDouble(); + m_minTemperature = measurments.value("min_temp").toDouble(); + m_maxTemperature = measurments.value("max_temp").toDouble(); + } + // update battery strength + if (data.contains("battery_vp")) { + int battery = data.value("battery_vp").toInt(); + if (battery >= 6000) { + m_battery = 100; + } else if (battery <= 3600) { + m_battery = 0; + } else { + int delta = battery - 3600; + m_battery = qRound(100.0 * delta / 2400); + } + } + + // update signal strength + if (data.contains("rf_status")) { + int signalStrength = data.value("rf_status").toInt(); + if (signalStrength <= 60) { + m_signalStrength = 100; + } else if (signalStrength >= 90) { + m_signalStrength = 0; + } else { + int delta = 30 - (signalStrength - 60); + m_signalStrength = qRound(100.0 * delta / 30.0); + } + } + emit statesChanged(); + +} diff --git a/plugins/deviceplugins/netatmo/netatmooutdoormodule.h b/plugins/deviceplugins/netatmo/netatmooutdoormodule.h new file mode 100644 index 00000000..18b3b981 --- /dev/null +++ b/plugins/deviceplugins/netatmo/netatmooutdoormodule.h @@ -0,0 +1,68 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef NETATMOOUTDOORMODULE_H +#define NETATMOOUTDOORMODULE_H + +#include + +class NetatmoOutdoorModule : public QObject +{ + Q_OBJECT +public: + explicit NetatmoOutdoorModule(const QString &name, const QString &macAddress, const QString &connectionId, QObject *parent = 0); + + // Params + QString name() const; + QString macAddress() const; + QString connectionId() const; + + // States + int lastUpdate() const; + int humidity() const; + double temperature() const; + double minTemperature() const; + double maxTemperature() const; + int signalStrength() const; + int battery() const; + + void updateStates(const QVariantMap &data); + +private: + // Params + QString m_name; + QString m_macAddress; + QString m_connectionId; + + // States + int m_lastUpdate; + int m_humidity; + double m_temperature; + double m_minTemperature; + double m_maxTemperature; + int m_signalStrength; + int m_battery; + +signals: + void statesChanged(); + +}; + +#endif // NETATMOOUTDOORMODULE_H