diff --git a/libguh/hardware/gpio.cpp b/libguh/hardware/gpio.cpp
index 6ce72cbd..8951ed1c 100644
--- a/libguh/hardware/gpio.cpp
+++ b/libguh/hardware/gpio.cpp
@@ -42,7 +42,6 @@
Gpio::Gpio(QObject *parent, int gpio) :
QObject(parent),m_gpio(gpio)
{
- exportGpio();
}
/*! Destroys the Gpio object and unexports the GPIO. */
diff --git a/libguh/hardware/radio433receiver.cpp b/libguh/hardware/radio433receiver.cpp
index 67d2c107..0f27fcff 100644
--- a/libguh/hardware/radio433receiver.cpp
+++ b/libguh/hardware/radio433receiver.cpp
@@ -36,6 +36,17 @@ Radio433Receiver::~Radio433Receiver()
{
}
+bool Radio433Receiver::setUpGpio()
+{
+ if(!m_gpio->exportGpio()){
+ return false;
+ }else{
+ m_gpio->setDirection(INPUT);
+ m_gpio->setEdgeInterrupt(EDGE_BOTH);
+ }
+ return true;
+}
+
bool Radio433Receiver::startReceiver()
{
if(setUpGpio()){
@@ -99,17 +110,6 @@ void Radio433Receiver::run()
}
}
-bool Radio433Receiver::setUpGpio()
-{
- if(!m_gpio->openGpio()){
- return false;
- }else{
- m_gpio->setDirection(INPUT);
- m_gpio->setEdgeInterrupt(EDGE_BOTH);
- }
- return true;
-}
-
int Radio433Receiver::micros()
{
struct timeval tv ;
diff --git a/libguh/hardware/radio433receiver.h b/libguh/hardware/radio433receiver.h
index 78c4c308..525448f5 100644
--- a/libguh/hardware/radio433receiver.h
+++ b/libguh/hardware/radio433receiver.h
@@ -36,6 +36,7 @@ public:
ProtocolNone
};
+ bool setUpGpio();
bool startReceiver();
bool stopReceiver();
@@ -54,7 +55,6 @@ private:
bool m_reading;
void run();
- bool setUpGpio();
int micros();
bool valueInTolerance(int value, int sollValue);
bool checkValue(int value);
diff --git a/libguh/hardware/radio433transmitter.cpp b/libguh/hardware/radio433transmitter.cpp
index f08e24f4..ce44b9ae 100644
--- a/libguh/hardware/radio433transmitter.cpp
+++ b/libguh/hardware/radio433transmitter.cpp
@@ -50,7 +50,7 @@ bool Radio433Trasmitter::stopTransmitter()
bool Radio433Trasmitter::setUpGpio()
{
- if(!m_gpio->openGpio()){
+ if(!m_gpio->exportGpio()){
return false;
}else{
m_gpio->setDirection(OUTPUT);
diff --git a/plugins/deviceplugins/deviceplugins.pro b/plugins/deviceplugins/deviceplugins.pro
index 71c9d2ba..58efbd9a 100644
--- a/plugins/deviceplugins/deviceplugins.pro
+++ b/plugins/deviceplugins/deviceplugins.pro
@@ -10,6 +10,7 @@ SUBDIRS += elro \
wakeonlan \
mailnotification \
philipshue \
+ eq-3 \
boblight {
SUBDIRS += boblight
diff --git a/plugins/deviceplugins/eq-3/deviceplugineq-3.cpp b/plugins/deviceplugins/eq-3/deviceplugineq-3.cpp
new file mode 100644
index 00000000..b705f0e1
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/deviceplugineq-3.cpp
@@ -0,0 +1,184 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * 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 "deviceplugineq-3.h"
+
+#include "plugin/device.h"
+#include "devicemanager.h"
+#include "types/param.h"
+
+#include
+
+VendorId maxVendorId = VendorId("2cac0645-855e-44fa-837e-1cab0ae4304c");
+
+PluginId eq3PluginUuid = PluginId("f324c43c-9680-48d8-852a-93b2227139b9");
+
+DeviceClassId cubeDeviceClassId = DeviceClassId("1e892268-8bd7-442c-a001-bd4e2e6b2949");
+StateTypeId dateTimeStateTypeId = StateTypeId("78aed123-ca8e-4e11-a823-52043c4a4370");
+
+DevicePluginEQ3::DevicePluginEQ3()
+{
+ m_cubeDiscovery = new MaxCubeDiscovery(this);
+ connect(m_cubeDiscovery,SIGNAL(cubesDetected(QList)),this,SLOT(discoveryDone(QList)));
+}
+
+QList DevicePluginEQ3::supportedVendors() const
+{
+ QList ret;
+ Vendor max(maxVendorId, "Max!");
+ ret.append(max);
+ return ret;
+}
+
+QList DevicePluginEQ3::supportedDevices() const
+{
+ QList ret;
+
+ // Cube
+ DeviceClass cubeDeviceClass(pluginId(),maxVendorId,cubeDeviceClassId);
+ cubeDeviceClass.setName("Max! Cube LAN Gateway");
+ cubeDeviceClass.setCreateMethod(DeviceClass::CreateMethodDiscovery);
+ cubeDeviceClass.setSetupMethod(DeviceClass::SetupMethodJustAdd);
+
+ // Params
+ QList params;
+ ParamType hostParam("host address", QVariant::String);
+ params.append(hostParam);
+
+ ParamType portParam("port", QVariant::Int);
+ params.append(portParam);
+
+ ParamType serialNumberParam("serial number", QVariant::String);
+ params.append(serialNumberParam);
+
+ ParamType firmwareParam("firmware version", QVariant::Int);
+ params.append(firmwareParam);
+
+ cubeDeviceClass.setParamTypes(params);
+
+ // States
+ QList states;
+ StateType dateTimeState(dateTimeStateTypeId);
+ dateTimeState.setName("cube time [unixtime]");
+ dateTimeState.setType(QVariant::UInt);
+ dateTimeState.setDefaultValue(0);
+ states.append(dateTimeState);
+
+ cubeDeviceClass.setStateTypes(states);
+
+ ret.append(cubeDeviceClass);
+
+ return ret;
+}
+
+DeviceManager::HardwareResources DevicePluginEQ3::requiredHardware() const
+{
+ return DeviceManager::HardwareResourceTimer;
+}
+
+QString DevicePluginEQ3::pluginName() const
+{
+ return "eQ-3";
+}
+
+PluginId DevicePluginEQ3::pluginId() const
+{
+ return eq3PluginUuid;
+}
+
+QList DevicePluginEQ3::configurationDescription() const
+{
+ QList params;
+ return params;
+}
+
+DeviceManager::DeviceError DevicePluginEQ3::discoverDevices(const DeviceClassId &deviceClassId, const QList ¶ms) const
+{
+ if(deviceClassId == cubeDeviceClassId){
+ m_cubeDiscovery->detectCubes();
+ return DeviceManager::DeviceErrorAsync;
+ }
+ return DeviceManager::DeviceErrorDeviceClassNotFound;
+}
+
+QPair DevicePluginEQ3::setupDevice(Device *device)
+{
+ qDebug() << "setupDevice" << device->params();
+
+ foreach (MaxCube *cube, m_cubes.keys()) {
+ if(cube->serialNumber() == device->paramValue("serial number").toString()){
+ qDebug() << cube->serialNumber() << " allready exists...";
+ return reportDeviceSetup(DeviceManager::DeviceSetupStatusFailure,QString("Cube allready in added"));
+ }
+ }
+
+ MaxCube *cube = new MaxCube(this,device->paramValue("serial number").toString(),QHostAddress(device->paramValue("host address").toString()),device->paramValue("port").toInt());
+ connect(cube,SIGNAL(cubeConnectionStatusChanged(bool)),this,SLOT(cubeConnectionStatusChanged(bool)));
+
+ m_cubes.insert(cube,device);
+
+ cube->connectToCube();
+
+ return reportDeviceSetup(DeviceManager::DeviceSetupStatusAsync);
+}
+
+void DevicePluginEQ3::guhTimer()
+{
+ foreach (MaxCube *cube, m_cubes.keys()) {
+ cube->refresh();
+ }
+}
+
+QPair DevicePluginEQ3::executeAction(Device *device, const Action &action)
+{
+
+}
+
+void DevicePluginEQ3::cubeConnectionStatusChanged(const bool &connected)
+{
+ if(connected){
+ MaxCube *cube = static_cast(sender());
+ Device *device;
+ if (m_cubes.contains(cube)) {
+ device = m_cubes.take(cube);
+ device->setName("Max! Cube " + cube->serialNumber());
+ emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess, QString());
+ }
+ }
+}
+
+void DevicePluginEQ3::discoveryDone(const QList &cubeList)
+{
+ QList retList;
+ foreach (MaxCube *cube, cubeList) {
+ DeviceDescriptor descriptor(cubeDeviceClassId, "Max! Cube LAN Gateway",cube->serialNumber());
+ QList params;
+ Param hostParam("host address", cube->hostAddress().toString());
+ params.append(hostParam);
+ Param portParam("port", cube->port());
+ params.append(portParam);
+ Param firmwareParam("firmware version", QString::number(cube->firmware()));
+ params.append(firmwareParam);
+ Param serialNumberParam("serial number", cube->serialNumber());
+ params.append(serialNumberParam);
+
+ descriptor.setParams(params);
+ retList.append(descriptor);
+ }
+ emit devicesDiscovered(cubeDeviceClassId,retList);
+}
diff --git a/plugins/deviceplugins/eq-3/deviceplugineq-3.h b/plugins/deviceplugins/eq-3/deviceplugineq-3.h
new file mode 100644
index 00000000..6d771758
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/deviceplugineq-3.h
@@ -0,0 +1,69 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * 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 DEVICEPLUGINEQ3_H
+#define DEVICEPLUGINEQ3_H
+
+#include "plugin/deviceplugin.h"
+#include "maxcubediscovery.h"
+
+#include
+
+class QNetworkReply;
+
+class DevicePluginEQ3: public DevicePlugin
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "deviceplugineq-3.json")
+ Q_INTERFACES(DevicePlugin)
+
+public:
+ explicit DevicePluginEQ3();
+
+ QList supportedVendors() const override;
+ QList supportedDevices() const override;
+ DeviceManager::HardwareResources requiredHardware() const override;
+
+ QString pluginName() const override;
+ PluginId pluginId() const override;
+
+ QList configurationDescription() const override;
+ DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const QList ¶ms) const override;
+
+ QPair setupDevice(Device *device) override;
+
+ void guhTimer() override;
+
+private:
+ QList m_config;
+ MaxCubeDiscovery *m_cubeDiscovery;
+ QHash m_cubes;
+
+
+public slots:
+ QPair executeAction(Device *device, const Action &action);
+ void cubeConnectionStatusChanged(const bool &connected);
+
+private slots:
+ void discoveryDone(const QList &cubeList);
+
+
+};
+
+#endif // DEVICEPLUGINEQ3_H
diff --git a/plugins/deviceplugins/eq-3/deviceplugineq-3.json b/plugins/deviceplugins/eq-3/deviceplugineq-3.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/deviceplugineq-3.json
@@ -0,0 +1 @@
+{}
diff --git a/plugins/deviceplugins/eq-3/eq-3.pro b/plugins/deviceplugins/eq-3/eq-3.pro
new file mode 100644
index 00000000..8d0f868d
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/eq-3.pro
@@ -0,0 +1,20 @@
+include(../../plugins.pri)
+
+TARGET = $$qtLibraryTarget(guh_deviceplugineq3)
+
+QT += network
+
+SOURCES += \
+ deviceplugineq-3.cpp \
+ maxcubediscovery.cpp \
+ maxcube.cpp \
+ maxdevice.cpp \
+ room.cpp \
+
+HEADERS += \
+ deviceplugineq-3.h \
+ maxcubediscovery.h \
+ maxcube.h \
+ maxdevice.h \
+ room.h \
+
diff --git a/plugins/deviceplugins/eq-3/maxcube.cpp b/plugins/deviceplugins/eq-3/maxcube.cpp
new file mode 100644
index 00000000..2a5ec565
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/maxcube.cpp
@@ -0,0 +1,467 @@
+#include "maxcube.h"
+
+MaxCube::MaxCube(QObject *parent, QString serialNumber, QHostAddress hostAdress, quint16 port):
+ QTcpSocket(parent), m_serialNumber(serialNumber), m_hostAddress(hostAdress), m_port(port)
+{
+ connect(this,SIGNAL(connected()),this,SLOT(connected()));
+ connect(this,SIGNAL(disconnected()),this,SLOT(disconnected()));
+ connect(this,SIGNAL(readyRead()),this,SLOT(readData()));
+ connect(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError)));
+
+ connect(this,SIGNAL(cubeDataAvailable(QByteArray)),this,SLOT(processCubeData(QByteArray)));
+}
+
+QString MaxCube::serialNumber()
+{
+ return m_serialNumber;
+}
+
+void MaxCube::setSerialNumber(QString serialNumber)
+{
+ m_serialNumber = serialNumber;
+}
+
+QByteArray MaxCube::rfAddress()
+{
+ return m_rfAddress;
+}
+
+void MaxCube::setRfAddress(QByteArray rfAddress)
+{
+ m_rfAddress = rfAddress;
+}
+
+int MaxCube::firmware()
+{
+ return m_firmware;
+}
+
+void MaxCube::setFirmware(int firmware)
+{
+ m_firmware = firmware;
+}
+
+QHostAddress MaxCube::hostAddress()
+{
+ return m_hostAddress;
+}
+
+void MaxCube::setHostAddress(QHostAddress hostAddress)
+{
+ m_hostAddress = hostAddress;
+}
+
+quint16 MaxCube::port()
+{
+ return m_port;
+}
+
+void MaxCube::setPort(quint16 port)
+{
+ m_port = port;
+}
+
+QByteArray MaxCube::httpConnectionId()
+{
+ return m_httpConnectionId;
+}
+
+void MaxCube::setHttpConnectionId(QByteArray httpConnectionId)
+{
+ m_httpConnectionId = httpConnectionId;
+}
+
+int MaxCube::freeMemorySlots()
+{
+ return m_freeMemorySlots;
+}
+
+void MaxCube::setFreeMemorySlots(int freeMemorySlots)
+{
+ m_freeMemorySlots = freeMemorySlots;
+}
+
+QList MaxCube::deviceList()
+{
+ return m_deviceList;
+}
+
+QList MaxCube::roomList()
+{
+ return m_roomList;
+}
+
+void MaxCube::connectToCube()
+{
+ connectToHost(m_hostAddress,m_port);
+}
+
+void MaxCube::disconnectFromCube()
+{
+ disconnectFromHost();
+}
+
+bool MaxCube::sendData(QByteArray data)
+{
+ if(write(data) < 0){
+ return false;
+ }
+ return true;
+}
+
+void MaxCube::parseHelloMessage(QByteArray data)
+{
+
+ QList list = data.split(',');
+ m_cubeDateTime = calculateDateTime(list.at(7),list.at(8));
+ qDebug() << "====================================================";
+ qDebug() << "HELLO message:";
+ qDebug() << "====================================================";
+ qDebug() << " serial number | " << list.at(0);
+ qDebug() << " RF address (hex) | " << list.at(1);
+ qDebug() << " firmware | " << QString::number(list.at(2).toInt());
+ qDebug() << " ? | " << list.at(3);
+ qDebug() << " HTTP connection id | " << list.at(4);
+ qDebug() << " duty cycle (hex) | " << list.at(5);
+ qDebug() << " free memory slots (hex) | " << list.at(6);
+ qDebug() << " Cube date | " << m_cubeDateTime.date().toString("dd.MM.yyyy");
+ qDebug() << " Cube time | " << m_cubeDateTime.time().toString("HH:mm");
+ qDebug() << " State Cube Time | " << list.at(9);
+ qDebug() << " NTP counter | " << list.at(10);
+}
+
+void MaxCube::parseMetadataMessage(QByteArray data)
+{
+ QList list = data.left(data.length()-2).split(',');
+ QByteArray dataDecoded = QByteArray::fromBase64(list.at(2));
+ qDebug() << "====================================================";
+ qDebug() << "METADATA message:";
+ qDebug() << "====================================================";
+ // qDebug() << " Index | " << list.at(0);
+ // qDebug() << " Count | " << list.at(1);
+ // qDebug() << " Data Base64 encoded | " << list.at(2);
+ // qDebug() << " Data Base64 decoded | " << dataDecoded;
+ // qDebug() << " Data Base64 decoded hex | " << dataDecoded.toHex();
+
+
+ // parse room list
+ int roomCount = dataDecoded.toHex().mid(4,2).toInt(0,16);
+
+ QByteArray roomRawData = dataDecoded.toHex();
+ roomRawData = roomRawData.right(roomRawData.length()-6);
+
+ for(int i = 0; i < roomCount; i++){
+ Room *room = new Room(this);
+ room->setRoomId(roomRawData.left(2).toInt(0,16));
+ int roomNameLength = roomRawData.mid(2,2).toInt(0,16);
+ room->setRoomName(QByteArray::fromHex(roomRawData.mid(4,roomNameLength*2)));
+ room->setGroupRfAddress(roomRawData.mid(roomNameLength*2 + 4, 6));
+ m_roomList.append(room);
+ roomRawData = roomRawData.right(roomRawData.length() - ((roomNameLength*2) + 10));
+ }
+ qDebug() << "-------------------------|-------------------------";
+ qDebug() << "found " << m_roomList.count() << "rooms";
+ qDebug() << "-------------------------|-------------------------";
+
+ foreach (Room *room, m_roomList) {
+ qDebug() << " Room Name | " << room->roomName();
+ qDebug() << " Room ID | " << room->roomId();
+ qDebug() << " Group RF Address | " << room->groupRfAddress();
+ qDebug() << "-------------------------|-------------------------";
+ }
+
+ // parse device list
+ int deviceCount = roomRawData.left(2).toInt(0,16);
+ QByteArray deviceRawData = roomRawData.right(roomRawData.length() - 2);
+
+ for(int i = 0; i < deviceCount; i++){
+ MaxDevice* device = new MaxDevice(this);
+ device->setDeviceType(deviceRawData.left(2).toInt(0,16));
+ device->setRfAddress(deviceRawData.mid(2,6));
+ device->setSerialNumber(QByteArray::fromHex(deviceRawData.mid(8,20)));
+ int deviceNameLenght = deviceRawData.mid(28,2).toInt(0,16);
+ device->setDeviceName(QByteArray::fromHex(deviceRawData.mid(30,deviceNameLenght*2)));
+ device->setRoomId(deviceRawData.mid(30 + deviceNameLenght*2,2).toInt(0,16));
+ deviceRawData = deviceRawData.right(deviceRawData.length() - (30 + deviceNameLenght*2));
+ //qDebug() << "rawdata left :" << deviceRawData;
+ m_deviceList.append(device);
+ }
+
+ qDebug() << "-------------------------|-------------------------";
+ qDebug() << "found " << m_deviceList.count() << "devices";
+ qDebug() << "-------------------------|-------------------------";
+
+ foreach (MaxDevice *device, m_deviceList) {
+ qDebug() << " Device Name | " << device->deviceName();
+ qDebug() << " Serial Number| " << device->serialNumber();
+ qDebug() << " Device Type String | " << device->deviceTypeString();
+ qDebug() << " RF address (hex) | " << device->rfAddress();
+ //qDebug() << " Device Type | " << device->deviceType();
+ qDebug() << " Room ID | " << device->roomId();
+ qDebug() << "-------------------------|-------------------------";
+ }
+}
+
+void MaxCube::parseConfigMessage(QByteArray data)
+{
+ QList list = data.split(',');
+ QByteArray rfAddress = list.at(0);
+ QByteArray dataRaw = QByteArray::fromBase64(list.at(1)).toHex();
+ //int lengthData = dataRaw.left(2).toInt(0,16);
+ //QByteArray rfAddress = dataRaw.mid(2,6);
+ int deviceType = dataRaw.mid(8,2).toInt(0,16);
+ int roomId = dataRaw.mid(10,2).toInt(0,16);
+ //QByteArray unknown = dataRaw.mid(12,6);
+
+ QByteArray serialNumber = QByteArray::fromHex(dataRaw.mid(16,20));
+ qDebug() << "====================================================";
+ qDebug() << "CONFIG message:";
+ qDebug() << "====================================================";
+ qDebug() << " device Type | " << deviceTypeString(deviceType);
+ qDebug() << " Serial Number | " << serialNumber;
+ qDebug() << " RF address (hex) | " << rfAddress;
+ qDebug() << " Room ID | " << roomId;
+ qDebug() << "-------------------------|-------------------------";
+
+ switch (deviceType) {
+ case MaxDevice::DeviceCube:{
+ qDebug() << QByteArray::fromHex(dataRaw.mid(dataRaw.length() - 32));
+ break;
+ }
+ case MaxDevice::DeviceEcoButton:
+ break;
+ case MaxDevice::DeviceWallThermostat:
+ break;
+ case MaxDevice::DeviceRadiatorThermostatPlus:
+ break;
+ case MaxDevice::DeviceRadiatorThermostat:{
+ double confortTemp = dataRaw.mid(36,2).toInt(0,16)/2;
+ double ecoTemp = dataRaw.mid(38,2).toInt(0,16)/2;
+ double maxSetPointTemp = dataRaw.mid(40,2).toInt(0,16)/2;
+ double minSetPointTemp = dataRaw.mid(42,2).toInt(0,16)/2;
+ double offsetTemp = (dataRaw.mid(44,2).toInt(0,16) / 2 ) - 3.5;
+ double windowOpenTemp = dataRaw.mid(46,2).toInt(0,16)/2;
+ int windowOpenDuration = dataRaw.mid(48,2).toInt(0,16);
+ // boost code
+ QByteArray boostDurationCode = QByteArray::number(dataRaw.mid(50,2).toInt(0,16),2);
+ qDebug() << boostDurationCode;
+ int boostDuration = boostDurationCode.left(3).toInt(0,2);
+ if(boostDuration = 7){
+ boostDuration = 30;
+ }else{
+ boostDuration *= 5;
+ }
+ int valveValue = boostDurationCode.right(5).toInt(0,2);
+ // day of week an time
+ QByteArray dowTime = QByteArray::number(dataRaw.mid(52,2).toInt(0,16),2);
+ double valveMaximumSettings = dataRaw.mid(54,2).toInt(0,16)*(double)100/255;
+ double valveOffset = dataRaw.mid(56,2).toInt(0,16)*(double)100/255;
+
+ qDebug() << " Serial Number | " << serialNumber;
+ qDebug() << " Confort Temp. | " << confortTemp;
+ qDebug() << " Eco Temp. | " << ecoTemp;
+ qDebug() << " Max. Set Point Temp. | " << maxSetPointTemp;
+ qDebug() << " Min. Set Point Temp. | " << minSetPointTemp;
+ qDebug() << " Temp. Offset | " << offsetTemp;
+ qDebug() << " Window Open Temp. | " << windowOpenTemp;
+ qDebug() << " Window Open Duration | " << windowOpenDuration;
+ qDebug() << " Boost Duration | " << boostDuration << "min";
+ qDebug() << " Valve value | " << valveValue << "%";
+ qDebug() << " Day of week and time | " << dowTime;
+ qDebug() << " Valve Maximum Settings | " << valveMaximumSettings << "%";
+ qDebug() << " Valve Offset | " << valveOffset << "%";
+ parseWeeklyProgram(dataRaw.right(dataRaw.length() - 58));
+
+ break;
+ }
+ default:
+ qWarning() << "unknown device type: " << deviceType;
+ break;
+ }
+}
+
+void MaxCube::parseDevicelistMessage(QByteArray data)
+{
+ QList list = data.split(',');
+ qDebug() << "====================================================";
+ qDebug() << "DEVICELIST message:";
+ qDebug() << "====================================================";
+ foreach (const QByteArray &code, list) {
+ QByteArray rawData = QByteArray::fromBase64(code).toHex();
+ qDebug() << " Code | " << rawData.toBase64();
+ qDebug() << " Code (Hex) | " << rawData;
+ qDebug() << " Length of data | " << rawData.left(2).toInt(0,16);
+ qDebug() << " RF address (hex) | " << rawData.mid(2,6);
+ qDebug() << " Initialization | " << QByteArray::number(rawData.mid(10,2).toInt(0,16),2);
+ qDebug() << " Battery, ... , | " << QByteArray::number(rawData.mid(12,2).toInt(0,16),2);
+ qDebug() << " Valve Position | " << QByteArray::number(rawData.mid(14,2).toInt(0,16),2) << "%";
+ qDebug() << " Temperatur Setpoint | " << (double)rawData.mid(16,2).toInt(0,16) / 2.0 << "%";
+ QDateTime dateTime = calculateDateTime(rawData.mid(18,4), rawData.mid(22,2));
+ qDebug() << " Cube date | " << dateTime.date().toString("dd.MM.yyyy");
+ qDebug() << " Cube time | " << dateTime.time().toString("HH:mm");
+ }
+}
+
+void MaxCube::parseWeeklyProgram(QByteArray data)
+{
+ for(int i=0; i<7; i++){
+ QByteArray dayData = data.left(52);
+ qDebug() << dayData;
+ data = data.right(data.length() - 52);
+ }
+ qDebug() << "data left" << data;
+}
+
+void MaxCube::parseNewDeviceFoundMessage(QByteArray data)
+{
+ if(data.isEmpty()){
+ return;
+ }
+
+ qDebug() << "====================================================";
+ qDebug() << "NEW DEVICE message:";
+ qDebug() << "====================================================";
+
+ qDebug() << " Serial Number | " << QByteArray::fromBase64(data);
+
+}
+
+QDateTime MaxCube::calculateDateTime(QByteArray dateRaw, QByteArray timeRaw)
+{
+ QDate date;
+ QTime time;
+ date.setDate(dateRaw.left(2).toInt(0,16) + 2000, dateRaw.mid(2,2).toInt(0,16), dateRaw.right(2).toInt(0,16));
+ time.setHMS(timeRaw.left(2).toInt(0,16), timeRaw.right(2).toInt(0,16), 0);
+
+ return QDateTime(date,time);
+}
+
+QString MaxCube::deviceTypeString(int deviceType)
+{
+ QString deviceTypeString;
+
+ switch (deviceType) {
+ case MaxDevice::DeviceCube:
+ deviceTypeString = "Cube";
+ break;
+ case MaxDevice::DeviceRadiatorThermostat:
+ deviceTypeString = "Radiator Thermostat";
+ break;
+ case MaxDevice::DeviceRadiatorThermostatPlus:
+ deviceTypeString = "Radiator Thermostat Plus";
+ break;
+ case MaxDevice::DeviceEcoButton:
+ deviceTypeString = "Eco Button";
+ break;
+ case MaxDevice::DeviceWindowContact:
+ deviceTypeString = "Window Contact";
+ break;
+ case MaxDevice::DeviceWallThermostat:
+ deviceTypeString = "Wall Thermostat";
+ break;
+ default:
+ deviceTypeString = "-";
+ break;
+ }
+
+ return deviceTypeString;
+}
+
+QByteArray MaxCube::fillBin(QByteArray data, int dataLength)
+{
+
+}
+
+void MaxCube::connected()
+{
+ qDebug() << "-> connected to cube " << m_serialNumber << m_hostAddress.toString();
+ emit cubeConnectionStatusChanged(true);
+}
+
+void MaxCube::disconnected()
+{
+ qDebug() << "-> disconnected from cube " << m_serialNumber << m_hostAddress.toString();
+ emit cubeConnectionStatusChanged(false);
+}
+
+void MaxCube::error(QAbstractSocket::SocketError error)
+{
+ qDebug() << "connection error (" << m_serialNumber << "): " << error;
+ emit cubeConnectionStatusChanged(false);
+}
+
+void MaxCube::readData()
+{
+ QByteArray message;
+ while(canReadLine()){
+ QByteArray dataLine = readLine();
+ message.append(dataLine);
+ }
+ emit cubeDataAvailable(message);
+}
+
+void MaxCube::processCubeData(const QByteArray &data)
+{
+ //qDebug() << "data" << data;
+ if(data.startsWith("H")){
+ parseHelloMessage(data.right(data.length() -2 ));
+ return;
+ }
+ // METADATA message
+ if(data.startsWith("M")){
+ parseMetadataMessage(data.right(data.length() -2 ));
+ return;
+ }
+ // CONFIG message
+ if(data.startsWith("C")){
+ parseConfigMessage(data.right(data.length() -2 ));
+ return;
+ }
+ // DEVICELIST message
+ if(data.startsWith("L")){
+ //customRequest("g:");
+ parseDevicelistMessage(data.right(data.length() -2 ));
+ return;
+ }
+ // NEWDEVICEFOUND message
+ if(data.startsWith("N")){
+ parseNewDeviceFoundMessage(data.right(data.length() -2));
+ return;
+ }
+ // ACK message
+ if(data.startsWith("A")){
+ qDebug() << "cube ACK!";
+ emit cubeACK();
+ return;
+ }
+ qDebug() << " -> unknown message!!!!!!! from cube:" << data;
+}
+
+void MaxCube::enablePairingMode()
+{
+ qDebug() << "-------> enable pairing mode! press the boost button for min. 3 seconds";
+ write("n:003c\r\n");
+}
+
+void MaxCube::disablePairingMode()
+{
+ qDebug() << " ----> disable pairing mode!";
+ write("x:\r\n");
+}
+
+void MaxCube::refresh()
+{
+ qDebug() << "refresh cube " << m_serialNumber;
+ if(isWritable()){
+ write("l:\r\n");
+ }else{
+ qDebug() << "ERROR: could not send to " << m_hostAddress.toString();
+ }
+}
+
+void MaxCube::customRequest(QByteArray data)
+{
+ qDebug() << " ----> custom request" << data;
+ write(data + "\r\n");
+}
+
diff --git a/plugins/deviceplugins/eq-3/maxcube.h b/plugins/deviceplugins/eq-3/maxcube.h
new file mode 100644
index 00000000..9d22228b
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/maxcube.h
@@ -0,0 +1,96 @@
+#ifndef MAXCUBE_H
+#define MAXCUBE_H
+
+#include
+#include
+#include
+#include
+
+#include "maxdevice.h"
+#include "room.h"
+
+class MaxCube : public QTcpSocket
+{
+ Q_OBJECT
+public:
+ MaxCube(QObject *parent = 0, QString serialNumber = QString(), QHostAddress hostAdress = QHostAddress(), quint16 port = 0);
+
+ // cube data access functions
+ QString serialNumber();
+ void setSerialNumber(QString serialNumber);
+
+ QByteArray rfAddress();
+ void setRfAddress(QByteArray rfAddress);
+
+ int firmware();
+ void setFirmware(int firmware);
+
+ QHostAddress hostAddress();
+ void setHostAddress(QHostAddress hostAddress);
+
+ quint16 port();
+ void setPort(quint16 port);
+
+ QByteArray httpConnectionId();
+ void setHttpConnectionId(QByteArray httpConnectionId);
+
+ int freeMemorySlots();
+ void setFreeMemorySlots(int freeMemorySlots);
+
+ QDateTime cubeDateTime();
+ void setCubeDateTime(QDateTime cubeDateTime);
+
+ QList deviceList();
+ QList roomList();
+
+ void connectToCube();
+ void disconnectFromCube();
+ bool sendData(QByteArray data);
+
+private:
+ // cube data
+ QString m_serialNumber;
+ QByteArray m_rfAddress;
+ int m_firmware;
+ QHostAddress m_hostAddress;
+ quint16 m_port;
+ QByteArray m_httpConnectionId;
+ int m_freeMemorySlots;
+ QDateTime m_cubeDateTime;
+
+ QList m_roomList;
+ QList m_deviceList;
+
+ void parseHelloMessage(QByteArray data);
+ void parseMetadataMessage(QByteArray data);
+ void parseConfigMessage(QByteArray data);
+ void parseDevicelistMessage(QByteArray data);
+ void parseWeeklyProgram(QByteArray data);
+ void parseNewDeviceFoundMessage(QByteArray data);
+
+ QDateTime calculateDateTime(QByteArray dateRaw, QByteArray timeRaw);
+ QString deviceTypeString(int deviceType);
+ QByteArray fillBin(QByteArray data, int dataLength);
+
+signals:
+ void cubeDataAvailable(const QByteArray &data);
+ void cubeACK();
+ void cubeConnectionStatusChanged(const bool &connected);
+
+private slots:
+ void connected();
+ void disconnected();
+ void error(QAbstractSocket::SocketError error);
+ void readData();
+ void processCubeData(const QByteArray &data);
+
+
+public slots:
+ void enablePairingMode();
+ void disablePairingMode();
+ void refresh();
+ void customRequest(QByteArray data);
+
+};
+
+#endif // MAXCUBE_H
diff --git a/plugins/deviceplugins/eq-3/maxcubediscovery.cpp b/plugins/deviceplugins/eq-3/maxcubediscovery.cpp
new file mode 100644
index 00000000..acc50c7f
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/maxcubediscovery.cpp
@@ -0,0 +1,74 @@
+#include "maxcubediscovery.h"
+
+MaxCubeDiscovery::MaxCubeDiscovery(QObject *parent) :
+ QObject(parent)
+{
+ // UDP broadcast for cube detection in the network
+ m_udpSocket = new QUdpSocket(this);
+ m_port = 23272;
+ m_udpSocket->bind(m_port,QUdpSocket::ShareAddress);
+
+ m_timeout = new QTimer(this);
+ m_timeout->setSingleShot(true);
+
+ connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(readData()));
+ connect(m_timeout,SIGNAL(timeout()),this,SLOT(discoverTimeout()));
+}
+
+void MaxCubeDiscovery::detectCubes()
+{
+ qDebug() << "====================================================";
+ qDebug() << " searching for cubes....";
+
+ m_cubeList.clear();
+
+ // broadcast the hello message, every cube should respond with a 26 byte message
+ m_udpSocket->writeDatagram("eQ3Max*.**********I", QHostAddress::Broadcast, m_port);
+
+ m_timeout->start(1500);
+}
+
+void MaxCubeDiscovery::readData()
+{
+ QByteArray data;
+ QHostAddress sender;
+ quint16 udpPort;
+
+ // read the answere from the
+ while (m_udpSocket->hasPendingDatagrams()) {
+ data.resize(m_udpSocket->pendingDatagramSize());
+ m_udpSocket->readDatagram(data.data(), data.size(), &sender, &udpPort);
+ }
+ if(!data.isEmpty() && data.contains("eQ3MaxAp")){
+
+ QString serialNumber = data.mid(8,10);
+ QByteArray rfAddress = data.mid(21,3).toHex();
+ int firmware = data.mid(24,2).toHex().toInt();
+ qint16 port;
+ // set port depending on the firmware
+ if(firmware < 109){
+ port= 80;
+ }else{
+ port = 62910;
+ }
+
+ MaxCube *cube = new MaxCube(this, serialNumber, sender, port);
+ cube->setRfAddress(rfAddress);
+ qDebug() << "====================================================";
+ qDebug() << " cube detected...";
+ qDebug() << "====================================================";
+ qDebug() << " serial number | " << cube->serialNumber();
+ qDebug() << " host address | " << cube->hostAddress().toString();
+ qDebug() << " port | " << QString::number(cube->port());
+ qDebug() << " rf address | " << cube->rfAddress();
+ qDebug() << " firmware | " << QString::number(cube->firmware());
+ qDebug() << "====================================================";
+
+ m_cubeList.append(cube);
+ }
+}
+
+void MaxCubeDiscovery::discoverTimeout()
+{
+ emit cubesDetected(m_cubeList);
+}
diff --git a/plugins/deviceplugins/eq-3/maxcubediscovery.h b/plugins/deviceplugins/eq-3/maxcubediscovery.h
new file mode 100644
index 00000000..03699084
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/maxcubediscovery.h
@@ -0,0 +1,38 @@
+#ifndef MAXCUBEDISCOVERY_H
+#define MAXCUBEDISCOVERY_H
+
+#include
+#include
+#include
+#include
+
+#include "maxcube.h"
+
+class MaxCubeDiscovery : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MaxCubeDiscovery(QObject *parent = 0);
+
+ void detectCubes();
+
+private:
+ QUdpSocket *m_udpSocket;
+ QTimer *m_timeout;
+
+ quint16 m_port;
+
+ QList m_cubeList;
+
+private slots:
+ void readData();
+ void discoverTimeout();
+
+signals:
+ void cubesDetected(const QList &cubeList);
+
+public slots:
+
+};
+
+#endif // MAXCUBEDISCOVERY_H
diff --git a/plugins/deviceplugins/eq-3/maxdevice.cpp b/plugins/deviceplugins/eq-3/maxdevice.cpp
new file mode 100644
index 00000000..c5c86b09
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/maxdevice.cpp
@@ -0,0 +1,96 @@
+#include "maxdevice.h"
+
+MaxDevice::MaxDevice(QObject *parent) :
+ QObject(parent)
+{
+}
+
+int MaxDevice::deviceType()
+{
+ return m_deviceType;
+}
+
+void MaxDevice::setDeviceType(int deviceType)
+{
+ m_deviceType = deviceType;
+
+ switch (m_deviceType) {
+ case DeviceCube:
+ m_deviceTypeString = "Cube";
+ break;
+ case DeviceRadiatorThermostat:
+ m_deviceTypeString = "Radiator Thermostat";
+ break;
+ case DeviceRadiatorThermostatPlus:
+ m_deviceTypeString = "Radiator Thermostat Plus";
+ break;
+ case DeviceEcoButton:
+ m_deviceTypeString = "Eco Button";
+ break;
+ case DeviceWindowContact:
+ m_deviceTypeString = "Window Contact";
+ break;
+ case DeviceWallThermostat:
+ m_deviceTypeString = "Wall Thermostat";
+ break;
+ default:
+ m_deviceTypeString = "-";
+ break;
+ }
+}
+
+QString MaxDevice::deviceTypeString()
+{
+ return m_deviceTypeString;
+}
+
+QByteArray MaxDevice::rfAddress()
+{
+ return m_rfAddress;
+}
+
+void MaxDevice::setRfAddress(QByteArray rfAddress)
+{
+ m_rfAddress = rfAddress;
+}
+
+QString MaxDevice::serialNumber()
+{
+ return m_serialNumber;
+}
+
+void MaxDevice::setSerialNumber(QString serialNumber)
+{
+ m_serialNumber = serialNumber;
+}
+
+QString MaxDevice::deviceName()
+{
+ return m_deviceName;
+}
+
+void MaxDevice::setDeviceName(QString deviceName)
+{
+ m_deviceName = deviceName;
+}
+
+int MaxDevice::roomId()
+{
+ return m_roomId;
+}
+
+void MaxDevice::setRoomId(int roomId)
+{
+ m_roomId = roomId;
+}
+
+Room *MaxDevice::room()
+{
+ return m_room;
+}
+
+void MaxDevice::setRoom(Room *room)
+{
+ m_room = room;
+}
+
diff --git a/plugins/deviceplugins/eq-3/maxdevice.h b/plugins/deviceplugins/eq-3/maxdevice.h
new file mode 100644
index 00000000..2efd4442
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/maxdevice.h
@@ -0,0 +1,58 @@
+#ifndef MAXDEVICE_H
+#define MAXDEVICE_H
+
+#include
+
+#include "room.h"
+
+class MaxDevice : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MaxDevice(QObject *parent = 0);
+
+ enum MaxDeviceType{
+ DeviceCube = 0,
+ DeviceRadiatorThermostat = 1,
+ DeviceRadiatorThermostatPlus = 2,
+ DeviceWallThermostat = 3,
+ DeviceWindowContact = 4,
+ DeviceEcoButton = 5
+ };
+
+ int deviceType();
+ void setDeviceType(int deviceType);
+
+ QString deviceTypeString();
+
+ QByteArray rfAddress();
+ void setRfAddress(QByteArray rfAddress);
+
+ QString serialNumber();
+ void setSerialNumber(QString serialNumber);
+
+ QString deviceName();
+ void setDeviceName(QString deviceName);
+
+ int roomId();
+ void setRoomId(int roomId);
+
+ Room *room();
+ void setRoom(Room *room);
+private:
+ int m_deviceType;
+ QString m_deviceTypeString;
+ QByteArray m_rfAddress;
+ QString m_serialNumber;
+ QString m_deviceName;
+ int m_roomId;
+ Room *m_room;
+ bool m_batteryOk;
+
+signals:
+
+public slots:
+
+};
+
+#endif // MAXDEVICE_H
diff --git a/plugins/deviceplugins/eq-3/room.cpp b/plugins/deviceplugins/eq-3/room.cpp
new file mode 100644
index 00000000..dc94cfb6
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/room.cpp
@@ -0,0 +1,36 @@
+#include "room.h"
+
+Room::Room(QObject *parent) :
+ QObject(parent)
+{
+}
+
+int Room::roomId()
+{
+ return m_roomId;
+}
+
+void Room::setRoomId(int roomId)
+{
+ m_roomId = roomId;
+}
+
+QString Room::roomName()
+{
+ return m_roomName;
+}
+
+void Room::setRoomName(QString roomName)
+{
+ m_roomName = roomName;
+}
+
+QByteArray Room::groupRfAddress()
+{
+ return m_groupRfAddress;
+}
+
+void Room::setGroupRfAddress(QByteArray groupRfAddress)
+{
+ m_groupRfAddress = groupRfAddress;
+}
diff --git a/plugins/deviceplugins/eq-3/room.h b/plugins/deviceplugins/eq-3/room.h
new file mode 100644
index 00000000..750c6405
--- /dev/null
+++ b/plugins/deviceplugins/eq-3/room.h
@@ -0,0 +1,34 @@
+#ifndef ROOM_H
+#define ROOM_H
+
+#include
+
+class Room : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Room(QObject *parent = 0);
+
+ int roomId();
+ void setRoomId(int roomId);
+
+ QString roomName();
+ void setRoomName(QString roomName);
+
+ QByteArray groupRfAddress();
+ void setGroupRfAddress(QByteArray groupRfAddress);
+
+private:
+ int m_roomId;
+ QString m_roomName;
+ QByteArray m_groupRfAddress;
+
+signals:
+
+
+
+public slots:
+
+};
+
+#endif // ROOM_H
diff --git a/server/main.cpp b/server/main.cpp
index 38cd4b99..590c021b 100644
--- a/server/main.cpp
+++ b/server/main.cpp
@@ -32,6 +32,7 @@ Q_IMPORT_PLUGIN(DevicePluginLircd)
Q_IMPORT_PLUGIN(DevicePluginWakeOnLan)
Q_IMPORT_PLUGIN(DevicePluginMailNotification)
Q_IMPORT_PLUGIN(DevicePluginPhilipsHue)
+Q_IMPORT_PLUGIN(DevicePluginEQ3)
#if USE_BOBLIGHT
Q_IMPORT_PLUGIN(DevicePluginBoblight)
diff --git a/server/server.pro b/server/server.pro
index f17a03d0..1b7d4e4e 100644
--- a/server/server.pro
+++ b/server/server.pro
@@ -30,6 +30,7 @@ LIBS += -L../plugins/deviceplugins/lircd -lguh_devicepluginlircd
LIBS += -L../plugins/deviceplugins/mailnotification -lguh_devicepluginmailnotification
LIBS += -L../plugins/deviceplugins/wakeonlan -lguh_devicepluginwakeonlan
LIBS += -L../plugins/deviceplugins/philipshue -lguh_devicepluginphilipshue
+LIBS += -L../plugins/deviceplugins/eq-3 -lguh_deviceplugineq3
boblight {
xcompile {