diff --git a/alphainnotec/README.md b/alphainnotec/README.md
new file mode 100644
index 0000000..ae540d4
--- /dev/null
+++ b/alphainnotec/README.md
@@ -0,0 +1,16 @@
+# alpha innotec
+
+Connect nymea to alpha innotec heat pumps.
+
+## Supported Things
+
+* alpha connect
+
+## Requirements
+
+* The package 'nymea-plugin-alphainnotec' must be installed
+* Both devices must be in the same local area network.
+
+## More
+
+https://www.alpha-innotec.de
diff --git a/alphainnotec/alpha-innotec.png b/alphainnotec/alpha-innotec.png
new file mode 100644
index 0000000..3fd2fcc
Binary files /dev/null and b/alphainnotec/alpha-innotec.png differ
diff --git a/alphainnotec/alphaconnectmodbustcpconnection.cpp b/alphainnotec/alphaconnectmodbustcpconnection.cpp
new file mode 100644
index 0000000..9f6dd9b
--- /dev/null
+++ b/alphainnotec/alphaconnectmodbustcpconnection.cpp
@@ -0,0 +1,1273 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2021, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This fileDescriptor 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 .
+*
+* 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 "alphaconnectmodbustcpconnection.h"
+#include "loggingcategories.h"
+
+NYMEA_LOGGING_CATEGORY(dcAlphaConnectModbusTcpConnection, "AlphaConnectModbusTcpConnection")
+
+AlphaConnectModbusTcpConnection::AlphaConnectModbusTcpConnection(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent) :
+ ModbusTCPMaster(hostAddress, port, parent),
+ m_slaveId(slaveId)
+{
+
+}
+
+float AlphaConnectModbusTcpConnection::flowTemperature() const
+{
+ return m_flowTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::returnTemperature() const
+{
+ return m_returnTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::externalReturnTemperature() const
+{
+ return m_externalReturnTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::hotWaterTemperature() const
+{
+ return m_hotWaterTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::hotGasTemperature() const
+{
+ return m_hotGasTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::heatSourceInletTemperature() const
+{
+ return m_heatSourceInletTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::heatSourceOutletTemperature() const
+{
+ return m_heatSourceOutletTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::roomTemperature1() const
+{
+ return m_roomTemperature1;
+}
+
+float AlphaConnectModbusTcpConnection::roomTemperature2() const
+{
+ return m_roomTemperature2;
+}
+
+float AlphaConnectModbusTcpConnection::roomTemperature3() const
+{
+ return m_roomTemperature3;
+}
+
+float AlphaConnectModbusTcpConnection::solarCollectorTemperature() const
+{
+ return m_solarCollectorTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::solarStorageTankTemperature() const
+{
+ return m_solarStorageTankTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::externalEnergySourceTemperature() const
+{
+ return m_externalEnergySourceTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::supplyAirTemperature() const
+{
+ return m_supplyAirTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::externalAirTemperature() const
+{
+ return m_externalAirTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::rbeRoomActualTemperature() const
+{
+ return m_rbeRoomActualTemperature;
+}
+
+float AlphaConnectModbusTcpConnection::rbeRoomSetpointTemperature() const
+{
+ return m_rbeRoomSetpointTemperature;
+}
+
+quint16 AlphaConnectModbusTcpConnection::heatingPumpOperatingHours() const
+{
+ return m_heatingPumpOperatingHours;
+}
+
+AlphaConnectModbusTcpConnection::SystemStatus AlphaConnectModbusTcpConnection::systemStatus() const
+{
+ return m_systemStatus;
+}
+
+float AlphaConnectModbusTcpConnection::heatingEnergy() const
+{
+ return m_heatingEnergy;
+}
+
+float AlphaConnectModbusTcpConnection::waterHeatEnergy() const
+{
+ return m_waterHeatEnergy;
+}
+
+float AlphaConnectModbusTcpConnection::totalHeatEnergy() const
+{
+ return m_totalHeatEnergy;
+}
+
+float AlphaConnectModbusTcpConnection::outdoorTemperature() const
+{
+ return m_outdoorTemperature;
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::setOutdoorTemperature(float outdoorTemperature)
+{
+ QVector values = ModbusDataUtils::convertFromUInt16(static_cast(outdoorTemperature * 1.0 / pow(10, -1)));
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Write \"Outdoor temperature\" register:" << 0 << "size:" << 1 << values;
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 0, values.count());
+ request.setValues(values);
+ return sendWriteRequest(request, m_slaveId);
+}
+
+float AlphaConnectModbusTcpConnection::returnSetpointTemperature() const
+{
+ return m_returnSetpointTemperature;
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::setReturnSetpointTemperature(float returnSetpointTemperature)
+{
+ QVector values = ModbusDataUtils::convertFromUInt16(static_cast(returnSetpointTemperature * 1.0 / pow(10, -1)));
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Write \"Return setpoint temperature\" register:" << 1 << "size:" << 1 << values;
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 1, values.count());
+ request.setValues(values);
+ return sendWriteRequest(request, m_slaveId);
+}
+
+float AlphaConnectModbusTcpConnection::hotWaterSetpointTemperature() const
+{
+ return m_hotWaterSetpointTemperature;
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::setHotWaterSetpointTemperature(float hotWaterSetpointTemperature)
+{
+ QVector values = ModbusDataUtils::convertFromUInt16(static_cast(hotWaterSetpointTemperature * 1.0 / pow(10, -1)));
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Write \"Hot water setpoint temperature\" register:" << 5 << "size:" << 1 << values;
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 5, values.count());
+ request.setValues(values);
+ return sendWriteRequest(request, m_slaveId);
+}
+
+AlphaConnectModbusTcpConnection::SmartGridState AlphaConnectModbusTcpConnection::smartGrid() const
+{
+ return m_smartGrid;
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::setSmartGrid(SmartGridState smartGrid)
+{
+ QVector values = ModbusDataUtils::convertFromUInt16(static_cast(smartGrid));
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Write \"Smart grid control\" register:" << 14 << "size:" << 1 << values;
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 14, values.count());
+ request.setValues(values);
+ return sendWriteRequest(request, m_slaveId);
+}
+
+void AlphaConnectModbusTcpConnection::initialize()
+{
+ // No init registers defined. Nothing to be done and we are finished.
+ emit initializationFinished();
+}
+
+void AlphaConnectModbusTcpConnection::update()
+{
+ updateFlowTemperature();
+ updateReturnTemperature();
+ updateExternalReturnTemperature();
+ updateHotWaterTemperature();
+ updateHotGasTemperature();
+ updateHeatSourceInletTemperature();
+ updateHeatSourceOutletTemperature();
+ updateRoomTemperature1();
+ updateRoomTemperature2();
+ updateRoomTemperature3();
+ updateSolarCollectorTemperature();
+ updateSolarStorageTankTemperature();
+ updateExternalEnergySourceTemperature();
+ updateSupplyAirTemperature();
+ updateExternalAirTemperature();
+ updateRbeRoomActualTemperature();
+ updateRbeRoomSetpointTemperature();
+ updateHeatingPumpOperatingHours();
+ updateSystemStatus();
+ updateHeatingEnergy();
+ updateWaterHeatEnergy();
+ updateTotalHeatEnergy();
+ updateOutdoorTemperature();
+ updateReturnSetpointTemperature();
+ updateHotWaterSetpointTemperature();
+ updateSmartGrid();
+}
+
+void AlphaConnectModbusTcpConnection::updateFlowTemperature()
+{
+ // Update registers from Flow
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Flow\" register:" << 1 << "size:" << 1;
+ QModbusReply *reply = readFlowTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Flow\" register" << 1 << "size:" << 1 << unit.values();
+ float receivedFlowTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_flowTemperature != receivedFlowTemperature) {
+ m_flowTemperature = receivedFlowTemperature;
+ emit flowTemperatureChanged(m_flowTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Flow\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Flow\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateReturnTemperature()
+{
+ // Update registers from Return
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Return\" register:" << 2 << "size:" << 1;
+ QModbusReply *reply = readReturnTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Return\" register" << 2 << "size:" << 1 << unit.values();
+ float receivedReturnTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_returnTemperature != receivedReturnTemperature) {
+ m_returnTemperature = receivedReturnTemperature;
+ emit returnTemperatureChanged(m_returnTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Return\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Return\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateExternalReturnTemperature()
+{
+ // Update registers from External return
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"External return\" register:" << 3 << "size:" << 1;
+ QModbusReply *reply = readExternalReturnTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"External return\" register" << 3 << "size:" << 1 << unit.values();
+ float receivedExternalReturnTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_externalReturnTemperature != receivedExternalReturnTemperature) {
+ m_externalReturnTemperature = receivedExternalReturnTemperature;
+ emit externalReturnTemperatureChanged(m_externalReturnTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"External return\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"External return\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateHotWaterTemperature()
+{
+ // Update registers from Hot water temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Hot water temperature\" register:" << 4 << "size:" << 1;
+ QModbusReply *reply = readHotWaterTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Hot water temperature\" register" << 4 << "size:" << 1 << unit.values();
+ float receivedHotWaterTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_hotWaterTemperature != receivedHotWaterTemperature) {
+ m_hotWaterTemperature = receivedHotWaterTemperature;
+ emit hotWaterTemperatureChanged(m_hotWaterTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Hot water temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Hot water temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateHotGasTemperature()
+{
+ // Update registers from Hot gas temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Hot gas temperature\" register:" << 8 << "size:" << 1;
+ QModbusReply *reply = readHotGasTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Hot gas temperature\" register" << 8 << "size:" << 1 << unit.values();
+ float receivedHotGasTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_hotGasTemperature != receivedHotGasTemperature) {
+ m_hotGasTemperature = receivedHotGasTemperature;
+ emit hotGasTemperatureChanged(m_hotGasTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Hot gas temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Hot gas temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateHeatSourceInletTemperature()
+{
+ // Update registers from Heat source inlet temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Heat source inlet temperature\" register:" << 9 << "size:" << 1;
+ QModbusReply *reply = readHeatSourceInletTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Heat source inlet temperature\" register" << 9 << "size:" << 1 << unit.values();
+ float receivedHeatSourceInletTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_heatSourceInletTemperature != receivedHeatSourceInletTemperature) {
+ m_heatSourceInletTemperature = receivedHeatSourceInletTemperature;
+ emit heatSourceInletTemperatureChanged(m_heatSourceInletTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Heat source inlet temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Heat source inlet temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateHeatSourceOutletTemperature()
+{
+ // Update registers from Heat source outlet temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Heat source outlet temperature\" register:" << 10 << "size:" << 1;
+ QModbusReply *reply = readHeatSourceOutletTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Heat source outlet temperature\" register" << 10 << "size:" << 1 << unit.values();
+ float receivedHeatSourceOutletTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_heatSourceOutletTemperature != receivedHeatSourceOutletTemperature) {
+ m_heatSourceOutletTemperature = receivedHeatSourceOutletTemperature;
+ emit heatSourceOutletTemperatureChanged(m_heatSourceOutletTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Heat source outlet temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Heat source outlet temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateRoomTemperature1()
+{
+ // Update registers from Room remote adjuster 1 temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Room remote adjuster 1 temperature\" register:" << 11 << "size:" << 1;
+ QModbusReply *reply = readRoomTemperature1();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Room remote adjuster 1 temperature\" register" << 11 << "size:" << 1 << unit.values();
+ float receivedRoomTemperature1 = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_roomTemperature1 != receivedRoomTemperature1) {
+ m_roomTemperature1 = receivedRoomTemperature1;
+ emit roomTemperature1Changed(m_roomTemperature1);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Room remote adjuster 1 temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Room remote adjuster 1 temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateRoomTemperature2()
+{
+ // Update registers from Room remote adjuster 2 temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Room remote adjuster 2 temperature\" register:" << 12 << "size:" << 1;
+ QModbusReply *reply = readRoomTemperature2();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Room remote adjuster 2 temperature\" register" << 12 << "size:" << 1 << unit.values();
+ float receivedRoomTemperature2 = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_roomTemperature2 != receivedRoomTemperature2) {
+ m_roomTemperature2 = receivedRoomTemperature2;
+ emit roomTemperature2Changed(m_roomTemperature2);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Room remote adjuster 2 temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Room remote adjuster 2 temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateRoomTemperature3()
+{
+ // Update registers from Room remote adjuster 3 temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Room remote adjuster 3 temperature\" register:" << 13 << "size:" << 1;
+ QModbusReply *reply = readRoomTemperature3();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Room remote adjuster 3 temperature\" register" << 13 << "size:" << 1 << unit.values();
+ float receivedRoomTemperature3 = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_roomTemperature3 != receivedRoomTemperature3) {
+ m_roomTemperature3 = receivedRoomTemperature3;
+ emit roomTemperature3Changed(m_roomTemperature3);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Room remote adjuster 3 temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Room remote adjuster 3 temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateSolarCollectorTemperature()
+{
+ // Update registers from Solar collector temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Solar collector temperature\" register:" << 14 << "size:" << 1;
+ QModbusReply *reply = readSolarCollectorTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Solar collector temperature\" register" << 14 << "size:" << 1 << unit.values();
+ float receivedSolarCollectorTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_solarCollectorTemperature != receivedSolarCollectorTemperature) {
+ m_solarCollectorTemperature = receivedSolarCollectorTemperature;
+ emit solarCollectorTemperatureChanged(m_solarCollectorTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Solar collector temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Solar collector temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateSolarStorageTankTemperature()
+{
+ // Update registers from Solar storage tank temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Solar storage tank temperature\" register:" << 15 << "size:" << 1;
+ QModbusReply *reply = readSolarStorageTankTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Solar storage tank temperature\" register" << 15 << "size:" << 1 << unit.values();
+ float receivedSolarStorageTankTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_solarStorageTankTemperature != receivedSolarStorageTankTemperature) {
+ m_solarStorageTankTemperature = receivedSolarStorageTankTemperature;
+ emit solarStorageTankTemperatureChanged(m_solarStorageTankTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Solar storage tank temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Solar storage tank temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateExternalEnergySourceTemperature()
+{
+ // Update registers from External energy source temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"External energy source temperature\" register:" << 16 << "size:" << 1;
+ QModbusReply *reply = readExternalEnergySourceTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"External energy source temperature\" register" << 16 << "size:" << 1 << unit.values();
+ float receivedExternalEnergySourceTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_externalEnergySourceTemperature != receivedExternalEnergySourceTemperature) {
+ m_externalEnergySourceTemperature = receivedExternalEnergySourceTemperature;
+ emit externalEnergySourceTemperatureChanged(m_externalEnergySourceTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"External energy source temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"External energy source temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateSupplyAirTemperature()
+{
+ // Update registers from Supply air temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Supply air temperature\" register:" << 17 << "size:" << 1;
+ QModbusReply *reply = readSupplyAirTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Supply air temperature\" register" << 17 << "size:" << 1 << unit.values();
+ float receivedSupplyAirTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_supplyAirTemperature != receivedSupplyAirTemperature) {
+ m_supplyAirTemperature = receivedSupplyAirTemperature;
+ emit supplyAirTemperatureChanged(m_supplyAirTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Supply air temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Supply air temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateExternalAirTemperature()
+{
+ // Update registers from External air temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"External air temperature\" register:" << 18 << "size:" << 1;
+ QModbusReply *reply = readExternalAirTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"External air temperature\" register" << 18 << "size:" << 1 << unit.values();
+ float receivedExternalAirTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_externalAirTemperature != receivedExternalAirTemperature) {
+ m_externalAirTemperature = receivedExternalAirTemperature;
+ emit externalAirTemperatureChanged(m_externalAirTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"External air temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"External air temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateRbeRoomActualTemperature()
+{
+ // Update registers from RBE actual room temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"RBE actual room temperature\" register:" << 24 << "size:" << 1;
+ QModbusReply *reply = readRbeRoomActualTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"RBE actual room temperature\" register" << 24 << "size:" << 1 << unit.values();
+ float receivedRbeRoomActualTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_rbeRoomActualTemperature != receivedRbeRoomActualTemperature) {
+ m_rbeRoomActualTemperature = receivedRbeRoomActualTemperature;
+ emit rbeRoomActualTemperatureChanged(m_rbeRoomActualTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"RBE actual room temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"RBE actual room temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateRbeRoomSetpointTemperature()
+{
+ // Update registers from RBE room temperature setpoint
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"RBE room temperature setpoint\" register:" << 24 << "size:" << 1;
+ QModbusReply *reply = readRbeRoomSetpointTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"RBE room temperature setpoint\" register" << 24 << "size:" << 1 << unit.values();
+ float receivedRbeRoomSetpointTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_rbeRoomSetpointTemperature != receivedRbeRoomSetpointTemperature) {
+ m_rbeRoomSetpointTemperature = receivedRbeRoomSetpointTemperature;
+ emit rbeRoomSetpointTemperatureChanged(m_rbeRoomSetpointTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"RBE room temperature setpoint\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"RBE room temperature setpoint\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateHeatingPumpOperatingHours()
+{
+ // Update registers from Heating pump operating hours
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Heating pump operating hours\" register:" << 33 << "size:" << 1;
+ QModbusReply *reply = readHeatingPumpOperatingHours();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Heating pump operating hours\" register" << 33 << "size:" << 1 << unit.values();
+ quint16 receivedHeatingPumpOperatingHours = ModbusDataUtils::convertToUInt16(unit.values());
+ if (m_heatingPumpOperatingHours != receivedHeatingPumpOperatingHours) {
+ m_heatingPumpOperatingHours = receivedHeatingPumpOperatingHours;
+ emit heatingPumpOperatingHoursChanged(m_heatingPumpOperatingHours);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Heating pump operating hours\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Heating pump operating hours\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateSystemStatus()
+{
+ // Update registers from System status
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"System status\" register:" << 37 << "size:" << 1;
+ QModbusReply *reply = readSystemStatus();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"System status\" register" << 37 << "size:" << 1 << unit.values();
+ SystemStatus receivedSystemStatus = static_cast(ModbusDataUtils::convertToUInt16(unit.values()));
+ if (m_systemStatus != receivedSystemStatus) {
+ m_systemStatus = receivedSystemStatus;
+ emit systemStatusChanged(m_systemStatus);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"System status\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"System status\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateHeatingEnergy()
+{
+ // Update registers from Heating energy
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Heating energy\" register:" << 38 << "size:" << 2;
+ QModbusReply *reply = readHeatingEnergy();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Heating energy\" register" << 38 << "size:" << 2 << unit.values();
+ float receivedHeatingEnergy = ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -1);
+ if (m_heatingEnergy != receivedHeatingEnergy) {
+ m_heatingEnergy = receivedHeatingEnergy;
+ emit heatingEnergyChanged(m_heatingEnergy);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Heating energy\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Heating energy\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateWaterHeatEnergy()
+{
+ // Update registers from Water heat energy
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Water heat energy\" register:" << 40 << "size:" << 2;
+ QModbusReply *reply = readWaterHeatEnergy();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Water heat energy\" register" << 40 << "size:" << 2 << unit.values();
+ float receivedWaterHeatEnergy = ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -1);
+ if (m_waterHeatEnergy != receivedWaterHeatEnergy) {
+ m_waterHeatEnergy = receivedWaterHeatEnergy;
+ emit waterHeatEnergyChanged(m_waterHeatEnergy);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Water heat energy\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Water heat energy\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateTotalHeatEnergy()
+{
+ // Update registers from Total energy
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Total energy\" register:" << 44 << "size:" << 2;
+ QModbusReply *reply = readTotalHeatEnergy();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Total energy\" register" << 44 << "size:" << 2 << unit.values();
+ float receivedTotalHeatEnergy = ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -1);
+ if (m_totalHeatEnergy != receivedTotalHeatEnergy) {
+ m_totalHeatEnergy = receivedTotalHeatEnergy;
+ emit totalHeatEnergyChanged(m_totalHeatEnergy);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Total energy\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Total energy\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateOutdoorTemperature()
+{
+ // Update registers from Outdoor temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Outdoor temperature\" register:" << 0 << "size:" << 1;
+ QModbusReply *reply = readOutdoorTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Outdoor temperature\" register" << 0 << "size:" << 1 << unit.values();
+ float receivedOutdoorTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_outdoorTemperature != receivedOutdoorTemperature) {
+ m_outdoorTemperature = receivedOutdoorTemperature;
+ emit outdoorTemperatureChanged(m_outdoorTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Outdoor temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Outdoor temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateReturnSetpointTemperature()
+{
+ // Update registers from Return setpoint temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Return setpoint temperature\" register:" << 1 << "size:" << 1;
+ QModbusReply *reply = readReturnSetpointTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Return setpoint temperature\" register" << 1 << "size:" << 1 << unit.values();
+ float receivedReturnSetpointTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_returnSetpointTemperature != receivedReturnSetpointTemperature) {
+ m_returnSetpointTemperature = receivedReturnSetpointTemperature;
+ emit returnSetpointTemperatureChanged(m_returnSetpointTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Return setpoint temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Return setpoint temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateHotWaterSetpointTemperature()
+{
+ // Update registers from Hot water setpoint temperature
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Hot water setpoint temperature\" register:" << 5 << "size:" << 1;
+ QModbusReply *reply = readHotWaterSetpointTemperature();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Hot water setpoint temperature\" register" << 5 << "size:" << 1 << unit.values();
+ float receivedHotWaterSetpointTemperature = ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, -1);
+ if (m_hotWaterSetpointTemperature != receivedHotWaterSetpointTemperature) {
+ m_hotWaterSetpointTemperature = receivedHotWaterSetpointTemperature;
+ emit hotWaterSetpointTemperatureChanged(m_hotWaterSetpointTemperature);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Hot water setpoint temperature\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Hot water setpoint temperature\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+void AlphaConnectModbusTcpConnection::updateSmartGrid()
+{
+ // Update registers from Smart grid control
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "--> Read \"Smart grid control\" register:" << 14 << "size:" << 1;
+ QModbusReply *reply = readSmartGrid();
+ if (reply) {
+ if (!reply->isFinished()) {
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, this, [this, reply](){
+ if (reply->error() == QModbusDevice::NoError) {
+ const QModbusDataUnit unit = reply->result();
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "<-- Response from \"Smart grid control\" register" << 14 << "size:" << 1 << unit.values();
+ SmartGridState receivedSmartGrid = static_cast(ModbusDataUtils::convertToUInt16(unit.values()));
+ if (m_smartGrid != receivedSmartGrid) {
+ m_smartGrid = receivedSmartGrid;
+ emit smartGridChanged(m_smartGrid);
+ }
+ }
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Modbus reply error occurred while updating \"Smart grid control\" registers from" << hostAddress().toString() << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else {
+ delete reply; // Broadcast reply returns immediatly
+ }
+ } else {
+ qCWarning(dcAlphaConnectModbusTcpConnection()) << "Error occurred while reading \"Smart grid control\" registers from" << hostAddress().toString() << errorString();
+ }
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readFlowTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 1, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readReturnTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 2, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readExternalReturnTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 3, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readHotWaterTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 4, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readHotGasTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 8, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readHeatSourceInletTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 9, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readHeatSourceOutletTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 10, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readRoomTemperature1()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 11, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readRoomTemperature2()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 12, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readRoomTemperature3()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 13, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readSolarCollectorTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 14, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readSolarStorageTankTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 15, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readExternalEnergySourceTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 16, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readSupplyAirTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 17, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readExternalAirTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 18, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readRbeRoomActualTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 24, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readRbeRoomSetpointTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 24, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readHeatingPumpOperatingHours()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 33, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readSystemStatus()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 37, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readHeatingEnergy()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 38, 2);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readWaterHeatEnergy()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 40, 2);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readTotalHeatEnergy()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, 44, 2);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readOutdoorTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 0, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readReturnSetpointTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 1, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readHotWaterSetpointTemperature()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 5, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+QModbusReply *AlphaConnectModbusTcpConnection::readSmartGrid()
+{
+ QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 14, 1);
+ return sendReadRequest(request, m_slaveId);
+}
+
+void AlphaConnectModbusTcpConnection::verifyInitFinished()
+{
+ if (m_pendingInitReplies.isEmpty()) {
+ qCDebug(dcAlphaConnectModbusTcpConnection()) << "Initialization finished of AlphaConnectModbusTcpConnection" << hostAddress().toString();
+ emit initializationFinished();
+ }
+}
+
+QDebug operator<<(QDebug debug, AlphaConnectModbusTcpConnection *alphaConnectModbusTcpConnection)
+{
+ debug.nospace().noquote() << "AlphaConnectModbusTcpConnection(" << alphaConnectModbusTcpConnection->hostAddress().toString() << ":" << alphaConnectModbusTcpConnection->port() << ")" << "\n";
+ debug.nospace().noquote() << " - Flow:" << alphaConnectModbusTcpConnection->flowTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Return:" << alphaConnectModbusTcpConnection->returnTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - External return:" << alphaConnectModbusTcpConnection->externalReturnTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Hot water temperature:" << alphaConnectModbusTcpConnection->hotWaterTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Hot gas temperature:" << alphaConnectModbusTcpConnection->hotGasTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Heat source inlet temperature:" << alphaConnectModbusTcpConnection->heatSourceInletTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Heat source outlet temperature:" << alphaConnectModbusTcpConnection->heatSourceOutletTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Room remote adjuster 1 temperature:" << alphaConnectModbusTcpConnection->roomTemperature1() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Room remote adjuster 2 temperature:" << alphaConnectModbusTcpConnection->roomTemperature2() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Room remote adjuster 3 temperature:" << alphaConnectModbusTcpConnection->roomTemperature3() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Solar collector temperature:" << alphaConnectModbusTcpConnection->solarCollectorTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Solar storage tank temperature:" << alphaConnectModbusTcpConnection->solarStorageTankTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - External energy source temperature:" << alphaConnectModbusTcpConnection->externalEnergySourceTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Supply air temperature:" << alphaConnectModbusTcpConnection->supplyAirTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - External air temperature:" << alphaConnectModbusTcpConnection->externalAirTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - RBE actual room temperature:" << alphaConnectModbusTcpConnection->rbeRoomActualTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - RBE room temperature setpoint:" << alphaConnectModbusTcpConnection->rbeRoomSetpointTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Heating pump operating hours:" << alphaConnectModbusTcpConnection->heatingPumpOperatingHours() << " [h]" << "\n";
+ debug.nospace().noquote() << " - System status:" << alphaConnectModbusTcpConnection->systemStatus() << "\n";
+ debug.nospace().noquote() << " - Heating energy:" << alphaConnectModbusTcpConnection->heatingEnergy() << " [kWh]" << "\n";
+ debug.nospace().noquote() << " - Water heat energy:" << alphaConnectModbusTcpConnection->waterHeatEnergy() << " [kWh]" << "\n";
+ debug.nospace().noquote() << " - Total energy:" << alphaConnectModbusTcpConnection->totalHeatEnergy() << " [kWh]" << "\n";
+ debug.nospace().noquote() << " - Outdoor temperature:" << alphaConnectModbusTcpConnection->outdoorTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Return setpoint temperature:" << alphaConnectModbusTcpConnection->returnSetpointTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Hot water setpoint temperature:" << alphaConnectModbusTcpConnection->hotWaterSetpointTemperature() << " [°C]" << "\n";
+ debug.nospace().noquote() << " - Smart grid control:" << alphaConnectModbusTcpConnection->smartGrid() << "\n";
+ return debug.quote().space();
+}
+
diff --git a/alphainnotec/alphaconnectmodbustcpconnection.h b/alphainnotec/alphaconnectmodbustcpconnection.h
new file mode 100644
index 0000000..4b27fd1
--- /dev/null
+++ b/alphainnotec/alphaconnectmodbustcpconnection.h
@@ -0,0 +1,273 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2021, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This fileDescriptor 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 .
+*
+* 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 ALPHACONNECTMODBUSTCPCONNECTION_H
+#define ALPHACONNECTMODBUSTCPCONNECTION_H
+
+#include
+
+#include "../modbus/modbusdatautils.h"
+#include "../modbus/modbustcpmaster.h"
+
+class AlphaConnectModbusTcpConnection : public ModbusTCPMaster
+{
+ Q_OBJECT
+public:
+ enum SystemStatus {
+ SystemStatusHeatingMode = 0,
+ SystemStatusDomesticHotWater = 1,
+ SystemStatusSwimmingPool = 2,
+ SystemStatusEVUOff = 3,
+ SystemStatusDefrost = 4,
+ SystemStatusOff = 5,
+ SystemStatusExternalEnergySource = 6,
+ SystemStatusCoolingMode = 7
+ };
+ Q_ENUM(SystemStatus)
+
+ enum SmartGridState {
+ SmartGridStateOff = 0,
+ SmartGridStateLow = 1,
+ SmartGridStateStandard = 2,
+ SmartGridStateHigh = 3
+ };
+ Q_ENUM(SmartGridState)
+
+ explicit AlphaConnectModbusTcpConnection(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr);
+ ~AlphaConnectModbusTcpConnection() = default;
+
+ /* Flow [°C] - Address: 1, Size: 1 */
+ float flowTemperature() const;
+
+ /* Return [°C] - Address: 2, Size: 1 */
+ float returnTemperature() const;
+
+ /* External return [°C] - Address: 3, Size: 1 */
+ float externalReturnTemperature() const;
+
+ /* Hot water temperature [°C] - Address: 4, Size: 1 */
+ float hotWaterTemperature() const;
+
+ /* Hot gas temperature [°C] - Address: 8, Size: 1 */
+ float hotGasTemperature() const;
+
+ /* Heat source inlet temperature [°C] - Address: 9, Size: 1 */
+ float heatSourceInletTemperature() const;
+
+ /* Heat source outlet temperature [°C] - Address: 10, Size: 1 */
+ float heatSourceOutletTemperature() const;
+
+ /* Room remote adjuster 1 temperature [°C] - Address: 11, Size: 1 */
+ float roomTemperature1() const;
+
+ /* Room remote adjuster 2 temperature [°C] - Address: 12, Size: 1 */
+ float roomTemperature2() const;
+
+ /* Room remote adjuster 3 temperature [°C] - Address: 13, Size: 1 */
+ float roomTemperature3() const;
+
+ /* Solar collector temperature [°C] - Address: 14, Size: 1 */
+ float solarCollectorTemperature() const;
+
+ /* Solar storage tank temperature [°C] - Address: 15, Size: 1 */
+ float solarStorageTankTemperature() const;
+
+ /* External energy source temperature [°C] - Address: 16, Size: 1 */
+ float externalEnergySourceTemperature() const;
+
+ /* Supply air temperature [°C] - Address: 17, Size: 1 */
+ float supplyAirTemperature() const;
+
+ /* External air temperature [°C] - Address: 18, Size: 1 */
+ float externalAirTemperature() const;
+
+ /* RBE actual room temperature [°C] - Address: 24, Size: 1 */
+ float rbeRoomActualTemperature() const;
+
+ /* RBE room temperature setpoint [°C] - Address: 24, Size: 1 */
+ float rbeRoomSetpointTemperature() const;
+
+ /* Heating pump operating hours [h] - Address: 33, Size: 1 */
+ quint16 heatingPumpOperatingHours() const;
+
+ /* System status - Address: 37, Size: 1 */
+ SystemStatus systemStatus() const;
+
+ /* Heating energy [kWh] - Address: 38, Size: 2 */
+ float heatingEnergy() const;
+
+ /* Water heat energy [kWh] - Address: 40, Size: 2 */
+ float waterHeatEnergy() const;
+
+ /* Total energy [kWh] - Address: 44, Size: 2 */
+ float totalHeatEnergy() const;
+
+ /* Outdoor temperature [°C] - Address: 0, Size: 1 */
+ float outdoorTemperature() const;
+ QModbusReply *setOutdoorTemperature(float outdoorTemperature);
+
+ /* Return setpoint temperature [°C] - Address: 1, Size: 1 */
+ float returnSetpointTemperature() const;
+ QModbusReply *setReturnSetpointTemperature(float returnSetpointTemperature);
+
+ /* Hot water setpoint temperature [°C] - Address: 5, Size: 1 */
+ float hotWaterSetpointTemperature() const;
+ QModbusReply *setHotWaterSetpointTemperature(float hotWaterSetpointTemperature);
+
+ /* Smart grid control - Address: 14, Size: 1 */
+ SmartGridState smartGrid() const;
+ QModbusReply *setSmartGrid(SmartGridState smartGrid);
+
+ virtual void initialize();
+ virtual void update();
+
+ void updateFlowTemperature();
+ void updateReturnTemperature();
+ void updateExternalReturnTemperature();
+ void updateHotWaterTemperature();
+ void updateHotGasTemperature();
+ void updateHeatSourceInletTemperature();
+ void updateHeatSourceOutletTemperature();
+ void updateRoomTemperature1();
+ void updateRoomTemperature2();
+ void updateRoomTemperature3();
+ void updateSolarCollectorTemperature();
+ void updateSolarStorageTankTemperature();
+ void updateExternalEnergySourceTemperature();
+ void updateSupplyAirTemperature();
+ void updateExternalAirTemperature();
+ void updateRbeRoomActualTemperature();
+ void updateRbeRoomSetpointTemperature();
+ void updateHeatingPumpOperatingHours();
+ void updateSystemStatus();
+ void updateHeatingEnergy();
+ void updateWaterHeatEnergy();
+ void updateTotalHeatEnergy();
+ void updateOutdoorTemperature();
+ void updateReturnSetpointTemperature();
+ void updateHotWaterSetpointTemperature();
+ void updateSmartGrid();
+
+signals:
+ void initializationFinished();
+
+ void flowTemperatureChanged(float flowTemperature);
+ void returnTemperatureChanged(float returnTemperature);
+ void externalReturnTemperatureChanged(float externalReturnTemperature);
+ void hotWaterTemperatureChanged(float hotWaterTemperature);
+ void hotGasTemperatureChanged(float hotGasTemperature);
+ void heatSourceInletTemperatureChanged(float heatSourceInletTemperature);
+ void heatSourceOutletTemperatureChanged(float heatSourceOutletTemperature);
+ void roomTemperature1Changed(float roomTemperature1);
+ void roomTemperature2Changed(float roomTemperature2);
+ void roomTemperature3Changed(float roomTemperature3);
+ void solarCollectorTemperatureChanged(float solarCollectorTemperature);
+ void solarStorageTankTemperatureChanged(float solarStorageTankTemperature);
+ void externalEnergySourceTemperatureChanged(float externalEnergySourceTemperature);
+ void supplyAirTemperatureChanged(float supplyAirTemperature);
+ void externalAirTemperatureChanged(float externalAirTemperature);
+ void rbeRoomActualTemperatureChanged(float rbeRoomActualTemperature);
+ void rbeRoomSetpointTemperatureChanged(float rbeRoomSetpointTemperature);
+ void heatingPumpOperatingHoursChanged(quint16 heatingPumpOperatingHours);
+ void systemStatusChanged(SystemStatus systemStatus);
+ void heatingEnergyChanged(float heatingEnergy);
+ void waterHeatEnergyChanged(float waterHeatEnergy);
+ void totalHeatEnergyChanged(float totalHeatEnergy);
+ void outdoorTemperatureChanged(float outdoorTemperature);
+ void returnSetpointTemperatureChanged(float returnSetpointTemperature);
+ void hotWaterSetpointTemperatureChanged(float hotWaterSetpointTemperature);
+ void smartGridChanged(SmartGridState smartGrid);
+
+private:
+ quint16 m_slaveId = 1;
+ QVector m_pendingInitReplies;
+
+ float m_flowTemperature = 0;
+ float m_returnTemperature = 0;
+ float m_externalReturnTemperature = 0;
+ float m_hotWaterTemperature = 0;
+ float m_hotGasTemperature = 0;
+ float m_heatSourceInletTemperature = 0;
+ float m_heatSourceOutletTemperature = 0;
+ float m_roomTemperature1 = 0;
+ float m_roomTemperature2 = 0;
+ float m_roomTemperature3 = 0;
+ float m_solarCollectorTemperature = 0;
+ float m_solarStorageTankTemperature = 0;
+ float m_externalEnergySourceTemperature = 0;
+ float m_supplyAirTemperature = 0;
+ float m_externalAirTemperature = 0;
+ float m_rbeRoomActualTemperature = 0;
+ float m_rbeRoomSetpointTemperature = 0;
+ quint16 m_heatingPumpOperatingHours = 0;
+ SystemStatus m_systemStatus = SystemStatusHeatingMode;
+ float m_heatingEnergy = 0;
+ float m_waterHeatEnergy = 0;
+ float m_totalHeatEnergy = 0;
+ float m_outdoorTemperature = 0;
+ float m_returnSetpointTemperature = 0;
+ float m_hotWaterSetpointTemperature = 0;
+ SmartGridState m_smartGrid = SmartGridStateStandard;
+
+ void verifyInitFinished();
+
+ QModbusReply *readFlowTemperature();
+ QModbusReply *readReturnTemperature();
+ QModbusReply *readExternalReturnTemperature();
+ QModbusReply *readHotWaterTemperature();
+ QModbusReply *readHotGasTemperature();
+ QModbusReply *readHeatSourceInletTemperature();
+ QModbusReply *readHeatSourceOutletTemperature();
+ QModbusReply *readRoomTemperature1();
+ QModbusReply *readRoomTemperature2();
+ QModbusReply *readRoomTemperature3();
+ QModbusReply *readSolarCollectorTemperature();
+ QModbusReply *readSolarStorageTankTemperature();
+ QModbusReply *readExternalEnergySourceTemperature();
+ QModbusReply *readSupplyAirTemperature();
+ QModbusReply *readExternalAirTemperature();
+ QModbusReply *readRbeRoomActualTemperature();
+ QModbusReply *readRbeRoomSetpointTemperature();
+ QModbusReply *readHeatingPumpOperatingHours();
+ QModbusReply *readSystemStatus();
+ QModbusReply *readHeatingEnergy();
+ QModbusReply *readWaterHeatEnergy();
+ QModbusReply *readTotalHeatEnergy();
+ QModbusReply *readOutdoorTemperature();
+ QModbusReply *readReturnSetpointTemperature();
+ QModbusReply *readHotWaterSetpointTemperature();
+ QModbusReply *readSmartGrid();
+
+
+};
+
+QDebug operator<<(QDebug debug, AlphaConnectModbusTcpConnection *alphaConnectModbusTcpConnection);
+
+#endif // ALPHACONNECTMODBUSTCPCONNECTION_H
diff --git a/alphainnotec/alphainnotec-registers.json b/alphainnotec/alphainnotec-registers.json
new file mode 100644
index 0000000..1908e0d
--- /dev/null
+++ b/alphainnotec/alphainnotec-registers.json
@@ -0,0 +1,401 @@
+{
+ "endianness": "BigEndian",
+ "enums": [
+ {
+ "name": "SystemStatus",
+ "values": [
+ {
+ "key": "HeatingMode",
+ "value": 0
+ },
+ {
+ "key": "DomesticHotWater",
+ "value": 1
+ },
+ {
+ "key": "SwimmingPool",
+ "value": 2
+ },
+ {
+ "key": "EVUOff",
+ "value": 3
+ },
+ {
+ "key": "Defrost",
+ "value": 4
+ },
+ {
+ "key": "Off",
+ "value": 5
+ },
+ {
+ "key": "ExternalEnergySource",
+ "value": 6
+ },
+ {
+ "key": "CoolingMode",
+ "value": 7
+ }
+ ]
+ },
+ {
+ "name": "SmartGridState",
+ "values": [
+ {
+ "key": "Off",
+ "value": 0
+ },
+ {
+ "key": "Low",
+ "value": 1
+ },
+ {
+ "key": "Standard",
+ "value": 2
+ },
+ {
+ "key": "High",
+ "value": 3
+ }
+ ]
+ }
+ ],
+ "registers": [
+ {
+ "id": "flowTemperature",
+ "address": 1,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Flow",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "returnTemperature",
+ "address": 2,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Return",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "externalReturnTemperature",
+ "address": 3,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "External return",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "hotWaterTemperature",
+ "address": 4,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Hot water temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "hotGasTemperature",
+ "address": 8,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Hot gas temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "heatSourceInletTemperature",
+ "address": 9,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Heat source inlet temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "heatSourceOutletTemperature",
+ "address": 10,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Heat source outlet temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "roomTemperature1",
+ "address": 11,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Room remote adjuster 1 temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "roomTemperature2",
+ "address": 12,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Room remote adjuster 2 temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "roomTemperature3",
+ "address": 13,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Room remote adjuster 3 temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "solarCollectorTemperature",
+ "address": 14,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Solar collector temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "solarStorageTankTemperature",
+ "address": 15,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Solar storage tank temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "externalEnergySourceTemperature",
+ "address": 16,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "External energy source temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "supplyAirTemperature",
+ "address": 17,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Supply air temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "externalAirTemperature",
+ "address": 18,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "External air temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "rbeRoomActualTemperature",
+ "address": 24,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "RBE actual room temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "rbeRoomSetpointTemperature",
+ "address": 24,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "RBE room temperature setpoint",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "heatingPumpOperatingHours",
+ "address": 33,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Heating pump operating hours",
+ "defaultValue": "0",
+ "unit": "h",
+ "access": "RO"
+ },
+ {
+ "id": "systemStatus",
+ "address": 37,
+ "size": 1,
+ "type": "uint16",
+ "enum": "SystemStatus",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "System status",
+ "defaultValue": "SystemStatusHeatingMode",
+ "access": "RO"
+ },
+ {
+ "id": "heatingEnergy",
+ "address": 38,
+ "size": 2,
+ "type": "uint32",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "kWh",
+ "description": "Heating energy",
+ "access": "RO"
+ },
+ {
+ "id": "waterHeatEnergy",
+ "address": 40,
+ "size": 2,
+ "type": "uint32",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "kWh",
+ "description": "Water heat energy",
+ "access": "RO"
+ },
+ {
+ "id": "totalHeatEnergy",
+ "address": 44,
+ "size": 2,
+ "type": "uint32",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "kWh",
+ "description": "Total energy",
+ "access": "RO"
+ },
+
+ {
+ "id": "outdoorTemperature",
+ "address": 0,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "holdingRegister",
+ "readSchedule": "update",
+ "description": "Outdoor temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RW"
+ },
+ {
+ "id": "returnSetpointTemperature",
+ "address": 1,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "holdingRegister",
+ "readSchedule": "update",
+ "description": "Return setpoint temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RW"
+ },
+ {
+ "id": "hotWaterSetpointTemperature",
+ "address": 5,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "holdingRegister",
+ "readSchedule": "update",
+ "description": "Hot water setpoint temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RW"
+ },
+ {
+ "id": "smartGrid",
+ "address": 14,
+ "size": 1,
+ "type": "uint16",
+ "enum": "SmartGridState",
+ "registerType": "holdingRegister",
+ "readSchedule": "update",
+ "description": "Smart grid control",
+ "defaultValue": "SmartGridStateStandard",
+ "access": "RW"
+ }
+ ]
+}
diff --git a/alphainnotec/alphainnotec.pro b/alphainnotec/alphainnotec.pro
new file mode 100644
index 0000000..b88c856
--- /dev/null
+++ b/alphainnotec/alphainnotec.pro
@@ -0,0 +1,15 @@
+include(../plugins.pri)
+
+QT += network serialbus
+
+SOURCES += \
+ integrationpluginalphainnotec.cpp \
+ alphaconnectmodbustcpconnection.cpp \
+ ../modbus/modbustcpmaster.cpp \
+ ../modbus/modbusdatautils.cpp
+
+HEADERS += \
+ integrationpluginalphainnotec.h \
+ alphaconnectmodbustcpconnection.h \
+ ../modbus/modbustcpmaster.h \
+ ../modbus/modbusdatautils.h
diff --git a/alphainnotec/integrationpluginalphainnotec.cpp b/alphainnotec/integrationpluginalphainnotec.cpp
new file mode 100644
index 0000000..153d6b3
--- /dev/null
+++ b/alphainnotec/integrationpluginalphainnotec.cpp
@@ -0,0 +1,474 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2021, 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 .
+*
+* 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 "integrationpluginalphainnotec.h"
+
+#include "network/networkdevicediscovery.h"
+#include "hardwaremanager.h"
+#include "plugininfo.h"
+
+IntegrationPluginAlphaInnotec::IntegrationPluginAlphaInnotec()
+{
+
+}
+
+void IntegrationPluginAlphaInnotec::discoverThings(ThingDiscoveryInfo *info)
+{
+ if (!hardwareManager()->networkDeviceDiscovery()->available()) {
+ qCWarning(dcAlphaInnotec()) << "The network discovery is not available on this platform.";
+ info->finish(Thing::ThingErrorUnsupportedFeature, QT_TR_NOOP("The network device discovery is not available."));
+ return;
+ }
+
+ NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover();
+ connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
+ foreach (const NetworkDeviceInfo &networkDeviceInfo, discoveryReply->networkDeviceInfos()) {
+
+ qCDebug(dcAlphaInnotec()) << "Found" << networkDeviceInfo;
+
+ QString title;
+ if (networkDeviceInfo.hostName().isEmpty()) {
+ title = networkDeviceInfo.address().toString();
+ } else {
+ title = networkDeviceInfo.hostName() + " (" + networkDeviceInfo.address().toString() + ")";
+ }
+
+ QString description;
+ if (networkDeviceInfo.macAddressManufacturer().isEmpty()) {
+ description = networkDeviceInfo.macAddress();
+ } else {
+ description = networkDeviceInfo.macAddress() + " (" + networkDeviceInfo.macAddressManufacturer() + ")";
+ }
+
+ ThingDescriptor descriptor(alphaConnectThingClassId, title, description);
+ ParamList params;
+ params << Param(alphaConnectThingIpAddressParamTypeId, networkDeviceInfo.address().toString());
+ params << Param(alphaConnectThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
+ descriptor.setParams(params);
+
+ // Check if we already have set up this device
+ Things existingThings = myThings().filterByParam(alphaConnectThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
+ if (existingThings.count() == 1) {
+ qCDebug(dcAlphaInnotec()) << "This connection already exists in the system:" << networkDeviceInfo;
+ descriptor.setThingId(existingThings.first()->id());
+ }
+
+ info->addThingDescriptor(descriptor);
+ }
+
+ info->finish(Thing::ThingErrorNoError);
+ });
+}
+
+void IntegrationPluginAlphaInnotec::startMonitoringAutoThings()
+{
+
+}
+
+void IntegrationPluginAlphaInnotec::setupThing(ThingSetupInfo *info)
+{
+ Thing *thing = info->thing();
+ qCDebug(dcAlphaInnotec()) << "Setup" << thing << thing->params();
+
+ if (thing->thingClassId() == alphaConnectThingClassId) {
+ QHostAddress hostAddress = QHostAddress(thing->paramValue(alphaConnectThingIpAddressParamTypeId).toString());
+ if (hostAddress.isNull()) {
+ info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("No IP address given"));
+ return;
+ }
+
+ uint port = thing->paramValue(alphaConnectThingPortParamTypeId).toUInt();
+ quint16 slaveId = thing->paramValue(alphaConnectThingSlaveIdParamTypeId).toUInt();
+
+ AlphaConnectModbusTcpConnection *alphaConnectTcpConnection = new AlphaConnectModbusTcpConnection(hostAddress, port, slaveId, this);
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::connectionStateChanged, this, [thing, alphaConnectTcpConnection](bool status){
+ qCDebug(dcAlphaInnotec()) << "Connected changed to" << status << "for" << thing;
+ if (status) {
+ alphaConnectTcpConnection->update();
+ }
+
+ thing->setStateValue(alphaConnectConnectedStateTypeId, status);
+ });
+
+
+ // Input registers
+// connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::meanTemperatureChanged, this, [thing](float meanTemperature){
+// qCDebug(dcAlphaInnotec()) << thing << "mean temperature changed" << meanTemperature << "°C";
+// thing->setStateValue(alphaConnectMeanTemperatureStateTypeId, meanTemperature);
+// });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::flowTemperatureChanged, this, [thing](float flowTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "flow temperature changed" << flowTemperature << "°C";
+ thing->setStateValue(alphaConnectFlowTemperatureStateTypeId, flowTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::returnTemperatureChanged, this, [thing](float returnTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "return temperature changed" << returnTemperature << "°C";
+ thing->setStateValue(alphaConnectReturnTemperatureStateTypeId, returnTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::externalReturnTemperatureChanged, this, [thing](float externalReturnTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "external return temperature changed" << externalReturnTemperature << "°C";
+ thing->setStateValue(alphaConnectExternalReturnTemperatureStateTypeId, externalReturnTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::hotWaterTemperatureChanged, this, [thing](float hotWaterTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "hot water temperature changed" << hotWaterTemperature << "°C";
+ thing->setStateValue(alphaConnectHotWaterTemperatureStateTypeId, hotWaterTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::hotGasTemperatureChanged, this, [thing](float hotGasTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "hot gas temperature changed" << hotGasTemperature << "°C";
+ thing->setStateValue(alphaConnectHotGasTemperatureStateTypeId, hotGasTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::heatSourceInletTemperatureChanged, this, [thing](float heatSourceInletTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "heat source inlet temperature changed" << heatSourceInletTemperature << "°C";
+ thing->setStateValue(alphaConnectHeatSourceInletTemperatureStateTypeId, heatSourceInletTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::heatSourceOutletTemperatureChanged, this, [thing](float heatSourceOutletTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "heat source outlet temperature changed" << heatSourceOutletTemperature << "°C";
+ thing->setStateValue(alphaConnectHeatSourceOutletTemperatureStateTypeId, heatSourceOutletTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::roomTemperature1Changed, this, [thing](float roomTemperature1){
+ qCDebug(dcAlphaInnotec()) << thing << "room remote adjuster 1 temperature changed" << roomTemperature1 << "°C";
+ thing->setStateValue(alphaConnectRoomTemperature1StateTypeId, roomTemperature1);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::roomTemperature2Changed, this, [thing](float roomTemperature2){
+ qCDebug(dcAlphaInnotec()) << thing << "room remote adjuster 2 temperature changed" << roomTemperature2 << "°C";
+ thing->setStateValue(alphaConnectRoomTemperature2StateTypeId, roomTemperature2);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::roomTemperature3Changed, this, [thing](float roomTemperature3){
+ qCDebug(dcAlphaInnotec()) << thing << "room remote adjuster 3 temperature changed" << roomTemperature3 << "°C";
+ thing->setStateValue(alphaConnectRoomTemperature2StateTypeId, roomTemperature3);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::solarCollectorTemperatureChanged, this, [thing](float solarCollectorTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "solar collector temperature changed" << solarCollectorTemperature << "°C";
+ thing->setStateValue(alphaConnectSolarCollectorTemperatureStateTypeId, solarCollectorTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::solarStorageTankTemperatureChanged, this, [thing](float solarStorageTankTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "solar storage tank temperature changed" << solarStorageTankTemperature << "°C";
+ thing->setStateValue(alphaConnectSolarCollectorTemperatureStateTypeId, solarStorageTankTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::externalEnergySourceTemperatureChanged, this, [thing](float externalEnergySourceTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "external energy source temperature changed" << externalEnergySourceTemperature << "°C";
+ thing->setStateValue(alphaConnectExternalEnergySourceTemperatureStateTypeId, externalEnergySourceTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::supplyAirTemperatureChanged, this, [thing](float supplyAirTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "supply air temperature changed" << supplyAirTemperature << "°C";
+ thing->setStateValue(alphaConnectSupplyAirTemperatureStateTypeId, supplyAirTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::externalAirTemperatureChanged, this, [thing](float externalAirTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "external air temperature changed" << externalAirTemperature << "°C";
+ thing->setStateValue(alphaConnectExternalAirTemperatureStateTypeId, externalAirTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::heatingPumpOperatingHoursChanged, this, [thing](quint16 heatingPumpOperatingHours){
+ qCDebug(dcAlphaInnotec()) << thing << "heating pump operating hours changed" << heatingPumpOperatingHours;
+ thing->setStateValue(alphaConnectHeatingPumpOperatingHoursStateTypeId, heatingPumpOperatingHours);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::systemStatusChanged, this, [thing](AlphaConnectModbusTcpConnection::SystemStatus systemStatus){
+ qCDebug(dcAlphaInnotec()) << thing << "system status changed" << systemStatus;
+ switch (systemStatus) {
+ case AlphaConnectModbusTcpConnection::SystemStatusHeatingMode:
+ thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Heating mode");
+ break;
+ case AlphaConnectModbusTcpConnection::SystemStatusDomesticHotWater:
+ thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Domestic hot water");
+ break;
+ case AlphaConnectModbusTcpConnection::SystemStatusSwimmingPool:
+ thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Swimming pool");
+ break;
+ case AlphaConnectModbusTcpConnection::SystemStatusEVUOff:
+ thing->setStateValue(alphaConnectSystemStatusStateTypeId, "EUV off");
+ break;
+ case AlphaConnectModbusTcpConnection::SystemStatusDefrost:
+ thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Defrost");
+ break;
+ case AlphaConnectModbusTcpConnection::SystemStatusOff:
+ thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Off");
+ break;
+ case AlphaConnectModbusTcpConnection::SystemStatusExternalEnergySource:
+ thing->setStateValue(alphaConnectSystemStatusStateTypeId, "External energy source");
+ break;
+ case AlphaConnectModbusTcpConnection::SystemStatusCoolingMode:
+ thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Cooling mode");
+ break;
+ }
+
+ // Set heating and cooling states according to the system state
+ thing->setStateValue(alphaConnectHeatingOnStateTypeId, systemStatus == AlphaConnectModbusTcpConnection::SystemStatusHeatingMode);
+ thing->setStateValue(alphaConnectCoolingOnStateTypeId, systemStatus == AlphaConnectModbusTcpConnection::SystemStatusCoolingMode);
+ });
+
+ // Energy
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::totalHeatEnergyChanged, this, [thing](float totalHeatEnergy){
+ qCDebug(dcAlphaInnotec()) << thing << "total heating energy changed" << totalHeatEnergy << "kWh";
+ thing->setStateValue(alphaConnectTotalEnergyStateTypeId, totalHeatEnergy);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::heatingEnergyChanged, this, [thing](float heatingEnergy){
+ qCDebug(dcAlphaInnotec()) << thing << "heating energy changed" << heatingEnergy << "kWh";
+ thing->setStateValue(alphaConnectHeatingEnergyStateTypeId, heatingEnergy);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::waterHeatEnergyChanged, this, [thing](float waterHeatEnergy){
+ qCDebug(dcAlphaInnotec()) << thing << "water heat energy changed" << waterHeatEnergy << "kWh";
+ thing->setStateValue(alphaConnectHotWaterEnergyStateTypeId, waterHeatEnergy);
+ });
+
+// connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::swimmingPoolHeatEnergyChanged, this, [thing](float swimmingPoolHeatEnergy){
+// qCDebug(dcAlphaInnotec()) << thing << "swimming pool heat energy changed" << swimmingPoolHeatEnergy << "kWh";
+// thing->setStateValue(alphaConnectSwimmingPoolEnergyStateTypeId, swimmingPoolHeatEnergy);
+// });
+
+ // Holding registers
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::outdoorTemperatureChanged, this, [thing](float outdoorTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "outdoor temperature changed" << outdoorTemperature << "°C";
+ thing->setStateValue(alphaConnectOutdoorTemperatureStateTypeId, outdoorTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::returnSetpointTemperatureChanged, this, [thing](float returnSetpointTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "return setpoint temperature changed" << returnSetpointTemperature << "°C";
+ thing->setStateValue(alphaConnectReturnSetpointTemperatureStateTypeId, returnSetpointTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::hotWaterSetpointTemperatureChanged, this, [thing](float hotWaterSetpointTemperature){
+ qCDebug(dcAlphaInnotec()) << thing << "hot water setpoint temperature changed" << hotWaterSetpointTemperature << "°C";
+ thing->setStateValue(alphaConnectHotWaterSetpointTemperatureStateTypeId, hotWaterSetpointTemperature);
+ });
+
+ connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::smartGridChanged, this, [thing](AlphaConnectModbusTcpConnection::SmartGridState smartGridState){
+ qCDebug(dcAlphaInnotec()) << thing << "smart grid state changed" << smartGridState;
+ switch (smartGridState) {
+ case AlphaConnectModbusTcpConnection::SmartGridStateOff:
+ thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Off");
+ break;
+ case AlphaConnectModbusTcpConnection::SmartGridStateLow:
+ thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Low");
+ break;
+ case AlphaConnectModbusTcpConnection::SmartGridStateStandard:
+ thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Standard");
+ break;
+ case AlphaConnectModbusTcpConnection::SmartGridStateHigh:
+ thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "High");
+ break;
+ }
+ });
+
+ m_alpaConnectTcpThings.insert(thing, alphaConnectTcpConnection);
+ alphaConnectTcpConnection->connectDevice();
+
+ // FIXME: make async and check if this is really an alpha connect
+ info->finish(Thing::ThingErrorNoError);
+ }
+}
+
+void IntegrationPluginAlphaInnotec::postSetupThing(Thing *thing)
+{
+ if (thing->thingClassId() == alphaConnectThingClassId) {
+ if (!m_pluginTimer) {
+ qCDebug(dcAlphaInnotec()) << "Starting plugin timer...";
+ m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
+ connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
+ foreach (AlphaConnectModbusTcpConnection *connection, m_alpaConnectTcpThings) {
+ if (connection->connected()) {
+ connection->update();
+ }
+ }
+ });
+
+ m_pluginTimer->start();
+ }
+ }
+}
+
+void IntegrationPluginAlphaInnotec::thingRemoved(Thing *thing)
+{
+ if (thing->thingClassId() == alphaConnectThingClassId && m_alpaConnectTcpThings.contains(thing)) {
+ AlphaConnectModbusTcpConnection *connection = m_alpaConnectTcpThings.take(thing);
+ delete connection;
+ }
+
+ if (myThings().isEmpty() && m_pluginTimer) {
+ hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
+ m_pluginTimer = nullptr;
+ }
+}
+
+void IntegrationPluginAlphaInnotec::executeAction(ThingActionInfo *info)
+{
+ Thing *thing = info->thing();
+ AlphaConnectModbusTcpConnection *connection = m_alpaConnectTcpThings.value(thing);
+
+ if (!connection->connected()) {
+ qCWarning(dcAlphaInnotec()) << "Could not execute action. The modbus connection is currently not available.";
+ info->finish(Thing::ThingErrorHardwareNotAvailable);
+ return;
+ }
+
+ if (thing->thingClassId() == alphaConnectThingClassId) {
+ /* if (info->action().actionTypeId() == alphaConnectOutdoorTemperatureActionTypeId) {
+ double outdoorTemperature = info->action().paramValue(alphaConnectOutdoorTemperatureActionOutdoorTemperatureParamTypeId).toDouble();
+ qCDebug(dcAlphaInnotec()) << "Execute action" << info->action().actionTypeId().toString() << info->action().params();
+ QModbusReply *reply = connection->setOutdoorTemperature(outdoorTemperature);
+ if (!reply) {
+ qCWarning(dcAlphaInnotec()) << "Execute action failed because the reply could not be created.";
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, info, [info, reply, outdoorTemperature]{
+ if (reply->error() != QModbusDevice::NoError) {
+ info->finish(Thing::ThingErrorHardwareFailure);
+ qCWarning(dcAlphaInnotec()) << "Set outdoor temperature finished with error" << reply->errorString();
+ return;
+ }
+
+ qCDebug(dcAlphaInnotec()) << "Execute action finished successfully" << info->action().actionTypeId().toString() << info->action().params();
+ info->thing()->setStateValue(alphaConnectOutdoorTemperatureStateTypeId, outdoorTemperature);
+ info->finish(Thing::ThingErrorNoError);
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaInnotec()) << "Modbus reply error occurred while execute action" << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else */
+ if (info->action().actionTypeId() == alphaConnectHotWaterSetpointTemperatureActionTypeId) {
+ double temperature = info->action().paramValue(alphaConnectHotWaterSetpointTemperatureActionHotWaterSetpointTemperatureParamTypeId).toDouble();
+ qCDebug(dcAlphaInnotec()) << "Execute action" << info->action().actionTypeId().toString() << info->action().params();
+ QModbusReply *reply = connection->setHotWaterSetpointTemperature(temperature);
+ if (!reply) {
+ qCWarning(dcAlphaInnotec()) << "Execute action failed because the reply could not be created.";
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, info, [info, reply, temperature]{
+ if (reply->error() != QModbusDevice::NoError) {
+ qCWarning(dcAlphaInnotec()) << "Set hot water setpoint temperature finished with error" << reply->errorString();
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ qCDebug(dcAlphaInnotec()) << "Execute action finished successfully" << info->action().actionTypeId().toString() << info->action().params();
+ info->thing()->setStateValue(alphaConnectHotWaterSetpointTemperatureStateTypeId, temperature);
+ info->finish(Thing::ThingErrorNoError);
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaInnotec()) << "Modbus reply error occurred while execute action" << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else if (info->action().actionTypeId() == alphaConnectReturnSetpointTemperatureActionTypeId) {
+ double temperature = info->action().paramValue(alphaConnectReturnSetpointTemperatureActionReturnSetpointTemperatureParamTypeId).toDouble();
+ qCDebug(dcAlphaInnotec()) << "Execute action" << info->action().actionTypeId().toString() << info->action().params();
+ QModbusReply *reply = connection->setReturnSetpointTemperature(temperature);
+ if (!reply) {
+ qCWarning(dcAlphaInnotec()) << "Execute action failed because the reply could not be created.";
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, info, [info, reply, temperature]{
+ if (reply->error() != QModbusDevice::NoError) {
+ qCWarning(dcAlphaInnotec()) << "Set return setpoint temperature finished with error" << reply->errorString();
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ qCDebug(dcAlphaInnotec()) << "Execute action finished successfully" << info->action().actionTypeId().toString() << info->action().params();
+ info->thing()->setStateValue(alphaConnectReturnSetpointTemperatureStateTypeId, temperature);
+ info->finish(Thing::ThingErrorNoError);
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaInnotec()) << "Modbus reply error occurred while execute action" << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ } else if (info->action().actionTypeId() == alphaConnectSgReadyModeActionTypeId) {
+ QString sgReadyModeString = info->action().paramValue(alphaConnectSgReadyModeActionSgReadyModeParamTypeId).toString();
+ qCDebug(dcAlphaInnotec()) << "Execute action" << info->action().actionTypeId().toString() << info->action().params();
+ AlphaConnectModbusTcpConnection::SmartGridState sgReadyState;
+ if (sgReadyModeString == "Off") {
+ sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateOff;
+ } else if (sgReadyModeString == "Low") {
+ sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateLow;
+ } else if (sgReadyModeString == "High") {
+ sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateHigh;
+ } else {
+ sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateStandard;
+ }
+
+ QModbusReply *reply = connection->setSmartGrid(sgReadyState);
+ if (!reply) {
+ qCWarning(dcAlphaInnotec()) << "Execute action failed because the reply could not be created.";
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
+ connect(reply, &QModbusReply::finished, info, [info, reply, sgReadyModeString]{
+ if (reply->error() != QModbusDevice::NoError) {
+ qCWarning(dcAlphaInnotec()) << "Set SG ready mode finished with error" << reply->errorString();
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ qCDebug(dcAlphaInnotec()) << "Execute action finished successfully" << info->action().actionTypeId().toString() << info->action().params();
+ info->thing()->setStateValue(alphaConnectSgReadyModeStateTypeId, sgReadyModeString);
+ info->finish(Thing::ThingErrorNoError);
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){
+ qCWarning(dcAlphaInnotec()) << "Modbus reply error occurred while execute action" << error << reply->errorString();
+ emit reply->finished(); // To make sure it will be deleted
+ });
+ }
+ }
+
+ info->finish(Thing::ThingErrorNoError);
+}
+
+
diff --git a/alphainnotec/integrationpluginalphainnotec.h b/alphainnotec/integrationpluginalphainnotec.h
new file mode 100644
index 0000000..0f6a4cc
--- /dev/null
+++ b/alphainnotec/integrationpluginalphainnotec.h
@@ -0,0 +1,62 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* 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 .
+*
+* 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 INTEGRATIONPLUGINALPHAINNOTEC_H
+#define INTEGRATIONPLUGINALPHAINNOTEC_H
+
+#include "plugintimer.h"
+#include "alphaconnectmodbustcpconnection.h"
+#include "integrations/integrationplugin.h"
+
+class IntegrationPluginAlphaInnotec: public IntegrationPlugin
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginalphainnotec.json")
+ Q_INTERFACES(IntegrationPlugin)
+
+public:
+ explicit IntegrationPluginAlphaInnotec();
+
+ void discoverThings(ThingDiscoveryInfo *info) override;
+ void startMonitoringAutoThings() override;
+ void setupThing(ThingSetupInfo *info) override;
+ void postSetupThing(Thing *thing) override;
+ void thingRemoved(Thing *thing) override;
+ void executeAction(ThingActionInfo *info) override;
+
+private:
+ PluginTimer *m_pluginTimer = nullptr;
+ QHash m_alpaConnectTcpThings;
+};
+
+#endif // INTEGRATIONPLUGINALPHAINNOTEC_H
+
+
diff --git a/alphainnotec/integrationpluginalphainnotec.json b/alphainnotec/integrationpluginalphainnotec.json
new file mode 100644
index 0000000..14990a4
--- /dev/null
+++ b/alphainnotec/integrationpluginalphainnotec.json
@@ -0,0 +1,343 @@
+{
+ "name": "AlphaInnotec",
+ "displayName": "alpha innotec",
+ "id": "b3225a18-e9b0-443e-8c88-802d3132f94d",
+ "vendors": [
+ {
+ "name": "alphaInnotec",
+ "displayName": "alpha Innotec",
+ "id": "2c2101ae-7bb8-4012-97ba-cedf4cecd924",
+ "thingClasses": [
+ {
+ "name": "alphaConnect",
+ "displayName": "alpha connect",
+ "id": "c5437b68-cfd2-4ec8-bad6-006fb5e8a8da",
+ "createMethods": ["discovery", "user"],
+ "interfaces": ["smartgridheatpump", "connectable"],
+ "paramTypes": [
+ {
+ "id": "64a18910-9111-4eaf-986d-f7b64b03b99a",
+ "name": "ipAddress",
+ "displayName": "IP address",
+ "type": "QString",
+ "inputType": "IPv4Address",
+ "defaultValue": "127.0.0.1"
+ },
+ {
+ "id": "f791c219-98a5-41ee-8e5f-1bfb5136dc9c",
+ "name":"macAddress",
+ "displayName": "MAC address",
+ "type": "QString",
+ "inputType": "MacAddress",
+ "defaultValue": ""
+ },
+ {
+ "id": "b92025c1-8978-4d47-bd3c-4df749dbfd0f",
+ "name":"port",
+ "displayName": "Port",
+ "type": "int",
+ "defaultValue": 502
+ },
+ {
+ "id": "1d9517ca-680c-49e2-a8d1-320743c27559",
+ "name":"slaveId",
+ "displayName": "Modbus slave ID",
+ "type": "int",
+ "defaultValue": 1
+ }
+ ],
+ "stateTypes": [
+ {
+ "id": "01ce0d61-3813-4c1b-a18b-555913d689a2",
+ "name": "connected",
+ "displayName": "Connected",
+ "displayNameEvent": "Connected changed",
+ "type": "bool",
+ "defaultValue": false,
+ "cached": false
+ },
+ {
+ "id": "07465fbb-6949-4bd1-90d5-acf2d80c161d",
+ "name": "heatingOn",
+ "displayName": "Heating on",
+ "displayNameEvent": "Heating turned on/off",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "8b407c1d-b84f-48d4-9961-b29bc58fff0e",
+ "name": "coolingOn",
+ "displayName": "Cooling on",
+ "displayNameEvent": "Cooling turned on/off",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "fb448191-69d7-4f2e-87bf-6e4fb61e403f",
+ "name": "flowTemperature",
+ "displayName": "Flow temperature",
+ "displayNameEvent": "Flow temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "6f96706e-67a3-43d3-bf74-e2e3e5fd0d6d",
+ "name": "returnTemperature",
+ "displayName": "Return temperature",
+ "displayNameEvent": "Return temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "b6702fc5-889b-48b6-9257-64c5ee6e5e95",
+ "name": "externalReturnTemperature",
+ "displayName": "External return temperature",
+ "displayNameEvent": "External return temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "da7e6bc9-95fd-4c90-931f-5b1cd69d864a",
+ "name": "hotWaterTemperature",
+ "displayName": "Hot water temperature",
+ "displayNameEvent": "Hot water temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "bea6658e-64bf-4476-b75d-38c34a5fed85",
+ "name": "hotGasTemperature",
+ "displayName": "Hot gas temperature",
+ "displayNameEvent": "Hot gas temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "e9facc5d-f41c-4256-85aa-b0f777431975",
+ "name": "heatSourceInletTemperature",
+ "displayName": "Heat source inlet temperature",
+ "displayNameEvent": "Heat source inlet temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "48424285-4bc4-4110-8089-0486292d7371",
+ "name": "heatSourceOutletTemperature",
+ "displayName": "Heat source outlet temperature",
+ "displayNameEvent": "Heat source outlet temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "52f8a581-7b9c-4c15-8aaa-c083763e7820",
+ "name": "roomTemperature1",
+ "displayName": "Room remote adjuster 1 temperature",
+ "displayNameEvent": "Room remote adjuster 1 temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "91b57690-5daa-4766-86ae-f205fa0c805a",
+ "name": "roomTemperature2",
+ "displayName": "Room remote adjuster 2 temperature",
+ "displayNameEvent": "Room remote adjuster 2 temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "a8c7e706-57ba-4572-b6e6-5eec91065ea8",
+ "name": "roomTemperature3",
+ "displayName": "Room remote adjuster 3 temperature",
+ "displayNameEvent": "Room remote adjuster 3 temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "d4484305-eb0f-418b-bb15-f71b08e6fce1",
+ "name": "solarCollectorTemperature",
+ "displayName": "Solar collector temperature",
+ "displayNameEvent": "Solar collector temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "75089369-c224-4fe5-91d1-9bdc5578f0a5",
+ "name": "solarStorageTankTemperature",
+ "displayName": "Solar storage tank temperature",
+ "displayNameEvent": "Solar storage tank temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "519d7d45-1f3d-4118-ade9-3d7508451005",
+ "name": "externalEnergySourceTemperature",
+ "displayName": "External energy source temperature",
+ "displayNameEvent": "External energy source temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "90d88164-3083-47c7-a396-b338bd9ea54c",
+ "name": "supplyAirTemperature",
+ "displayName": "Supply air temperature",
+ "displayNameEvent": "Supply air temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "92594f19-8e4c-485b-bfd5-5371a0454267",
+ "name": "externalAirTemperature",
+ "displayName": "External air temperature",
+ "displayNameEvent": "External air temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "5a21a131-f3a0-4ebd-9b2e-12eb25c84853",
+ "name": "systemStatus",
+ "displayName": "System status",
+ "displayNameEvent": "System status changed",
+ "type": "QString",
+ "possibleValues": [
+ "Heating mode",
+ "Domestic hot water",
+ "Swimming pool",
+ "EUV off",
+ "Defrost",
+ "Off",
+ "External energy source",
+ "Cooling mode"
+ ],
+ "defaultValue": "Heating mode",
+ "suggestLogging": true
+ },
+ {
+ "id": "ef378ce6-f112-4022-8535-78cbd6ccfeeb",
+ "name": "heatingPumpOperatingHours",
+ "displayName": "Heating pump operating hours",
+ "displayNameEvent": "Heating pump operating hours changed",
+ "unit": "Hours",
+ "type": "uint",
+ "defaultValue": 0
+ },
+ {
+ "id": "d0c8f168-49b5-47ca-9988-c9922be38dd5",
+ "name": "outdoorTemperature",
+ "displayName": "Outdoor temperature",
+ "displayNameEvent": "Outdoor temperature changed",
+ "displayNameAction": "Set outdoor temperature",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "1ee6b189-ceff-4912-a577-2e3320307c3f",
+ "name": "returnSetpointTemperature",
+ "displayName": "Return temperature setpoint",
+ "displayNameEvent": "Return temperature setpoint changed",
+ "displayNameAction": "Set return temperature setpoint",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "writable": true,
+ "suggestLogging": true
+ },
+ {
+ "id": "a7f1a688-51d3-4f9e-a323-86117c5542a8",
+ "name": "hotWaterSetpointTemperature",
+ "displayName": "Hot water temperature setpoint",
+ "displayNameEvent": "Hot water temperature setpoint changed",
+ "displayNameAction": "Set hot water temperature setpoint",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "writable": true,
+ "suggestLogging": true
+ },
+ {
+ "id": "8cc9761f-b30e-4f54-aee7-b64190df57e1",
+ "name": "sgReadyMode",
+ "displayName": "Smart grid mode",
+ "displayNameEvent": "Smart grid mode changed",
+ "displayNameAction": "Set smart grid mode",
+ "type": "QString",
+ "possibleValues": [
+ "Off",
+ "Low",
+ "Standard",
+ "High"
+ ],
+ "writable": true,
+ "defaultValue": "Standard",
+ "suggestLogging": true
+ },
+ {
+ "id": "c7948cf6-fd1a-44fa-a91b-98f2474ecc62",
+ "name": "totalEnergy",
+ "displayName": "Total energy",
+ "displayNameEvent": "Total energy changed",
+ "type": "double",
+ "unit": "KiloWattHour",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "24367fba-2883-40da-9b92-5d4db3c71c2f",
+ "name": "heatingEnergy",
+ "displayName": "Heating energy",
+ "displayNameEvent": "Heating energy changed",
+ "type": "double",
+ "unit": "KiloWattHour",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "be2430c3-54ef-441e-b684-9aabc1d984d6",
+ "name": "hotWaterEnergy",
+ "displayName": "Hot water energy",
+ "displayNameEvent": "Hot water energy changed",
+ "type": "double",
+ "unit": "KiloWattHour",
+ "defaultValue": 0,
+ "suggestLogging": true
+ }
+ ],
+ "actionTypes": [ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/alphainnotec/meta.json b/alphainnotec/meta.json
new file mode 100644
index 0000000..09832c9
--- /dev/null
+++ b/alphainnotec/meta.json
@@ -0,0 +1,13 @@
+{
+ "title": "alpha innotec",
+ "tagline": "Integrate alpha innotec heat pumps into nymea.",
+ "icon": "alpha-innotec.png",
+ "stability": "community",
+ "offline": true,
+ "technologies": [
+ "network"
+ ],
+ "categories": [
+ "heating"
+ ]
+}
diff --git a/alphainnotec/translations/b3225a18-e9b0-443e-8c88-802d3132f94d-en_US.ts b/alphainnotec/translations/b3225a18-e9b0-443e-8c88-802d3132f94d-en_US.ts
new file mode 100644
index 0000000..563414f
--- /dev/null
+++ b/alphainnotec/translations/b3225a18-e9b0-443e-8c88-802d3132f94d-en_US.ts
@@ -0,0 +1,431 @@
+
+
+
+
+ AlphaInnotec
+
+
+
+ Connected
+ The name of the ParamType (ThingClass: alphaConnect, EventType: connected, ID: {01ce0d61-3813-4c1b-a18b-555913d689a2})
+----------
+The name of the StateType ({01ce0d61-3813-4c1b-a18b-555913d689a2}) of ThingClass alphaConnect
+
+
+
+
+ Connected changed
+ The name of the EventType ({01ce0d61-3813-4c1b-a18b-555913d689a2}) of ThingClass alphaConnect
+
+
+
+
+
+ Cooling on
+ The name of the ParamType (ThingClass: alphaConnect, EventType: coolingOn, ID: {8b407c1d-b84f-48d4-9961-b29bc58fff0e})
+----------
+The name of the StateType ({8b407c1d-b84f-48d4-9961-b29bc58fff0e}) of ThingClass alphaConnect
+
+
+
+
+ Cooling turned on/off
+ The name of the EventType ({8b407c1d-b84f-48d4-9961-b29bc58fff0e}) of ThingClass alphaConnect
+
+
+
+
+
+ External air temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: externalAirTemperature, ID: {92594f19-8e4c-485b-bfd5-5371a0454267})
+----------
+The name of the StateType ({92594f19-8e4c-485b-bfd5-5371a0454267}) of ThingClass alphaConnect
+
+
+
+
+ External air temperature changed
+ The name of the EventType ({92594f19-8e4c-485b-bfd5-5371a0454267}) of ThingClass alphaConnect
+
+
+
+
+
+ External energy source temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: externalEnergySourceTemperature, ID: {519d7d45-1f3d-4118-ade9-3d7508451005})
+----------
+The name of the StateType ({519d7d45-1f3d-4118-ade9-3d7508451005}) of ThingClass alphaConnect
+
+
+
+
+ External energy source temperature changed
+ The name of the EventType ({519d7d45-1f3d-4118-ade9-3d7508451005}) of ThingClass alphaConnect
+
+
+
+
+
+ External return temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: externalReturnTemperature, ID: {b6702fc5-889b-48b6-9257-64c5ee6e5e95})
+----------
+The name of the StateType ({b6702fc5-889b-48b6-9257-64c5ee6e5e95}) of ThingClass alphaConnect
+
+
+
+
+ External return temperature changed
+ The name of the EventType ({b6702fc5-889b-48b6-9257-64c5ee6e5e95}) of ThingClass alphaConnect
+
+
+
+
+
+ Flow temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: flowTemperature, ID: {fb448191-69d7-4f2e-87bf-6e4fb61e403f})
+----------
+The name of the StateType ({fb448191-69d7-4f2e-87bf-6e4fb61e403f}) of ThingClass alphaConnect
+
+
+
+
+ Flow temperature changed
+ The name of the EventType ({fb448191-69d7-4f2e-87bf-6e4fb61e403f}) of ThingClass alphaConnect
+
+
+
+
+
+ Heat source inlet temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: heatSourceInletTemperature, ID: {e9facc5d-f41c-4256-85aa-b0f777431975})
+----------
+The name of the StateType ({e9facc5d-f41c-4256-85aa-b0f777431975}) of ThingClass alphaConnect
+
+
+
+
+ Heat source inlet temperature changed
+ The name of the EventType ({e9facc5d-f41c-4256-85aa-b0f777431975}) of ThingClass alphaConnect
+
+
+
+
+
+ Heat source outlet temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: heatSourceOutletTemperature, ID: {48424285-4bc4-4110-8089-0486292d7371})
+----------
+The name of the StateType ({48424285-4bc4-4110-8089-0486292d7371}) of ThingClass alphaConnect
+
+
+
+
+ Heat source outlet temperature changed
+ The name of the EventType ({48424285-4bc4-4110-8089-0486292d7371}) of ThingClass alphaConnect
+
+
+
+
+
+ Heating on
+ The name of the ParamType (ThingClass: alphaConnect, EventType: heatingOn, ID: {07465fbb-6949-4bd1-90d5-acf2d80c161d})
+----------
+The name of the StateType ({07465fbb-6949-4bd1-90d5-acf2d80c161d}) of ThingClass alphaConnect
+
+
+
+
+
+ Heating pump operating hours
+ The name of the ParamType (ThingClass: alphaConnect, EventType: heatingPumpOperatingHours, ID: {ef378ce6-f112-4022-8535-78cbd6ccfeeb})
+----------
+The name of the StateType ({ef378ce6-f112-4022-8535-78cbd6ccfeeb}) of ThingClass alphaConnect
+
+
+
+
+ Heating pump operating hours changed
+ The name of the EventType ({ef378ce6-f112-4022-8535-78cbd6ccfeeb}) of ThingClass alphaConnect
+
+
+
+
+ Heating turned on/off
+ The name of the EventType ({07465fbb-6949-4bd1-90d5-acf2d80c161d}) of ThingClass alphaConnect
+
+
+
+
+
+ Hot gas temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: hotGasTemperature, ID: {bea6658e-64bf-4476-b75d-38c34a5fed85})
+----------
+The name of the StateType ({bea6658e-64bf-4476-b75d-38c34a5fed85}) of ThingClass alphaConnect
+
+
+
+
+ Hot gas temperature changed
+ The name of the EventType ({bea6658e-64bf-4476-b75d-38c34a5fed85}) of ThingClass alphaConnect
+
+
+
+
+
+ Hot water temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: hotWaterTemperature, ID: {da7e6bc9-95fd-4c90-931f-5b1cd69d864a})
+----------
+The name of the StateType ({da7e6bc9-95fd-4c90-931f-5b1cd69d864a}) of ThingClass alphaConnect
+
+
+
+
+ Hot water temperature changed
+ The name of the EventType ({da7e6bc9-95fd-4c90-931f-5b1cd69d864a}) of ThingClass alphaConnect
+
+
+
+
+ IP address
+ The name of the ParamType (ThingClass: alphaConnect, Type: thing, ID: {64a18910-9111-4eaf-986d-f7b64b03b99a})
+
+
+
+
+ MAC address
+ The name of the ParamType (ThingClass: alphaConnect, Type: thing, ID: {f791c219-98a5-41ee-8e5f-1bfb5136dc9c})
+
+
+
+
+
+ Mean temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: meanTemperature, ID: {956051a6-8677-4b25-b899-71aa3590d4e5})
+----------
+The name of the StateType ({956051a6-8677-4b25-b899-71aa3590d4e5}) of ThingClass alphaConnect
+
+
+
+
+ Mean temperature changed
+ The name of the EventType ({956051a6-8677-4b25-b899-71aa3590d4e5}) of ThingClass alphaConnect
+
+
+
+
+ Modbus slave ID
+ The name of the ParamType (ThingClass: alphaConnect, Type: thing, ID: {1d9517ca-680c-49e2-a8d1-320743c27559})
+
+
+
+
+
+ Outdoor temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: outdoorTemperature, ID: {d0c8f168-49b5-47ca-9988-c9922be38dd5})
+----------
+The name of the StateType ({d0c8f168-49b5-47ca-9988-c9922be38dd5}) of ThingClass alphaConnect
+
+
+
+
+ Outdoor temperature changed
+ The name of the EventType ({d0c8f168-49b5-47ca-9988-c9922be38dd5}) of ThingClass alphaConnect
+
+
+
+
+ Port
+ The name of the ParamType (ThingClass: alphaConnect, Type: thing, ID: {b92025c1-8978-4d47-bd3c-4df749dbfd0f})
+
+
+
+
+
+ Return temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: returnTemperature, ID: {6f96706e-67a3-43d3-bf74-e2e3e5fd0d6d})
+----------
+The name of the StateType ({6f96706e-67a3-43d3-bf74-e2e3e5fd0d6d}) of ThingClass alphaConnect
+
+
+
+
+ Return temperature changed
+ The name of the EventType ({6f96706e-67a3-43d3-bf74-e2e3e5fd0d6d}) of ThingClass alphaConnect
+
+
+
+
+
+ Room remote adjuster 1 temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: roomTemperature1, ID: {52f8a581-7b9c-4c15-8aaa-c083763e7820})
+----------
+The name of the StateType ({52f8a581-7b9c-4c15-8aaa-c083763e7820}) of ThingClass alphaConnect
+
+
+
+
+ Room remote adjuster 1 temperature changed
+ The name of the EventType ({52f8a581-7b9c-4c15-8aaa-c083763e7820}) of ThingClass alphaConnect
+
+
+
+
+
+ Room remote adjuster 2 temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: roomTemperature2, ID: {91b57690-5daa-4766-86ae-f205fa0c805a})
+----------
+The name of the StateType ({91b57690-5daa-4766-86ae-f205fa0c805a}) of ThingClass alphaConnect
+
+
+
+
+ Room remote adjuster 2 temperature changed
+ The name of the EventType ({91b57690-5daa-4766-86ae-f205fa0c805a}) of ThingClass alphaConnect
+
+
+
+
+
+ Room remote adjuster 3 temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: roomTemperature3, ID: {a8c7e706-57ba-4572-b6e6-5eec91065ea8})
+----------
+The name of the StateType ({a8c7e706-57ba-4572-b6e6-5eec91065ea8}) of ThingClass alphaConnect
+
+
+
+
+ Room remote adjuster 3 temperature changed
+ The name of the EventType ({a8c7e706-57ba-4572-b6e6-5eec91065ea8}) of ThingClass alphaConnect
+
+
+
+
+
+ Room temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: temperature, ID: {0b978a61-4340-443a-8ea6-69217a593508})
+----------
+The name of the StateType ({0b978a61-4340-443a-8ea6-69217a593508}) of ThingClass alphaConnect
+
+
+
+
+ Room temperature changed
+ The name of the EventType ({0b978a61-4340-443a-8ea6-69217a593508}) of ThingClass alphaConnect
+
+
+
+
+ Set target room temperature
+ The name of the ActionType ({2e8f44c5-c4e3-4539-b85b-45898bbbf6c2}) of ThingClass alphaConnect
+
+
+
+
+
+ Solar collector temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: solarCollectorTemperature, ID: {d4484305-eb0f-418b-bb15-f71b08e6fce1})
+----------
+The name of the StateType ({d4484305-eb0f-418b-bb15-f71b08e6fce1}) of ThingClass alphaConnect
+
+
+
+
+ Solar collector temperature changed
+ The name of the EventType ({d4484305-eb0f-418b-bb15-f71b08e6fce1}) of ThingClass alphaConnect
+
+
+
+
+
+ Solar storage tank temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: solarStorageTankTemperature, ID: {75089369-c224-4fe5-91d1-9bdc5578f0a5})
+----------
+The name of the StateType ({75089369-c224-4fe5-91d1-9bdc5578f0a5}) of ThingClass alphaConnect
+
+
+
+
+ Solar storage tank temperature changed
+ The name of the EventType ({75089369-c224-4fe5-91d1-9bdc5578f0a5}) of ThingClass alphaConnect
+
+
+
+
+
+ Supply air temperature
+ The name of the ParamType (ThingClass: alphaConnect, EventType: supplyAirTemperature, ID: {90d88164-3083-47c7-a396-b338bd9ea54c})
+----------
+The name of the StateType ({90d88164-3083-47c7-a396-b338bd9ea54c}) of ThingClass alphaConnect
+
+
+
+
+ Supply air temperature changed
+ The name of the EventType ({90d88164-3083-47c7-a396-b338bd9ea54c}) of ThingClass alphaConnect
+
+
+
+
+
+ System status
+ The name of the ParamType (ThingClass: alphaConnect, EventType: systemStatus, ID: {5a21a131-f3a0-4ebd-9b2e-12eb25c84853})
+----------
+The name of the StateType ({5a21a131-f3a0-4ebd-9b2e-12eb25c84853}) of ThingClass alphaConnect
+
+
+
+
+ System status changed
+ The name of the EventType ({5a21a131-f3a0-4ebd-9b2e-12eb25c84853}) of ThingClass alphaConnect
+
+
+
+
+
+
+ Target room temperature
+ The name of the ParamType (ThingClass: alphaConnect, ActionType: targetTemperature, ID: {2e8f44c5-c4e3-4539-b85b-45898bbbf6c2})
+----------
+The name of the ParamType (ThingClass: alphaConnect, EventType: targetTemperature, ID: {2e8f44c5-c4e3-4539-b85b-45898bbbf6c2})
+----------
+The name of the StateType ({2e8f44c5-c4e3-4539-b85b-45898bbbf6c2}) of ThingClass alphaConnect
+
+
+
+
+ Target room temperature changed
+ The name of the EventType ({2e8f44c5-c4e3-4539-b85b-45898bbbf6c2}) of ThingClass alphaConnect
+
+
+
+
+ alpha Innotec
+ The name of the vendor ({2c2101ae-7bb8-4012-97ba-cedf4cecd924})
+
+
+
+
+ alpha connect
+ The name of the ThingClass ({c5437b68-cfd2-4ec8-bad6-006fb5e8a8da})
+
+
+
+
+ alpha innotec
+ The name of the plugin AlphaInnotec ({b3225a18-e9b0-443e-8c88-802d3132f94d})
+
+
+
+
+ IntegrationPluginAlphaInnotec
+
+
+ The network device discovery is not available.
+
+
+
+
+ No IP address given
+
+
+
+
diff --git a/debian/control b/debian/control
index b5d0f21..e11bcbf 100644
--- a/debian/control
+++ b/debian/control
@@ -46,6 +46,21 @@ Description: The main libraries and header files for developing with nymea sunsp
.
This package will install the development files for nymea sunspec.
+Package: nymea-plugin-alphainnotec
+Architecture: any
+Section: libs
+Depends: ${shlibs:Depends},
+ ${misc:Depends},
+ nymea-plugins-modbus-translations
+Description: nymea.io plugin for alpha innotec heat pumps
+ 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 alpha innotec heat pumps
+
Package: nymea-plugin-drexelundweiss
Architecture: any
diff --git a/debian/nymea-plugin-alphainnotec.install.in b/debian/nymea-plugin-alphainnotec.install.in
new file mode 100644
index 0000000..ed59ad5
--- /dev/null
+++ b/debian/nymea-plugin-alphainnotec.install.in
@@ -0,0 +1 @@
+usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginalphainnotec.so
diff --git a/modbus/modbusdatautils.cpp b/modbus/modbusdatautils.cpp
index ba1caea..d3fea27 100644
--- a/modbus/modbusdatautils.cpp
+++ b/modbus/modbusdatautils.cpp
@@ -49,13 +49,18 @@ qint16 ModbusDataUtils::convertToInt16(const QVector ®isters)
return static_cast(registers.at(0));
}
-quint32 ModbusDataUtils::convertToUInt32(const QVector ®isters)
+quint32 ModbusDataUtils::convertToUInt32(const QVector ®isters, ByteOrder byteOrder)
{
Q_ASSERT_X(registers.count() == 2, "ModbusDataUtils", "invalid raw data size for converting value to quint32");
QByteArray data;
QDataStream inputStream(&data, QIODevice::WriteOnly);
- inputStream << registers.at(1);
- inputStream << registers.at(0);
+ if (byteOrder == ByteOrderBigEndian) {
+ inputStream << registers.at(0);
+ inputStream << registers.at(1);
+ } else {
+ inputStream << registers.at(1);
+ inputStream << registers.at(0);
+ }
QDataStream outputStream(&data, QIODevice::ReadOnly);
quint32 result = 0;
@@ -63,13 +68,18 @@ quint32 ModbusDataUtils::convertToUInt32(const QVector ®isters)
return result;
}
-qint32 ModbusDataUtils::convertToInt32(const QVector ®isters)
+qint32 ModbusDataUtils::convertToInt32(const QVector ®isters, ByteOrder byteOrder)
{
Q_ASSERT_X(registers.count() == 2, "ModbusDataUtils", "invalid raw data size for converting value to quint32");
QByteArray data;
QDataStream inputStream(&data, QIODevice::WriteOnly);
- inputStream << registers.at(1);
- inputStream << registers.at(0);
+ if (byteOrder == ByteOrderBigEndian) {
+ inputStream << registers.at(0);
+ inputStream << registers.at(1);
+ } else {
+ inputStream << registers.at(1);
+ inputStream << registers.at(0);
+ }
QDataStream outputStream(&data, QIODevice::ReadOnly);
qint32 result = 0;
@@ -77,15 +87,22 @@ qint32 ModbusDataUtils::convertToInt32(const QVector ®isters)
return result;
}
-quint64 ModbusDataUtils::convertToUInt64(const QVector ®isters)
+quint64 ModbusDataUtils::convertToUInt64(const QVector ®isters, ByteOrder byteOrder)
{
Q_ASSERT_X(registers.count() == 4, "ModbusDataUtils", "invalid raw data size for converting value to quint64");
QByteArray data;
QDataStream inputStream(&data, QIODevice::WriteOnly);
- inputStream << registers.at(3);
- inputStream << registers.at(2);
- inputStream << registers.at(1);
- inputStream << registers.at(0);
+ if (byteOrder == ByteOrderBigEndian) {
+ inputStream << registers.at(0);
+ inputStream << registers.at(1);
+ inputStream << registers.at(2);
+ inputStream << registers.at(3);
+ } else {
+ inputStream << registers.at(3);
+ inputStream << registers.at(2);
+ inputStream << registers.at(1);
+ inputStream << registers.at(0);
+ }
QDataStream outputStream(&data, QIODevice::ReadOnly);
quint64 result = 0;
@@ -93,15 +110,22 @@ quint64 ModbusDataUtils::convertToUInt64(const QVector ®isters)
return result;
}
-qint64 ModbusDataUtils::convertToInt64(const QVector ®isters)
+qint64 ModbusDataUtils::convertToInt64(const QVector ®isters, ByteOrder byteOrder)
{
Q_ASSERT_X(registers.count() == 4, "ModbusDataUtils", "invalid raw data size for converting value to qint64");
QByteArray data;
QDataStream inputStream(&data, QIODevice::WriteOnly);
- inputStream << registers.at(3);
- inputStream << registers.at(2);
- inputStream << registers.at(1);
- inputStream << registers.at(0);
+ if (byteOrder == ByteOrderBigEndian) {
+ inputStream << registers.at(0);
+ inputStream << registers.at(1);
+ inputStream << registers.at(2);
+ inputStream << registers.at(3);
+ } else {
+ inputStream << registers.at(3);
+ inputStream << registers.at(2);
+ inputStream << registers.at(1);
+ inputStream << registers.at(0);
+ }
QDataStream outputStream(&data, QIODevice::ReadOnly);
qint64 result = 0;
@@ -120,20 +144,20 @@ QString ModbusDataUtils::convertToString(const QVector ®isters)
return QString::fromUtf8(bytes).trimmed();
}
-float ModbusDataUtils::convertToFloat32(const QVector ®isters)
+float ModbusDataUtils::convertToFloat32(const QVector ®isters, ByteOrder byteOrder)
{
Q_ASSERT_X(registers.count() == 2, "ModbusDataUtils", "invalid raw data size for converting value to float32");
- quint32 rawValue = ModbusDataUtils::convertToUInt32(registers);
+ quint32 rawValue = ModbusDataUtils::convertToUInt32(registers, byteOrder);
float value = 0;
memcpy(&value, &rawValue, sizeof(quint32));
return value;
}
-double ModbusDataUtils::convertToFloat64(const QVector ®isters)
+double ModbusDataUtils::convertToFloat64(const QVector ®isters, ByteOrder byteOrder)
{
Q_ASSERT_X(registers.count() == 4, "ModbusDataUtils", "invalid raw data size for converting value to float64");
- quint64 rawValue = ModbusDataUtils::convertToUInt64(registers);
+ quint64 rawValue = ModbusDataUtils::convertToUInt64(registers, byteOrder);
double value = 0;
memcpy(&value, &rawValue, sizeof(quint64));
return value;
@@ -149,28 +173,33 @@ QVector ModbusDataUtils::convertFromInt16(qint16 value)
return ModbusDataUtils::convertFromUInt16(static_cast(value));
}
-QVector ModbusDataUtils::convertFromUInt32(quint32 value)
+QVector ModbusDataUtils::convertFromUInt32(quint32 value, ByteOrder byteOrder)
{
QByteArray data;
- QDataStream inputStream(&data, QIODevice::WriteOnly);
- inputStream << value;
+ QDataStream inputStream(&data, QIODevice::WriteOnly);
+ inputStream << value;
- QDataStream outputStream(&data, QIODevice::ReadOnly);
- QVector values;
- for (int i = 0; i < 2; i++) {
- quint16 registerValue = 0;
- outputStream >> registerValue;
- values.prepend(registerValue);
- }
- return values;
+ QDataStream outputStream(&data, QIODevice::ReadOnly);
+ QVector values;
+ for (int i = 0; i < 2; i++) {
+ quint16 registerValue = 0;
+ outputStream >> registerValue;
+ if (byteOrder == ByteOrderBigEndian) {
+ values.append(registerValue);
+ } else {
+ values.prepend(registerValue);
+ }
+ }
+
+ return values;
}
-QVector ModbusDataUtils::convertFromInt32(qint32 value)
+QVector ModbusDataUtils::convertFromInt32(qint32 value, ByteOrder byteOrder)
{
- return ModbusDataUtils::convertFromUInt32(static_cast(value));
+ return ModbusDataUtils::convertFromUInt32(static_cast(value), byteOrder);
}
-QVector ModbusDataUtils::convertFromUInt64(quint64 value)
+QVector ModbusDataUtils::convertFromUInt64(quint64 value, ByteOrder byteOrder)
{
QByteArray data;
QDataStream inputStream(&data, QIODevice::WriteOnly);
@@ -181,12 +210,16 @@ QVector ModbusDataUtils::convertFromUInt64(quint64 value)
for (int i = 0; i < 4; i++) {
quint16 registerValue = 0;
outputStream >> registerValue;
- values.prepend(registerValue);
+ if (byteOrder == ByteOrderBigEndian) {
+ values.append(registerValue);
+ } else {
+ values.prepend(registerValue);
+ }
}
return values;
}
-QVector ModbusDataUtils::convertFromInt64(qint64 value)
+QVector ModbusDataUtils::convertFromInt64(qint64 value, ByteOrder byteOrder)
{
QByteArray data;
QDataStream inputStream(&data, QIODevice::WriteOnly);
@@ -197,7 +230,11 @@ QVector ModbusDataUtils::convertFromInt64(qint64 value)
for (int i = 0; i < 4; i++) {
quint16 registerValue = 0;
outputStream >> registerValue;
- values.prepend(registerValue);
+ if (byteOrder == ByteOrderBigEndian) {
+ values.append(registerValue);
+ } else {
+ values.prepend(registerValue);
+ }
}
return values;
}
@@ -216,16 +253,16 @@ QVector ModbusDataUtils::convertFromString(const QString &value, quint1
return values;
}
-QVector ModbusDataUtils::convertFromFloat32(float value)
+QVector ModbusDataUtils::convertFromFloat32(float value, ByteOrder byteOrder)
{
quint32 rawValue = 0;
- memcpy(&rawValue, &value, sizeof(float));
- return ModbusDataUtils::convertFromUInt32(rawValue);
+ memcpy(&rawValue, &value, sizeof(float));
+ return ModbusDataUtils::convertFromUInt32(rawValue, byteOrder);
}
-QVector ModbusDataUtils::convertFromFloat64(double value)
+QVector ModbusDataUtils::convertFromFloat64(double value, ByteOrder byteOrder)
{
quint64 rawValue = 0;
memcpy(&rawValue, &value, sizeof(double));
- return ModbusDataUtils::convertFromUInt64(rawValue);
+ return ModbusDataUtils::convertFromUInt64(rawValue, byteOrder);
}
diff --git a/modbus/modbusdatautils.h b/modbus/modbusdatautils.h
index f442dab..f7a4bc6 100644
--- a/modbus/modbusdatautils.h
+++ b/modbus/modbusdatautils.h
@@ -45,6 +45,12 @@ public:
};
Q_ENUM(Access)
+ enum ByteOrder {
+ ByteOrderLittleEndian,
+ ByteOrderBigEndian
+ };
+ Q_ENUM(ByteOrder)
+
enum DataType {
UInt8,
UInt16,
@@ -78,24 +84,24 @@ public:
// Convert to
static quint16 convertToUInt16(const QVector ®isters);
static qint16 convertToInt16(const QVector ®isters);
- static quint32 convertToUInt32(const QVector ®isters);
- static qint32 convertToInt32(const QVector ®isters);
- static quint64 convertToUInt64(const QVector ®isters);
- static qint64 convertToInt64(const QVector ®isters);
+ static quint32 convertToUInt32(const QVector ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
+ static qint32 convertToInt32(const QVector ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
+ static quint64 convertToUInt64(const QVector ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
+ static qint64 convertToInt64(const QVector ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
static QString convertToString(const QVector ®isters);
- static float convertToFloat32(const QVector ®isters);
- static double convertToFloat64(const QVector ®isters);
+ static float convertToFloat32(const QVector ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
+ static double convertToFloat64(const QVector ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
// Convert from
static QVector convertFromUInt16(quint16 value);
static QVector convertFromInt16(qint16 value);
- static QVector convertFromUInt32(quint32 value);
- static QVector convertFromInt32(qint32 value);
- static QVector convertFromUInt64(quint64 value);
- static QVector convertFromInt64(qint64 value);
+ static QVector convertFromUInt32(quint32 value, ByteOrder byteOrder = ByteOrderLittleEndian);
+ static QVector convertFromInt32(qint32 value, ByteOrder byteOrder = ByteOrderLittleEndian);
+ static QVector convertFromUInt64(quint64 value, ByteOrder byteOrder = ByteOrderLittleEndian);
+ static QVector convertFromInt64(qint64 value, ByteOrder byteOrder = ByteOrderLittleEndian);
static QVector convertFromString(const QString &value, quint16 stringLength);
- static QVector convertFromFloat32(float value);
- static QVector convertFromFloat64(double value);
+ static QVector convertFromFloat32(float value, ByteOrder byteOrder = ByteOrderLittleEndian);
+ static QVector convertFromFloat64(double value, ByteOrder byteOrder = ByteOrderLittleEndian);
};
#endif // MODBUSDATAUTILS_H
diff --git a/modbus/tools/README.md b/modbus/tools/README.md
index b8d4127..400b082 100644
--- a/modbus/tools/README.md
+++ b/modbus/tools/README.md
@@ -23,6 +23,7 @@ The basic structure of the modbus register JSON looks like following example:
```
{
+ "endianness": "BigEndian",
"enums": [
{
"name": "NameOfEnum",
@@ -68,6 +69,15 @@ The basic structure of the modbus register JSON looks like following example:
```
+## Endianness
+
+When converting multiple registers to one data type (i.e. 2 registers uint16 values to one uint32), the order of the registers are important to align with the endiness of the data receiving.
+
+There are 2 possibilities:
+
+* `BigEndian`: default if not specified: register bytes come in following order `[0, 1, 2, 3]`: `ABCD`
+* `LittleEndian`: register bytes come in following order `[0, 1, 2, 3]`: `CDAB`
+
## Enums
Many modbus devices provide inforation using `Enums`, indicating a special state trough a defined list of values. If a register implements an enum, you can define it in the `enums` section. The `name` property defines the name of the enum, and the script will generate a c++ enum definition from this section. Each enum value will then be generated using ` = `.
diff --git a/modbus/tools/generate-connection.py b/modbus/tools/generate-connection.py
index f6be585..83f3214 100644
--- a/modbus/tools/generate-connection.py
+++ b/modbus/tools/generate-connection.py
@@ -129,12 +129,13 @@ def writeEnumDefinition(fileDescriptor, enumDefinition):
writeLine(fileDescriptor)
-def getCppDataType(registerDefinition):
- if 'enum' in registerDefinition:
- return registerDefinition['enum']
+def getCppDataType(registerDefinition, rawType = False):
+ if not rawType:
+ if 'enum' in registerDefinition:
+ return registerDefinition['enum']
- if 'scaleFactor' in registerDefinition:
- return 'float'
+ if 'scaleFactor' in registerDefinition or 'staticScaleFactor' in registerDefinition:
+ return 'float'
if registerDefinition['type'] == 'uint16':
return 'quint16'
@@ -164,7 +165,68 @@ def getCppDataType(registerDefinition):
return 'QString'
+def getConversionToValueMethod(registerDefinition):
+ # Handle enums
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition, True)
+
+ if 'enum' in registerDefinition:
+ enumName = registerDefinition['enum']
+ if registerDefinition['type'] == 'uint16':
+ return ('ModbusDataUtils::convertFromUInt16(static_cast<%s>(%s))' % (propertyTyp, propertyName))
+ elif registerDefinition['type'] == 'int16':
+ return ('ModbusDataUtils::convertFromInt16(static_cast<%s>(%s))' % (propertyTyp, propertyName))
+ elif registerDefinition['type'] == 'uint32':
+ return ('ModbusDataUtils::convertFromUInt32(static_cast<%s>(%s), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, endianness))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, endianness))
+
+ # Handle scale factors
+ if 'scaleFactor' in registerDefinition:
+ scaleFactorProperty = 'm_%s' % registerDefinition['scaleFactor']
+ if registerDefinition['type'] == 'uint16':
+ return ('ModbusDataUtils::convertFromUInt16(static_cast<%s>(%s * 1.0 / pow(10, %s)))' % (propertyTyp, propertyName, scaleFactorProperty))
+ elif registerDefinition['type'] == 'int16':
+ return ('ModbusDataUtils::convertFromInt16(static_cast<%s>(%s * 1.0 / pow(10, %s)))' % (propertyTyp, propertyName, scaleFactorProperty))
+ elif registerDefinition['type'] == 'uint32':
+ return ('ModbusDataUtils::convertFromUInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, scaleFactorProperty, endianness))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, scaleFactorProperty, endianness))
+
+ elif 'staticScaleFactor' in registerDefinition:
+ scaleFactor = registerDefinition['staticScaleFactor']
+ if registerDefinition['type'] == 'uint16':
+ return ('ModbusDataUtils::convertFromUInt16(static_cast<%s>(%s * 1.0 / pow(10, %s)))' % (propertyTyp, propertyName, scaleFactor))
+ elif registerDefinition['type'] == 'int16':
+ return ('ModbusDataUtils::convertFromInt16(static_cast<%s>(%s * 1.0 / pow(10, %s)))' % (propertyTyp, propertyName, scaleFactor))
+ elif registerDefinition['type'] == 'uint32':
+ return ('ModbusDataUtils::convertFromUInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, scaleFactor, endianness))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, scaleFactor, endianness))
+
+ # Handle default types
+ elif registerDefinition['type'] == 'uint16':
+ return ('ModbusDataUtils::convertFromUInt16(%s)' % propertyName)
+ elif registerDefinition['type'] == 'int16':
+ return ('ModbusDataUtils::convertFromInt16(%s)' % propertyName)
+ elif registerDefinition['type'] == 'uint32':
+ return ('ModbusDataUtils::convertFromUInt32(%s, ModbusDataUtils::ByteOrder%s)' % (propertyName, endianness))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertFromInt32(%s, ModbusDataUtils::ByteOrder%s)' % (propertyName, endianness))
+ elif registerDefinition['type'] == 'uint64':
+ return ('ModbusDataUtils::convertFromUInt64(%s, ModbusDataUtils::ByteOrder%s)' % (propertyName, endianness))
+ elif registerDefinition['type'] == 'int64':
+ return ('ModbusDataUtils::convertFromInt64(%s, ModbusDataUtils::ByteOrder%s)' % (propertyName, endianness))
+ elif registerDefinition['type'] == 'float':
+ return ('ModbusDataUtils::convertFromFloat32(%s, ModbusDataUtils::ByteOrder%s)' % propertyName, endianness)
+ elif registerDefinition['type'] == 'float64':
+ return ('ModbusDataUtils::convertFromFloat64(%s, ModbusDataUtils::ByteOrder%s)' % propertyName, endianness)
+ elif registerDefinition['type'] == 'string':
+ return ('ModbusDataUtils::convertFromString(%s)' % propertyName)
+
+
def getValueConversionMethod(registerDefinition):
+ # Handle enums
if 'enum' in registerDefinition:
enumName = registerDefinition['enum']
if registerDefinition['type'] == 'uint16':
@@ -172,10 +234,11 @@ def getValueConversionMethod(registerDefinition):
elif registerDefinition['type'] == 'int16':
return ('static_cast<%s>(ModbusDataUtils::convertToInt16(unit.values()))' % (enumName))
elif registerDefinition['type'] == 'uint32':
- return ('static_cast<%s>(ModbusDataUtils::convertToUInt32(unit.values()))' % (enumName))
+ return ('static_cast<%s>(ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
elif registerDefinition['type'] == 'int32':
- return ('static_cast<%s>(ModbusDataUtils::convertToInt32(unit.values()))' % (enumName))
+ return ('static_cast<%s>(ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
+ # Handle scale factors
if 'scaleFactor' in registerDefinition:
scaleFactorProperty = 'm_%s' % registerDefinition['scaleFactor']
if registerDefinition['type'] == 'uint16':
@@ -183,32 +246,43 @@ def getValueConversionMethod(registerDefinition):
elif registerDefinition['type'] == 'int16':
return ('ModbusDataUtils::convertToInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
elif registerDefinition['type'] == 'uint32':
- return ('ModbusDataUtils::convertToUInt32(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
+ return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactorProperty))
elif registerDefinition['type'] == 'int32':
- return ('ModbusDataUtils::convertToInt32(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
+ return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactorProperty))
+ elif 'staticScaleFactor' in registerDefinition:
+ scaleFactor = registerDefinition['staticScaleFactor']
+ if registerDefinition['type'] == 'uint16':
+ return ('ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactor))
+ elif registerDefinition['type'] == 'int16':
+ return ('ModbusDataUtils::convertToInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactor))
+ elif registerDefinition['type'] == 'uint32':
+ return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
+ # Handle default types
elif registerDefinition['type'] == 'uint16':
return ('ModbusDataUtils::convertToUInt16(unit.values())')
elif registerDefinition['type'] == 'int16':
return ('ModbusDataUtils::convertToInt16(unit.values())')
elif registerDefinition['type'] == 'uint32':
- return ('ModbusDataUtils::convertToUInt32(unit.values())')
+ return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'int32':
- return ('ModbusDataUtils::convertToInt32(unit.values())')
+ return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'uint64':
- return ('ModbusDataUtils::convertToUInt64(unit.values())')
+ return ('ModbusDataUtils::convertToUInt64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'int64':
- return ('ModbusDataUtils::convertToInt64(unit.values())')
+ return ('ModbusDataUtils::convertToInt64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'float':
- return ('ModbusDataUtils::convertToFloat32(unit.values())')
+ return ('ModbusDataUtils::convertToFloat32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'float64':
- return ('ModbusDataUtils::convertToFloat64(unit.values())')
+ return ('ModbusDataUtils::convertToFloat64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'string':
return ('ModbusDataUtils::convertToString(unit.values())')
-def writePropertyGetMethodDeclarations(fileDescriptor, registerDefinitions):
+def writePropertyGetSetMethodDeclarations(fileDescriptor, registerDefinitions):
for registerDefinition in registerDefinitions:
propertyName = registerDefinition['id']
propertyTyp = getCppDataType(registerDefinition)
@@ -218,13 +292,19 @@ def writePropertyGetMethodDeclarations(fileDescriptor, registerDefinitions):
writeLine(fileDescriptor, ' /* %s - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
writeLine(fileDescriptor, ' %s %s() const;' % (propertyTyp, propertyName))
+
+ # Check if we require a set method
+ if registerDefinition['access'] == 'RW' or registerDefinition['access'] == 'WO':
+ writeLine(fileDescriptor, ' QModbusReply *set%s(%s %s);' % (propertyName[0].upper() + propertyName[1:], propertyTyp, propertyName))
+
writeLine(fileDescriptor)
-def writePropertyGetMethodImplementations(fileDescriptor, className, registerDefinitions):
+def writePropertyGetSetMethodImplementations(fileDescriptor, className, registerDefinitions):
for registerDefinition in registerDefinitions:
propertyName = registerDefinition['id']
propertyTyp = getCppDataType(registerDefinition)
+ # Get
if 'enum' in registerDefinition:
writeLine(fileDescriptor, '%s::%s %s::%s() const' % (className, propertyTyp, className, propertyName))
else:
@@ -235,6 +315,24 @@ def writePropertyGetMethodImplementations(fileDescriptor, className, registerDef
writeLine(fileDescriptor, '}')
writeLine(fileDescriptor)
+ # Check if we require a set method
+ if registerDefinition['access'] == 'RW' or registerDefinition['access'] == 'WO':
+ writeLine(fileDescriptor, 'QModbusReply *%s::set%s(%s %s)' % (className, propertyName[0].upper() + propertyName[1:], propertyTyp, propertyName))
+ writeLine(fileDescriptor, '{')
+
+ writeLine(fileDescriptor, ' QVector values = %s;' % getConversionToValueMethod(registerDefinition))
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Write \\"%s\\" register:" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ if registerDefinition['registerType'] == 'holdingRegister':
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, %s, values.count());' % (registerDefinition['address']))
+
+ # TODO: other write methods
+
+ writeLine(fileDescriptor, ' request.setValues(values);')
+ writeLine(fileDescriptor, ' return sendWriteRequest(request, m_slaveId);')
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+
def writePropertyUpdateMethodDeclarations(fileDescriptor, registerDefinitions):
for registerDefinition in registerDefinitions:
@@ -256,6 +354,7 @@ def writePropertyUpdateMethodImplementations(fileDescriptor, className, register
writeLine(fileDescriptor, 'void %s::update%s()' % (className, propertyName[0].upper() + propertyName[1:]))
writeLine(fileDescriptor, '{')
writeLine(fileDescriptor, ' // Update registers from %s' % registerDefinition['description'])
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read \\"%s\\" register:" << %s << "size:" << %s;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
writeLine(fileDescriptor, ' QModbusReply *reply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
writeLine(fileDescriptor, ' if (reply) {')
writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
@@ -263,6 +362,9 @@ def writePropertyUpdateMethodImplementations(fileDescriptor, className, register
writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){')
writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {')
writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();')
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+
+ # FIXME: introduce bool and check register type for parsing
writeLine(fileDescriptor, ' %s received%s = %s;' % (propertyTyp, propertyName[0].upper() + propertyName[1:], getValueConversionMethod(registerDefinition)))
writeLine(fileDescriptor, ' if (m_%s != received%s) {' % (propertyName, propertyName[0].upper() + propertyName[1:]))
writeLine(fileDescriptor, ' m_%s = received%s;' % (propertyName, propertyName[0].upper() + propertyName[1:]))
@@ -296,7 +398,18 @@ def writeInternalPropertyReadMethodImplementations(fileDescriptor, className, re
propertyName = registerDefinition['id']
writeLine(fileDescriptor, 'QModbusReply *%s::read%s()' % (className, propertyName[0].upper() + propertyName[1:]))
writeLine(fileDescriptor, '{')
- writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+
+ # Build request depending on the register type
+ if registerDefinition['registerType'] == 'inputRegister':
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+ elif registerDefinition['registerType'] == 'discreteInputs':
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::DiscreteInputs, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+ elif registerDefinition['registerType'] == 'coils':
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+ else:
+ #Default to holdingRegister
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+
writeLine(fileDescriptor, ' return sendReadRequest(request, m_slaveId);')
writeLine(fileDescriptor, '}')
writeLine(fileDescriptor)
@@ -326,52 +439,63 @@ def writeInitializeMethod(fileDescriptor, className, registerDefinitions):
writeLine(fileDescriptor, 'void %s::initialize()' % (className))
writeLine(fileDescriptor, '{')
- writeLine(fileDescriptor, ' QModbusReply *reply = nullptr;')
- writeLine(fileDescriptor)
- writeLine(fileDescriptor, ' if (!m_pendingInitReplies.isEmpty()) {')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Tried to initialize but there are still some init replies pending.";' % className)
- writeLine(fileDescriptor, ' return;')
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor)
-
+ # First check if there are any init registers
+ initRequired = False
for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
+ if registerDefinition['readSchedule'] == 'init':
+ initRequired = True
+ break
- if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
- writeLine(fileDescriptor, ' // Read %s' % registerDefinition['description'])
- writeLine(fileDescriptor, ' reply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
- writeLine(fileDescriptor, ' if (reply) {')
- writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
- writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);')
- writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);')
- writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){')
- writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {')
- writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();')
- writeLine(fileDescriptor, ' %s received%s = %s;' % (propertyTyp, propertyName[0].upper() + propertyName[1:], getValueConversionMethod(registerDefinition)))
- writeLine(fileDescriptor, ' if (m_%s != received%s) {' % (propertyName, propertyName[0].upper() + propertyName[1:]))
- writeLine(fileDescriptor, ' m_%s = received%s;' % (propertyName, propertyName[0].upper() + propertyName[1:]))
- writeLine(fileDescriptor, ' emit %sChanged(m_%s);' % (propertyName, propertyName))
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor)
- writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);')
- writeLine(fileDescriptor, ' verifyInitFinished();')
- writeLine(fileDescriptor, ' });')
- writeLine(fileDescriptor)
- writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description']))
- writeLine(fileDescriptor, ' emit reply->finished(); // To make sure it will be deleted')
- writeLine(fileDescriptor, ' });')
- writeLine(fileDescriptor, ' } else {')
- writeLine(fileDescriptor, ' delete reply; // Broadcast reply returns immediatly')
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' } else {')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << errorString();' % (className, registerDefinition['description']))
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor)
+ if initRequired:
+ writeLine(fileDescriptor, ' QModbusReply *reply = nullptr;')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' if (!m_pendingInitReplies.isEmpty()) {')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Tried to initialize but there are still some init replies pending.";' % className)
+ writeLine(fileDescriptor, ' return;')
+ writeLine(fileDescriptor, ' }')
+
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+
+ if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' // Read %s' % registerDefinition['description'])
+ writeLine(fileDescriptor, ' reply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, ' if (reply) {')
+ writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
+ writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);')
+ writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);')
+ writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){')
+ writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {')
+ writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();')
+ writeLine(fileDescriptor, ' %s received%s = %s;' % (propertyTyp, propertyName[0].upper() + propertyName[1:], getValueConversionMethod(registerDefinition)))
+ writeLine(fileDescriptor, ' if (m_%s != received%s) {' % (propertyName, propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, ' m_%s = received%s;' % (propertyName, propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, ' emit %sChanged(m_%s);' % (propertyName, propertyName))
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);')
+ writeLine(fileDescriptor, ' verifyInitFinished();')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description']))
+ writeLine(fileDescriptor, ' emit reply->finished(); // To make sure it will be deleted')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor, ' } else {')
+ writeLine(fileDescriptor, ' delete reply; // Broadcast reply returns immediatly')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' } else {')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << errorString();' % (className, registerDefinition['description']))
+ writeLine(fileDescriptor, ' }')
+
+
+ else:
+ writeLine(fileDescriptor, ' // No init registers defined. Nothing to be done and we are finished.')
+ writeLine(fileDescriptor, ' emit initializationFinished();')
- writeLine(fileDescriptor, ' ')
writeLine(fileDescriptor, '}')
writeLine(fileDescriptor)
@@ -417,6 +541,11 @@ print('Source file: %s' % sourceFileName)
print('Header file path: %s' % headerFilePath)
print('Source file path: %s' % sourceFilePath)
+endianness = 'BigEndian'
+if 'endianness' in registerJson:
+ endianness = registerJson['endianness']
+
+
#############################################################################
# Write header file
#############################################################################
@@ -452,7 +581,7 @@ writeLine(headerFile, ' ~%s() = default;' % className)
writeLine(headerFile)
# Write registers get method declarations
-writePropertyGetMethodDeclarations(headerFile, registerJson['registers'])
+writePropertyGetSetMethodDeclarations(headerFile, registerJson['registers'])
# Write init and update method declarations
writeLine(headerFile, ' virtual void initialize();')
@@ -516,7 +645,7 @@ writeLine(sourceFile, '}')
writeLine(sourceFile)
# Property get methods
-writePropertyGetMethodImplementations(sourceFile, className, registerJson['registers'])
+writePropertyGetSetMethodImplementations(sourceFile, className, registerJson['registers'])
# Write init and update method implementation
writeInitializeMethod(sourceFile, className, registerJson['registers'])
diff --git a/nymea-plugins-modbus.pro b/nymea-plugins-modbus.pro
index 2afbded..d27afcf 100644
--- a/nymea-plugins-modbus.pro
+++ b/nymea-plugins-modbus.pro
@@ -5,6 +5,7 @@ CONFIG += ordered
SUBDIRS += libnymea-sunspec
PLUGIN_DIRS = \
+ alphainnotec \
drexelundweiss \
energymeters \
modbuscommander \