diff --git a/.gitignore b/.gitignore
index d73d76c..9e237a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
builddir
doc/html
*.qm
+__pycache__
diff --git a/alphainnotec/alphaconnectmodbustcpconnection.cpp b/alphainnotec/alphaconnectmodbustcpconnection.cpp
deleted file mode 100644
index 9f6dd9b..0000000
--- a/alphainnotec/alphaconnectmodbustcpconnection.cpp
+++ /dev/null
@@ -1,1273 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* 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
deleted file mode 100644
index 4b27fd1..0000000
--- a/alphainnotec/alphaconnectmodbustcpconnection.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* 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
index 1908e0d..2068ce0 100644
--- a/alphainnotec/alphainnotec-registers.json
+++ b/alphainnotec/alphainnotec-registers.json
@@ -1,4 +1,6 @@
{
+ "className": "AlphaInnotec",
+ "protocol": "TCP",
"endianness": "BigEndian",
"enums": [
{
@@ -397,5 +399,6 @@
"defaultValue": "SmartGridStateStandard",
"access": "RW"
}
- ]
+ ],
+ "blocks": [ ]
}
diff --git a/alphainnotec/alphainnotec.pro b/alphainnotec/alphainnotec.pro
index b88c856..18fd540 100644
--- a/alphainnotec/alphainnotec.pro
+++ b/alphainnotec/alphainnotec.pro
@@ -1,15 +1,12 @@
include(../plugins.pri)
-QT += network serialbus
+# Generate modbus connection
+MODBUS_CONNECTIONS += alphainnotec-registers.json
+#MODBUS_TOOLS_CONFIG += VERBOSE
+include(../modbus.pri)
SOURCES += \
- integrationpluginalphainnotec.cpp \
- alphaconnectmodbustcpconnection.cpp \
- ../modbus/modbustcpmaster.cpp \
- ../modbus/modbusdatautils.cpp
+ integrationpluginalphainnotec.cpp
HEADERS += \
- integrationpluginalphainnotec.h \
- alphaconnectmodbustcpconnection.h \
- ../modbus/modbustcpmaster.h \
- ../modbus/modbusdatautils.h
+ integrationpluginalphainnotec.h
diff --git a/alphainnotec/integrationpluginalphainnotec.cpp b/alphainnotec/integrationpluginalphainnotec.cpp
index 153d6b3..96b6f96 100644
--- a/alphainnotec/integrationpluginalphainnotec.cpp
+++ b/alphainnotec/integrationpluginalphainnotec.cpp
@@ -29,11 +29,11 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "integrationpluginalphainnotec.h"
-
-#include "network/networkdevicediscovery.h"
-#include "hardwaremanager.h"
#include "plugininfo.h"
+#include
+#include
+
IntegrationPluginAlphaInnotec::IntegrationPluginAlphaInnotec()
{
@@ -107,8 +107,8 @@ void IntegrationPluginAlphaInnotec::setupThing(ThingSetupInfo *info)
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){
+ AlphaInnotecModbusTcpConnection *alphaConnectTcpConnection = new AlphaInnotecModbusTcpConnection(hostAddress, port, slaveId, this);
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::connectionStateChanged, this, [thing, alphaConnectTcpConnection](bool status){
qCDebug(dcAlphaInnotec()) << "Connected changed to" << status << "for" << thing;
if (status) {
alphaConnectTcpConnection->update();
@@ -119,181 +119,181 @@ void IntegrationPluginAlphaInnotec::setupThing(ThingSetupInfo *info)
// Input registers
-// connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::meanTemperatureChanged, this, [thing](float meanTemperature){
+// connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::systemStatusChanged, this, [thing](AlphaInnotecModbusTcpConnection::SystemStatus systemStatus){
qCDebug(dcAlphaInnotec()) << thing << "system status changed" << systemStatus;
switch (systemStatus) {
- case AlphaConnectModbusTcpConnection::SystemStatusHeatingMode:
+ case AlphaInnotecModbusTcpConnection::SystemStatusHeatingMode:
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Heating mode");
break;
- case AlphaConnectModbusTcpConnection::SystemStatusDomesticHotWater:
+ case AlphaInnotecModbusTcpConnection::SystemStatusDomesticHotWater:
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Domestic hot water");
break;
- case AlphaConnectModbusTcpConnection::SystemStatusSwimmingPool:
+ case AlphaInnotecModbusTcpConnection::SystemStatusSwimmingPool:
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Swimming pool");
break;
- case AlphaConnectModbusTcpConnection::SystemStatusEVUOff:
+ case AlphaInnotecModbusTcpConnection::SystemStatusEVUOff:
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "EUV off");
break;
- case AlphaConnectModbusTcpConnection::SystemStatusDefrost:
+ case AlphaInnotecModbusTcpConnection::SystemStatusDefrost:
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Defrost");
break;
- case AlphaConnectModbusTcpConnection::SystemStatusOff:
+ case AlphaInnotecModbusTcpConnection::SystemStatusOff:
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Off");
break;
- case AlphaConnectModbusTcpConnection::SystemStatusExternalEnergySource:
+ case AlphaInnotecModbusTcpConnection::SystemStatusExternalEnergySource:
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "External energy source");
break;
- case AlphaConnectModbusTcpConnection::SystemStatusCoolingMode:
+ case AlphaInnotecModbusTcpConnection::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);
+ thing->setStateValue(alphaConnectHeatingOnStateTypeId, systemStatus == AlphaInnotecModbusTcpConnection::SystemStatusHeatingMode);
+ thing->setStateValue(alphaConnectCoolingOnStateTypeId, systemStatus == AlphaInnotecModbusTcpConnection::SystemStatusCoolingMode);
});
// Energy
- connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::totalHeatEnergyChanged, this, [thing](float totalHeatEnergy){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+// connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::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){
+ connect(alphaConnectTcpConnection, &AlphaInnotecModbusTcpConnection::smartGridChanged, this, [thing](AlphaInnotecModbusTcpConnection::SmartGridState smartGridState){
qCDebug(dcAlphaInnotec()) << thing << "smart grid state changed" << smartGridState;
switch (smartGridState) {
- case AlphaConnectModbusTcpConnection::SmartGridStateOff:
+ case AlphaInnotecModbusTcpConnection::SmartGridStateOff:
thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Off");
break;
- case AlphaConnectModbusTcpConnection::SmartGridStateLow:
+ case AlphaInnotecModbusTcpConnection::SmartGridStateLow:
thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Low");
break;
- case AlphaConnectModbusTcpConnection::SmartGridStateStandard:
+ case AlphaInnotecModbusTcpConnection::SmartGridStateStandard:
thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Standard");
break;
- case AlphaConnectModbusTcpConnection::SmartGridStateHigh:
+ case AlphaInnotecModbusTcpConnection::SmartGridStateHigh:
thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "High");
break;
}
});
- m_alpaConnectTcpThings.insert(thing, alphaConnectTcpConnection);
+ m_connections.insert(thing, alphaConnectTcpConnection);
alphaConnectTcpConnection->connectDevice();
// FIXME: make async and check if this is really an alpha connect
@@ -308,7 +308,7 @@ void IntegrationPluginAlphaInnotec::postSetupThing(Thing *thing)
qCDebug(dcAlphaInnotec()) << "Starting plugin timer...";
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
- foreach (AlphaConnectModbusTcpConnection *connection, m_alpaConnectTcpThings) {
+ foreach (AlphaInnotecModbusTcpConnection *connection, m_connections) {
if (connection->connected()) {
connection->update();
}
@@ -322,8 +322,8 @@ void IntegrationPluginAlphaInnotec::postSetupThing(Thing *thing)
void IntegrationPluginAlphaInnotec::thingRemoved(Thing *thing)
{
- if (thing->thingClassId() == alphaConnectThingClassId && m_alpaConnectTcpThings.contains(thing)) {
- AlphaConnectModbusTcpConnection *connection = m_alpaConnectTcpThings.take(thing);
+ if (thing->thingClassId() == alphaConnectThingClassId && m_connections.contains(thing)) {
+ AlphaInnotecModbusTcpConnection *connection = m_connections.take(thing);
delete connection;
}
@@ -336,7 +336,7 @@ void IntegrationPluginAlphaInnotec::thingRemoved(Thing *thing)
void IntegrationPluginAlphaInnotec::executeAction(ThingActionInfo *info)
{
Thing *thing = info->thing();
- AlphaConnectModbusTcpConnection *connection = m_alpaConnectTcpThings.value(thing);
+ AlphaInnotecModbusTcpConnection *connection = m_connections.value(thing);
if (!connection->connected()) {
qCWarning(dcAlphaInnotec()) << "Could not execute action. The modbus connection is currently not available.";
@@ -430,15 +430,15 @@ void IntegrationPluginAlphaInnotec::executeAction(ThingActionInfo *info)
} 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;
+ AlphaInnotecModbusTcpConnection::SmartGridState sgReadyState;
if (sgReadyModeString == "Off") {
- sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateOff;
+ sgReadyState = AlphaInnotecModbusTcpConnection::SmartGridStateOff;
} else if (sgReadyModeString == "Low") {
- sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateLow;
+ sgReadyState = AlphaInnotecModbusTcpConnection::SmartGridStateLow;
} else if (sgReadyModeString == "High") {
- sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateHigh;
+ sgReadyState = AlphaInnotecModbusTcpConnection::SmartGridStateHigh;
} else {
- sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateStandard;
+ sgReadyState = AlphaInnotecModbusTcpConnection::SmartGridStateStandard;
}
QModbusReply *reply = connection->setSmartGrid(sgReadyState);
diff --git a/alphainnotec/integrationpluginalphainnotec.h b/alphainnotec/integrationpluginalphainnotec.h
index 0f6a4cc..8f94c4a 100644
--- a/alphainnotec/integrationpluginalphainnotec.h
+++ b/alphainnotec/integrationpluginalphainnotec.h
@@ -31,9 +31,10 @@
#ifndef INTEGRATIONPLUGINALPHAINNOTEC_H
#define INTEGRATIONPLUGINALPHAINNOTEC_H
-#include "plugintimer.h"
-#include "alphaconnectmodbustcpconnection.h"
-#include "integrations/integrationplugin.h"
+#include
+#include
+
+#include "alphainnotecmodbustcpconnection.h"
class IntegrationPluginAlphaInnotec: public IntegrationPlugin
{
@@ -54,7 +55,7 @@ public:
private:
PluginTimer *m_pluginTimer = nullptr;
- QHash m_alpaConnectTcpThings;
+ QHash m_connections;
};
#endif // INTEGRATIONPLUGINALPHAINNOTEC_H
diff --git a/bgetech/bgetech.pro b/bgetech/bgetech.pro
index 080685d..bb12ae8 100644
--- a/bgetech/bgetech.pro
+++ b/bgetech/bgetech.pro
@@ -1,14 +1,13 @@
include(../plugins.pri)
-QT += serialport serialbus
+# Generate modbus connection
+MODBUS_CONNECTIONS += sdm630-registers.json
+#MODBUS_TOOLS_CONFIG += VERBOSE
+include(../modbus.pri)
HEADERS += \
- integrationpluginbgetech.h \
- sdm630modbusrtuconnection.h \
- ../modbus/modbusdatautils.h
+ integrationpluginbgetech.h
SOURCES += \
- integrationpluginbgetech.cpp \
- sdm630modbusrtuconnection.cpp \
- ../modbus/modbusdatautils.cpp
+ integrationpluginbgetech.cpp
diff --git a/bgetech/sdm630-registers.json b/bgetech/sdm630-registers.json
index b4d9f0d..1bdbabf 100644
--- a/bgetech/sdm630-registers.json
+++ b/bgetech/sdm630-registers.json
@@ -1,4 +1,5 @@
{
+ "className": "Sdm630",
"protocol": "RTU",
"endianness": "BigEndian",
"registers": [
@@ -257,4 +258,4 @@
]
}
]
-}
\ No newline at end of file
+}
diff --git a/bgetech/sdm630modbusrtuconnection.cpp b/bgetech/sdm630modbusrtuconnection.cpp
deleted file mode 100644
index 1134d2f..0000000
--- a/bgetech/sdm630modbusrtuconnection.cpp
+++ /dev/null
@@ -1,455 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* 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 "sdm630modbusrtuconnection.h"
-#include "loggingcategories.h"
-
-NYMEA_LOGGING_CATEGORY(dcSdm630ModbusRtuConnection, "Sdm630ModbusRtuConnection")
-
-Sdm630ModbusRtuConnection::Sdm630ModbusRtuConnection(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent) :
- QObject(parent),
- m_modbusRtuMaster(modbusRtuMaster),
- m_slaveId(slaveId)
-{
-
-}
-
-ModbusRtuMaster *Sdm630ModbusRtuConnection::modbusRtuMaster() const
-{
- return m_modbusRtuMaster;
-}
-quint16 Sdm630ModbusRtuConnection::slaveId() const
-{
- return m_slaveId;
-}
-float Sdm630ModbusRtuConnection::totalCurrentPower() const
-{
- return m_totalCurrentPower;
-}
-
-float Sdm630ModbusRtuConnection::voltagePhaseA() const
-{
- return m_voltagePhaseA;
-}
-
-float Sdm630ModbusRtuConnection::voltagePhaseB() const
-{
- return m_voltagePhaseB;
-}
-
-float Sdm630ModbusRtuConnection::voltagePhaseC() const
-{
- return m_voltagePhaseC;
-}
-
-float Sdm630ModbusRtuConnection::currentPhaseA() const
-{
- return m_currentPhaseA;
-}
-
-float Sdm630ModbusRtuConnection::currentPhaseB() const
-{
- return m_currentPhaseB;
-}
-
-float Sdm630ModbusRtuConnection::currentPhaseC() const
-{
- return m_currentPhaseC;
-}
-
-float Sdm630ModbusRtuConnection::powerPhaseA() const
-{
- return m_powerPhaseA;
-}
-
-float Sdm630ModbusRtuConnection::powerPhaseB() const
-{
- return m_powerPhaseB;
-}
-
-float Sdm630ModbusRtuConnection::powerPhaseC() const
-{
- return m_powerPhaseC;
-}
-
-float Sdm630ModbusRtuConnection::frequency() const
-{
- return m_frequency;
-}
-
-float Sdm630ModbusRtuConnection::totalEnergyConsumed() const
-{
- return m_totalEnergyConsumed;
-}
-
-float Sdm630ModbusRtuConnection::totalEnergyProduced() const
-{
- return m_totalEnergyProduced;
-}
-
-float Sdm630ModbusRtuConnection::energyProducedPhaseA() const
-{
- return m_energyProducedPhaseA;
-}
-
-float Sdm630ModbusRtuConnection::energyProducedPhaseB() const
-{
- return m_energyProducedPhaseB;
-}
-
-float Sdm630ModbusRtuConnection::energyProducedPhaseC() const
-{
- return m_energyProducedPhaseC;
-}
-
-float Sdm630ModbusRtuConnection::energyConsumedPhaseA() const
-{
- return m_energyConsumedPhaseA;
-}
-
-float Sdm630ModbusRtuConnection::energyConsumedPhaseB() const
-{
- return m_energyConsumedPhaseB;
-}
-
-float Sdm630ModbusRtuConnection::energyConsumedPhaseC() const
-{
- return m_energyConsumedPhaseC;
-}
-
-void Sdm630ModbusRtuConnection::initialize()
-{
- // No init registers defined. Nothing to be done and we are finished.
- emit initializationFinished();
-}
-
-void Sdm630ModbusRtuConnection::update()
-{
- updateTotalCurrentPower();
- updatePhaseVoltageAndCurrentBlock();
- updatePhasePowerBlock();
- updateFrequencyAndTotalEnergyBlock();
- updatePhaseEnergyEnergyBlock();
-}
-
-void Sdm630ModbusRtuConnection::updateTotalCurrentPower()
-{
- // Update registers from Total system power
- qCDebug(dcSdm630ModbusRtuConnection()) << "--> Read \"Total system power\" register:" << 52 << "size:" << 2;
- ModbusRtuReply *reply = readTotalCurrentPower();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcSdm630ModbusRtuConnection()) << "<-- Response from \"Total system power\" register" << 52 << "size:" << 2 << values;
- float receivedTotalCurrentPower = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_totalCurrentPower != receivedTotalCurrentPower) {
- m_totalCurrentPower = receivedTotalCurrentPower;
- emit totalCurrentPowerChanged(m_totalCurrentPower);
- }
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcSdm630ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Total system power\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcSdm630ModbusRtuConnection()) << "Error occurred while reading \"Total system power\" registers";
- }
-}
-
-void Sdm630ModbusRtuConnection::updatePhaseVoltageAndCurrentBlock()
-{
- // Update register block "phaseVoltageAndCurrent"
- qCDebug(dcSdm630ModbusRtuConnection()) << "--> Read block \"phaseVoltageAndCurrent\" registers from:" << 0 << "size:" << 12;
- ModbusRtuReply *reply = m_modbusRtuMaster->readInputRegister(m_slaveId, 0, 12);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcSdm630ModbusRtuConnection()) << "<-- Response from reading block \"phaseVoltageAndCurrent\" register" << 0 << "size:" << 12 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedVoltagePhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_voltagePhaseA != receivedVoltagePhaseA) {
- m_voltagePhaseA = receivedVoltagePhaseA;
- emit voltagePhaseAChanged(m_voltagePhaseA);
- }
-
- values = blockValues.mid(2, 2);
- float receivedVoltagePhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_voltagePhaseB != receivedVoltagePhaseB) {
- m_voltagePhaseB = receivedVoltagePhaseB;
- emit voltagePhaseBChanged(m_voltagePhaseB);
- }
-
- values = blockValues.mid(4, 2);
- float receivedVoltagePhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_voltagePhaseC != receivedVoltagePhaseC) {
- m_voltagePhaseC = receivedVoltagePhaseC;
- emit voltagePhaseCChanged(m_voltagePhaseC);
- }
-
- values = blockValues.mid(6, 2);
- float receivedCurrentPhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_currentPhaseA != receivedCurrentPhaseA) {
- m_currentPhaseA = receivedCurrentPhaseA;
- emit currentPhaseAChanged(m_currentPhaseA);
- }
-
- values = blockValues.mid(8, 2);
- float receivedCurrentPhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_currentPhaseB != receivedCurrentPhaseB) {
- m_currentPhaseB = receivedCurrentPhaseB;
- emit currentPhaseBChanged(m_currentPhaseB);
- }
-
- values = blockValues.mid(10, 2);
- float receivedCurrentPhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_currentPhaseC != receivedCurrentPhaseC) {
- m_currentPhaseC = receivedCurrentPhaseC;
- emit currentPhaseCChanged(m_currentPhaseC);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcSdm630ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"phaseVoltageAndCurrent\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcSdm630ModbusRtuConnection()) << "Error occurred while reading block \"phaseVoltageAndCurrent\" registers";
- }
-}
-
-void Sdm630ModbusRtuConnection::updatePhasePowerBlock()
-{
- // Update register block "phasePower"
- qCDebug(dcSdm630ModbusRtuConnection()) << "--> Read block \"phasePower\" registers from:" << 12 << "size:" << 6;
- ModbusRtuReply *reply = m_modbusRtuMaster->readInputRegister(m_slaveId, 12, 6);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcSdm630ModbusRtuConnection()) << "<-- Response from reading block \"phasePower\" register" << 12 << "size:" << 6 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedPowerPhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_powerPhaseA != receivedPowerPhaseA) {
- m_powerPhaseA = receivedPowerPhaseA;
- emit powerPhaseAChanged(m_powerPhaseA);
- }
-
- values = blockValues.mid(2, 2);
- float receivedPowerPhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_powerPhaseB != receivedPowerPhaseB) {
- m_powerPhaseB = receivedPowerPhaseB;
- emit powerPhaseBChanged(m_powerPhaseB);
- }
-
- values = blockValues.mid(4, 2);
- float receivedPowerPhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_powerPhaseC != receivedPowerPhaseC) {
- m_powerPhaseC = receivedPowerPhaseC;
- emit powerPhaseCChanged(m_powerPhaseC);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcSdm630ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"phasePower\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcSdm630ModbusRtuConnection()) << "Error occurred while reading block \"phasePower\" registers";
- }
-}
-
-void Sdm630ModbusRtuConnection::updateFrequencyAndTotalEnergyBlock()
-{
- // Update register block "frequencyAndTotalEnergy"
- qCDebug(dcSdm630ModbusRtuConnection()) << "--> Read block \"frequencyAndTotalEnergy\" registers from:" << 70 << "size:" << 6;
- ModbusRtuReply *reply = m_modbusRtuMaster->readInputRegister(m_slaveId, 70, 6);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcSdm630ModbusRtuConnection()) << "<-- Response from reading block \"frequencyAndTotalEnergy\" register" << 70 << "size:" << 6 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedFrequency = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_frequency != receivedFrequency) {
- m_frequency = receivedFrequency;
- emit frequencyChanged(m_frequency);
- }
-
- values = blockValues.mid(2, 2);
- float receivedTotalEnergyConsumed = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_totalEnergyConsumed != receivedTotalEnergyConsumed) {
- m_totalEnergyConsumed = receivedTotalEnergyConsumed;
- emit totalEnergyConsumedChanged(m_totalEnergyConsumed);
- }
-
- values = blockValues.mid(4, 2);
- float receivedTotalEnergyProduced = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_totalEnergyProduced != receivedTotalEnergyProduced) {
- m_totalEnergyProduced = receivedTotalEnergyProduced;
- emit totalEnergyProducedChanged(m_totalEnergyProduced);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcSdm630ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"frequencyAndTotalEnergy\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcSdm630ModbusRtuConnection()) << "Error occurred while reading block \"frequencyAndTotalEnergy\" registers";
- }
-}
-
-void Sdm630ModbusRtuConnection::updatePhaseEnergyEnergyBlock()
-{
- // Update register block "phaseEnergyEnergy"
- qCDebug(dcSdm630ModbusRtuConnection()) << "--> Read block \"phaseEnergyEnergy\" registers from:" << 346 << "size:" << 12;
- ModbusRtuReply *reply = m_modbusRtuMaster->readInputRegister(m_slaveId, 346, 12);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcSdm630ModbusRtuConnection()) << "<-- Response from reading block \"phaseEnergyEnergy\" register" << 346 << "size:" << 12 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedEnergyProducedPhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyProducedPhaseA != receivedEnergyProducedPhaseA) {
- m_energyProducedPhaseA = receivedEnergyProducedPhaseA;
- emit energyProducedPhaseAChanged(m_energyProducedPhaseA);
- }
-
- values = blockValues.mid(2, 2);
- float receivedEnergyProducedPhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyProducedPhaseB != receivedEnergyProducedPhaseB) {
- m_energyProducedPhaseB = receivedEnergyProducedPhaseB;
- emit energyProducedPhaseBChanged(m_energyProducedPhaseB);
- }
-
- values = blockValues.mid(4, 2);
- float receivedEnergyProducedPhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyProducedPhaseC != receivedEnergyProducedPhaseC) {
- m_energyProducedPhaseC = receivedEnergyProducedPhaseC;
- emit energyProducedPhaseCChanged(m_energyProducedPhaseC);
- }
-
- values = blockValues.mid(6, 2);
- float receivedEnergyConsumedPhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyConsumedPhaseA != receivedEnergyConsumedPhaseA) {
- m_energyConsumedPhaseA = receivedEnergyConsumedPhaseA;
- emit energyConsumedPhaseAChanged(m_energyConsumedPhaseA);
- }
-
- values = blockValues.mid(8, 2);
- float receivedEnergyConsumedPhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyConsumedPhaseB != receivedEnergyConsumedPhaseB) {
- m_energyConsumedPhaseB = receivedEnergyConsumedPhaseB;
- emit energyConsumedPhaseBChanged(m_energyConsumedPhaseB);
- }
-
- values = blockValues.mid(10, 2);
- float receivedEnergyConsumedPhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyConsumedPhaseC != receivedEnergyConsumedPhaseC) {
- m_energyConsumedPhaseC = receivedEnergyConsumedPhaseC;
- emit energyConsumedPhaseCChanged(m_energyConsumedPhaseC);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcSdm630ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"phaseEnergyEnergy\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcSdm630ModbusRtuConnection()) << "Error occurred while reading block \"phaseEnergyEnergy\" registers";
- }
-}
-
-ModbusRtuReply *Sdm630ModbusRtuConnection::readTotalCurrentPower()
-{
- return m_modbusRtuMaster->readInputRegister(m_slaveId, 52, 2);
-}
-
-void Sdm630ModbusRtuConnection::verifyInitFinished()
-{
- if (m_pendingInitReplies.isEmpty()) {
- qCDebug(dcSdm630ModbusRtuConnection()) << "Initialization finished of Sdm630ModbusRtuConnection";
- emit initializationFinished();
- }
-}
-
-QDebug operator<<(QDebug debug, Sdm630ModbusRtuConnection *sdm630ModbusRtuConnection)
-{
- debug.nospace().noquote() << "Sdm630ModbusRtuConnection(" << sdm630ModbusRtuConnection->modbusRtuMaster()->modbusUuid().toString() << ", " << sdm630ModbusRtuConnection->modbusRtuMaster()->serialPort() << ", slave ID:" << sdm630ModbusRtuConnection->slaveId() << ")" << "\n";
- debug.nospace().noquote() << " - Total system power:" << sdm630ModbusRtuConnection->totalCurrentPower() << " [W]" << "\n";
- debug.nospace().noquote() << " - Voltage phase L1:" << sdm630ModbusRtuConnection->voltagePhaseA() << " [V]" << "\n";
- debug.nospace().noquote() << " - Voltage phase L2:" << sdm630ModbusRtuConnection->voltagePhaseB() << " [V]" << "\n";
- debug.nospace().noquote() << " - Voltage phase L3:" << sdm630ModbusRtuConnection->voltagePhaseC() << " [V]" << "\n";
- debug.nospace().noquote() << " - Current phase L1:" << sdm630ModbusRtuConnection->currentPhaseA() << " [A]" << "\n";
- debug.nospace().noquote() << " - Current phase L2:" << sdm630ModbusRtuConnection->currentPhaseB() << " [A]" << "\n";
- debug.nospace().noquote() << " - Current phase L3:" << sdm630ModbusRtuConnection->currentPhaseC() << " [A]" << "\n";
- debug.nospace().noquote() << " - Power phase L1:" << sdm630ModbusRtuConnection->powerPhaseA() << " [W]" << "\n";
- debug.nospace().noquote() << " - Power phase L2:" << sdm630ModbusRtuConnection->powerPhaseB() << " [W]" << "\n";
- debug.nospace().noquote() << " - Power phase L3:" << sdm630ModbusRtuConnection->powerPhaseC() << " [W]" << "\n";
- debug.nospace().noquote() << " - Frequency:" << sdm630ModbusRtuConnection->frequency() << " [Hz]" << "\n";
- debug.nospace().noquote() << " - Total energy consumed:" << sdm630ModbusRtuConnection->totalEnergyConsumed() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Total energy produced:" << sdm630ModbusRtuConnection->totalEnergyProduced() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy produced phase A:" << sdm630ModbusRtuConnection->energyProducedPhaseA() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy produced phase B:" << sdm630ModbusRtuConnection->energyProducedPhaseB() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy produced phase C:" << sdm630ModbusRtuConnection->energyProducedPhaseC() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy consumed phase A:" << sdm630ModbusRtuConnection->energyConsumedPhaseA() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy consumed phase B:" << sdm630ModbusRtuConnection->energyConsumedPhaseB() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy consumed phase C:" << sdm630ModbusRtuConnection->energyConsumedPhaseC() << " [kWh]" << "\n";
- return debug.quote().space();
-}
-
diff --git a/bgetech/sdm630modbusrtuconnection.h b/bgetech/sdm630modbusrtuconnection.h
deleted file mode 100644
index 649a667..0000000
--- a/bgetech/sdm630modbusrtuconnection.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* 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 SDM630MODBUSRTUCONNECTION_H
-#define SDM630MODBUSRTUCONNECTION_H
-
-#include
-
-#include "../modbus/modbusdatautils.h"
-#include
-
-class Sdm630ModbusRtuConnection : public QObject
-{
- Q_OBJECT
-public:
- explicit Sdm630ModbusRtuConnection(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent = nullptr);
- ~Sdm630ModbusRtuConnection() = default;
-
- ModbusRtuMaster *modbusRtuMaster() const;
- quint16 slaveId() const;
-
- /* Total system power [W] - Address: 52, Size: 2 */
- float totalCurrentPower() const;
-
- /* Voltage phase L1 [V] - Address: 0, Size: 2 */
- float voltagePhaseA() const;
-
- /* Voltage phase L2 [V] - Address: 2, Size: 2 */
- float voltagePhaseB() const;
-
- /* Voltage phase L3 [V] - Address: 4, Size: 2 */
- float voltagePhaseC() const;
-
- /* Current phase L1 [A] - Address: 6, Size: 2 */
- float currentPhaseA() const;
-
- /* Current phase L2 [A] - Address: 8, Size: 2 */
- float currentPhaseB() const;
-
- /* Current phase L3 [A] - Address: 10, Size: 2 */
- float currentPhaseC() const;
-
- /* Read block from start addess 0 with size of 12 registers containing following 6 properties:
- - Voltage phase L1 [V] - Address: 0, Size: 2
- - Voltage phase L2 [V] - Address: 2, Size: 2
- - Voltage phase L3 [V] - Address: 4, Size: 2
- - Current phase L1 [A] - Address: 6, Size: 2
- - Current phase L2 [A] - Address: 8, Size: 2
- - Current phase L3 [A] - Address: 10, Size: 2
- */
- void updatePhaseVoltageAndCurrentBlock();
- /* Power phase L1 [W] - Address: 12, Size: 2 */
- float powerPhaseA() const;
-
- /* Power phase L2 [W] - Address: 14, Size: 2 */
- float powerPhaseB() const;
-
- /* Power phase L3 [W] - Address: 16, Size: 2 */
- float powerPhaseC() const;
-
- /* Read block from start addess 12 with size of 6 registers containing following 3 properties:
- - Power phase L1 [W] - Address: 12, Size: 2
- - Power phase L2 [W] - Address: 14, Size: 2
- - Power phase L3 [W] - Address: 16, Size: 2
- */
- void updatePhasePowerBlock();
- /* Frequency [Hz] - Address: 70, Size: 2 */
- float frequency() const;
-
- /* Total energy consumed [kWh] - Address: 72, Size: 2 */
- float totalEnergyConsumed() const;
-
- /* Total energy produced [kWh] - Address: 74, Size: 2 */
- float totalEnergyProduced() const;
-
- /* Read block from start addess 70 with size of 6 registers containing following 3 properties:
- - Frequency [Hz] - Address: 70, Size: 2
- - Total energy consumed [kWh] - Address: 72, Size: 2
- - Total energy produced [kWh] - Address: 74, Size: 2
- */
- void updateFrequencyAndTotalEnergyBlock();
- /* Energy produced phase A [kWh] - Address: 346, Size: 2 */
- float energyProducedPhaseA() const;
-
- /* Energy produced phase B [kWh] - Address: 348, Size: 2 */
- float energyProducedPhaseB() const;
-
- /* Energy produced phase C [kWh] - Address: 350, Size: 2 */
- float energyProducedPhaseC() const;
-
- /* Energy consumed phase A [kWh] - Address: 352, Size: 2 */
- float energyConsumedPhaseA() const;
-
- /* Energy consumed phase B [kWh] - Address: 354, Size: 2 */
- float energyConsumedPhaseB() const;
-
- /* Energy consumed phase C [kWh] - Address: 356, Size: 2 */
- float energyConsumedPhaseC() const;
-
- /* Read block from start addess 346 with size of 12 registers containing following 6 properties:
- - Energy produced phase A [kWh] - Address: 346, Size: 2
- - Energy produced phase B [kWh] - Address: 348, Size: 2
- - Energy produced phase C [kWh] - Address: 350, Size: 2
- - Energy consumed phase A [kWh] - Address: 352, Size: 2
- - Energy consumed phase B [kWh] - Address: 354, Size: 2
- - Energy consumed phase C [kWh] - Address: 356, Size: 2
- */
- void updatePhaseEnergyEnergyBlock();
-
- void updateTotalCurrentPower();
-
- virtual void initialize();
- virtual void update();
-
-signals:
- void initializationFinished();
-
- void totalCurrentPowerChanged(float totalCurrentPower);
- void voltagePhaseAChanged(float voltagePhaseA);
- void voltagePhaseBChanged(float voltagePhaseB);
- void voltagePhaseCChanged(float voltagePhaseC);
- void currentPhaseAChanged(float currentPhaseA);
- void currentPhaseBChanged(float currentPhaseB);
- void currentPhaseCChanged(float currentPhaseC);
- void powerPhaseAChanged(float powerPhaseA);
- void powerPhaseBChanged(float powerPhaseB);
- void powerPhaseCChanged(float powerPhaseC);
- void frequencyChanged(float frequency);
- void totalEnergyConsumedChanged(float totalEnergyConsumed);
- void totalEnergyProducedChanged(float totalEnergyProduced);
- void energyProducedPhaseAChanged(float energyProducedPhaseA);
- void energyProducedPhaseBChanged(float energyProducedPhaseB);
- void energyProducedPhaseCChanged(float energyProducedPhaseC);
- void energyConsumedPhaseAChanged(float energyConsumedPhaseA);
- void energyConsumedPhaseBChanged(float energyConsumedPhaseB);
- void energyConsumedPhaseCChanged(float energyConsumedPhaseC);
-
-private:
- ModbusRtuMaster *m_modbusRtuMaster = nullptr;
- quint16 m_slaveId = 1;
- QVector m_pendingInitReplies;
-
- float m_totalCurrentPower = 0;
- float m_voltagePhaseA = 0;
- float m_voltagePhaseB = 0;
- float m_voltagePhaseC = 0;
- float m_currentPhaseA = 0;
- float m_currentPhaseB = 0;
- float m_currentPhaseC = 0;
- float m_powerPhaseA = 0;
- float m_powerPhaseB = 0;
- float m_powerPhaseC = 0;
- float m_frequency = 0;
- float m_totalEnergyConsumed = 0;
- float m_totalEnergyProduced = 0;
- float m_energyProducedPhaseA = 0;
- float m_energyProducedPhaseB = 0;
- float m_energyProducedPhaseC = 0;
- float m_energyConsumedPhaseA = 0;
- float m_energyConsumedPhaseB = 0;
- float m_energyConsumedPhaseC = 0;
-
- void verifyInitFinished();
-
- ModbusRtuReply *readTotalCurrentPower();
-
-
-};
-
-QDebug operator<<(QDebug debug, Sdm630ModbusRtuConnection *sdm630ModbusRtuConnection);
-
-#endif // SDM630MODBUSRTUCONNECTION_H
diff --git a/debian/control b/debian/control
index 0ab3eb2..2b6c5b8 100644
--- a/debian/control
+++ b/debian/control
@@ -2,6 +2,7 @@ Source: nymea-plugins-modbus
Section: utils
Priority: options
Maintainer: nymea GmbH
+Standards-Version: 3.9.3
Build-depends: debhelper (>= 9.0.0),
libnymea-dev (>= 0.17),
libnymea-gpio-dev,
@@ -10,8 +11,8 @@ Build-depends: debhelper (>= 9.0.0),
nymea-dev-tools:native,
pkg-config,
qtbase5-dev,
- libi2c-dev
-Standards-Version: 3.9.3
+ libi2c-dev,
+ python3:native
Package: libnymea-sunspec1
@@ -22,6 +23,7 @@ Depends: ${shlibs:Depends},
Description: nymea.io sunspec library
This package contains the nymea sunspec library.
+
Package: libnymea-sunspec-dev
Section: libdevel
Architecture: any
@@ -34,6 +36,30 @@ Depends: ${shlibs:Depends},
Description: The main libraries and header files for developing with nymea sunspec.
This package contains the nymea sunspec library - development files.
+
+Package: libnymea-modbus
+Architecture: any
+Section: libs
+Depends: ${shlibs:Depends},
+ ${misc:Depends}
+Description: nymea modbus integration plugins library
+ This package contains the nymea modbus library for integration plugins.
+
+
+Package: libnymea-modbus-dev
+Section: libdevel
+Architecture: any
+Multi-Arch: same
+Depends: ${shlibs:Depends},
+ ${misc:Depends},
+ libnymea-modbus (= ${binary:Version}),
+ pkg-config,
+ qtbase5-dev,
+ python3,
+Description: The main libraries and header files for developing with modbus based nymea integration plugins.
+ This package contains the nymea modbus integration plugin library - development files.
+
+
Package: nymea-plugin-alphainnotec
Architecture: any
Section: libs
@@ -130,6 +156,15 @@ Description: nymea integration plugin for Schrack wallboxes
This package contains the nymea integration plugin for Schrack wallboxes.
+Package: nymea-plugin-stiebeleltron
+Architecture: any
+Section: libs
+Depends: ${shlibs:Depends},
+ ${misc:Depends},
+Description: nymea.io plugin for Stiebel Eltron heat pumps
+ This package will install the nymea.io plugin for Stiebel Eltron heat pumps.
+
+
Package: nymea-plugin-sunspec
Architecture: any
Depends: ${shlibs:Depends},
diff --git a/debian/libnymea-modbus-dev.install.in b/debian/libnymea-modbus-dev.install.in
new file mode 100644
index 0000000..d743d89
--- /dev/null
+++ b/debian/libnymea-modbus-dev.install.in
@@ -0,0 +1,4 @@
+usr/lib/@DEB_HOST_MULTIARCH@/libnymea-modbus.so
+usr/include/nymea-modbus/
+usr/lib/@DEB_HOST_MULTIARCH@/pkgconfig/nymea-modbus.pc
+
diff --git a/debian/libnymea-modbus.install.in b/debian/libnymea-modbus.install.in
new file mode 100644
index 0000000..a180f98
--- /dev/null
+++ b/debian/libnymea-modbus.install.in
@@ -0,0 +1,4 @@
+usr/lib/@DEB_HOST_MULTIARCH@/libnymea-modbus.so.1
+usr/lib/@DEB_HOST_MULTIARCH@/libnymea-modbus.so.1.0
+usr/lib/@DEB_HOST_MULTIARCH@/libnymea-modbus.so.1.0.0
+
diff --git a/debian/nymea-plugin-stiebeleltron.install.in b/debian/nymea-plugin-stiebeleltron.install.in
new file mode 100644
index 0000000..84035a8
--- /dev/null
+++ b/debian/nymea-plugin-stiebeleltron.install.in
@@ -0,0 +1,2 @@
+usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginstiebeleltron.so
+stiebeleltron/translations/*qm usr/share/nymea/translations/
diff --git a/debian/rules b/debian/rules
index 7a8679f..dcdbe2b 100755
--- a/debian/rules
+++ b/debian/rules
@@ -21,5 +21,6 @@ override_dh_auto_clean:
dh_auto_clean
find -name *plugininfo.h -exec rm {} \;
find -name *.qm -exec rm {} \;
+ find -name "autogenerated" -type d -exec rm -rvf {} +
rm -rf $(PREPROCESS_FILES:.in=)
diff --git a/drexelundweiss/integrationplugindrexelundweiss.cpp b/drexelundweiss/integrationplugindrexelundweiss.cpp
index 493a8e0..c4eff29 100644
--- a/drexelundweiss/integrationplugindrexelundweiss.cpp
+++ b/drexelundweiss/integrationplugindrexelundweiss.cpp
@@ -31,9 +31,9 @@
#include "integrationplugindrexelundweiss.h"
#include "plugininfo.h"
-#include "hardwaremanager.h"
-#include "hardware/modbus/modbusrtumaster.h"
-#include "hardware/modbus/modbusrtuhardwareresource.h"
+#include
+#include
+#include
IntegrationPluginDrexelUndWeiss::IntegrationPluginDrexelUndWeiss()
{
diff --git a/drexelundweiss/integrationplugindrexelundweiss.h b/drexelundweiss/integrationplugindrexelundweiss.h
index 12235eb..a93d0ed 100644
--- a/drexelundweiss/integrationplugindrexelundweiss.h
+++ b/drexelundweiss/integrationplugindrexelundweiss.h
@@ -31,9 +31,10 @@
#ifndef INTEGRATIONPLUGINDREXELUNDWEISS_H
#define INTEGRATIONPLUGINDREXELUNDWEISS_H
-#include "integrations/integrationplugin.h"
-#include "hardware/modbus/modbusrtumaster.h"
-#include "plugintimer.h"
+#include
+#include
+#include
+
#include "modbusregisterdefinition.h"
#include
diff --git a/huawei/huawei-registers.json b/huawei/huawei-registers.json
index 0e559d1..e0b585d 100644
--- a/huawei/huawei-registers.json
+++ b/huawei/huawei-registers.json
@@ -1,4 +1,5 @@
{
+ "className": "Huawei",
"protocol": "TCP",
"endianness": "BigEndian",
"enums": [
diff --git a/huawei/huawei.pro b/huawei/huawei.pro
index 194853d..d5d9324 100644
--- a/huawei/huawei.pro
+++ b/huawei/huawei.pro
@@ -1,17 +1,14 @@
include(../plugins.pri)
-QT += network serialbus
+# Generate modbus connection
+MODBUS_CONNECTIONS += huawei-registers.json
+#MODBUS_TOOLS_CONFIG += VERBOSE
+include(../modbus.pri)
HEADERS += \
huaweifusionsolar.h \
- huaweimodbustcpconnection.h \
- integrationpluginhuawei.h \
- ../modbus/modbustcpmaster.h \
- ../modbus/modbusdatautils.h
+ integrationpluginhuawei.h
SOURCES += \
huaweifusionsolar.cpp \
- huaweimodbustcpconnection.cpp \
- integrationpluginhuawei.cpp \
- ../modbus/modbustcpmaster.cpp \
- ../modbus/modbusdatautils.cpp
+ integrationpluginhuawei.cpp
diff --git a/huawei/huaweifusionsolar.cpp b/huawei/huaweifusionsolar.cpp
index 3374c2a..e11c9e7 100644
--- a/huawei/huaweifusionsolar.cpp
+++ b/huawei/huaweifusionsolar.cpp
@@ -98,11 +98,7 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter active power\" register" << 32080 << "size:" << 2 << values;
- float receivedInverterActivePower = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -3);
- if (m_inverterActivePower != receivedInverterActivePower) {
- m_inverterActivePower = receivedInverterActivePower;
- emit inverterActivePowerChanged(m_inverterActivePower);
- }
+ processInverterActivePowerRegisterValues(values);
}
finishRequest();
});
@@ -133,12 +129,8 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter device status\" register" << 32089 << "size:" << 1 << values;
- InverterDeviceStatus receivedInverterDeviceStatus = static_cast(ModbusDataUtils::convertToUInt16(values));
- qCDebug(dcHuaweiFusionSolar()) << "Inverter status" << receivedInverterDeviceStatus;
- if (m_inverterDeviceStatus != receivedInverterDeviceStatus) {
- m_inverterDeviceStatus = receivedInverterDeviceStatus;
- emit inverterDeviceStatusChanged(m_inverterDeviceStatus);
- }
+ processInverterDeviceStatusRegisterValues(values);
+ qCDebug(dcHuaweiFusionSolar()) << "Inverter status" << inverterDeviceStatus();
}
finishRequest();
});
@@ -169,11 +161,7 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter energy produced\" register" << 32106 << "size:" << 2 << values;
- float receivedInverterEnergyProduced = ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -2);
- if (m_inverterEnergyProduced != receivedInverterEnergyProduced) {
- m_inverterEnergyProduced = receivedInverterEnergyProduced;
- emit inverterEnergyProducedChanged(m_inverterEnergyProduced);
- }
+ processInverterEnergyProducedRegisterValues(values);
}
finishRequest();
});
@@ -204,18 +192,13 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 status\" register" << 37000 << "size:" << 1 << values;
- BatteryDeviceStatus receivedLunaBattery1Status = static_cast(ModbusDataUtils::convertToUInt16(values));
- qCDebug(dcHuaweiFusionSolar()) << "Battery 1 status" << receivedLunaBattery1Status;
- if (receivedLunaBattery1Status == BatteryDeviceStatusOffline) {
+ processLunaBattery1StatusRegisterValues(values);
+ qCDebug(dcHuaweiFusionSolar()) << "Battery 1 status" << m_lunaBattery1Status;
+ if (m_lunaBattery1Status == BatteryDeviceStatusOffline) {
m_battery1Available = false;
} else {
m_battery1Available = true;
}
-
- if (m_lunaBattery1Status != receivedLunaBattery1Status) {
- m_lunaBattery1Status = receivedLunaBattery1Status;
- emit lunaBattery1StatusChanged(m_lunaBattery1Status);
- }
}
finishRequest();
});
@@ -246,11 +229,7 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 power\" register" << 37001 << "size:" << 2 << values;
- qint32 receivedLunaBattery1Power = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_lunaBattery1Power != receivedLunaBattery1Power) {
- m_lunaBattery1Power = receivedLunaBattery1Power;
- emit lunaBattery1PowerChanged(m_lunaBattery1Power);
- }
+ processLunaBattery1PowerRegisterValues(values);
}
finishRequest();
});
@@ -281,11 +260,7 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 state of charge\" register" << 37004 << "size:" << 1 << values;
- float receivedLunaBattery1Soc = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -1);
- if (m_lunaBattery1Soc != receivedLunaBattery1Soc) {
- m_lunaBattery1Soc = receivedLunaBattery1Soc;
- emit lunaBattery1SocChanged(m_lunaBattery1Soc);
- }
+ processLunaBattery1SocRegisterValues(values);
}
finishRequest();
});
@@ -316,11 +291,7 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Power meter active power\" register" << 37113 << "size:" << 2 << values;
- qint32 receivedPowerMeterActivePower = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_powerMeterActivePower != receivedPowerMeterActivePower) {
- m_powerMeterActivePower = receivedPowerMeterActivePower;
- emit powerMeterActivePowerChanged(m_powerMeterActivePower);
- }
+ processPowerMeterActivePowerRegisterValues(values);
}
finishRequest();
});
@@ -351,17 +322,13 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 status\" register" << 37741 << "size:" << 1 << values;
- BatteryDeviceStatus receivedLunaBattery2Status = static_cast(ModbusDataUtils::convertToUInt16(values));
- qCDebug(dcHuaweiFusionSolar()) << "Battery 2 status" << receivedLunaBattery2Status;
- if (receivedLunaBattery2Status == BatteryDeviceStatusOffline) {
+ processLunaBattery2StatusRegisterValues(values);
+ qCDebug(dcHuaweiFusionSolar()) << "Battery 2 status" << m_lunaBattery2Status;
+ if (m_lunaBattery2Status == BatteryDeviceStatusOffline) {
m_battery2Available = false;
} else {
m_battery2Available = true;
}
- if (m_lunaBattery2Status != receivedLunaBattery2Status) {
- m_lunaBattery2Status = receivedLunaBattery2Status;
- emit lunaBattery2StatusChanged(m_lunaBattery2Status);
- }
}
finishRequest();
});
@@ -392,11 +359,7 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 power\" register" << 37743 << "size:" << 2 << values;
- qint32 receivedLunaBattery2Power = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_lunaBattery2Power != receivedLunaBattery2Power) {
- m_lunaBattery2Power = receivedLunaBattery2Power;
- emit lunaBattery2PowerChanged(m_lunaBattery2Power);
- }
+ processLunaBattery2PowerRegisterValues(values);
}
finishRequest();
});
@@ -427,11 +390,7 @@ void HuaweiFusionSolar::readNextRegister()
const QModbusDataUnit unit = reply->result();
const QVector values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 state of charge\" register" << 37738 << "size:" << 1 << values;
- float receivedLunaBattery2Soc = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -1);
- if (m_lunaBattery2Soc != receivedLunaBattery2Soc) {
- m_lunaBattery2Soc = receivedLunaBattery2Soc;
- emit lunaBattery2SocChanged(m_lunaBattery2Soc);
- }
+ processLunaBattery2SocRegisterValues(values);
}
finishRequest();
});
diff --git a/huawei/huaweimodbustcpconnection.cpp b/huawei/huaweimodbustcpconnection.cpp
deleted file mode 100644
index cca8e02..0000000
--- a/huawei/huaweimodbustcpconnection.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* Copyright 2013 - 2022, 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 "huaweimodbustcpconnection.h"
-#include "loggingcategories.h"
-
-NYMEA_LOGGING_CATEGORY(dcHuaweiModbusTcpConnection, "HuaweiModbusTcpConnection")
-
-HuaweiModbusTcpConnection::HuaweiModbusTcpConnection(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent) :
- ModbusTCPMaster(hostAddress, port, parent),
- m_slaveId(slaveId)
-{
-
-}
-
-float HuaweiModbusTcpConnection::inverterActivePower() const
-{
- return m_inverterActivePower;
-}
-
-HuaweiModbusTcpConnection::InverterDeviceStatus HuaweiModbusTcpConnection::inverterDeviceStatus() const
-{
- return m_inverterDeviceStatus;
-}
-
-float HuaweiModbusTcpConnection::inverterEnergyProduced() const
-{
- return m_inverterEnergyProduced;
-}
-
-qint32 HuaweiModbusTcpConnection::powerMeterActivePower() const
-{
- return m_powerMeterActivePower;
-}
-
-HuaweiModbusTcpConnection::BatteryDeviceStatus HuaweiModbusTcpConnection::lunaBattery1Status() const
-{
- return m_lunaBattery1Status;
-}
-
-qint32 HuaweiModbusTcpConnection::lunaBattery1Power() const
-{
- return m_lunaBattery1Power;
-}
-
-float HuaweiModbusTcpConnection::lunaBattery1Soc() const
-{
- return m_lunaBattery1Soc;
-}
-
-HuaweiModbusTcpConnection::BatteryDeviceStatus HuaweiModbusTcpConnection::lunaBattery2Status() const
-{
- return m_lunaBattery2Status;
-}
-
-qint32 HuaweiModbusTcpConnection::lunaBattery2Power() const
-{
- return m_lunaBattery2Power;
-}
-
-float HuaweiModbusTcpConnection::lunaBattery2Soc() const
-{
- return m_lunaBattery2Soc;
-}
-
-void HuaweiModbusTcpConnection::initialize()
-{
- // No init registers defined. Nothing to be done and we are finished.
- emit initializationFinished();
-}
-
-void HuaweiModbusTcpConnection::update()
-{
- updateInverterActivePower();
- updateInverterDeviceStatus();
- updateInverterEnergyProduced();
- updatePowerMeterActivePower();
- updateLunaBattery1Status();
- updateLunaBattery1Power();
- updateLunaBattery1Soc();
- updateLunaBattery2Status();
- updateLunaBattery2Power();
- updateLunaBattery2Soc();
-}
-
-void HuaweiModbusTcpConnection::updateInverterActivePower()
-{
- // Update registers from Inverter active power
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Inverter active power\" register:" << 32080 << "size:" << 2;
- QModbusReply *reply = readInverterActivePower();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Inverter active power\" register" << 32080 << "size:" << 2 << values;
- float receivedInverterActivePower = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -3);
- if (m_inverterActivePower != receivedInverterActivePower) {
- m_inverterActivePower = receivedInverterActivePower;
- emit inverterActivePowerChanged(m_inverterActivePower);
- }
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Inverter active power\" 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Inverter active power\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updateInverterDeviceStatus()
-{
- // Update registers from Inverter device status
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Inverter device status\" register:" << 32089 << "size:" << 1;
- QModbusReply *reply = readInverterDeviceStatus();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Inverter device status\" register" << 32089 << "size:" << 1 << values;
- InverterDeviceStatus receivedInverterDeviceStatus = static_cast(ModbusDataUtils::convertToUInt16(values));
- if (m_inverterDeviceStatus != receivedInverterDeviceStatus) {
- m_inverterDeviceStatus = receivedInverterDeviceStatus;
- emit inverterDeviceStatusChanged(m_inverterDeviceStatus);
- }
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Inverter device 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Inverter device status\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updateInverterEnergyProduced()
-{
- // Update registers from Inverter energy produced
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Inverter energy produced\" register:" << 32106 << "size:" << 2;
- QModbusReply *reply = readInverterEnergyProduced();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Inverter energy produced\" register" << 32106 << "size:" << 2 << values;
- float receivedInverterEnergyProduced = ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -2);
- if (m_inverterEnergyProduced != receivedInverterEnergyProduced) {
- m_inverterEnergyProduced = receivedInverterEnergyProduced;
- emit inverterEnergyProducedChanged(m_inverterEnergyProduced);
- }
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Inverter energy produced\" 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Inverter energy produced\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updatePowerMeterActivePower()
-{
- // Update registers from Power meter active power
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Power meter active power\" register:" << 37113 << "size:" << 2;
- QModbusReply *reply = readPowerMeterActivePower();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Power meter active power\" register" << 37113 << "size:" << 2 << values;
- qint32 receivedPowerMeterActivePower = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_powerMeterActivePower != receivedPowerMeterActivePower) {
- m_powerMeterActivePower = receivedPowerMeterActivePower;
- emit powerMeterActivePowerChanged(m_powerMeterActivePower);
- }
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Power meter active power\" 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Power meter active power\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updateLunaBattery1Status()
-{
- // Update registers from Luna 2000 Battery 1 status
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 1 status\" register:" << 37000 << "size:" << 1;
- QModbusReply *reply = readLunaBattery1Status();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 1 status\" register" << 37000 << "size:" << 1 << values;
- BatteryDeviceStatus receivedLunaBattery1Status = static_cast(ModbusDataUtils::convertToUInt16(values));
- m_lunaBattery1Status = receivedLunaBattery1Status;
- emit lunaBattery1StatusChanged(m_lunaBattery1Status);
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 1 status\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updateLunaBattery1Power()
-{
- // Update registers from Luna 2000 Battery 1 power
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 1 power\" register:" << 37001 << "size:" << 2;
- QModbusReply *reply = readLunaBattery1Power();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 1 power\" register" << 37001 << "size:" << 2 << values;
- qint32 receivedLunaBattery1Power = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_lunaBattery1Power != receivedLunaBattery1Power) {
- m_lunaBattery1Power = receivedLunaBattery1Power;
- emit lunaBattery1PowerChanged(m_lunaBattery1Power);
- }
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 power\" 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 1 power\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updateLunaBattery1Soc()
-{
- // Update registers from Luna 2000 Battery 1 state of charge
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 1 state of charge\" register:" << 37004 << "size:" << 1;
- QModbusReply *reply = readLunaBattery1Soc();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 1 state of charge\" register" << 37004 << "size:" << 1 << values;
- float receivedLunaBattery1Soc = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -1);
- if (m_lunaBattery1Soc != receivedLunaBattery1Soc) {
- m_lunaBattery1Soc = receivedLunaBattery1Soc;
- emit lunaBattery1SocChanged(m_lunaBattery1Soc);
- }
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 state of charge\" 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 1 state of charge\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updateLunaBattery2Status()
-{
- // Update registers from Luna 2000 Battery 2 status
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 2 status\" register:" << 37741 << "size:" << 1;
- QModbusReply *reply = readLunaBattery2Status();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 2 status\" register" << 37741 << "size:" << 1 << values;
- BatteryDeviceStatus receivedLunaBattery2Status = static_cast(ModbusDataUtils::convertToUInt16(values));
- m_lunaBattery2Status = receivedLunaBattery2Status;
- emit lunaBattery2StatusChanged(m_lunaBattery2Status);
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 2 status\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updateLunaBattery2Power()
-{
- // Update registers from Luna 2000 Battery 2 power
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 2 power\" register:" << 37743 << "size:" << 2;
- QModbusReply *reply = readLunaBattery2Power();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 2 power\" register" << 37743 << "size:" << 2 << values;
- qint32 receivedLunaBattery2Power = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_lunaBattery2Power != receivedLunaBattery2Power) {
- m_lunaBattery2Power = receivedLunaBattery2Power;
- emit lunaBattery2PowerChanged(m_lunaBattery2Power);
- }
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 power\" 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 2 power\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-void HuaweiModbusTcpConnection::updateLunaBattery2Soc()
-{
- // Update registers from Luna 2000 Battery 2 state of charge
- qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 2 state of charge\" register:" << 37738 << "size:" << 1;
- QModbusReply *reply = readLunaBattery2Soc();
- 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();
- const QVector values = unit.values();
- qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 2 state of charge\" register" << 37738 << "size:" << 1 << values;
- float receivedLunaBattery2Soc = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -1);
- if (m_lunaBattery2Soc != receivedLunaBattery2Soc) {
- m_lunaBattery2Soc = receivedLunaBattery2Soc;
- emit lunaBattery2SocChanged(m_lunaBattery2Soc);
- }
- }
- });
-
- connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
- qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 state of charge\" 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(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 2 state of charge\" registers from" << hostAddress().toString() << errorString();
- }
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readInverterActivePower()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 32080, 2);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readInverterDeviceStatus()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 32089, 1);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readInverterEnergyProduced()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 32106, 2);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readPowerMeterActivePower()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37113, 2);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readLunaBattery1Status()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37000, 1);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readLunaBattery1Power()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37001, 2);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readLunaBattery1Soc()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37004, 1);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readLunaBattery2Status()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37741, 1);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readLunaBattery2Power()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37743, 2);
- return sendReadRequest(request, m_slaveId);
-}
-
-QModbusReply *HuaweiModbusTcpConnection::readLunaBattery2Soc()
-{
- QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37738, 1);
- return sendReadRequest(request, m_slaveId);
-}
-
-void HuaweiModbusTcpConnection::verifyInitFinished()
-{
- if (m_pendingInitReplies.isEmpty()) {
- qCDebug(dcHuaweiModbusTcpConnection()) << "Initialization finished of HuaweiModbusTcpConnection" << hostAddress().toString();
- emit initializationFinished();
- }
-}
-
-QDebug operator<<(QDebug debug, HuaweiModbusTcpConnection *huaweiModbusTcpConnection)
-{
- debug.nospace().noquote() << "HuaweiModbusTcpConnection(" << huaweiModbusTcpConnection->hostAddress().toString() << ":" << huaweiModbusTcpConnection->port() << ")" << "\n";
- debug.nospace().noquote() << " - Inverter active power:" << huaweiModbusTcpConnection->inverterActivePower() << " [kW]" << "\n";
- debug.nospace().noquote() << " - Inverter device status:" << huaweiModbusTcpConnection->inverterDeviceStatus() << "\n";
- debug.nospace().noquote() << " - Inverter energy produced:" << huaweiModbusTcpConnection->inverterEnergyProduced() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Power meter active power:" << huaweiModbusTcpConnection->powerMeterActivePower() << " [W]" << "\n";
- debug.nospace().noquote() << " - Luna 2000 Battery 1 status:" << huaweiModbusTcpConnection->lunaBattery1Status() << "\n";
- debug.nospace().noquote() << " - Luna 2000 Battery 1 power:" << huaweiModbusTcpConnection->lunaBattery1Power() << " [W]" << "\n";
- debug.nospace().noquote() << " - Luna 2000 Battery 1 state of charge:" << huaweiModbusTcpConnection->lunaBattery1Soc() << " [%]" << "\n";
- debug.nospace().noquote() << " - Luna 2000 Battery 2 status:" << huaweiModbusTcpConnection->lunaBattery2Status() << "\n";
- debug.nospace().noquote() << " - Luna 2000 Battery 2 power:" << huaweiModbusTcpConnection->lunaBattery2Power() << " [W]" << "\n";
- debug.nospace().noquote() << " - Luna 2000 Battery 2 state of charge:" << huaweiModbusTcpConnection->lunaBattery2Soc() << " [%]" << "\n";
- return debug.quote().space();
-}
-
diff --git a/huawei/huaweimodbustcpconnection.h b/huawei/huaweimodbustcpconnection.h
deleted file mode 100644
index 40ce1b3..0000000
--- a/huawei/huaweimodbustcpconnection.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* Copyright 2013 - 2022, 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 HUAWEIMODBUSTCPCONNECTION_H
-#define HUAWEIMODBUSTCPCONNECTION_H
-
-#include
-
-#include "../modbus/modbusdatautils.h"
-#include "../modbus/modbustcpmaster.h"
-
-class HuaweiModbusTcpConnection : public ModbusTCPMaster
-{
- Q_OBJECT
-public:
- enum Registers {
- RegisterInverterActivePower = 32080,
- RegisterInverterDeviceStatus = 32089,
- RegisterInverterEnergyProduced = 32106,
- RegisterLunaBattery1Status = 37000,
- RegisterLunaBattery1Power = 37001,
- RegisterLunaBattery1Soc = 37004,
- RegisterPowerMeterActivePower = 37113,
- RegisterLunaBattery2Soc = 37738,
- RegisterLunaBattery2Status = 37741,
- RegisterLunaBattery2Power = 37743
- };
- Q_ENUM(Registers)
-
- enum InverterDeviceStatus {
- InverterDeviceStatusStandbyInitializing = 0,
- InverterDeviceStatusStandbyDetectingInsulationResistance = 1,
- InverterDeviceStatusStandbyDetectingIrradiation = 2,
- InverterDeviceStatusStandbyDridDetecting = 3,
- InverterDeviceStatusStarting = 256,
- InverterDeviceStatusOnGrid = 512,
- InverterDeviceStatusPowerLimited = 513,
- InverterDeviceStatusSelfDerating = 514,
- InverterDeviceStatusShutdownFault = 768,
- InverterDeviceStatusShutdownCommand = 769,
- InverterDeviceStatusShutdownOVGR = 770,
- InverterDeviceStatusShutdownCommunicationDisconnected = 771,
- InverterDeviceStatusShutdownPowerLimit = 772,
- InverterDeviceStatusShutdownManualStartupRequired = 773,
- InverterDeviceStatusShutdownInputUnderpower = 774,
- InverterDeviceStatusGridSchedulingPCurve = 1025,
- InverterDeviceStatusGridSchedulingQUCurve = 1026,
- InverterDeviceStatusGridSchedulingPFUCurve = 1027,
- InverterDeviceStatusGridSchedulingDryContact = 1028,
- InverterDeviceStatusGridSchedulingQPCurve = 1029,
- InverterDeviceStatusSpotCheckReady = 1280,
- InverterDeviceStatusSpotChecking = 1281,
- InverterDeviceStatusInspecting = 1536,
- InverterDeviceStatusAfciSelfCheck = 1792,
- InverterDeviceStatusIVScanning = 2048,
- InverterDeviceStatusDCInputDetection = 2304,
- InverterDeviceStatusRunningOffGridCharging = 2560,
- InverterDeviceStatusStandbyNoIrradiation = 40960
- };
- Q_ENUM(InverterDeviceStatus)
-
- enum BatteryDeviceStatus {
- BatteryDeviceStatusOffline = 0,
- BatteryDeviceStatusStandby = 1,
- BatteryDeviceStatusRunning = 1,
- BatteryDeviceStatusFault = 1,
- BatteryDeviceStatusSleepMode = 1
- };
- Q_ENUM(BatteryDeviceStatus)
-
- explicit HuaweiModbusTcpConnection(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr);
- ~HuaweiModbusTcpConnection() = default;
-
- /* Inverter active power [kW] - Address: 32080, Size: 2 */
- float inverterActivePower() const;
-
- /* Inverter device status - Address: 32089, Size: 1 */
- InverterDeviceStatus inverterDeviceStatus() const;
-
- /* Inverter energy produced [kWh] - Address: 32106, Size: 2 */
- float inverterEnergyProduced() const;
-
- /* Power meter active power [W] - Address: 37113, Size: 2 */
- qint32 powerMeterActivePower() const;
-
- /* Luna 2000 Battery 1 status - Address: 37000, Size: 1 */
- BatteryDeviceStatus lunaBattery1Status() const;
-
- /* Luna 2000 Battery 1 power [W] - Address: 37001, Size: 2 */
- qint32 lunaBattery1Power() const;
-
- /* Luna 2000 Battery 1 state of charge [%] - Address: 37004, Size: 1 */
- float lunaBattery1Soc() const;
-
- /* Luna 2000 Battery 2 status - Address: 37741, Size: 1 */
- BatteryDeviceStatus lunaBattery2Status() const;
-
- /* Luna 2000 Battery 2 power [W] - Address: 37743, Size: 2 */
- qint32 lunaBattery2Power() const;
-
- /* Luna 2000 Battery 2 state of charge [%] - Address: 37738, Size: 1 */
- float lunaBattery2Soc() const;
-
-
- virtual void initialize();
- virtual void update();
-
- void updateInverterActivePower();
- void updateInverterDeviceStatus();
- void updateInverterEnergyProduced();
- void updatePowerMeterActivePower();
- void updateLunaBattery1Status();
- void updateLunaBattery1Power();
- void updateLunaBattery1Soc();
- void updateLunaBattery2Status();
- void updateLunaBattery2Power();
- void updateLunaBattery2Soc();
-
-signals:
- void initializationFinished();
-
- void inverterActivePowerChanged(float inverterActivePower);
- void inverterDeviceStatusChanged(InverterDeviceStatus inverterDeviceStatus);
- void inverterEnergyProducedChanged(float inverterEnergyProduced);
- void powerMeterActivePowerChanged(qint32 powerMeterActivePower);
- void lunaBattery1StatusChanged(BatteryDeviceStatus lunaBattery1Status);
- void lunaBattery1PowerChanged(qint32 lunaBattery1Power);
- void lunaBattery1SocChanged(float lunaBattery1Soc);
- void lunaBattery2StatusChanged(BatteryDeviceStatus lunaBattery2Status);
- void lunaBattery2PowerChanged(qint32 lunaBattery2Power);
- void lunaBattery2SocChanged(float lunaBattery2Soc);
-
-protected:
- QModbusReply *readInverterActivePower();
- QModbusReply *readInverterDeviceStatus();
- QModbusReply *readInverterEnergyProduced();
- QModbusReply *readPowerMeterActivePower();
- QModbusReply *readLunaBattery1Status();
- QModbusReply *readLunaBattery1Power();
- QModbusReply *readLunaBattery1Soc();
- QModbusReply *readLunaBattery2Status();
- QModbusReply *readLunaBattery2Power();
- QModbusReply *readLunaBattery2Soc();
-
- float m_inverterActivePower = 0;
- InverterDeviceStatus m_inverterDeviceStatus = InverterDeviceStatusStandbyInitializing;
- float m_inverterEnergyProduced = 0;
- qint32 m_powerMeterActivePower = 0;
- BatteryDeviceStatus m_lunaBattery1Status = BatteryDeviceStatusOffline;
- qint32 m_lunaBattery1Power = 0;
- float m_lunaBattery1Soc = 0;
- BatteryDeviceStatus m_lunaBattery2Status = BatteryDeviceStatusOffline;
- qint32 m_lunaBattery2Power = 0;
- float m_lunaBattery2Soc = 0;
-
-private:
- quint16 m_slaveId = 1;
- QVector m_pendingInitReplies;
-
- void verifyInitFinished();
-
-
-};
-
-QDebug operator<<(QDebug debug, HuaweiModbusTcpConnection *huaweiModbusTcpConnection);
-
-#endif // HUAWEIMODBUSTCPCONNECTION_H
diff --git a/huawei/integrationpluginhuawei.cpp b/huawei/integrationpluginhuawei.cpp
index fcdfee7..1c83ee2 100644
--- a/huawei/integrationpluginhuawei.cpp
+++ b/huawei/integrationpluginhuawei.cpp
@@ -29,11 +29,11 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "integrationpluginhuawei.h"
-
-#include "network/networkdevicediscovery.h"
-#include "hardwaremanager.h"
#include "plugininfo.h"
+#include
+#include
+
IntegrationPluginHuawei::IntegrationPluginHuawei()
{
diff --git a/huawei/integrationpluginhuawei.h b/huawei/integrationpluginhuawei.h
index 5c05e09..8e5afe6 100644
--- a/huawei/integrationpluginhuawei.h
+++ b/huawei/integrationpluginhuawei.h
@@ -31,8 +31,9 @@
#ifndef INTEGRATIONPLUGINHUAWEI_H
#define INTEGRATIONPLUGINHUAWEI_H
-#include "plugintimer.h"
-#include "integrations/integrationplugin.h"
+#include
+#include
+
#include "huaweifusionsolar.h"
class IntegrationPluginHuawei: public IntegrationPlugin
diff --git a/idm/idm.cpp b/idm/idm.cpp
index dc96863..9ea769e 100644
--- a/idm/idm.cpp
+++ b/idm/idm.cpp
@@ -30,7 +30,7 @@
#include "idm.h"
#include "extern-plugininfo.h"
-#include "../modbus/modbushelpers.h"
+#include "modbushelpers.h"
#include
diff --git a/idm/idm.h b/idm/idm.h
index 53f1d02..7c78d21 100644
--- a/idm/idm.h
+++ b/idm/idm.h
@@ -33,7 +33,7 @@
#include
-#include "../modbus/modbustcpmaster.h"
+#include
#include "idminfo.h"
diff --git a/idm/idm.pro b/idm/idm.pro
index 6bc6551..d8a1e12 100644
--- a/idm/idm.pro
+++ b/idm/idm.pro
@@ -1,19 +1,14 @@
include(../plugins.pri)
-
-QT += \
- network \
- serialbus \
+include(../modbus.pri)
SOURCES += \
idm.cpp \
integrationpluginidm.cpp \
- ../modbus/modbustcpmaster.cpp \
- ../modbus/modbushelpers.cpp \
+ modbushelpers.cpp
HEADERS += \
idm.h \
idminfo.h \
integrationpluginidm.h \
- ../modbus/modbustcpmaster.h \
- ../modbus/modbushelpers.h \
+ modbushelpers.h
diff --git a/idm/integrationpluginidm.cpp b/idm/integrationpluginidm.cpp
index 7f92ed1..1f0790e 100644
--- a/idm/integrationpluginidm.cpp
+++ b/idm/integrationpluginidm.cpp
@@ -28,10 +28,11 @@
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#include "network/networkdevicediscovery.h"
#include "integrationpluginidm.h"
#include "plugininfo.h"
+#include
+
IntegrationPluginIdm::IntegrationPluginIdm()
{
diff --git a/idm/integrationpluginidm.h b/idm/integrationpluginidm.h
index 058988e..860196c 100644
--- a/idm/integrationpluginidm.h
+++ b/idm/integrationpluginidm.h
@@ -31,8 +31,9 @@
#ifndef INTEGRATIONPLUGINIDM_H
#define INTEGRATIONPLUGINIDM_H
-#include "integrations/integrationplugin.h"
-#include "plugintimer.h"
+#include
+#include
+
#include "idm.h"
#include
diff --git a/modbus/modbushelpers.cpp b/idm/modbushelpers.cpp
similarity index 100%
rename from modbus/modbushelpers.cpp
rename to idm/modbushelpers.cpp
diff --git a/modbus/modbushelpers.h b/idm/modbushelpers.h
similarity index 100%
rename from modbus/modbushelpers.h
rename to idm/modbushelpers.h
diff --git a/inepro/inepro.pro b/inepro/inepro.pro
index 4067273..d4395d8 100644
--- a/inepro/inepro.pro
+++ b/inepro/inepro.pro
@@ -1,14 +1,13 @@
include(../plugins.pri)
-QT += serialport serialbus
+# Generate modbus connection
+MODBUS_CONNECTIONS += pro380-registers.json
+#MODBUS_TOOLS_CONFIG += VERBOSE
+include(../modbus.pri)
HEADERS += \
- integrationplugininepro.h \
- pro380modbusrtuconnection.h \
- ../modbus/modbusdatautils.h
+ integrationplugininepro.h
SOURCES += \
- integrationplugininepro.cpp \
- pro380modbusrtuconnection.cpp \
- ../modbus/modbusdatautils.cpp
+ integrationplugininepro.cpp
diff --git a/inepro/integrationplugininepro.cpp b/inepro/integrationplugininepro.cpp
index af5ff77..9d5cf2c 100644
--- a/inepro/integrationplugininepro.cpp
+++ b/inepro/integrationplugininepro.cpp
@@ -45,7 +45,7 @@ void IntegrationPluginInepro::init()
qCWarning(dcInepro()) << "Modbus RTU hardware resource removed for" << thing << ". The thing will not be functional any more until a new resource has been configured for it.";
thing->setStateValue(pro380ConnectedStateTypeId, false);
- delete m_pro380Connections.take(thing);
+ delete m_connections.take(thing);
}
}
});
@@ -101,9 +101,9 @@ void IntegrationPluginInepro::setupThing(ThingSetupInfo *info)
return;
}
- if (m_pro380Connections.contains(thing)) {
+ if (m_connections.contains(thing)) {
qCDebug(dcInepro()) << "Setup after rediscovery, cleaning up ...";
- m_pro380Connections.take(thing)->deleteLater();
+ m_connections.take(thing)->deleteLater();
}
Pro380ModbusRtuConnection *proConnection = new Pro380ModbusRtuConnection(hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), address, this);
@@ -194,7 +194,7 @@ void IntegrationPluginInepro::setupThing(ThingSetupInfo *info)
// FIXME: try to read before setup success
- m_pro380Connections.insert(thing, proConnection);
+ m_connections.insert(thing, proConnection);
info->finish(Thing::ThingErrorNoError);
}
@@ -205,7 +205,7 @@ void IntegrationPluginInepro::postSetupThing(Thing *thing)
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(2);
connect(m_refreshTimer, &PluginTimer::timeout, this, [this] {
foreach (Thing *thing, myThings()) {
- m_pro380Connections.value(thing)->update();
+ m_connections.value(thing)->update();
}
});
@@ -218,8 +218,8 @@ void IntegrationPluginInepro::thingRemoved(Thing *thing)
{
qCDebug(dcInepro()) << "Thing removed" << thing->name();
- if (m_pro380Connections.contains(thing))
- m_pro380Connections.take(thing)->deleteLater();
+ if (m_connections.contains(thing))
+ m_connections.take(thing)->deleteLater();
if (myThings().isEmpty() && m_refreshTimer) {
qCDebug(dcInepro()) << "Stopping reconnect timer";
diff --git a/inepro/integrationplugininepro.h b/inepro/integrationplugininepro.h
index dfd8ce0..f74a38b 100644
--- a/inepro/integrationplugininepro.h
+++ b/inepro/integrationplugininepro.h
@@ -37,8 +37,6 @@
#include "pro380modbusrtuconnection.h"
-#include "extern-plugininfo.h"
-
#include
#include
@@ -59,8 +57,8 @@ public:
private:
PluginTimer *m_refreshTimer = nullptr;
+ QHash m_connections;
- QHash m_pro380Connections;
};
#endif // INTEGRATIONPLUGININEPRO_H
diff --git a/inepro/pro380-registers.json b/inepro/pro380-registers.json
index d9c189e..0c9fe50 100644
--- a/inepro/pro380-registers.json
+++ b/inepro/pro380-registers.json
@@ -1,4 +1,5 @@
{
+ "className": "Pro380",
"protocol": "RTU",
"endianness": "BigEndian",
"blocks": [
@@ -263,4 +264,4 @@
"access": "RO"
}
]
-}
\ No newline at end of file
+}
diff --git a/inepro/pro380modbusrtuconnection.cpp b/inepro/pro380modbusrtuconnection.cpp
deleted file mode 100644
index 013b80c..0000000
--- a/inepro/pro380modbusrtuconnection.cpp
+++ /dev/null
@@ -1,537 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* 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 "pro380modbusrtuconnection.h"
-#include "loggingcategories.h"
-
-NYMEA_LOGGING_CATEGORY(dcPro380ModbusRtuConnection, "Pro380ModbusRtuConnection")
-
-Pro380ModbusRtuConnection::Pro380ModbusRtuConnection(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent) :
- QObject(parent),
- m_modbusRtuMaster(modbusRtuMaster),
- m_slaveId(slaveId)
-{
-
-}
-
-ModbusRtuMaster *Pro380ModbusRtuConnection::modbusRtuMaster() const
-{
- return m_modbusRtuMaster;
-}
-quint16 Pro380ModbusRtuConnection::slaveId() const
-{
- return m_slaveId;
-}
-float Pro380ModbusRtuConnection::frequency() const
-{
- return m_frequency;
-}
-
-float Pro380ModbusRtuConnection::totalEnergyConsumed() const
-{
- return m_totalEnergyConsumed;
-}
-
-float Pro380ModbusRtuConnection::totalEnergyProduced() const
-{
- return m_totalEnergyProduced;
-}
-
-float Pro380ModbusRtuConnection::voltagePhaseA() const
-{
- return m_voltagePhaseA;
-}
-
-float Pro380ModbusRtuConnection::voltagePhaseB() const
-{
- return m_voltagePhaseB;
-}
-
-float Pro380ModbusRtuConnection::voltagePhaseC() const
-{
- return m_voltagePhaseC;
-}
-
-float Pro380ModbusRtuConnection::currentPhaseA() const
-{
- return m_currentPhaseA;
-}
-
-float Pro380ModbusRtuConnection::currentPhaseB() const
-{
- return m_currentPhaseB;
-}
-
-float Pro380ModbusRtuConnection::currentPhaseC() const
-{
- return m_currentPhaseC;
-}
-
-float Pro380ModbusRtuConnection::totalCurrentPower() const
-{
- return m_totalCurrentPower;
-}
-
-float Pro380ModbusRtuConnection::powerPhaseA() const
-{
- return m_powerPhaseA;
-}
-
-float Pro380ModbusRtuConnection::powerPhaseB() const
-{
- return m_powerPhaseB;
-}
-
-float Pro380ModbusRtuConnection::powerPhaseC() const
-{
- return m_powerPhaseC;
-}
-
-float Pro380ModbusRtuConnection::energyConsumedPhaseA() const
-{
- return m_energyConsumedPhaseA;
-}
-
-float Pro380ModbusRtuConnection::energyConsumedPhaseB() const
-{
- return m_energyConsumedPhaseB;
-}
-
-float Pro380ModbusRtuConnection::energyConsumedPhaseC() const
-{
- return m_energyConsumedPhaseC;
-}
-
-float Pro380ModbusRtuConnection::energyProducedPhaseA() const
-{
- return m_energyProducedPhaseA;
-}
-
-float Pro380ModbusRtuConnection::energyProducedPhaseB() const
-{
- return m_energyProducedPhaseB;
-}
-
-float Pro380ModbusRtuConnection::energyProducedPhaseC() const
-{
- return m_energyProducedPhaseC;
-}
-
-void Pro380ModbusRtuConnection::initialize()
-{
- // No init registers defined. Nothing to be done and we are finished.
- emit initializationFinished();
-}
-
-void Pro380ModbusRtuConnection::update()
-{
- updateFrequency();
- updateTotalEnergyConsumed();
- updateTotalEnergyProduced();
- updatePhasesVoltageBlock();
- updatePhasesCurrentBlock();
- updateCurrentPowerBlock();
- updatePhasesEnergyConsumedBlock();
- updatePhasesEnergyProducedBlock();
-}
-
-void Pro380ModbusRtuConnection::updateFrequency()
-{
- // Update registers from Frequency
- qCDebug(dcPro380ModbusRtuConnection()) << "--> Read \"Frequency\" register:" << 20488 << "size:" << 2;
- ModbusRtuReply *reply = readFrequency();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcPro380ModbusRtuConnection()) << "<-- Response from \"Frequency\" register" << 20488 << "size:" << 2 << values;
- float receivedFrequency = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_frequency != receivedFrequency) {
- m_frequency = receivedFrequency;
- emit frequencyChanged(m_frequency);
- }
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcPro380ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Frequency\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcPro380ModbusRtuConnection()) << "Error occurred while reading \"Frequency\" registers";
- }
-}
-
-void Pro380ModbusRtuConnection::updateTotalEnergyConsumed()
-{
- // Update registers from Total energy consumed (Forward active energy)
- qCDebug(dcPro380ModbusRtuConnection()) << "--> Read \"Total energy consumed (Forward active energy)\" register:" << 24588 << "size:" << 2;
- ModbusRtuReply *reply = readTotalEnergyConsumed();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcPro380ModbusRtuConnection()) << "<-- Response from \"Total energy consumed (Forward active energy)\" register" << 24588 << "size:" << 2 << values;
- float receivedTotalEnergyConsumed = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_totalEnergyConsumed != receivedTotalEnergyConsumed) {
- m_totalEnergyConsumed = receivedTotalEnergyConsumed;
- emit totalEnergyConsumedChanged(m_totalEnergyConsumed);
- }
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcPro380ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Total energy consumed (Forward active energy)\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcPro380ModbusRtuConnection()) << "Error occurred while reading \"Total energy consumed (Forward active energy)\" registers";
- }
-}
-
-void Pro380ModbusRtuConnection::updateTotalEnergyProduced()
-{
- // Update registers from Total energy produced (Reverse active energy)
- qCDebug(dcPro380ModbusRtuConnection()) << "--> Read \"Total energy produced (Reverse active energy)\" register:" << 24600 << "size:" << 2;
- ModbusRtuReply *reply = readTotalEnergyProduced();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcPro380ModbusRtuConnection()) << "<-- Response from \"Total energy produced (Reverse active energy)\" register" << 24600 << "size:" << 2 << values;
- float receivedTotalEnergyProduced = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_totalEnergyProduced != receivedTotalEnergyProduced) {
- m_totalEnergyProduced = receivedTotalEnergyProduced;
- emit totalEnergyProducedChanged(m_totalEnergyProduced);
- }
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcPro380ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Total energy produced (Reverse active energy)\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcPro380ModbusRtuConnection()) << "Error occurred while reading \"Total energy produced (Reverse active energy)\" registers";
- }
-}
-
-void Pro380ModbusRtuConnection::updatePhasesVoltageBlock()
-{
- // Update register block "phasesVoltage"
- qCDebug(dcPro380ModbusRtuConnection()) << "--> Read block \"phasesVoltage\" registers from:" << 20482 << "size:" << 6;
- ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 20482, 6);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcPro380ModbusRtuConnection()) << "<-- Response from reading block \"phasesVoltage\" register" << 20482 << "size:" << 6 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedVoltagePhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_voltagePhaseA != receivedVoltagePhaseA) {
- m_voltagePhaseA = receivedVoltagePhaseA;
- emit voltagePhaseAChanged(m_voltagePhaseA);
- }
-
- values = blockValues.mid(2, 2);
- float receivedVoltagePhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_voltagePhaseB != receivedVoltagePhaseB) {
- m_voltagePhaseB = receivedVoltagePhaseB;
- emit voltagePhaseBChanged(m_voltagePhaseB);
- }
-
- values = blockValues.mid(4, 2);
- float receivedVoltagePhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_voltagePhaseC != receivedVoltagePhaseC) {
- m_voltagePhaseC = receivedVoltagePhaseC;
- emit voltagePhaseCChanged(m_voltagePhaseC);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcPro380ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"phasesVoltage\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcPro380ModbusRtuConnection()) << "Error occurred while reading block \"phasesVoltage\" registers";
- }
-}
-
-void Pro380ModbusRtuConnection::updatePhasesCurrentBlock()
-{
- // Update register block "phasesCurrent"
- qCDebug(dcPro380ModbusRtuConnection()) << "--> Read block \"phasesCurrent\" registers from:" << 20492 << "size:" << 6;
- ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 20492, 6);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcPro380ModbusRtuConnection()) << "<-- Response from reading block \"phasesCurrent\" register" << 20492 << "size:" << 6 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedCurrentPhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_currentPhaseA != receivedCurrentPhaseA) {
- m_currentPhaseA = receivedCurrentPhaseA;
- emit currentPhaseAChanged(m_currentPhaseA);
- }
-
- values = blockValues.mid(2, 2);
- float receivedCurrentPhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_currentPhaseB != receivedCurrentPhaseB) {
- m_currentPhaseB = receivedCurrentPhaseB;
- emit currentPhaseBChanged(m_currentPhaseB);
- }
-
- values = blockValues.mid(4, 2);
- float receivedCurrentPhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_currentPhaseC != receivedCurrentPhaseC) {
- m_currentPhaseC = receivedCurrentPhaseC;
- emit currentPhaseCChanged(m_currentPhaseC);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcPro380ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"phasesCurrent\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcPro380ModbusRtuConnection()) << "Error occurred while reading block \"phasesCurrent\" registers";
- }
-}
-
-void Pro380ModbusRtuConnection::updateCurrentPowerBlock()
-{
- // Update register block "currentPower"
- qCDebug(dcPro380ModbusRtuConnection()) << "--> Read block \"currentPower\" registers from:" << 20498 << "size:" << 8;
- ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 20498, 8);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcPro380ModbusRtuConnection()) << "<-- Response from reading block \"currentPower\" register" << 20498 << "size:" << 8 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedTotalCurrentPower = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_totalCurrentPower != receivedTotalCurrentPower) {
- m_totalCurrentPower = receivedTotalCurrentPower;
- emit totalCurrentPowerChanged(m_totalCurrentPower);
- }
-
- values = blockValues.mid(2, 2);
- float receivedPowerPhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_powerPhaseA != receivedPowerPhaseA) {
- m_powerPhaseA = receivedPowerPhaseA;
- emit powerPhaseAChanged(m_powerPhaseA);
- }
-
- values = blockValues.mid(4, 2);
- float receivedPowerPhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_powerPhaseB != receivedPowerPhaseB) {
- m_powerPhaseB = receivedPowerPhaseB;
- emit powerPhaseBChanged(m_powerPhaseB);
- }
-
- values = blockValues.mid(6, 2);
- float receivedPowerPhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_powerPhaseC != receivedPowerPhaseC) {
- m_powerPhaseC = receivedPowerPhaseC;
- emit powerPhaseCChanged(m_powerPhaseC);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcPro380ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"currentPower\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcPro380ModbusRtuConnection()) << "Error occurred while reading block \"currentPower\" registers";
- }
-}
-
-void Pro380ModbusRtuConnection::updatePhasesEnergyConsumedBlock()
-{
- // Update register block "phasesEnergyConsumed"
- qCDebug(dcPro380ModbusRtuConnection()) << "--> Read block \"phasesEnergyConsumed\" registers from:" << 24594 << "size:" << 6;
- ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 24594, 6);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcPro380ModbusRtuConnection()) << "<-- Response from reading block \"phasesEnergyConsumed\" register" << 24594 << "size:" << 6 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedEnergyConsumedPhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyConsumedPhaseA != receivedEnergyConsumedPhaseA) {
- m_energyConsumedPhaseA = receivedEnergyConsumedPhaseA;
- emit energyConsumedPhaseAChanged(m_energyConsumedPhaseA);
- }
-
- values = blockValues.mid(2, 2);
- float receivedEnergyConsumedPhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyConsumedPhaseB != receivedEnergyConsumedPhaseB) {
- m_energyConsumedPhaseB = receivedEnergyConsumedPhaseB;
- emit energyConsumedPhaseBChanged(m_energyConsumedPhaseB);
- }
-
- values = blockValues.mid(4, 2);
- float receivedEnergyConsumedPhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyConsumedPhaseC != receivedEnergyConsumedPhaseC) {
- m_energyConsumedPhaseC = receivedEnergyConsumedPhaseC;
- emit energyConsumedPhaseCChanged(m_energyConsumedPhaseC);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcPro380ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"phasesEnergyConsumed\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcPro380ModbusRtuConnection()) << "Error occurred while reading block \"phasesEnergyConsumed\" registers";
- }
-}
-
-void Pro380ModbusRtuConnection::updatePhasesEnergyProducedBlock()
-{
- // Update register block "phasesEnergyProduced"
- qCDebug(dcPro380ModbusRtuConnection()) << "--> Read block \"phasesEnergyProduced\" registers from:" << 24606 << "size:" << 6;
- ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 24606, 6);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- QVector values;
- qCDebug(dcPro380ModbusRtuConnection()) << "<-- Response from reading block \"phasesEnergyProduced\" register" << 24606 << "size:" << 6 << blockValues;
- values = blockValues.mid(0, 2);
- float receivedEnergyProducedPhaseA = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyProducedPhaseA != receivedEnergyProducedPhaseA) {
- m_energyProducedPhaseA = receivedEnergyProducedPhaseA;
- emit energyProducedPhaseAChanged(m_energyProducedPhaseA);
- }
-
- values = blockValues.mid(2, 2);
- float receivedEnergyProducedPhaseB = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyProducedPhaseB != receivedEnergyProducedPhaseB) {
- m_energyProducedPhaseB = receivedEnergyProducedPhaseB;
- emit energyProducedPhaseBChanged(m_energyProducedPhaseB);
- }
-
- values = blockValues.mid(4, 2);
- float receivedEnergyProducedPhaseC = ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrderBigEndian);
- if (m_energyProducedPhaseC != receivedEnergyProducedPhaseC) {
- m_energyProducedPhaseC = receivedEnergyProducedPhaseC;
- emit energyProducedPhaseCChanged(m_energyProducedPhaseC);
- }
-
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcPro380ModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"phasesEnergyProduced\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcPro380ModbusRtuConnection()) << "Error occurred while reading block \"phasesEnergyProduced\" registers";
- }
-}
-
-ModbusRtuReply *Pro380ModbusRtuConnection::readFrequency()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 20488, 2);
-}
-
-ModbusRtuReply *Pro380ModbusRtuConnection::readTotalEnergyConsumed()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 24588, 2);
-}
-
-ModbusRtuReply *Pro380ModbusRtuConnection::readTotalEnergyProduced()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 24600, 2);
-}
-
-void Pro380ModbusRtuConnection::verifyInitFinished()
-{
- if (m_pendingInitReplies.isEmpty()) {
- qCDebug(dcPro380ModbusRtuConnection()) << "Initialization finished of Pro380ModbusRtuConnection";
- emit initializationFinished();
- }
-}
-
-QDebug operator<<(QDebug debug, Pro380ModbusRtuConnection *pro380ModbusRtuConnection)
-{
- debug.nospace().noquote() << "Pro380ModbusRtuConnection(" << pro380ModbusRtuConnection->modbusRtuMaster()->modbusUuid().toString() << ", " << pro380ModbusRtuConnection->modbusRtuMaster()->serialPort() << ", slave ID:" << pro380ModbusRtuConnection->slaveId() << ")" << "\n";
- debug.nospace().noquote() << " - Frequency:" << pro380ModbusRtuConnection->frequency() << " [Hz]" << "\n";
- debug.nospace().noquote() << " - Total energy consumed (Forward active energy):" << pro380ModbusRtuConnection->totalEnergyConsumed() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Total energy produced (Reverse active energy):" << pro380ModbusRtuConnection->totalEnergyProduced() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Voltage phase L1:" << pro380ModbusRtuConnection->voltagePhaseA() << " [V]" << "\n";
- debug.nospace().noquote() << " - Voltage phase L2:" << pro380ModbusRtuConnection->voltagePhaseB() << " [V]" << "\n";
- debug.nospace().noquote() << " - Voltage phase L3:" << pro380ModbusRtuConnection->voltagePhaseC() << " [V]" << "\n";
- debug.nospace().noquote() << " - Current phase L1:" << pro380ModbusRtuConnection->currentPhaseA() << " [A]" << "\n";
- debug.nospace().noquote() << " - Current phase L2:" << pro380ModbusRtuConnection->currentPhaseB() << " [A]" << "\n";
- debug.nospace().noquote() << " - Current phase L3:" << pro380ModbusRtuConnection->currentPhaseC() << " [A]" << "\n";
- debug.nospace().noquote() << " - Total system power:" << pro380ModbusRtuConnection->totalCurrentPower() << " [kW]" << "\n";
- debug.nospace().noquote() << " - Power phase L1:" << pro380ModbusRtuConnection->powerPhaseA() << " [kW]" << "\n";
- debug.nospace().noquote() << " - Power phase L2:" << pro380ModbusRtuConnection->powerPhaseB() << " [kW]" << "\n";
- debug.nospace().noquote() << " - Power phase L3:" << pro380ModbusRtuConnection->powerPhaseC() << " [kW]" << "\n";
- debug.nospace().noquote() << " - Energy consumed phase A:" << pro380ModbusRtuConnection->energyConsumedPhaseA() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy consumed phase B:" << pro380ModbusRtuConnection->energyConsumedPhaseB() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy consumed phase C:" << pro380ModbusRtuConnection->energyConsumedPhaseC() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy produced phase A:" << pro380ModbusRtuConnection->energyProducedPhaseA() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy produced phase B:" << pro380ModbusRtuConnection->energyProducedPhaseB() << " [kWh]" << "\n";
- debug.nospace().noquote() << " - Energy produced phase C:" << pro380ModbusRtuConnection->energyProducedPhaseC() << " [kWh]" << "\n";
- return debug.quote().space();
-}
-
diff --git a/inepro/pro380modbusrtuconnection.h b/inepro/pro380modbusrtuconnection.h
deleted file mode 100644
index 3f26c0b..0000000
--- a/inepro/pro380modbusrtuconnection.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* 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 PRO380MODBUSRTUCONNECTION_H
-#define PRO380MODBUSRTUCONNECTION_H
-
-#include
-
-#include "../modbus/modbusdatautils.h"
-#include
-
-class Pro380ModbusRtuConnection : public QObject
-{
- Q_OBJECT
-public:
- explicit Pro380ModbusRtuConnection(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent = nullptr);
- ~Pro380ModbusRtuConnection() = default;
-
- ModbusRtuMaster *modbusRtuMaster() const;
- quint16 slaveId() const;
-
- /* Frequency [Hz] - Address: 20488, Size: 2 */
- float frequency() const;
-
- /* Total energy consumed (Forward active energy) [kWh] - Address: 24588, Size: 2 */
- float totalEnergyConsumed() const;
-
- /* Total energy produced (Reverse active energy) [kWh] - Address: 24600, Size: 2 */
- float totalEnergyProduced() const;
-
- /* Voltage phase L1 [V] - Address: 20482, Size: 2 */
- float voltagePhaseA() const;
-
- /* Voltage phase L2 [V] - Address: 20484, Size: 2 */
- float voltagePhaseB() const;
-
- /* Voltage phase L3 [V] - Address: 20486, Size: 2 */
- float voltagePhaseC() const;
-
- /* Read block from start addess 20482 with size of 6 registers containing following 3 properties:
- - Voltage phase L1 [V] - Address: 20482, Size: 2
- - Voltage phase L2 [V] - Address: 20484, Size: 2
- - Voltage phase L3 [V] - Address: 20486, Size: 2
- */
- void updatePhasesVoltageBlock();
- /* Current phase L1 [A] - Address: 20492, Size: 2 */
- float currentPhaseA() const;
-
- /* Current phase L2 [A] - Address: 20494, Size: 2 */
- float currentPhaseB() const;
-
- /* Current phase L3 [A] - Address: 20496, Size: 2 */
- float currentPhaseC() const;
-
- /* Read block from start addess 20492 with size of 6 registers containing following 3 properties:
- - Current phase L1 [A] - Address: 20492, Size: 2
- - Current phase L2 [A] - Address: 20494, Size: 2
- - Current phase L3 [A] - Address: 20496, Size: 2
- */
- void updatePhasesCurrentBlock();
- /* Total system power [kW] - Address: 20498, Size: 2 */
- float totalCurrentPower() const;
-
- /* Power phase L1 [kW] - Address: 20500, Size: 2 */
- float powerPhaseA() const;
-
- /* Power phase L2 [kW] - Address: 20502, Size: 2 */
- float powerPhaseB() const;
-
- /* Power phase L3 [kW] - Address: 20504, Size: 2 */
- float powerPhaseC() const;
-
- /* Read block from start addess 20498 with size of 8 registers containing following 4 properties:
- - Total system power [kW] - Address: 20498, Size: 2
- - Power phase L1 [kW] - Address: 20500, Size: 2
- - Power phase L2 [kW] - Address: 20502, Size: 2
- - Power phase L3 [kW] - Address: 20504, Size: 2
- */
- void updateCurrentPowerBlock();
- /* Energy consumed phase A [kWh] - Address: 24594, Size: 2 */
- float energyConsumedPhaseA() const;
-
- /* Energy consumed phase B [kWh] - Address: 24596, Size: 2 */
- float energyConsumedPhaseB() const;
-
- /* Energy consumed phase C [kWh] - Address: 24598, Size: 2 */
- float energyConsumedPhaseC() const;
-
- /* Read block from start addess 24594 with size of 6 registers containing following 3 properties:
- - Energy consumed phase A [kWh] - Address: 24594, Size: 2
- - Energy consumed phase B [kWh] - Address: 24596, Size: 2
- - Energy consumed phase C [kWh] - Address: 24598, Size: 2
- */
- void updatePhasesEnergyConsumedBlock();
- /* Energy produced phase A [kWh] - Address: 24606, Size: 2 */
- float energyProducedPhaseA() const;
-
- /* Energy produced phase B [kWh] - Address: 24608, Size: 2 */
- float energyProducedPhaseB() const;
-
- /* Energy produced phase C [kWh] - Address: 24610, Size: 2 */
- float energyProducedPhaseC() const;
-
- /* Read block from start addess 24606 with size of 6 registers containing following 3 properties:
- - Energy produced phase A [kWh] - Address: 24606, Size: 2
- - Energy produced phase B [kWh] - Address: 24608, Size: 2
- - Energy produced phase C [kWh] - Address: 24610, Size: 2
- */
- void updatePhasesEnergyProducedBlock();
-
- void updateFrequency();
- void updateTotalEnergyConsumed();
- void updateTotalEnergyProduced();
-
- virtual void initialize();
- virtual void update();
-
-signals:
- void initializationFinished();
-
- void frequencyChanged(float frequency);
- void totalEnergyConsumedChanged(float totalEnergyConsumed);
- void totalEnergyProducedChanged(float totalEnergyProduced);
- void voltagePhaseAChanged(float voltagePhaseA);
- void voltagePhaseBChanged(float voltagePhaseB);
- void voltagePhaseCChanged(float voltagePhaseC);
- void currentPhaseAChanged(float currentPhaseA);
- void currentPhaseBChanged(float currentPhaseB);
- void currentPhaseCChanged(float currentPhaseC);
- void totalCurrentPowerChanged(float totalCurrentPower);
- void powerPhaseAChanged(float powerPhaseA);
- void powerPhaseBChanged(float powerPhaseB);
- void powerPhaseCChanged(float powerPhaseC);
- void energyConsumedPhaseAChanged(float energyConsumedPhaseA);
- void energyConsumedPhaseBChanged(float energyConsumedPhaseB);
- void energyConsumedPhaseCChanged(float energyConsumedPhaseC);
- void energyProducedPhaseAChanged(float energyProducedPhaseA);
- void energyProducedPhaseBChanged(float energyProducedPhaseB);
- void energyProducedPhaseCChanged(float energyProducedPhaseC);
-
-private:
- ModbusRtuMaster *m_modbusRtuMaster = nullptr;
- quint16 m_slaveId = 1;
- QVector m_pendingInitReplies;
-
- float m_frequency = 0;
- float m_totalEnergyConsumed = 0;
- float m_totalEnergyProduced = 0;
- float m_voltagePhaseA = 0;
- float m_voltagePhaseB = 0;
- float m_voltagePhaseC = 0;
- float m_currentPhaseA = 0;
- float m_currentPhaseB = 0;
- float m_currentPhaseC = 0;
- float m_totalCurrentPower = 0;
- float m_powerPhaseA = 0;
- float m_powerPhaseB = 0;
- float m_powerPhaseC = 0;
- float m_energyConsumedPhaseA = 0;
- float m_energyConsumedPhaseB = 0;
- float m_energyConsumedPhaseC = 0;
- float m_energyProducedPhaseA = 0;
- float m_energyProducedPhaseB = 0;
- float m_energyProducedPhaseC = 0;
-
- void verifyInitFinished();
-
- ModbusRtuReply *readFrequency();
- ModbusRtuReply *readTotalEnergyConsumed();
- ModbusRtuReply *readTotalEnergyProduced();
-
-
-};
-
-QDebug operator<<(QDebug debug, Pro380ModbusRtuConnection *pro380ModbusRtuConnection);
-
-#endif // PRO380MODBUSRTUCONNECTION_H
diff --git a/libnymea-modbus/libnymea-modbus.pro b/libnymea-modbus/libnymea-modbus.pro
new file mode 100644
index 0000000..61d8b3b
--- /dev/null
+++ b/libnymea-modbus/libnymea-modbus.pro
@@ -0,0 +1,57 @@
+QMAKE_CXXFLAGS += -Werror -std=c++11 -z defs
+QMAKE_LFLAGS += -std=c++11 -z defs
+
+QT += network serialbus
+
+CONFIG += link_pkgconfig
+PKGCONFIG += nymea
+
+TARGET = nymea-modbus
+TEMPLATE = lib
+
+gcc {
+ COMPILER_VERSION = $$system($$QMAKE_CXX " -dumpversion")
+ COMPILER_MAJOR_VERSION = $$str_member($$COMPILER_VERSION)
+ greaterThan(COMPILER_MAJOR_VERSION, 7): QMAKE_CXXFLAGS += -Wno-deprecated-copy
+}
+
+HEADERS += \
+ modbusdatautils.h \
+ modbustcpmaster.h
+
+SOURCES += \
+ modbusdatautils.cpp \
+ modbustcpmaster.cpp
+
+
+# define install target
+target.path = $$[QT_INSTALL_LIBS]
+INSTALLS += target
+
+# install modbustool for external plugins
+modbustoolpri.files = modbus-tool.pri
+modbustoolpri.path = $$[QT_INSTALL_PREFIX]/include/nymea-modbus/
+modbustool.files = tools/generate-connection.py
+modbustool.path = $$[QT_INSTALL_PREFIX]/include/nymea-modbus/tools/
+modbustoolmodules.files = tools/connectiontool/*.py
+modbustoolmodules.path = $$[QT_INSTALL_PREFIX]/include/nymea-modbus/tools/connectiontool/
+INSTALLS += modbustoolpri modbustool modbustoolmodules
+
+# install header file with relative subdirectory
+for (header, HEADERS) {
+ path = $$[QT_INSTALL_PREFIX]/include/nymea-modbus/$${dirname(header)}
+ eval(headers_$${path}.files += $${header})
+ eval(headers_$${path}.path = $${path})
+ eval(INSTALLS *= headers_$${path})
+}
+
+# Create pkgconfig file
+CONFIG += create_pc create_prl no_install_prl
+QMAKE_PKGCONFIG_NAME = libnymea-modbus
+QMAKE_PKGCONFIG_DESCRIPTION = nymea modbus integrations development library
+QMAKE_PKGCONFIG_PREFIX = $$[QT_INSTALL_PREFIX]
+QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_PREFIX]/include/nymea-modbus/
+QMAKE_PKGCONFIG_LIBDIR = $$target.path
+QMAKE_PKGCONFIG_VERSION = 1.0.0
+QMAKE_PKGCONFIG_FILE = nymea-modbus
+QMAKE_PKGCONFIG_DESTDIR = pkgconfig
diff --git a/libnymea-modbus/modbus-tool.pri b/libnymea-modbus/modbus-tool.pri
new file mode 100644
index 0000000..c507b6f
--- /dev/null
+++ b/libnymea-modbus/modbus-tool.pri
@@ -0,0 +1,56 @@
+# 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
+
+# This project include file is meant to be used by nymea modbus integration plugins.
+# For external plugins you can generate connection by including this project like following:
+
+# # Generate modbus connection
+# MODBUS_CONNECTIONS += modbus-registers.json
+# MODBUS_TOOLS_CONFIG += VERBOSE
+# include($$[QT_INSTALL_PREFIX]/include/nymea-modbus/modbus-tool.pri)
+
+# On each qmake run the classes will be generated in the build directory.
+
+GENERATE_MODBUS_CONNECTION_BINARY=$${PWD}/tools/generate-connection.py
+
+for(registerDefinition, MODBUS_CONNECTIONS) {
+ contains(MODBUS_TOOLS_CONFIG, VERBOSE) {
+ message("Generating modbus connection class for $${registerDefinition} (verbose)")
+ system(python3 $${GENERATE_MODBUS_CONNECTION_BINARY} -j $${_PRO_FILE_PWD_}/$${registerDefinition} -o $${OUT_PWD}/autogenerated -v)
+ } else {
+ message("Generating class for $${registerDefinition}")
+ system(python3 $${GENERATE_MODBUS_CONNECTION_BINARY} -j $${_PRO_FILE_PWD_}/$${registerDefinition} -o $${OUT_PWD}/autogenerated)
+ }
+}
+
+# Add all generated pri files to the project
+MODBUS_CONNECTIONS_INCLUDES = $$files($${OUT_PWD}/autogenerated/*.pri)
+for(MODBUS_CONNECTION, MODBUS_CONNECTIONS_INCLUDES) {
+ message("Adding generated connection to project $${MODBUS_CONNECTION}")
+ include($${MODBUS_CONNECTION})
+ INCLUDEPATH += $${OUT_PWD}/autogenerated
+}
+
diff --git a/modbus/modbusdatautils.cpp b/libnymea-modbus/modbusdatautils.cpp
similarity index 100%
rename from modbus/modbusdatautils.cpp
rename to libnymea-modbus/modbusdatautils.cpp
diff --git a/modbus/modbusdatautils.h b/libnymea-modbus/modbusdatautils.h
similarity index 100%
rename from modbus/modbusdatautils.h
rename to libnymea-modbus/modbusdatautils.h
diff --git a/modbus/modbustcpmaster.cpp b/libnymea-modbus/modbustcpmaster.cpp
similarity index 87%
rename from modbus/modbustcpmaster.cpp
rename to libnymea-modbus/modbustcpmaster.cpp
index 880f4c6..8c6a448 100644
--- a/modbus/modbustcpmaster.cpp
+++ b/libnymea-modbus/modbustcpmaster.cpp
@@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
-* Copyright 2013 - 2021, nymea GmbH
+* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
@@ -30,8 +30,7 @@
#include "modbustcpmaster.h"
-#include
-NYMEA_LOGGING_CATEGORY(dcModbusTCP, "ModbusTCP")
+Q_LOGGING_CATEGORY(dcModbusTcpMaster, "ModbusTcpMaster")
ModbusTCPMaster::ModbusTCPMaster(const QHostAddress &hostAddress, uint port, QObject *parent) :
QObject(parent),
@@ -91,7 +90,7 @@ bool ModbusTCPMaster::connectDevice() {
// Only connect if we are in the unconnected state
if (m_modbusTcpClient->state() == QModbusDevice::UnconnectedState) {
- qCDebug(dcModbusTCP()) << "Connecting modbus TCP client to" << QString("%1:%2").arg(m_hostAddress.toString()).arg(m_port);
+ qCDebug(dcModbusTcpMaster()) << "Connecting modbus TCP client to" << QString("%1:%2").arg(m_hostAddress.toString()).arg(m_port);
m_modbusTcpClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, m_port);
m_modbusTcpClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, m_hostAddress.toString());
m_modbusTcpClient->setTimeout(m_timeout);
@@ -101,7 +100,7 @@ bool ModbusTCPMaster::connectDevice() {
// Restart the timer in case of connecting not finished yet or closing
m_reconnectTimer->start();
} else {
- qCWarning(dcModbusTCP()) << "Connect modbus TCP device" << QString("%1:%2").arg(m_hostAddress.toString()).arg(m_port) << "called, but the socket is currently in the" << m_modbusTcpClient->state();
+ qCWarning(dcModbusTcpMaster()) << "Connect modbus TCP device" << QString("%1:%2").arg(m_hostAddress.toString()).arg(m_port) << "called, but the socket is currently in the" << m_modbusTcpClient->state();
}
return false;
@@ -119,7 +118,7 @@ void ModbusTCPMaster::disconnectDevice()
bool ModbusTCPMaster::reconnectDevice()
{
- qCWarning(dcModbusTCP()) << "Reconnecting modbus TCP device" << QString("%1:%2").arg(m_hostAddress.toString()).arg(m_port);
+ qCWarning(dcModbusTcpMaster()) << "Reconnecting modbus TCP device" << QString("%1:%2").arg(m_hostAddress.toString()).arg(m_port);
if (!m_modbusTcpClient)
return false;
@@ -184,12 +183,12 @@ QUuid ModbusTCPMaster::readCoil(uint slaveAddress, uint registerAddress, uint si
emit receivedCoil(reply->serverAddress(), modbusAddress, unit.values());
} else {
emit readRequestExecuted(requestId, false);
- qCWarning(dcModbusTCP()) << "Read response error:" << reply->error();
+ qCWarning(dcModbusTcpMaster()) << "Read response error:" << reply->error();
}
});
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
- qCWarning(dcModbusTCP()) << "Modbus reply error:" << error;
+ qCWarning(dcModbusTcpMaster()) << "Modbus reply error:" << error;
emit readRequestError(requestId, reply->errorString());
emit reply->finished(); // To make sure it will be deleted
});
@@ -200,7 +199,7 @@ QUuid ModbusTCPMaster::readCoil(uint slaveAddress, uint registerAddress, uint si
return QUuid();
}
} else {
- qCWarning(dcModbusTCP()) << "Read error: " << m_modbusTcpClient->errorString();
+ qCWarning(dcModbusTcpMaster()) << "Read error: " << m_modbusTcpClient->errorString();
return QUuid();
}
return requestId;
@@ -226,13 +225,13 @@ QUuid ModbusTCPMaster::writeHoldingRegisters(uint slaveAddress, uint registerAdd
emit receivedHoldingRegister(reply->serverAddress(), modbusAddress, unit.values());
} else {
emit writeRequestExecuted(requestId, false);
- qCWarning(dcModbusTCP()) << "Read response error:" << reply->error();
+ qCWarning(dcModbusTcpMaster()) << "Read response error:" << reply->error();
}
reply->deleteLater();
});
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
- qCWarning(dcModbusTCP()) << "Modbus replay error:" << error;
+ qCWarning(dcModbusTcpMaster()) << "Modbus replay error:" << error;
emit writeRequestError(requestId, reply->errorString());
emit reply->finished(); // To make sure it will be deleted
});
@@ -243,7 +242,7 @@ QUuid ModbusTCPMaster::writeHoldingRegisters(uint slaveAddress, uint registerAdd
return QUuid();
}
} else {
- qCWarning(dcModbusTCP()) << "Read error: " << m_modbusTcpClient->errorString();
+ qCWarning(dcModbusTcpMaster()) << "Read error: " << m_modbusTcpClient->errorString();
return QUuid();
}
return requestId;
@@ -289,12 +288,12 @@ QUuid ModbusTCPMaster::readDiscreteInput(uint slaveAddress, uint registerAddress
emit receivedDiscreteInput(reply->serverAddress(), modbusAddress, unit.values());
} else {
emit readRequestExecuted(requestId, false);
- qCWarning(dcModbusTCP()) << "Read response error:" << reply->error();
+ qCWarning(dcModbusTcpMaster()) << "Read response error:" << reply->error();
}
});
connect(reply, &QModbusReply::errorOccurred, this, [requestId, this] (QModbusDevice::Error error){
- qCWarning(dcModbusTCP()) << "Modbus replay error:" << error;
+ qCWarning(dcModbusTcpMaster()) << "Modbus replay error:" << error;
QModbusReply *reply = qobject_cast(sender());
emit readRequestError(requestId, reply->errorString());
emit reply->finished(); // To make sure it will be deleted
@@ -306,7 +305,7 @@ QUuid ModbusTCPMaster::readDiscreteInput(uint slaveAddress, uint registerAddress
return QUuid();
}
} else {
- qCWarning(dcModbusTCP()) << "Read error: " << m_modbusTcpClient->errorString();
+ qCWarning(dcModbusTcpMaster()) << "Read error: " << m_modbusTcpClient->errorString();
return QUuid();
}
return requestId;
@@ -333,12 +332,12 @@ QUuid ModbusTCPMaster::readInputRegister(uint slaveAddress, uint registerAddress
emit receivedInputRegister(reply->serverAddress(), modbusAddress, unit.values());
} else {
emit readRequestExecuted(requestId, false);
- qCWarning(dcModbusTCP()) << "Read response error:" << reply->error();
+ qCWarning(dcModbusTcpMaster()) << "Read response error:" << reply->error();
}
});
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
- qCWarning(dcModbusTCP()) << "Modbus reply error:" << error;
+ qCWarning(dcModbusTcpMaster()) << "Modbus reply error:" << error;
emit readRequestError(requestId, reply->errorString());
emit reply->finished(); // To make sure it will be deleted
});
@@ -350,7 +349,7 @@ QUuid ModbusTCPMaster::readInputRegister(uint slaveAddress, uint registerAddress
return QUuid();
}
} else {
- qCWarning(dcModbusTCP()) << "Read error: " << m_modbusTcpClient->errorString();
+ qCWarning(dcModbusTcpMaster()) << "Read error: " << m_modbusTcpClient->errorString();
return QUuid();
}
return requestId;
@@ -378,7 +377,7 @@ QUuid ModbusTCPMaster::readHoldingRegister(uint slaveAddress, uint registerAddre
} else {
emit writeRequestExecuted(requestId, false);
- qCWarning(dcModbusTCP()) << "Read response error:" << reply->error();
+ qCWarning(dcModbusTcpMaster()) << "Read response error:" << reply->error();
emit readRequestError(requestId, reply->errorString());
}
reply->deleteLater();
@@ -386,7 +385,7 @@ QUuid ModbusTCPMaster::readHoldingRegister(uint slaveAddress, uint registerAddre
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
- qCWarning(dcModbusTCP()) << "Modbus reply error:" << error;
+ qCWarning(dcModbusTcpMaster()) << "Modbus reply error:" << error;
emit readRequestError(requestId, reply->errorString());
emit reply->finished(); // To make sure it will be deleted
});
@@ -397,7 +396,7 @@ QUuid ModbusTCPMaster::readHoldingRegister(uint slaveAddress, uint registerAddre
return QUuid();
}
} else {
- qCWarning(dcModbusTCP()) << "Read error: " << m_modbusTcpClient->errorString();
+ qCWarning(dcModbusTcpMaster()) << "Read error: " << m_modbusTcpClient->errorString();
return QUuid();
}
return requestId;
@@ -431,13 +430,13 @@ QUuid ModbusTCPMaster::writeCoils(uint slaveAddress, uint registerAddress, const
} else {
emit writeRequestExecuted(requestId, false);
- qCWarning(dcModbusTCP()) << "Write response error:" << reply->error();
+ qCWarning(dcModbusTcpMaster()) << "Write response error:" << reply->error();
}
reply->deleteLater();
});
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
- qCWarning(dcModbusTCP()) << "Modbus reply error:" << error;
+ qCWarning(dcModbusTcpMaster()) << "Modbus reply error:" << error;
emit writeRequestError(requestId, reply->errorString());
emit reply->finished(); // To make sure it will be deleted
});
@@ -448,7 +447,7 @@ QUuid ModbusTCPMaster::writeCoils(uint slaveAddress, uint registerAddress, const
return QUuid();
}
} else {
- qCWarning(dcModbusTCP()) << "Read error: " << m_modbusTcpClient->errorString();
+ qCWarning(dcModbusTcpMaster()) << "Read error: " << m_modbusTcpClient->errorString();
return QUuid();
}
return requestId;
@@ -461,12 +460,12 @@ QUuid ModbusTCPMaster::writeHoldingRegister(uint slaveAddress, uint registerAddr
void ModbusTCPMaster::onModbusErrorOccurred(QModbusDevice::Error error)
{
- qCWarning(dcModbusTCP()) << "An error occured" << error;
+ qCWarning(dcModbusTcpMaster()) << "An error occured" << error;
}
void ModbusTCPMaster::onModbusStateChanged(QModbusDevice::State state)
{
- qCDebug(dcModbusTCP()) << "Connection state changed for" << m_hostAddress << state;
+ qCDebug(dcModbusTcpMaster()) << "Connection state changed for" << m_hostAddress << state;
bool connected = (state == QModbusDevice::ConnectedState);
if (m_connected != connected) {
m_connected = connected;
diff --git a/modbus/modbustcpmaster.h b/libnymea-modbus/modbustcpmaster.h
similarity index 97%
rename from modbus/modbustcpmaster.h
rename to libnymea-modbus/modbustcpmaster.h
index 7857922..4b456ee 100644
--- a/modbus/modbustcpmaster.h
+++ b/libnymea-modbus/modbustcpmaster.h
@@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
-* Copyright 2013 - 2021, nymea GmbH
+* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
@@ -31,11 +31,14 @@
#ifndef MODBUSTCPMASTER_H
#define MODBUSTCPMASTER_H
+#include
+#include
#include
#include
#include
-#include
-#include
+#include
+
+Q_DECLARE_LOGGING_CATEGORY(dcModbusTcpMaster)
class ModbusTCPMaster : public QObject
{
@@ -112,6 +115,7 @@ signals:
void receivedDiscreteInput(uint slaveAddress, uint modbusRegister, const QVector &values);
void receivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector &values);
void receivedInputRegister(uint slaveAddress, uint modbusRegister, const QVector &values);
+
};
#endif // MODBUSTCPMASTER_H
diff --git a/modbus/tools/README.md b/libnymea-modbus/tools/README.md
similarity index 77%
rename from modbus/tools/README.md
rename to libnymea-modbus/tools/README.md
index 72b0309..a3fc623 100644
--- a/modbus/tools/README.md
+++ b/libnymea-modbus/tools/README.md
@@ -14,7 +14,7 @@ The class will provide 2 main methods for fetching information from the modbus d
* `initialize()` will read all registers with `"readSchedule": "init"` and emits the signal `initializationFinished()` once all replies returned.
* `update()` can be used to update all registers with `"readSchedule": "update"`. The class will then fetch each register and update the specified value internally. If the value has changed, the `Changed()` signal will be emitted.
-The reulting class will inhert from the `ModbusTCPMaster` class, providing easy access to all possible modbus operations and inform about the connected state.
+The resulting class will inhert from the `ModbusTCPMaster` class, providing easy access to all possible modbus operations and inform about the connected state.
# JSON format
@@ -23,6 +23,8 @@ The basic structure of the modbus register JSON looks like following example:
```
{
+ "className": "MyConnection",
+ "protocol": "BOTH",
"endianness": "BigEndian",
"enums": [
{
@@ -64,29 +66,73 @@ The basic structure of the modbus register JSON looks like following example:
"access": "RO"
},
...
+ ],
+ "blocks": [
+ {
+ "id": "blockName",
+ "readSchedule": "update",
+ "registers": [
+ {
+ "id": "registerOne",
+ "address": 0,
+ "size": 2,
+ ...
+ },
+ {
+ "id": "registerOne",
+ "address": 0,
+ "size": 2,
+ ...
+ },
+ ...
+ ]
+ }
]
}
```
-## Endianness
+## Class name
-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.
+If no name class name has been passed to the generator script, the classname defined in the JSON file will be used.
-There are 2 possibilities:
+The naming convention for the classname and the resulting source code files looks like this:
+
+The class will be defined as
+
+ * `Connection`.
+
+The source code files will be calld:
+
+ * `classnameprotocolconnection.h`
+ * `classnameprotocolconnection.cpp`
-* `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`
## Protocol
Depending on the communication protocol, a different base class will be used for the resulting output class.
-There are 2 possibilities:
+There are 2 protocol types:
* `RTU`: a communication based on the RS485 serial RTU transport protocol
* `TCP`: a communication based on the TCP transport protocol
+If the modbus device supports both protocols and you want to generate a class for each protocol you can set the protocol to `BOTH` and a class for `RTU` and one for `TCP` will be generated.
+
+ ...
+ "protocol": "TCP",
+ ...
+
+
+## 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 endianness 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 ` = `.
@@ -133,9 +179,9 @@ Earch register will be defined as a property in the resulting class modbus TCP c
On many device it is possible to read multiple registers in one modbus call. This can improve speed significantly when reading many register addresses which are in a row.
-> Important: all registers within the block must exist, be in a row with no gaps inbetween!
+> Important: all registers within the block must exist, be in a row with no gaps inbetween and from the same function type!
-A block sequence looks like this and will define a read method for reading the entwire block. Writing multiple blocks is currently not supported since not needed so far, but could be added to. In any case, all registers must be read or written, never have combinations.
+A block sequence looks like this and will define a read method for reading the entwire block. Writing multiple blocks is currently not supported since not needed so far, but could be added too. In any case, all registers must be read or written, never have combinations.
* `id`: Mandatory. The id defines the name of the block used in the resulting class.
* `readSchedule`: Optional. Defines when the register needs to be fetched. If no read schedule has been defined, the class will provide only the update methods, but will not read the value during `initialize()` or `update()` calls. Possible values are:
@@ -173,20 +219,16 @@ Example block:
]
-# Example
+# Autogenerate modbus classes
-Change into your plugin sub directory.
-Assuming you wrote the registers.json file you can run now following command to generate your modbus class:
-
-`$ python3 ../modbus/tools/generate-connection.py -j registers.json -o . -c MyModbusConnection`
-
-You the result will be a header and a source file called:
-
-* `mymodbusconnection.h`
-* `mymodbusconnection.cpp`
-
-You can include this class in your project and provide one connection per thing.
+In order to get always the latest generated code from this tool, the entire process can be automated.
+Assuming you have defined the registers in the `my-registers.json` within your plugin directory, and following lines to your plugin project file and run `qmake`.
+ # Generate modbus connection
+ MODBUS_CONNECTIONS += my-registers.json
+ include(../modbus.pri)
+If you want to get information about the autogenerating class process, you can add `MODBUS_TOOLS_CONFIG += VERBOSE` in order to get much more information of the process.
+Once you run qmake, in the build directory the autogenerated classes can be found. Also in your project you can find the generated classes for inspection.
diff --git a/libnymea-modbus/tools/connectiontool/__init__.py b/libnymea-modbus/tools/connectiontool/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/libnymea-modbus/tools/connectiontool/modbusrtu.py b/libnymea-modbus/tools/connectiontool/modbusrtu.py
new file mode 100644
index 0000000..2d490c6
--- /dev/null
+++ b/libnymea-modbus/tools/connectiontool/modbusrtu.py
@@ -0,0 +1,383 @@
+# Copyright (C) 2021 - 2022 nymea GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+import logging
+
+from .toolcommon import *
+
+##############################################################
+
+def writePropertyGetSetMethodDeclarationsRtu(fileDescriptor, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ if 'unit' in registerDefinition and registerDefinition['unit'] != '':
+ writeLine(fileDescriptor, ' /* %s [%s] - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
+ else:
+ 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, ' ModbusRtuReply *set%s(%s %s);' % (propertyName[0].upper() + propertyName[1:], propertyTyp, propertyName))
+
+ writeLine(fileDescriptor)
+
+
+def writePropertyGetSetMethodImplementationsRtu(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:
+ writeLine(fileDescriptor, '%s %s::%s() const' % (propertyTyp, className, propertyName))
+
+ writeLine(fileDescriptor, '{')
+ writeLine(fileDescriptor, ' return m_%s;' % propertyName)
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+ # Check if we require a set method
+ if registerDefinition['access'] == 'RW' or registerDefinition['access'] == 'WO':
+ writeLine(fileDescriptor, 'ModbusRtuReply *%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, ' return m_modbusRtuMaster->writeHoldingRegisters(m_slaveId, %s, values);' % (registerDefinition['address']))
+ elif registerDefinition['registerType'] == 'coils':
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->writeCoils(m_slaveId, %s, values);' % (registerDefinition['address']))
+ else:
+ logger.warning('Error: invalid register type for writing.')
+ exit(1)
+
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+
+def writePropertyUpdateMethodImplementationsRtu(fileDescriptor, className, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
+ continue
+
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ 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, ' ModbusRtuReply *reply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, ' if (reply) {')
+ writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
+ writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){')
+ writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {')
+ writeLine(fileDescriptor, ' QVector values = reply->result();')
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ writeLine(fileDescriptor, ' process%sRegisterValues(values);' % (propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating \\"%s\\" registers" << error << reply->errorString();' % (className, registerDefinition['description']))
+ writeLine(fileDescriptor, ' emit reply->finished();')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' } else {')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers";' % (className, registerDefinition['description']))
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+def writeBlockUpdateMethodImplementationsRtu(fileDescriptor, className, blockDefinitions):
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerType = blockRegister['registerType']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+ writeLine(fileDescriptor, 'void %s::update%sBlock()' % (className, blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor, '{')
+ writeLine(fileDescriptor, ' // Update register block \"%s\"' % blockName)
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read block \\"%s\\" registers from:" << %s << "size:" << %s;' % (className, blockName, blockStartAddress, blockSize))
+
+
+ # Build request depending on the register type
+ if registerType == 'inputRegister':
+ writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readInputRegister(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
+ elif registerType == 'discreteInputs':
+ writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readDiscreteInput(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
+ elif registerType == 'coils':
+ writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readCoil(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
+ else:
+ #Default to holdingRegister
+ writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
+
+ writeLine(fileDescriptor, ' if (reply) {')
+ writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
+ writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){')
+ writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {')
+ writeLine(fileDescriptor, ' QVector blockValues = reply->result();')
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize))
+
+ # Start parsing the registers using offsets
+ offset = 0
+ for i, blockRegister in enumerate(blockRegisters):
+ propertyName = blockRegister['id']
+ writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size']))
+ offset += blockRegister['size']
+
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName))
+ writeLine(fileDescriptor, ' emit reply->finished();')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' } else {')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName))
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+def writeInternalPropertyReadMethodDeclarationsRtu(fileDescriptor, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ writeLine(fileDescriptor, ' ModbusRtuReply *read%s();' % (propertyName[0].upper() + propertyName[1:]))
+
+
+def writeInternalPropertyReadMethodImplementationsRtu(fileDescriptor, className, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ writeLine(fileDescriptor, 'ModbusRtuReply *%s::read%s()' % (className, propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, '{')
+
+ # Build request depending on the register type
+ if registerDefinition['registerType'] == 'inputRegister':
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->readInputRegister(m_slaveId, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+ elif registerDefinition['registerType'] == 'discreteInputs':
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->readDiscreteInput(m_slaveId, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+ elif registerDefinition['registerType'] == 'coils':
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->readCoil(m_slaveId, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+ else:
+ #Default to holdingRegister
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->readHoldingRegister(m_slaveId, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
+
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+def writeInternalBlockReadMethodDeclarationsRtu(fileDescriptor, blockDefinitions):
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerType = blockRegister['registerType']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+ writeLine(fileDescriptor, ' /* Read block from start addess %s with size of %s registers containing following %s properties:' % (blockStartAddress, blockSize, registerCount))
+ for i, registerDefinition in enumerate(blockRegisters):
+ if 'unit' in registerDefinition and registerDefinition['unit'] != '':
+ writeLine(fileDescriptor, ' - %s [%s] - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
+ else:
+ writeLine(fileDescriptor, ' -- %s - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ writeLine(fileDescriptor, ' */' )
+ writeLine(fileDescriptor, ' ModbusRtuReply *readBlock%s();' % (blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor)
+
+
+def writeInternalBlockReadMethodImplementationsRtu(fileDescriptor, className, blockDefinitions):
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerType = blockRegister['registerType']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+
+ writeLine(fileDescriptor, 'ModbusRtuReply *%s::readBlock%s()' % (className, blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor, '{')
+
+ # Build request depending on the register type
+ if registerType == 'inputRegister':
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->readInputRegister(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
+ elif registerType == 'discreteInputs':
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->readDiscreteInput(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
+ elif registerType == 'coils':
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->readCoil(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
+ else:
+ #Default to holdingRegister
+ writeLine(fileDescriptor, ' return m_modbusRtuMaster->readHoldingRegister(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
+
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefinitions, blockDefinitions):
+ writeLine(fileDescriptor, 'void %s::initialize()' % (className))
+ writeLine(fileDescriptor, '{')
+
+ # First check if there are any init registers
+ initRequired = False
+ for registerDefinition in registerDefinitions:
+ if registerDefinition['readSchedule'] == 'init':
+ initRequired = True
+ break
+
+ for blockDefinition in blockDefinitions:
+ if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'init':
+ initRequired = True
+ break
+
+ if initRequired:
+ writeLine(fileDescriptor, ' ModbusRtuReply *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, ' }')
+
+ # Read individual registers
+ 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, &ModbusRtuReply::finished, this, [this, reply](){')
+ writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {')
+ writeLine(fileDescriptor, ' QVector values = reply->result();')
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ writeLine(fileDescriptor, ' process%sRegisterValues(values);' % (propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);')
+ writeLine(fileDescriptor, ' verifyInitFinished();')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating \\"%s\\" registers" << error << reply->errorString();' % (className, registerDefinition['description']))
+ writeLine(fileDescriptor, ' emit reply->finished();')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' } else {')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers";' % (className, registerDefinition['description']))
+ writeLine(fileDescriptor, ' }')
+
+ # Read init blocks
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+
+ if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'init':
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerType = blockRegister['registerType']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' // Read %s' % blockName)
+ writeLine(fileDescriptor, ' reply = readBlock%s();' % (blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor, ' if (reply) {')
+ writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
+ writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);')
+ writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){')
+ writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {')
+ writeLine(fileDescriptor, ' QVector blockValues = reply->result();')
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize))
+
+ # Start parsing the registers using offsets
+ offset = 0
+ for i, blockRegister in enumerate(blockRegisters):
+ propertyName = blockRegister['id']
+ propertyTyp = getCppDataType(blockRegister)
+ writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size']))
+ offset += blockRegister['size']
+
+ writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);')
+ writeLine(fileDescriptor, ' verifyInitFinished();')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName))
+ writeLine(fileDescriptor, ' emit reply->finished();')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' } else {')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName))
+ writeLine(fileDescriptor, ' }')
+ 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)
diff --git a/libnymea-modbus/tools/connectiontool/modbustcp.py b/libnymea-modbus/tools/connectiontool/modbustcp.py
new file mode 100644
index 0000000..1fbd057
--- /dev/null
+++ b/libnymea-modbus/tools/connectiontool/modbustcp.py
@@ -0,0 +1,385 @@
+# Copyright (C) 2021 - 2022 nymea GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+from .toolcommon import *
+
+##############################################################
+
+def writePropertyGetSetMethodDeclarationsTcp(fileDescriptor, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ if 'unit' in registerDefinition and registerDefinition['unit'] != '':
+ writeLine(fileDescriptor, ' /* %s [%s] - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
+ else:
+ 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 writePropertyGetSetMethodImplementationsTcp(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:
+ writeLine(fileDescriptor, '%s %s::%s() const' % (propertyTyp, className, propertyName))
+
+ writeLine(fileDescriptor, '{')
+ writeLine(fileDescriptor, ' return m_%s;' % propertyName)
+ 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']))
+ elif registerDefinition['registerType'] == 'coils':
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, %s, values.count());' % (registerDefinition['address']))
+ else:
+ logger.warning('Error: invalid register type for writing.')
+ exit(1)
+
+ writeLine(fileDescriptor, ' request.setValues(values);')
+ writeLine(fileDescriptor, ' return sendWriteRequest(request, m_slaveId);')
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+def writePropertyUpdateMethodImplementationsTcp(fileDescriptor, className, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
+ continue
+
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ 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()) {')
+ 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, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ writeLine(fileDescriptor, ' process%sRegisterValues(unit.values());' % (propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, ' }')
+ 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 updating \\"%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, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+def writeBlockUpdateMethodImplementationsTcp(fileDescriptor, className, blockDefinitions):
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerType = blockRegister['registerType']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+ writeLine(fileDescriptor, 'void %s::update%sBlock()' % (className, blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor, '{')
+ writeLine(fileDescriptor, ' // Update register block \"%s\"' % blockName)
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read block \\"%s\\" registers from:" << %s << "size:" << %s;' % (className, blockName, blockStartAddress, blockSize))
+ writeLine(fileDescriptor, ' QModbusReply *reply = readBlock%s();' % (blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor, ' if (reply) {')
+ writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
+ 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, ' const QVector blockValues = unit.values();')
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize))
+
+ # Start parsing the registers using offsets
+ offset = 0
+ for i, blockRegister in enumerate(blockRegisters):
+ propertyName = blockRegister['id']
+ propertyTyp = getCppDataType(blockRegister)
+ writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size']))
+ offset += blockRegister['size']
+
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName))
+ writeLine(fileDescriptor, ' emit reply->finished();')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' } else {')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName))
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+def writeInternalPropertyReadMethodDeclarationsTcp(fileDescriptor, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ writeLine(fileDescriptor, ' QModbusReply *read%s();' % (propertyName[0].upper() + propertyName[1:]))
+
+
+def writeInternalPropertyReadMethodImplementationsTcp(fileDescriptor, className, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ writeLine(fileDescriptor, 'QModbusReply *%s::read%s()' % (className, propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, '{')
+
+ # 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)
+
+
+##############################################################
+
+def writeInternalBlockReadMethodDeclarationsTcp(fileDescriptor, blockDefinitions):
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerType = blockRegister['registerType']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+ writeLine(fileDescriptor, ' /* Read block from start addess %s with size of %s registers containing following %s properties:' % (blockStartAddress, blockSize, registerCount))
+ for i, registerDefinition in enumerate(blockRegisters):
+ if 'unit' in registerDefinition and registerDefinition['unit'] != '':
+ writeLine(fileDescriptor, ' - %s [%s] - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
+ else:
+ writeLine(fileDescriptor, ' - %s - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ writeLine(fileDescriptor, ' */' )
+ writeLine(fileDescriptor, ' QModbusReply *readBlock%s();' % (blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor)
+
+
+def writeInternalBlockReadMethodImplementationsTcp(fileDescriptor, className, blockDefinitions):
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerType = blockRegister['registerType']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+
+ writeLine(fileDescriptor, 'QModbusReply *%s::readBlock%s()' % (className, blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor, '{')
+
+ # Build request depending on the register type
+ if registerType == 'inputRegister':
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, %s, %s);' % (blockStartAddress, blockSize))
+ elif registerType == 'discreteInputs':
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::DiscreteInputs, %s, %s);' % (blockStartAddress, blockSize))
+ elif registerType == 'coils':
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, %s, %s);' % (blockStartAddress, blockSize))
+ else:
+ #Default to holdingRegister
+ writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, %s, %s);' % (blockStartAddress, blockSize))
+
+ writeLine(fileDescriptor, ' return sendReadRequest(request, m_slaveId);')
+
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+##############################################################
+
+def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefinitions, blockDefinitions):
+ writeLine(fileDescriptor, 'void %s::initialize()' % (className))
+ writeLine(fileDescriptor, '{')
+
+ # First check if there are any init registers
+ initRequired = False
+ for registerDefinition in registerDefinitions:
+ if registerDefinition['readSchedule'] == 'init':
+ initRequired = True
+ break
+
+ for blockDefinition in blockDefinitions:
+ if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'init':
+ initRequired = True
+ break
+
+ 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, ' }')
+
+ # Read individual registers
+ 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, ' qCDebug(dc%s()) << "--> Read init \\"%s\\" register:" << %s << "size:" << %s;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ 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, ' qCDebug(dc%s()) << "<-- Response from init \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ writeLine(fileDescriptor, ' process%sRegisterValues(unit.values());' % (propertyName[0].upper() + propertyName[1:]))
+ 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, ' }')
+
+ # Read init blocks
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+
+ if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'init':
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerType = blockRegister['registerType']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' // Read %s' % blockName)
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read init block \\"%s\\" registers from:" << %s << "size:" << %s;' % (className, blockName, blockStartAddress, blockSize))
+ writeLine(fileDescriptor, ' reply = readBlock%s();' % (blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor, ' if (reply) {')
+ writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
+ writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);')
+ 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, ' const QVector blockValues = unit.values();')
+ writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading init block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize))
+
+ # Start parsing the registers using offsets
+ offset = 0
+ for i, blockRegister in enumerate(blockRegisters):
+ propertyName = blockRegister['id']
+ propertyTyp = getCppDataType(blockRegister)
+ writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size']))
+ offset += blockRegister['size']
+
+ writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);')
+ writeLine(fileDescriptor, ' verifyInitFinished();')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName))
+ writeLine(fileDescriptor, ' emit reply->finished();')
+ writeLine(fileDescriptor, ' });')
+ writeLine(fileDescriptor, ' }')
+ writeLine(fileDescriptor, ' } else {')
+ writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName))
+ writeLine(fileDescriptor, ' }')
+ 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)
diff --git a/libnymea-modbus/tools/connectiontool/toolcommon.py b/libnymea-modbus/tools/connectiontool/toolcommon.py
new file mode 100644
index 0000000..66cac9c
--- /dev/null
+++ b/libnymea-modbus/tools/connectiontool/toolcommon.py
@@ -0,0 +1,499 @@
+# Copyright (C) 2021 - 2022 nymea GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+import os
+import re
+import sys
+import json
+import shutil
+import datetime
+import logging
+
+logger = logging.getLogger('modbus-tools')
+
+def convertToAlphaNumeric(text):
+ finalText = ''
+ for character in text:
+ if character.isalnum():
+ finalText += character
+ else:
+ finalText += ' '
+ return finalText
+
+
+def splitCamelCase(text):
+ return re.sub('([A-Z][a-z]+)', r' \1', re.sub('([A-Z]+)', r' \1', text)).split()
+
+
+def convertToCamelCase(text, capitalize = False):
+ s = convertToAlphaNumeric(text)
+ s = s.replace("-", " ").replace("_", " ")
+ words = s.split()
+ logger.debug('--> words', words)
+ finalWords = []
+
+ for i in range(len(words)):
+ camelCaseSplit = splitCamelCase(words[i])
+ if len(camelCaseSplit) == 0:
+ finalWords.append(words[i])
+ else:
+ logging.debug('Camel calse split words', camelCaseSplit)
+ for j in range(len(camelCaseSplit)):
+ finalWords.append(camelCaseSplit[j])
+
+ if len(finalWords) == 0:
+ return text
+
+ finalText = ''
+ if capitalize:
+ finalText = finalWords[0].capitalize() + ''.join(i.capitalize() for i in finalWords[1:])
+ else:
+ finalText = finalWords[0].lower() + ''.join(i.capitalize() for i in finalWords[1:])
+ logging.debug('Convert camel case:', text, '-->', finalText)
+ return finalText
+
+
+def loadJsonFile(filePath):
+ logger.info('Loading JSON file %s', filePath)
+ jsonFile = open(filePath, 'r')
+ return json.load(jsonFile)
+
+
+def writeLine(fileDescriptor, line = ''):
+ fileDescriptor.write(line + '\n')
+
+
+def writeLicenseHeader(fileDescriptor):
+ writeLine(fileDescriptor, '/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* Copyright 2013 - %s, nymea GmbH' % datetime.datetime.now().year)
+ writeLine(fileDescriptor, '* Contact: contact@nymea.io')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* This fileDescriptor is part of nymea.')
+ writeLine(fileDescriptor, '* This project including source code and documentation is protected by')
+ writeLine(fileDescriptor, '* copyright law, and remains the property of nymea GmbH. All rights, including')
+ writeLine(fileDescriptor, '* reproduction, publication, editing and translation, are reserved. The use of')
+ writeLine(fileDescriptor, '* this project is subject to the terms of a license agreement to be concluded')
+ writeLine(fileDescriptor, '* with nymea GmbH in accordance with the terms of use of nymea GmbH, available')
+ writeLine(fileDescriptor, '* under https://nymea.io/license')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* GNU Lesser General Public License Usage')
+ writeLine(fileDescriptor, '* Alternatively, this project may be redistributed and/or modified under the')
+ writeLine(fileDescriptor, '* terms of the GNU Lesser General Public License as published by the Free')
+ writeLine(fileDescriptor, '* Software Foundation; version 3. This project is distributed in the hope that')
+ writeLine(fileDescriptor, '* it will be useful, but WITHOUT ANY WARRANTY; without even the implied')
+ writeLine(fileDescriptor, '* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU')
+ writeLine(fileDescriptor, '* Lesser General Public License for more details.')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* You should have received a copy of the GNU Lesser General Public License')
+ writeLine(fileDescriptor, '* along with this project. If not, see .')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* For any further details and any questions please contact us under')
+ writeLine(fileDescriptor, '* contact@nymea.io or see our FAQ/Licensing Information on')
+ writeLine(fileDescriptor, '* https://nymea.io/license/faq')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */')
+ writeLine(fileDescriptor)
+ writeLine(fileDescriptor, '/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* WARNING')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* This file has been autogenerated. Any changes in this file may be overwritten.')
+ writeLine(fileDescriptor, '* If you want to change something, update the register json or the tool.')
+ writeLine(fileDescriptor, '*')
+ writeLine(fileDescriptor, '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */')
+ writeLine(fileDescriptor)
+
+
+def writeRegistersEnum(fileDescriptor, registerJson):
+ logger.debug('Writing enum for all registers')
+
+ registerEnums = {}
+
+ # Read all register names and addresses
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ blockRegisters = blockDefinition['registers']
+ for blockRegister in blockRegisters:
+ registerName = blockRegister['id']
+ registerAddress = blockRegister['address']
+ registerEnums[registerAddress] = registerName
+
+ for registerDefinition in registerJson['registers']:
+ registerName = registerDefinition['id']
+ registerAddress = registerDefinition['address']
+ registerEnums[registerAddress] = registerName
+
+
+ # Sort the enum map
+ registersKeys = registerEnums.keys()
+ sortedRegistersKeys = sorted(registersKeys)
+ sortedRegisterEnumList = []
+
+ logger.debug('Sorted registers')
+ for registerAddress in sortedRegistersKeys:
+ logger.debug('--> %s : %s' % (registerAddress, registerEnums[registerAddress]))
+ enumData = {}
+ enumData['key'] = registerEnums[registerAddress]
+ enumData['value'] = registerAddress
+ sortedRegisterEnumList.append(enumData)
+
+ enumName = 'Registers'
+ writeLine(fileDescriptor, ' enum %s {' % enumName)
+ for i in range(len(sortedRegisterEnumList)):
+ enumData = sortedRegisterEnumList[i]
+ line = (' Register%s = %s' % (enumData['key'][0].upper() + enumData['key'][1:] , enumData['value']))
+ if i < (len(sortedRegisterEnumList) - 1):
+ line += ','
+
+ writeLine(fileDescriptor, line)
+
+ writeLine(fileDescriptor, ' };')
+ writeLine(fileDescriptor, ' Q_ENUM(%s)' % enumName)
+ writeLine(fileDescriptor)
+
+
+def writeEnumDefinition(fileDescriptor, enumDefinition):
+ logger.debug('Writing enum %s', enumDefinition)
+ enumName = enumDefinition['name']
+ enumValues = enumDefinition['values']
+ writeLine(fileDescriptor, ' enum %s {' % enumName)
+ for i in range(len(enumValues)):
+ enumData = enumValues[i]
+ line = (' %s%s = %s' % (enumName, enumData['key'], enumData['value']))
+ if i < (len(enumValues) - 1):
+ line += ','
+
+ writeLine(fileDescriptor, line)
+
+ writeLine(fileDescriptor, ' };')
+ writeLine(fileDescriptor, ' Q_ENUM(%s)' % enumName)
+ writeLine(fileDescriptor)
+
+
+def getCppDataType(registerDefinition, rawType = False):
+ if not rawType:
+ if 'enum' in registerDefinition:
+ return registerDefinition['enum']
+
+ if 'scaleFactor' in registerDefinition or 'staticScaleFactor' in registerDefinition:
+ return 'float'
+
+ if registerDefinition['type'] == 'uint16':
+ return 'quint16'
+
+ if registerDefinition['type'] == 'int16':
+ return 'qint16'
+
+ if registerDefinition['type'] == 'uint32':
+ return 'quint32'
+
+ if registerDefinition['type'] == 'int32':
+ return 'qint32'
+
+ if registerDefinition['type'] == 'uint64':
+ return 'quint64'
+
+ if registerDefinition['type'] == 'int64':
+ return 'qint64'
+
+ if registerDefinition['type'] == 'float':
+ return 'float'
+
+ if registerDefinition['type'] == 'float64':
+ return 'double'
+
+ if registerDefinition['type'] == 'string':
+ 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), m_endianness)' % (propertyTyp, propertyName))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s), m_endianness)' % (propertyTyp, propertyName))
+
+ # 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)), m_endianness)' % (propertyTyp, propertyName, scaleFactorProperty))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), m_endianness)' % (propertyTyp, propertyName, scaleFactorProperty))
+
+ 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)), m_endianness)' % (propertyTyp, propertyName, scaleFactor))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), m_endianness)' % (propertyTyp, propertyName, scaleFactor))
+
+ # 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, m_endianness)' % (propertyName))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertFromInt32(%s, m_endianness)' % (propertyName))
+ elif registerDefinition['type'] == 'uint64':
+ return ('ModbusDataUtils::convertFromUInt64(%s, m_endianness)' % (propertyName))
+ elif registerDefinition['type'] == 'int64':
+ return ('ModbusDataUtils::convertFromInt64(%s, m_endianness)' % (propertyName))
+ elif registerDefinition['type'] == 'float':
+ return ('ModbusDataUtils::convertFromFloat32(%s, m_endianness)' % propertyName)
+ elif registerDefinition['type'] == 'float64':
+ return ('ModbusDataUtils::convertFromFloat64(%s, m_endianness)' % propertyName)
+ 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':
+ return ('static_cast<%s>(ModbusDataUtils::convertToUInt16(values))' % (enumName))
+ elif registerDefinition['type'] == 'int16':
+ return ('static_cast<%s>(ModbusDataUtils::convertToInt16(values))' % (enumName))
+ elif registerDefinition['type'] == 'uint32':
+ return ('static_cast<%s>(ModbusDataUtils::convertToUInt32(values, m_endianness))' % (enumName))
+ elif registerDefinition['type'] == 'int32':
+ return ('static_cast<%s>(ModbusDataUtils::convertToInt32(values, m_endianness))' % (enumName))
+
+ # Handle scale factors
+ if 'scaleFactor' in registerDefinition:
+ scaleFactorProperty = 'm_%s' % registerDefinition['scaleFactor']
+ if registerDefinition['type'] == 'uint16':
+ return ('ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
+ elif registerDefinition['type'] == 'int16':
+ return ('ModbusDataUtils::convertToInt16(values) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
+ elif registerDefinition['type'] == 'uint32':
+ return ('ModbusDataUtils::convertToUInt32(values, m_endianness) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertToInt32(values, m_endianness) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
+
+ elif 'staticScaleFactor' in registerDefinition:
+ scaleFactor = registerDefinition['staticScaleFactor']
+ if registerDefinition['type'] == 'uint16':
+ return ('ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, %s)' % (scaleFactor))
+ elif registerDefinition['type'] == 'int16':
+ return ('ModbusDataUtils::convertToInt16(values) * 1.0 * pow(10, %s)' % (scaleFactor))
+ elif registerDefinition['type'] == 'uint32':
+ return ('ModbusDataUtils::convertToUInt32(values, m_endianness) * 1.0 * pow(10, %s)' % (scaleFactor))
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertToInt32(values, m_endianness) * 1.0 * pow(10, %s)' % (scaleFactor))
+
+ # Handle default types
+ elif registerDefinition['type'] == 'uint16':
+ return ('ModbusDataUtils::convertToUInt16(values)')
+ elif registerDefinition['type'] == 'int16':
+ return ('ModbusDataUtils::convertToInt16(values)')
+ elif registerDefinition['type'] == 'uint32':
+ return ('ModbusDataUtils::convertToUInt32(values, m_endianness)')
+ elif registerDefinition['type'] == 'int32':
+ return ('ModbusDataUtils::convertToInt32(values, m_endianness)')
+ elif registerDefinition['type'] == 'uint64':
+ return ('ModbusDataUtils::convertToUInt64(values, m_endianness)')
+ elif registerDefinition['type'] == 'int64':
+ return ('ModbusDataUtils::convertToInt64(values, m_endianness)')
+ elif registerDefinition['type'] == 'float':
+ return ('ModbusDataUtils::convertToFloat32(values, m_endianness)')
+ elif registerDefinition['type'] == 'float64':
+ return ('ModbusDataUtils::convertToFloat64(values, m_endianness)')
+ elif registerDefinition['type'] == 'string':
+ return ('ModbusDataUtils::convertToString(values)')
+
+
+def writeBlockGetMethodDeclarations(fileDescriptor, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ if 'unit' in registerDefinition and registerDefinition['unit'] != '':
+ writeLine(fileDescriptor, ' /* %s [%s] - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
+ else:
+ writeLine(fileDescriptor, ' /* %s - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+
+ writeLine(fileDescriptor, ' %s %s() const;' % (propertyTyp, propertyName))
+ writeLine(fileDescriptor)
+
+
+def writePropertyUpdateMethodDeclarations(fileDescriptor, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
+ continue
+
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ writeLine(fileDescriptor, ' void update%s();' % (propertyName[0].upper() + propertyName[1:]))
+
+
+def validateBlocks(blockDefinitions):
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+
+ blockStartAddress = 0
+ registerCount = 0
+ blockSize = 0
+ registerAccess = ""
+ registerType = ""
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+ registerAccess = blockRegister['access']
+ registerType = blockRegister['registerType']
+ else:
+ previouseRegisterAddress = blockRegisters[i - 1]['address']
+ previouseRegisterSize = blockRegisters[i - 1]['size']
+ previouseRegisterType = blockRegisters[i - 1]['registerType']
+ if previouseRegisterAddress + previouseRegisterSize != blockRegister['address']:
+ logger.warning('Error: block %s has invalid register order in register %s. There seems to be a gap between the registers.' % (blockName, blockRegister['id']))
+ exit(1)
+
+ if blockRegister['access'] != registerAccess:
+ logger.warning('Error: block %s has inconsistent register access in register %s. The block registers dont seem to have the same access rights.' % (blockName, blockRegister['id']))
+ exit(1)
+
+ if blockRegister['registerType'] != registerType:
+ logger.warning('Error: block %s has inconsistent register type in register %s. The block registers dont seem to be from the same type.' % (blockName, blockRegister['id']))
+ exit(1)
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+ logger.debug('Define valid block \"%s\" starting at %s with length %s containing %s properties to read.' % (blockName, blockStartAddress, blockSize, registerCount))
+
+
+def writeBlocksUpdateMethodDeclarations(fileDescriptor, blockDefinitions):
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ blockRegisters = blockDefinition['registers']
+ blockStartAddress = 0
+ blockSize = 0
+ registerCount = 0
+
+ for i, blockRegister in enumerate(blockRegisters):
+ if i == 0:
+ blockStartAddress = blockRegister['address']
+
+ registerCount += 1
+ blockSize += blockRegister['size']
+
+ # Write the block update method
+ writeLine(fileDescriptor, ' /* Read block from start addess %s with size of %s registers containing following %s properties:' % (blockStartAddress, blockSize, registerCount))
+ for i, registerDefinition in enumerate(blockRegisters):
+ if 'unit' in registerDefinition and registerDefinition['unit'] != '':
+ writeLine(fileDescriptor, ' - %s [%s] - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
+ else:
+ writeLine(fileDescriptor, ' - %s - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
+ writeLine(fileDescriptor, ' */' )
+ writeLine(fileDescriptor, ' void update%sBlock();' % (blockName[0].upper() + blockName[1:]))
+ writeLine(fileDescriptor)
+
+
+def writeRegistersDebugLine(fileDescriptor, debugObjectParamName, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ line = ('" - %s:" << %s->%s()' % (registerDefinition['description'], debugObjectParamName, propertyName))
+ if 'unit' in registerDefinition and registerDefinition['unit'] != '':
+ line += (' << " [%s]"' % registerDefinition['unit'])
+ writeLine(fileDescriptor, ' debug.nospace().noquote() << %s << "\\n";' % (line))
+
+
+def writeUpdateMethod(fileDescriptor, className, registerDefinitions, blockDefinitions):
+ writeLine(fileDescriptor, 'void %s::update()' % (className))
+ writeLine(fileDescriptor, '{')
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'update':
+ writeLine(fileDescriptor, ' update%s();' % (propertyName[0].upper() + propertyName[1:]))
+
+ # Add the update block methods
+ for blockDefinition in blockDefinitions:
+ blockName = blockDefinition['id']
+ if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'update':
+ writeLine(fileDescriptor, ' update%sBlock();' % (blockName[0].upper() + blockName[1:]))
+
+ writeLine(fileDescriptor, '}')
+ writeLine(fileDescriptor)
+
+
+def writePropertyChangedSignals(fileDescriptor, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ if propertyTyp == 'QString':
+ writeLine(fileDescriptor, ' void %sChanged(const %s &%s);' % (propertyName, propertyTyp, propertyName))
+ else:
+ writeLine(fileDescriptor, ' void %sChanged(%s %s);' % (propertyName, propertyTyp, propertyName))
+
+
+def writeProtectedPropertyMembers(fileDescriptor, registerDefinitions):
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+ if 'defaultValue' in registerDefinition:
+ writeLine(fileDescriptor, ' %s m_%s = %s;' % (propertyTyp, propertyName, registerDefinition['defaultValue']))
+ else:
+ writeLine(fileDescriptor, ' %s m_%s;' % (propertyTyp, propertyName))
+
+
+def writePropertyProcessMethodDeclaration(fileDescriptor, registerDefinitions):
+ propertyVariables = []
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ writeLine(fileDescriptor, ' void process%sRegisterValues(const QVector values);' % (propertyName[0].upper() + propertyName[1:]))
+
+ writeLine(fileDescriptor)
+
+
+def writePropertyProcessMethodImplementations(fileDescriptor, className, registerDefinitions):
+ propertyVariables = []
+ for registerDefinition in registerDefinitions:
+ propertyName = registerDefinition['id']
+ propertyTyp = getCppDataType(registerDefinition)
+
+ writeLine(fileDescriptor, 'void %s::process%sRegisterValues(const QVector values)' % (className, propertyName[0].upper() + propertyName[1:]))
+ writeLine(fileDescriptor, '{')
+ 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)
diff --git a/libnymea-modbus/tools/examples/example-registers.json b/libnymea-modbus/tools/examples/example-registers.json
new file mode 100644
index 0000000..3bb0b08
--- /dev/null
+++ b/libnymea-modbus/tools/examples/example-registers.json
@@ -0,0 +1,114 @@
+{
+ "className": "Example",
+ "protocol": "BOTH",
+ "endianness": "BigEndian",
+ "enums": [
+ {
+ "name": "NameOfEnum",
+ "values": [
+ {
+ "key": "EnumValue1",
+ "value": 0
+ },
+ {
+ "key": "EnumValue2",
+ "value": 1
+ }
+ ]
+ }
+ ],
+ "registers": [
+ {
+ "id": "foo",
+ "address": 10,
+ "size": 2,
+ "type": "float",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Foo register",
+ "unit": "ValueUnit",
+ "defaultValue": "0",
+ "access": "RO"
+ },
+ {
+ "id": "bar",
+ "address": 20,
+ "size": 2,
+ "type": "float",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Bar register",
+ "unit": "ValueUnit",
+ "defaultValue": "0",
+ "access": "RO"
+ }
+ ],
+ "blocks": [
+ {
+ "id": "testBlock",
+ "readSchedule": "update",
+ "registers": [
+ {
+ "id": "A",
+ "address": 0,
+ "size": 2,
+ "type": "float",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "A register",
+ "unit": "X",
+ "defaultValue": "0",
+ "access": "RO"
+ },
+ {
+ "id": "B",
+ "address": 2,
+ "size": 2,
+ "type": "float",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "B register",
+ "unit": "X",
+ "defaultValue": "0",
+ "access": "RO"
+ },
+ {
+ "id": "C",
+ "address": 4,
+ "size": 2,
+ "type": "float",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "C register",
+ "unit": "X",
+ "defaultValue": "0",
+ "access": "RO"
+ },
+ {
+ "id": "D",
+ "address": 6,
+ "size": 2,
+ "type": "float",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "D register",
+ "unit": "X",
+ "defaultValue": "0",
+ "access": "RO"
+ },
+ {
+ "id": "E",
+ "address": 8,
+ "size": 2,
+ "type": "float",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "E register",
+ "unit": "X",
+ "defaultValue": "0",
+ "access": "RO"
+ }
+ ]
+ }
+ ]
+}
diff --git a/libnymea-modbus/tools/generate-connection.py b/libnymea-modbus/tools/generate-connection.py
new file mode 100644
index 0000000..13aa183
--- /dev/null
+++ b/libnymea-modbus/tools/generate-connection.py
@@ -0,0 +1,618 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2021 - 2022 nymea GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# To lazy to type all those register plugins, let's make live much easier and generate code from a json register definition
+
+import os
+import re
+import sys
+import json
+import time
+import shutil
+import argparse
+import datetime
+import logging
+
+from connectiontool.toolcommon import *
+from connectiontool.modbusrtu import *
+from connectiontool.modbustcp import *
+
+def writeTcpHeaderFile():
+ logger.info('Writing modbus TCP header file %s' % headerFilePath)
+ headerFile = open(headerFilePath, 'w')
+
+ writeLicenseHeader(headerFile)
+ writeLine(headerFile, '#ifndef %s_H' % className.upper())
+ writeLine(headerFile, '#define %s_H' % className.upper())
+ writeLine(headerFile)
+ writeLine(headerFile, '#include ')
+ writeLine(headerFile)
+ writeLine(headerFile, '#include ')
+ writeLine(headerFile, '#include ')
+
+ writeLine(headerFile)
+
+ # Begin of class
+ writeLine(headerFile, 'class %s : public ModbusTCPMaster' % className)
+ writeLine(headerFile, '{')
+ writeLine(headerFile, ' Q_OBJECT')
+
+ # Public members
+ writeLine(headerFile, 'public:')
+
+ # Write enum for all register values
+ writeRegistersEnum(headerFile, registerJson)
+
+ # Enum declarations
+ if 'enums' in registerJson:
+ for enumDefinition in registerJson['enums']:
+ writeEnumDefinition(headerFile, enumDefinition)
+
+ # Constructor
+ writeLine(headerFile, ' explicit %s(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr);' % className)
+ writeLine(headerFile, ' ~%s() = default;' % className)
+ writeLine(headerFile)
+ writeLine(headerFile, ' ModbusDataUtils::ByteOrder endianness() const;')
+ writeLine(headerFile, ' void setEndianness(ModbusDataUtils::ByteOrder endianness);')
+ writeLine(headerFile)
+
+ # Write registers get method declarations
+ writePropertyGetSetMethodDeclarationsTcp(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyGetSetMethodDeclarationsTcp(headerFile, blockDefinition['registers'])
+
+ # Write block get/set method declarations
+ writeBlocksUpdateMethodDeclarations(headerFile, registerJson['blocks'])
+
+ # Write init and update method declarations
+ writeLine(headerFile, ' virtual void initialize();')
+ writeLine(headerFile, ' virtual void update();')
+ writeLine(headerFile)
+
+ writePropertyUpdateMethodDeclarations(headerFile, registerJson['registers'])
+ writeLine(headerFile)
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyUpdateMethodDeclarations(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+
+ writeInternalPropertyReadMethodDeclarationsTcp(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writeInternalPropertyReadMethodDeclarationsTcp(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+ writeInternalBlockReadMethodDeclarationsTcp(headerFile, registerJson['blocks'])
+
+ writeLine(headerFile)
+
+ # Write registers value changed signals
+ writeLine(headerFile, 'signals:')
+ writeLine(headerFile, ' void initializationFinished();')
+ writeLine(headerFile, ' void endiannessChanged(ModbusDataUtils::ByteOrder endianness);')
+ writeLine(headerFile)
+ writePropertyChangedSignals(headerFile, registerJson['registers'])
+ writeLine(headerFile)
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyChangedSignals(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+
+ # Protected members
+ writeLine(headerFile, 'protected:')
+
+ writeLine(headerFile)
+ writeProtectedPropertyMembers(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writeProtectedPropertyMembers(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+
+ writePropertyProcessMethodDeclaration(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyProcessMethodDeclaration(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+
+ # Private members
+ writeLine(headerFile, 'private:')
+ writeLine(headerFile, ' quint16 m_slaveId = 1;')
+ writeLine(headerFile, ' QVector m_pendingInitReplies;')
+ writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrder%s;' % endianness)
+ writeLine(headerFile)
+ writeLine(headerFile, ' void verifyInitFinished();')
+ writeLine(headerFile)
+
+ # End of class
+ writeLine(headerFile)
+ writeLine(headerFile, '};')
+ writeLine(headerFile)
+ writeLine(headerFile, 'QDebug operator<<(QDebug debug, %s *%s);' % (className, className[0].lower() + className[1:]))
+ writeLine(headerFile)
+ writeLine(headerFile, '#endif // %s_H' % className.upper())
+
+ headerFile.close()
+
+
+def writeTcpSourceFile():
+ logger.info('Writing modbus TCP source file %s' % sourceFilePath)
+ sourceFile = open(sourceFilePath, 'w')
+ writeLicenseHeader(sourceFile)
+ writeLine(sourceFile)
+ writeLine(sourceFile, '#include "%s"' % headerFileName)
+ writeLine(sourceFile, '#include ')
+ writeLine(sourceFile)
+ writeLine(sourceFile, 'NYMEA_LOGGING_CATEGORY(dc%s, "%s")' % (className, className))
+ writeLine(sourceFile)
+
+ # Constructor
+ writeLine(sourceFile, '%s::%s(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent) :' % (className, className))
+ writeLine(sourceFile, ' ModbusTCPMaster(hostAddress, port, parent),')
+ writeLine(sourceFile, ' m_slaveId(slaveId)')
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' ')
+ writeLine(sourceFile, '}')
+ writeLine(sourceFile)
+
+ writeLine(sourceFile, 'ModbusDataUtils::ByteOrder %s::endianness() const' % (className))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' return m_endianness;')
+ writeLine(sourceFile, '}')
+ writeLine(sourceFile)
+
+ writeLine(sourceFile, 'void %s::setEndianness(ModbusDataUtils::ByteOrder endianness)' % (className))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' if (m_endianness == endianness)')
+ writeLine(sourceFile, ' return;')
+ writeLine(sourceFile,)
+ writeLine(sourceFile, ' m_endianness = endianness;')
+ writeLine(sourceFile, ' emit endiannessChanged(m_endianness);')
+ writeLine(sourceFile, '}')
+ writeLine(sourceFile)
+
+ # Property get methods
+ writePropertyGetSetMethodImplementationsTcp(sourceFile, className, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyGetSetMethodImplementationsTcp(sourceFile, className, blockDefinition['registers'])
+
+ # Write init and update method implementation
+ writeInitMethodImplementationTcp(sourceFile, className, registerJson['registers'], registerJson['blocks'])
+ writeUpdateMethod(sourceFile, className, registerJson['registers'], registerJson['blocks'])
+
+ # Write update methods
+ writePropertyUpdateMethodImplementationsTcp(sourceFile, className, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyUpdateMethodImplementationsTcp(sourceFile, className, blockDefinition['registers'])
+
+ # Write block update method
+ writeBlockUpdateMethodImplementationsTcp(sourceFile, className, registerJson['blocks'])
+
+ # Write internal protected property read method implementations
+ writeInternalPropertyReadMethodImplementationsTcp(sourceFile, className, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writeInternalPropertyReadMethodImplementationsTcp(sourceFile, className, blockDefinition['registers'])
+
+ writeInternalBlockReadMethodImplementationsTcp(sourceFile, className, registerJson['blocks'])
+
+ # Write internal processors of properties
+ writePropertyProcessMethodImplementations(sourceFile, className, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyProcessMethodImplementations(sourceFile, className, blockDefinition['registers'])
+
+ writeLine(sourceFile, 'void %s::verifyInitFinished()' % (className))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' if (m_pendingInitReplies.isEmpty()) {')
+ writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s" << hostAddress().toString();' % (className, className))
+ writeLine(sourceFile, ' emit initializationFinished();')
+ writeLine(sourceFile, ' }')
+ writeLine(sourceFile, '}')
+ writeLine(sourceFile)
+
+ # Write the debug print
+ debugObjectParamName = className[0].lower() + className[1:]
+ writeLine(sourceFile, 'QDebug operator<<(QDebug debug, %s *%s)' % (className, debugObjectParamName))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' debug.nospace().noquote() << "%s(" << %s->hostAddress().toString() << ":" << %s->port() << ")" << "\\n";' % (className, debugObjectParamName, debugObjectParamName))
+ writeRegistersDebugLine(sourceFile, debugObjectParamName, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writeRegistersDebugLine(sourceFile, debugObjectParamName, blockDefinition['registers'])
+
+ writeLine(sourceFile, ' return debug.quote().space();')
+ writeLine(sourceFile, '}')
+ writeLine(sourceFile)
+
+ sourceFile.close()
+
+
+##########################################################################################################
+def writeRtuHeaderFile():
+ logger.info('Writing modbus RTU header file %s' % headerFilePath)
+ headerFile = open(headerFilePath, 'w')
+
+ writeLicenseHeader(headerFile)
+ writeLine(headerFile, '#ifndef %s_H' % className.upper())
+ writeLine(headerFile, '#define %s_H' % className.upper())
+ writeLine(headerFile)
+ writeLine(headerFile, '#include ')
+ writeLine(headerFile)
+ writeLine(headerFile, '#include ')
+ writeLine(headerFile, '#include ')
+
+ writeLine(headerFile)
+
+ # Begin of class
+ writeLine(headerFile, 'class %s : public QObject' % className)
+ writeLine(headerFile, '{')
+ writeLine(headerFile, ' Q_OBJECT')
+
+ # Public members
+ writeLine(headerFile, 'public:')
+
+ # Write enum for all register values
+ writeRegistersEnum(headerFile, registerJson)
+
+ # Enum declarations
+ if 'enums' in registerJson:
+ for enumDefinition in registerJson['enums']:
+ writeEnumDefinition(headerFile, enumDefinition)
+
+ # Constructor
+ writeLine(headerFile, ' explicit %s(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent = nullptr);' % className)
+ writeLine(headerFile, ' ~%s() = default;' % className)
+ writeLine(headerFile)
+
+ writeLine(headerFile, ' ModbusRtuMaster *modbusRtuMaster() const;')
+ writeLine(headerFile, ' quint16 slaveId() const;')
+ writeLine(headerFile)
+ writeLine(headerFile, ' ModbusDataUtils::ByteOrder endianness() const;')
+ writeLine(headerFile, ' void setEndianness(ModbusDataUtils::ByteOrder endianness);')
+ writeLine(headerFile)
+
+ # Write registers get method declarations
+ writePropertyGetSetMethodDeclarationsRtu(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyGetSetMethodDeclarationsRtu(headerFile, blockDefinition['registers'])
+
+ # Write block get/set method declarations
+ writeBlocksUpdateMethodDeclarations(headerFile, registerJson['blocks'])
+
+ # Write init and update method declarations
+ writeLine(headerFile, ' virtual void initialize();')
+ writeLine(headerFile, ' virtual void update();')
+ writeLine(headerFile)
+
+ writePropertyUpdateMethodDeclarations(headerFile, registerJson['registers'])
+ writeLine(headerFile)
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyUpdateMethodDeclarations(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+
+ writeInternalPropertyReadMethodDeclarationsRtu(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writeInternalPropertyReadMethodDeclarationsRtu(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+ writeInternalBlockReadMethodDeclarationsRtu(headerFile, registerJson['blocks'])
+
+
+ # Write registers value changed signals
+ writeLine(headerFile, 'signals:')
+ writeLine(headerFile, ' void initializationFinished();')
+ writeLine(headerFile, ' void endiannessChanged(ModbusDataUtils::ByteOrder endianness);')
+ writeLine(headerFile)
+ writePropertyChangedSignals(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyChangedSignals(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+
+ # Protected members
+ writeLine(headerFile, 'protected:')
+
+ writeProtectedPropertyMembers(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writeProtectedPropertyMembers(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+
+ writePropertyProcessMethodDeclaration(headerFile, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyProcessMethodDeclaration(headerFile, blockDefinition['registers'])
+
+ writeLine(headerFile)
+
+ # Private members
+ writeLine(headerFile, 'private:')
+ writeLine(headerFile, ' ModbusRtuMaster *m_modbusRtuMaster = nullptr;')
+ writeLine(headerFile, ' quint16 m_slaveId = 1;')
+ writeLine(headerFile, ' QVector m_pendingInitReplies;')
+ writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrder%s;' % endianness)
+ writeLine(headerFile)
+ writeLine(headerFile, ' void verifyInitFinished();')
+ writeLine(headerFile)
+
+ # End of class
+ writeLine(headerFile)
+ writeLine(headerFile, '};')
+ writeLine(headerFile)
+ writeLine(headerFile, 'QDebug operator<<(QDebug debug, %s *%s);' % (className, className[0].lower() + className[1:]))
+ writeLine(headerFile)
+ writeLine(headerFile, '#endif // %s_H' % className.upper())
+
+ headerFile.close()
+
+
+def writeRtuSourceFile():
+ logger.info('Writing modbus RTU source file %s' % sourceFilePath)
+ sourceFile = open(sourceFilePath, 'w')
+ writeLicenseHeader(sourceFile)
+
+ writeLine(sourceFile, '#include "%s"' % headerFileName)
+ writeLine(sourceFile, '#include ')
+ writeLine(sourceFile, '#include ')
+ writeLine(sourceFile)
+ writeLine(sourceFile, 'NYMEA_LOGGING_CATEGORY(dc%s, "%s")' % (className, className))
+ writeLine(sourceFile)
+
+ # Constructor
+ writeLine(sourceFile, '%s::%s(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent) :' % (className, className))
+ writeLine(sourceFile, ' QObject(parent),')
+ writeLine(sourceFile, ' m_modbusRtuMaster(modbusRtuMaster),')
+ writeLine(sourceFile, ' m_slaveId(slaveId)')
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' ')
+ writeLine(sourceFile, '}')
+ writeLine(sourceFile)
+
+ writeLine(sourceFile, 'ModbusRtuMaster *%s::modbusRtuMaster() const' % (className))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' return m_modbusRtuMaster;')
+ writeLine(sourceFile, '}')
+
+ writeLine(sourceFile, 'quint16 %s::slaveId() const' % (className))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' return m_slaveId;')
+ writeLine(sourceFile, '}')
+
+ writeLine(sourceFile, 'ModbusDataUtils::ByteOrder %s::endianness() const' % (className))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' return m_endianness;')
+ writeLine(sourceFile, '}')
+
+ writeLine(sourceFile, 'void %s::setEndianness(ModbusDataUtils::ByteOrder endianness)' % (className))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' if (m_endianness == endianness)')
+ writeLine(sourceFile, ' return;')
+ writeLine(sourceFile,)
+ writeLine(sourceFile, ' m_endianness = endianness;')
+ writeLine(sourceFile, ' emit endiannessChanged(m_endianness);')
+ writeLine(sourceFile, '}')
+
+ # Property get methods
+ writePropertyGetSetMethodImplementationsRtu(sourceFile, className, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyGetSetMethodImplementationsRtu(sourceFile, className, blockDefinition['registers'])
+
+ # Write init and update method implementation
+ writeInitMethodImplementationRtu(sourceFile, className, registerJson['registers'], registerJson['blocks'])
+ writeUpdateMethod(sourceFile, className, registerJson['registers'], registerJson['blocks'])
+
+ # Write update methods
+ writePropertyUpdateMethodImplementationsRtu(sourceFile, className, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyUpdateMethodImplementationsRtu(sourceFile, className, blockDefinition['registers'])
+
+ # Write block update method
+ writeBlockUpdateMethodImplementationsRtu(sourceFile, className, registerJson['blocks'])
+
+ # Write internal protected property read method implementations
+ writeInternalPropertyReadMethodImplementationsRtu(sourceFile, className, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writeInternalPropertyReadMethodImplementationsRtu(sourceFile, className, blockDefinition['registers'])
+
+ writeInternalBlockReadMethodImplementationsRtu(sourceFile, className, registerJson['blocks'])
+
+ # Write internal processors of properties
+ writePropertyProcessMethodImplementations(sourceFile, className, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writePropertyProcessMethodImplementations(sourceFile, className, blockDefinition['registers'])
+
+ writeLine(sourceFile, 'void %s::verifyInitFinished()' % (className))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' if (m_pendingInitReplies.isEmpty()) {')
+ writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s";' % (className, className))
+ writeLine(sourceFile, ' emit initializationFinished();')
+ writeLine(sourceFile, ' }')
+ writeLine(sourceFile, '}')
+ writeLine(sourceFile)
+
+ # Write the debug print
+ debugObjectParamName = className[0].lower() + className[1:]
+ writeLine(sourceFile, 'QDebug operator<<(QDebug debug, %s *%s)' % (className, debugObjectParamName))
+ writeLine(sourceFile, '{')
+ writeLine(sourceFile, ' debug.nospace().noquote() << "%s(" << %s->modbusRtuMaster()->modbusUuid().toString() << ", " << %s->modbusRtuMaster()->serialPort() << ", slave ID:" << %s->slaveId() << ")" << "\\n";' % (className, debugObjectParamName, debugObjectParamName, debugObjectParamName))
+ writeRegistersDebugLine(sourceFile, debugObjectParamName, registerJson['registers'])
+ if 'blocks' in registerJson:
+ for blockDefinition in registerJson['blocks']:
+ writeRegistersDebugLine(sourceFile, debugObjectParamName, blockDefinition['registers'])
+
+ writeLine(sourceFile, ' return debug.quote().space();')
+ writeLine(sourceFile, '}')
+ writeLine(sourceFile)
+
+ sourceFile.close()
+
+
+############################################################################################
+# Main
+############################################################################################
+
+logger = logging.getLogger('modbus-tools')
+logger.setLevel(logging.INFO)
+ch = logging.StreamHandler(sys.stdout)
+ch.setLevel(logging.INFO)
+formatter = logging.Formatter('%(name)s: %(message)s')
+ch.setFormatter(formatter)
+logger.addHandler(ch)
+
+parser = argparse.ArgumentParser(description='Generate modbus tcp connection class from JSON register definitions file.')
+parser.add_argument('-j', '--json', metavar='', help='The JSON file containing the register definitions.')
+parser.add_argument('-o', '--output-directory', metavar='', help='The output directory for the resulting class.')
+parser.add_argument('-v', '--verbose', dest='verboseOutput', action='store_true', help='More verbose output.')
+args = parser.parse_args()
+
+registerJsonFilePath = os.path.realpath(args.json)
+registerJson = loadJsonFile(registerJsonFilePath)
+scriptPath = os.path.dirname(os.path.realpath(sys.argv[0]))
+outputDirectory = os.path.realpath(args.output_directory)
+
+if not os.path.exists(outputDirectory):
+ logger.debug("Output directory does not exist. Creating directory %s", outputDirectory)
+ os.makedirs(outputDirectory)
+
+if args.verboseOutput:
+ logger.setLevel(logging.DEBUG)
+ ch.setLevel(logging.DEBUG)
+
+logger.debug("Verbose output enabled")
+
+if not 'className' in registerJson:
+ logger.warning('Classname missing. Please specify the classname in the json file or pass it to the generatori using -c .')
+ exit(1)
+
+classNamePrefix = registerJson['className']
+
+endianness = 'BigEndian'
+if 'endianness' in registerJson:
+ endianness = registerJson['endianness']
+
+logger.debug('Scrip path: %s' % scriptPath)
+logger.debug('Output directory: %s' % outputDirectory)
+logger.debug('Class name prefix: %s' % classNamePrefix)
+logger.debug('Endianness: %s' % endianness)
+
+protocol = 'TCP'
+if 'protocol' in registerJson:
+ protocol = registerJson['protocol']
+
+if 'blocks' in registerJson:
+ validateBlocks(registerJson['blocks'])
+
+# Create classes depending on the protocol
+writeTcp = protocol in ["TCP", "BOTH"]
+writeRtu = protocol in ["RTU", "BOTH"]
+if not writeTcp and not writeRtu:
+ logger.warning('Invalid protocol definition. Please use TCP, RTU or BOTH.')
+ exit(1)
+
+headerFiles = []
+sourceFiles = []
+
+if writeTcp:
+ className = classNamePrefix + 'ModbusTcpConnection'
+ headerFileName = className.lower() + '.h'
+ headerFiles.append(headerFileName)
+ sourceFileName = className.lower() + '.cpp'
+ sourceFiles.append(sourceFileName)
+
+ headerFilePath = os.path.join(outputDirectory, headerFileName)
+ sourceFilePath = os.path.join(outputDirectory, sourceFileName)
+ logger.debug('=======================================================')
+ logger.debug('Class name: %s' % className)
+ logger.debug('Header file: %s' % headerFileName)
+ logger.debug('Source file: %s' % sourceFileName)
+ logger.debug('Header file path: %s' % headerFilePath)
+ logger.debug('Source file path: %s' % sourceFilePath)
+ writeTcpHeaderFile()
+ writeTcpSourceFile()
+
+if writeRtu:
+ className = classNamePrefix + 'ModbusRtuConnection'
+ headerFileName = className.lower() + '.h'
+ headerFiles.append(headerFileName)
+ sourceFileName = className.lower() + '.cpp'
+ sourceFiles.append(sourceFileName)
+ headerFilePath = os.path.join(outputDirectory, headerFileName)
+ sourceFilePath = os.path.join(outputDirectory, sourceFileName)
+ logger.debug('=======================================================')
+ logger.debug('Class name: %s' % className)
+ logger.debug('Header file: %s' % headerFileName)
+ logger.debug('Source file: %s' % sourceFileName)
+ logger.debug('Header file path: %s' % headerFilePath)
+ logger.debug('Source file path: %s' % sourceFilePath)
+ writeRtuHeaderFile()
+ writeRtuSourceFile()
+
+# Write pri file
+projectIncludeFileName = classNamePrefix.lower() + '.pri'
+projectIncludeFilePath = os.path.join(outputDirectory, projectIncludeFileName)
+
+# Note: we write the project file only if the registers
+# file has been modified since the project has been modified the last time.
+# This prevents qt-creator to retrigger qmake runs on it's own by changing the
+# project file which retriggers a qmake run and so on...
+if os.path.exists(projectIncludeFilePath):
+ timestampRegistersJson = os.path.getmtime(registerJsonFilePath)
+ timestampProjectInclude = os.path.getmtime(projectIncludeFilePath)
+ if timestampRegistersJson > timestampProjectInclude:
+ logger.debug('Registers modified %s' % time.ctime(timestampRegistersJson))
+ logger.debug('Project file modified %s' % time.ctime(timestampProjectInclude))
+ logger.debug('Register JSON file has changed since last project file update. %s' % time.ctime(timestampRegistersJson))
+ logger.debug('Regenerating project file %s ...' % projectIncludeFileName)
+ else:
+ logger.debug('The register JSON file has not changed since the last run. Skip writing the project file %s ...' % projectIncludeFileName)
+ exit(0)
+
+logger.info('Writing connection project include file %s' % projectIncludeFileName)
+projectIncludeFile = open(projectIncludeFilePath, 'w')
+writeLine(projectIncludeFile, '# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #')
+writeLine(projectIncludeFile, '#')
+writeLine(projectIncludeFile, '# This file has been autogenerated.')
+writeLine(projectIncludeFile, '# Any changes in this file may be overwritten from qmake.')
+writeLine(projectIncludeFile, '#')
+writeLine(projectIncludeFile, '# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #')
+writeLine(projectIncludeFile)
+writeLine(projectIncludeFile, 'HEADERS = \\')
+for generatedHeaderFileName in headerFiles:
+ writeLine(projectIncludeFile, ' $${PWD}/%s \\' % generatedHeaderFileName)
+
+writeLine(projectIncludeFile)
+writeLine(projectIncludeFile, "SOURCES = \\")
+for generatedSourceFileName in sourceFiles:
+ writeLine(projectIncludeFile, ' $${PWD}/%s \\' % generatedSourceFileName)
diff --git a/modbus.pri b/modbus.pri
new file mode 100644
index 0000000..840bcb4
--- /dev/null
+++ b/modbus.pri
@@ -0,0 +1,12 @@
+QT += network serialport serialbus
+
+top_srcdir=$$PWD
+top_builddir=$$shadowed($$PWD)
+
+INCLUDEPATH += $$top_srcdir/libnymea-modbus
+LIBS += -L$$top_builddir/libnymea-modbus/ -lnymea-modbus
+
+OTHER_FILES += $${MODBUS_CONNECTIONS}
+
+include(libnymea-modbus/modbus-tool.pri)
+
diff --git a/modbus/tools/generate-connection.py b/modbus/tools/generate-connection.py
deleted file mode 100644
index 39c0969..0000000
--- a/modbus/tools/generate-connection.py
+++ /dev/null
@@ -1,1320 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (C) 2021 - 2022 nymea GmbH
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-# To lazy to type all those register plugins, let's make live much easier and generate code from a json register definition
-
-import os
-import re
-import sys
-import json
-import shutil
-import argparse
-import datetime
-
-def convertToAlphaNumeric(text):
- finalText = ''
- for character in text:
- if character.isalnum():
- finalText += character
- else:
- finalText += ' '
- return finalText
-
-
-def splitCamelCase(text):
- return re.sub('([A-Z][a-z]+)', r' \1', re.sub('([A-Z]+)', r' \1', text)).split()
-
-
-def convertToCamelCase(text, capitalize = False):
- s = convertToAlphaNumeric(text)
- s = s.replace("-", " ").replace("_", " ")
- words = s.split()
- #print('--> words', words)
- finalWords = []
-
- for i in range(len(words)):
- camelCaseSplit = splitCamelCase(words[i])
- if len(camelCaseSplit) == 0:
- finalWords.append(words[i])
- else:
- #print('--> camel split words', camelCaseSplit)
- for j in range(len(camelCaseSplit)):
- finalWords.append(camelCaseSplit[j])
-
- if len(finalWords) == 0:
- return text
-
- finalText = ''
- if capitalize:
- finalText = finalWords[0].capitalize() + ''.join(i.capitalize() for i in finalWords[1:])
- else:
- finalText = finalWords[0].lower() + ''.join(i.capitalize() for i in finalWords[1:])
- #print('Convert camel case:', text, '-->', finalText)
- return finalText
-
-
-def loadJsonFile(filePath):
- print('--> Loading JSON file', filePath)
- jsonFile = open(filePath, 'r')
- return json.load(jsonFile)
-
-
-def writeLine(fileDescriptor, line = ''):
- fileDescriptor.write(line + '\n')
-
-
-def writeLicenseHeader(fileDescriptor):
- writeLine(fileDescriptor, '/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *')
- writeLine(fileDescriptor, '*')
- writeLine(fileDescriptor, '* Copyright 2013 - %s, nymea GmbH' % datetime.datetime.now().year)
- writeLine(fileDescriptor, '* Contact: contact@nymea.io')
- writeLine(fileDescriptor, '*')
- writeLine(fileDescriptor, '* This fileDescriptor is part of nymea.')
- writeLine(fileDescriptor, '* This project including source code and documentation is protected by')
- writeLine(fileDescriptor, '* copyright law, and remains the property of nymea GmbH. All rights, including')
- writeLine(fileDescriptor, '* reproduction, publication, editing and translation, are reserved. The use of')
- writeLine(fileDescriptor, '* this project is subject to the terms of a license agreement to be concluded')
- writeLine(fileDescriptor, '* with nymea GmbH in accordance with the terms of use of nymea GmbH, available')
- writeLine(fileDescriptor, '* under https://nymea.io/license')
- writeLine(fileDescriptor, '*')
- writeLine(fileDescriptor, '* GNU Lesser General Public License Usage')
- writeLine(fileDescriptor, '* Alternatively, this project may be redistributed and/or modified under the')
- writeLine(fileDescriptor, '* terms of the GNU Lesser General Public License as published by the Free')
- writeLine(fileDescriptor, '* Software Foundation; version 3. This project is distributed in the hope that')
- writeLine(fileDescriptor, '* it will be useful, but WITHOUT ANY WARRANTY; without even the implied')
- writeLine(fileDescriptor, '* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU')
- writeLine(fileDescriptor, '* Lesser General Public License for more details.')
- writeLine(fileDescriptor, '*')
- writeLine(fileDescriptor, '* You should have received a copy of the GNU Lesser General Public License')
- writeLine(fileDescriptor, '* along with this project. If not, see .')
- writeLine(fileDescriptor, '*')
- writeLine(fileDescriptor, '* For any further details and any questions please contact us under')
- writeLine(fileDescriptor, '* contact@nymea.io or see our FAQ/Licensing Information on')
- writeLine(fileDescriptor, '* https://nymea.io/license/faq')
- writeLine(fileDescriptor, '*')
- writeLine(fileDescriptor, '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */')
- writeLine(fileDescriptor)
-
-
-def writeRegistersEnum(fileDescriptor, registerJson):
- print('Writing enum for all registers')
-
- registerEnums = {}
-
- # Read all register names and addresses
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- blockRegisters = blockDefinition['registers']
- for blockRegister in blockRegisters:
- registerName = blockRegister['id']
- registerAddress = blockRegister['address']
- registerEnums[registerAddress] = registerName
-
- for registerDefinition in registerJson['registers']:
- registerName = registerDefinition['id']
- registerAddress = registerDefinition['address']
- registerEnums[registerAddress] = registerName
-
-
- # Sort the enum map
- registersKeys = registerEnums.keys()
- sortedRegistersKeys = sorted(registersKeys)
- sortedRegisterEnumList = []
-
- print('Sorted registers')
- for registerAddress in sortedRegistersKeys:
- print('--> %s : %s' % (registerAddress, registerEnums[registerAddress]))
- enumData = {}
- enumData['key'] = registerEnums[registerAddress]
- enumData['value'] = registerAddress
- sortedRegisterEnumList.append(enumData)
-
- enumName = 'Registers'
- writeLine(fileDescriptor, ' enum %s {' % enumName)
- for i in range(len(sortedRegisterEnumList)):
- enumData = sortedRegisterEnumList[i]
- line = (' Register%s = %s' % (enumData['key'][0].upper() + enumData['key'][1:] , enumData['value']))
- if i < (len(sortedRegisterEnumList) - 1):
- line += ','
-
- writeLine(fileDescriptor, line)
-
- writeLine(fileDescriptor, ' };')
- writeLine(fileDescriptor, ' Q_ENUM(%s)' % enumName)
- writeLine(fileDescriptor)
-
-
-def writeEnumDefinition(fileDescriptor, enumDefinition):
- print('Writing enum', enumDefinition)
- enumName = enumDefinition['name']
- enumValues = enumDefinition['values']
- writeLine(fileDescriptor, ' enum %s {' % enumName)
- for i in range(len(enumValues)):
- enumData = enumValues[i]
- line = (' %s%s = %s' % (enumName, enumData['key'], enumData['value']))
- if i < (len(enumValues) - 1):
- line += ','
-
- writeLine(fileDescriptor, line)
-
- writeLine(fileDescriptor, ' };')
- writeLine(fileDescriptor, ' Q_ENUM(%s)' % enumName)
- writeLine(fileDescriptor)
-
-
-def getCppDataType(registerDefinition, rawType = False):
- if not rawType:
- if 'enum' in registerDefinition:
- return registerDefinition['enum']
-
- if 'scaleFactor' in registerDefinition or 'staticScaleFactor' in registerDefinition:
- return 'float'
-
- if registerDefinition['type'] == 'uint16':
- return 'quint16'
-
- if registerDefinition['type'] == 'int16':
- return 'qint16'
-
- if registerDefinition['type'] == 'uint32':
- return 'quint32'
-
- if registerDefinition['type'] == 'int32':
- return 'qint32'
-
- if registerDefinition['type'] == 'uint64':
- return 'quint64'
-
- if registerDefinition['type'] == 'int64':
- return 'qint64'
-
- if registerDefinition['type'] == 'float':
- return 'float'
-
- if registerDefinition['type'] == 'float64':
- return 'double'
-
- if registerDefinition['type'] == 'string':
- 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':
- return ('static_cast<%s>(ModbusDataUtils::convertToUInt16(values))' % (enumName))
- elif registerDefinition['type'] == 'int16':
- return ('static_cast<%s>(ModbusDataUtils::convertToInt16(values))' % (enumName))
- elif registerDefinition['type'] == 'uint32':
- return ('static_cast<%s>(ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
- elif registerDefinition['type'] == 'int32':
- return ('static_cast<%s>(ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
-
- # Handle scale factors
- if 'scaleFactor' in registerDefinition:
- scaleFactorProperty = 'm_%s' % registerDefinition['scaleFactor']
- if registerDefinition['type'] == 'uint16':
- return ('ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
- elif registerDefinition['type'] == 'int16':
- return ('ModbusDataUtils::convertToInt16(values) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
- elif registerDefinition['type'] == 'uint32':
- return ('ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactorProperty))
- elif registerDefinition['type'] == 'int32':
- return ('ModbusDataUtils::convertToInt32(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(values) * 1.0 * pow(10, %s)' % (scaleFactor))
- elif registerDefinition['type'] == 'int16':
- return ('ModbusDataUtils::convertToInt16(values) * 1.0 * pow(10, %s)' % (scaleFactor))
- elif registerDefinition['type'] == 'uint32':
- return ('ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
- elif registerDefinition['type'] == 'int32':
- return ('ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
-
- # Handle default types
- elif registerDefinition['type'] == 'uint16':
- return ('ModbusDataUtils::convertToUInt16(values)')
- elif registerDefinition['type'] == 'int16':
- return ('ModbusDataUtils::convertToInt16(values)')
- elif registerDefinition['type'] == 'uint32':
- return ('ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrder%s)' % endianness)
- elif registerDefinition['type'] == 'int32':
- return ('ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrder%s)' % endianness)
- elif registerDefinition['type'] == 'uint64':
- return ('ModbusDataUtils::convertToUInt64(values, ModbusDataUtils::ByteOrder%s)' % endianness)
- elif registerDefinition['type'] == 'int64':
- return ('ModbusDataUtils::convertToInt64(values, ModbusDataUtils::ByteOrder%s)' % endianness)
- elif registerDefinition['type'] == 'float':
- return ('ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrder%s)' % endianness)
- elif registerDefinition['type'] == 'float64':
- return ('ModbusDataUtils::convertToFloat64(values, ModbusDataUtils::ByteOrder%s)' % endianness)
- elif registerDefinition['type'] == 'string':
- return ('ModbusDataUtils::convertToString(values)')
-
-
-def writePropertyGetSetMethodDeclarationsTcp(fileDescriptor, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- if 'unit' in registerDefinition and registerDefinition['unit'] != '':
- writeLine(fileDescriptor, ' /* %s [%s] - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
- else:
- 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 writePropertyGetSetMethodDeclarationsRtu(fileDescriptor, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- if 'unit' in registerDefinition and registerDefinition['unit'] != '':
- writeLine(fileDescriptor, ' /* %s [%s] - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
- else:
- 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, ' ModbusRtuReply *set%s(%s %s);' % (propertyName[0].upper() + propertyName[1:], propertyTyp, propertyName))
-
- writeLine(fileDescriptor)
-
-
-def writeBlockGetMethodDeclarations(fileDescriptor, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- if 'unit' in registerDefinition and registerDefinition['unit'] != '':
- writeLine(fileDescriptor, ' /* %s [%s] - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
- else:
- writeLine(fileDescriptor, ' /* %s - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
-
- writeLine(fileDescriptor, ' %s %s() const;' % (propertyTyp, propertyName))
- writeLine(fileDescriptor)
-
-
-def writePropertyGetSetMethodImplementationsTcp(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:
- writeLine(fileDescriptor, '%s %s::%s() const' % (propertyTyp, className, propertyName))
-
- writeLine(fileDescriptor, '{')
- writeLine(fileDescriptor, ' return m_%s;' % propertyName)
- 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']))
- elif registerDefinition['registerType'] == 'coils':
- writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, %s, values.count());' % (registerDefinition['address']))
- else:
- print('Error: invalid register type for writing.')
- exit(1)
-
- writeLine(fileDescriptor, ' request.setValues(values);')
- writeLine(fileDescriptor, ' return sendWriteRequest(request, m_slaveId);')
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
-
-def writePropertyGetSetMethodImplementationsRtu(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:
- writeLine(fileDescriptor, '%s %s::%s() const' % (propertyTyp, className, propertyName))
-
- writeLine(fileDescriptor, '{')
- writeLine(fileDescriptor, ' return m_%s;' % propertyName)
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
- # Check if we require a set method
- if registerDefinition['access'] == 'RW' or registerDefinition['access'] == 'WO':
- writeLine(fileDescriptor, 'ModbusRtuReply *%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, ' return m_modbusRtuMaster->writeHoldingRegisters(m_slaveId, %s, values);' % (registerDefinition['address']))
- elif registerDefinition['registerType'] == 'coils':
- writeLine(fileDescriptor, ' return m_modbusRtuMaster->writeCoils(m_slaveId, %s, values);' % (registerDefinition['address']))
- else:
- print('Error: invalid register type for writing.')
- exit(1)
-
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
-
-def writePropertyUpdateMethodDeclarations(fileDescriptor, registerDefinitions):
- for registerDefinition in registerDefinitions:
- if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
- continue
-
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- writeLine(fileDescriptor, ' void update%s();' % (propertyName[0].upper() + propertyName[1:]))
-
-
-def validateBlocks(blockDefinitions):
- for blockDefinition in blockDefinitions:
- blockName = blockDefinition['id']
- blockRegisters = blockDefinition['registers']
-
- blockStartAddress = 0
- registerCount = 0
- blockSize = 0
- registerAccess = ""
- registerType = ""
-
- for i, blockRegister in enumerate(blockRegisters):
- if i == 0:
- blockStartAddress = blockRegister['address']
- registerAccess = blockRegister['access']
- registerType = blockRegister['registerType']
- else:
- previouseRegisterAddress = blockRegisters[i - 1]['address']
- previouseRegisterSize = blockRegisters[i - 1]['size']
- previouseRegisterType = blockRegisters[i - 1]['registerType']
- if previouseRegisterAddress + previouseRegisterSize != blockRegister['address']:
- print('Error: block %s has invalid register order in register %s. There seems to be a gap between the registers.' % (blockName, blockRegister['id']))
- exit(1)
-
- if blockRegister['access'] != registerAccess:
- print('Error: block %s has inconsistent register access in register %s. The block registers dont seem to have the same access rights.' % (blockName, blockRegister['id']))
- exit(1)
-
- if blockRegister['registerType'] != registerType:
- print('Error: block %s has inconsistent register type in register %s. The block registers dont seem to be from the same type.' % (blockName, blockRegister['id']))
- exit(1)
-
- registerCount += 1
- blockSize += blockRegister['size']
-
- print('Define valid block \"%s\" starting at %s with length %s containing %s properties to read.' % (blockName, blockStartAddress, blockSize, registerCount))
-
-
-def writeBlocksUpdateMethodDeclarations(fileDescriptor, blockDefinitions):
- for blockDefinition in blockDefinitions:
- blockName = blockDefinition['id']
- blockRegisters = blockDefinition['registers']
-
- # Write the property get / set methods for the block registers
- writeBlockGetMethodDeclarations(fileDescriptor, blockRegisters)
-
- blockStartAddress = 0
- blockSize = 0
- registerCount = 0
-
- for i, blockRegister in enumerate(blockRegisters):
- if i == 0:
- blockStartAddress = blockRegister['address']
-
- registerCount += 1
- blockSize += blockRegister['size']
-
- # Write the block update method
- writeLine(fileDescriptor, ' /* Read block from start addess %s with size of %s registers containing following %s properties:' % (blockStartAddress, blockSize, registerCount))
- for i, registerDefinition in enumerate(blockRegisters):
- if 'unit' in registerDefinition and registerDefinition['unit'] != '':
- writeLine(fileDescriptor, ' - %s [%s] - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
- else:
- writeLine(fileDescriptor, ' -- %s - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
- writeLine(fileDescriptor, ' */ ' )
- writeLine(fileDescriptor, ' void update%sBlock();' % (blockName[0].upper() + blockName[1:]))
- writeLine(fileDescriptor)
-
-
-def writePropertyUpdateMethodImplementationsTcp(fileDescriptor, className, registerDefinitions):
- for registerDefinition in registerDefinitions:
- if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
- continue
-
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- 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()) {')
- 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, ' const QVector values = unit.values();')
- writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
- 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)
- writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating \\"%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, '}')
- writeLine(fileDescriptor)
-
-
-def writePropertyUpdateMethodImplementationsRtu(fileDescriptor, className, registerDefinitions):
- for registerDefinition in registerDefinitions:
- if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
- continue
-
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- 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, ' ModbusRtuReply *reply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
- writeLine(fileDescriptor, ' if (reply) {')
- writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
- writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){')
- writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {')
- writeLine(fileDescriptor, ' QVector values = reply->result();')
- writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << 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:]))
- writeLine(fileDescriptor, ' emit %sChanged(m_%s);' % (propertyName, propertyName))
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' });')
- writeLine(fileDescriptor)
- writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating \\"%s\\" registers" << error << reply->errorString();' % (className, registerDefinition['description']))
- writeLine(fileDescriptor, ' emit reply->finished();')
- writeLine(fileDescriptor, ' });')
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' } else {')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers";' % (className, registerDefinition['description']))
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
-
-def writeBlockUpdateMethodImplementationsRtu(fileDescriptor, className, blockDefinitions):
- for blockDefinition in blockDefinitions:
- blockName = blockDefinition['id']
- blockRegisters = blockDefinition['registers']
- blockStartAddress = 0
- registerCount = 0
- blockSize = 0
- registerType = ""
-
- for i, blockRegister in enumerate(blockRegisters):
- if i == 0:
- blockStartAddress = blockRegister['address']
- registerType = blockRegister['registerType']
-
- registerCount += 1
- blockSize += blockRegister['size']
-
- writeLine(fileDescriptor, 'void %s::update%sBlock()' % (className, blockName[0].upper() + blockName[1:]))
- writeLine(fileDescriptor, '{')
- writeLine(fileDescriptor, ' // Update register block \"%s\"' % blockName)
- writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read block \\"%s\\" registers from:" << %s << "size:" << %s;' % (className, blockName, blockStartAddress, blockSize))
-
-
- # Build request depending on the register type
- if registerType == 'inputRegister':
- writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readInputRegister(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
- elif registerType == 'discreteInputs':
- writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readDiscreteInput(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
- elif registerType == 'coils':
- writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readCoil(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
- else:
- #Default to holdingRegister
- writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, %s, %s);' % (blockStartAddress, blockSize))
-
- writeLine(fileDescriptor, ' if (reply) {')
- writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
- writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){')
- writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {')
- writeLine(fileDescriptor, ' QVector blockValues = reply->result();')
- writeLine(fileDescriptor, ' QVector values;')
- writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize))
-
- # Start parsing the registers using offsets
- offset = 0
- for i, blockRegister in enumerate(blockRegisters):
- propertyName = blockRegister['id']
- propertyTyp = getCppDataType(blockRegister)
- writeLine(fileDescriptor, ' values = blockValues.mid(%s, %s);' % (offset, blockRegister['size']))
- writeLine(fileDescriptor, ' %s received%s = %s;' % (propertyTyp, propertyName[0].upper() + propertyName[1:], getValueConversionMethod(blockRegister)))
- 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)
- offset += blockRegister['size']
-
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' });')
- writeLine(fileDescriptor)
- writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName))
- writeLine(fileDescriptor, ' emit reply->finished();')
- writeLine(fileDescriptor, ' });')
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' } else {')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName))
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
-
-def writeBlockUpdateMethodImplementationsTcp(fileDescriptor, className, blockDefinitions):
- for blockDefinition in blockDefinitions:
- blockName = blockDefinition['id']
- blockRegisters = blockDefinition['registers']
- blockStartAddress = 0
- registerCount = 0
- blockSize = 0
- registerType = ""
-
- for i, blockRegister in enumerate(blockRegisters):
- if i == 0:
- blockStartAddress = blockRegister['address']
- registerType = blockRegister['registerType']
-
- registerCount += 1
- blockSize += blockRegister['size']
-
- writeLine(fileDescriptor, 'void %s::update%sBlock()' % (className, blockName[0].upper() + blockName[1:]))
- writeLine(fileDescriptor, '{')
- writeLine(fileDescriptor, ' // Update register block \"%s\"' % blockName)
- writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read block \\"%s\\" registers from:" << %s << "size:" << %s;' % (className, blockName, blockStartAddress, blockSize))
-
- # Build request depending on the register type
- # Build request depending on the register type
- if registerType == 'inputRegister':
- writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, %s, %s);' % (blockStartAddress, blockSize))
- elif registerType == 'discreteInputs':
- writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::DiscreteInputs, %s, %s);' % (blockStartAddress, blockSize))
- elif registerType == 'coils':
- writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, %s, %s);' % (blockStartAddress, blockSize))
- else:
- #Default to holdingRegister
- writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, %s, %s);' % (blockStartAddress, blockSize))
-
- writeLine(fileDescriptor, ' QModbusReply *reply = sendReadRequest(request, m_slaveId);')
-
- writeLine(fileDescriptor, ' if (reply) {')
- writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
- 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, ' const QVector blockValues = unit.values();')
- writeLine(fileDescriptor, ' QVector values;')
- writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize))
-
- # Start parsing the registers using offsets
- offset = 0
- for i, blockRegister in enumerate(blockRegisters):
- propertyName = blockRegister['id']
- propertyTyp = getCppDataType(blockRegister)
- writeLine(fileDescriptor, ' values = blockValues.mid(%s, %s);' % (offset, blockRegister['size']))
- writeLine(fileDescriptor, ' %s received%s = %s;' % (propertyTyp, propertyName[0].upper() + propertyName[1:], getValueConversionMethod(blockRegister)))
- 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)
- offset += blockRegister['size']
-
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' });')
- writeLine(fileDescriptor)
- writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName))
- writeLine(fileDescriptor, ' emit reply->finished();')
- writeLine(fileDescriptor, ' });')
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, ' } else {')
- writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName))
- writeLine(fileDescriptor, ' }')
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
-def writeInternalPropertyReadMethodDeclarationsTcp(fileDescriptor, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- writeLine(fileDescriptor, ' QModbusReply *read%s();' % (propertyName[0].upper() + propertyName[1:]))
-
-
-def writeInternalPropertyReadMethodDeclarationsRtu(fileDescriptor, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- writeLine(fileDescriptor, ' ModbusRtuReply *read%s();' % (propertyName[0].upper() + propertyName[1:]))
-
-
-def writeInternalPropertyReadMethodImplementationsTcp(fileDescriptor, className, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- writeLine(fileDescriptor, 'QModbusReply *%s::read%s()' % (className, propertyName[0].upper() + propertyName[1:]))
- writeLine(fileDescriptor, '{')
-
- # 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)
-
-
-def writeInternalPropertyReadMethodImplementationsRtu(fileDescriptor, className, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- writeLine(fileDescriptor, 'ModbusRtuReply *%s::read%s()' % (className, propertyName[0].upper() + propertyName[1:]))
- writeLine(fileDescriptor, '{')
-
- # Build request depending on the register type
- if registerDefinition['registerType'] == 'inputRegister':
- writeLine(fileDescriptor, ' return m_modbusRtuMaster->readInputRegister(m_slaveId, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
- elif registerDefinition['registerType'] == 'discreteInputs':
- writeLine(fileDescriptor, ' return m_modbusRtuMaster->readDiscreteInput(m_slaveId, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
- elif registerDefinition['registerType'] == 'coils':
- writeLine(fileDescriptor, ' return m_modbusRtuMaster->readCoil(m_slaveId, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
- else:
- #Default to holdingRegister
- writeLine(fileDescriptor, ' return m_modbusRtuMaster->readHoldingRegister(m_slaveId, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
-
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
-
-
-def writePropertyChangedSignals(fileDescriptor, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- if propertyTyp == 'QString':
- writeLine(fileDescriptor, ' void %sChanged(const %s &%s);' % (propertyName, propertyTyp, propertyName))
- else:
- writeLine(fileDescriptor, ' void %sChanged(%s %s);' % (propertyName, propertyTyp, propertyName))
-
-
-def writePrivatePropertyMembers(fileDescriptor, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- if 'defaultValue' in registerDefinition:
- writeLine(fileDescriptor, ' %s m_%s = %s;' % (propertyTyp, propertyName, registerDefinition['defaultValue']))
- else:
- writeLine(fileDescriptor, ' %s m_%s;' % (propertyTyp, propertyName))
-
-
-def writeInitializeMethod(fileDescriptor, className, registerDefinitions):
- writeLine(fileDescriptor, 'void %s::initialize()' % (className))
- writeLine(fileDescriptor, '{')
-
- # First check if there are any init registers
- initRequired = False
- for registerDefinition in registerDefinitions:
- if registerDefinition['readSchedule'] == 'init':
- initRequired = True
- break
-
- if initRequired:
- if protocol == 'TCP':
- # Init implementation for TCP
- 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, ' const QVector values = unit.values();')
- 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:
- print('TODO: this has not been implemented yet for RTU')
- exit(1)
-
- else:
- writeLine(fileDescriptor, ' // No init registers defined. Nothing to be done and we are finished.')
- writeLine(fileDescriptor, ' emit initializationFinished();')
-
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
-
-def writeUpdateMethod(fileDescriptor, className, registerDefinitions):
- writeLine(fileDescriptor, 'void %s::update()' % (className))
- writeLine(fileDescriptor, '{')
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'update':
- writeLine(fileDescriptor, ' update%s();' % (propertyName[0].upper() + propertyName[1:]))
-
- # Add the update block methods
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- blockName = blockDefinition['id']
- writeLine(fileDescriptor, ' update%sBlock();' % (blockName[0].upper() + blockName[1:]))
-
- writeLine(fileDescriptor, '}')
- writeLine(fileDescriptor)
-
-
-def writeRegistersDebugLine(fileDescriptor, debugObjectParamName, registerDefinitions):
- for registerDefinition in registerDefinitions:
- propertyName = registerDefinition['id']
- propertyTyp = getCppDataType(registerDefinition)
- line = ('" - %s:" << %s->%s()' % (registerDefinition['description'], debugObjectParamName, propertyName))
- if 'unit' in registerDefinition and registerDefinition['unit'] != '':
- line += (' << " [%s]"' % registerDefinition['unit'])
- writeLine(fileDescriptor, ' debug.nospace().noquote() << %s << "\\n";' % (line))
-
-
-def writeTcpHeaderFile():
- print('Writing modbus TCP hader file %s' % headerFilePath)
- headerFile = open(headerFilePath, 'w')
-
- writeLicenseHeader(headerFile)
- writeLine(headerFile, '#ifndef %s_H' % className.upper())
- writeLine(headerFile, '#define %s_H' % className.upper())
- writeLine(headerFile)
- writeLine(headerFile, '#include ')
- writeLine(headerFile)
- writeLine(headerFile, '#include "../modbus/modbusdatautils.h"')
- writeLine(headerFile, '#include "../modbus/modbustcpmaster.h"')
-
- writeLine(headerFile)
-
- # Begin of class
- writeLine(headerFile, 'class %s : public ModbusTCPMaster' % className)
- writeLine(headerFile, '{')
- writeLine(headerFile, ' Q_OBJECT')
-
- # Public members
- writeLine(headerFile, 'public:')
-
- # Write enum for all register values
- writeRegistersEnum(headerFile, registerJson)
-
- # Enum declarations
- if 'enums' in registerJson:
- for enumDefinition in registerJson['enums']:
- writeEnumDefinition(headerFile, enumDefinition)
-
- # Constructor
- writeLine(headerFile, ' explicit %s(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr);' % className)
- writeLine(headerFile, ' ~%s() = default;' % className)
- writeLine(headerFile)
-
- # Write registers get method declarations
- writePropertyGetSetMethodDeclarationsTcp(headerFile, registerJson['registers'])
-
- # Write block get/set method declarations
- if 'blocks' in registerJson:
- writeBlocksUpdateMethodDeclarations(headerFile, registerJson['blocks'])
-
- # Write init and update method declarations
- writeLine(headerFile, ' virtual void initialize();')
- writeLine(headerFile, ' virtual void update();')
- writeLine(headerFile)
-
- writePropertyUpdateMethodDeclarations(headerFile, registerJson['registers'])
- writeLine(headerFile)
-
- # Write registers value changed signals
- writeLine(headerFile, 'signals:')
- writeLine(headerFile, ' void initializationFinished();')
- writeLine(headerFile)
- writePropertyChangedSignals(headerFile, registerJson['registers'])
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- writePropertyChangedSignals(headerFile, blockDefinition['registers'])
-
- writeLine(headerFile)
-
- # Protected members
- writeLine(headerFile, 'protected:')
- writeInternalPropertyReadMethodDeclarationsTcp(headerFile, registerJson['registers'])
- writeLine(headerFile)
- writePrivatePropertyMembers(headerFile, registerJson['registers'])
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- writePrivatePropertyMembers(headerFile, blockDefinition['registers'])
-
- writeLine(headerFile)
-
- # Private members
- writeLine(headerFile, 'private:')
- writeLine(headerFile, ' quint16 m_slaveId = 1;')
- writeLine(headerFile, ' QVector m_pendingInitReplies;')
- writeLine(headerFile)
- writeLine(headerFile, ' void verifyInitFinished();')
- writeLine(headerFile)
-
- # End of class
- writeLine(headerFile)
- writeLine(headerFile, '};')
- writeLine(headerFile)
- writeLine(headerFile, 'QDebug operator<<(QDebug debug, %s *%s);' % (className, className[0].lower() + className[1:]))
- writeLine(headerFile)
- writeLine(headerFile, '#endif // %s_H' % className.upper())
-
- headerFile.close()
-
-
-def writeTcpSourceFile():
- print('Writing modbus TCP source file %s' % sourceFilePath)
- sourceFile = open(sourceFilePath, 'w')
- writeLicenseHeader(sourceFile)
- writeLine(sourceFile)
- writeLine(sourceFile, '#include "%s"' % headerFileName)
- writeLine(sourceFile, '#include "loggingcategories.h"')
- writeLine(sourceFile)
- writeLine(sourceFile, 'NYMEA_LOGGING_CATEGORY(dc%s, "%s")' % (className, className))
- writeLine(sourceFile)
-
- # Constructor
- writeLine(sourceFile, '%s::%s(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent) :' % (className, className))
- writeLine(sourceFile, ' ModbusTCPMaster(hostAddress, port, parent),')
- writeLine(sourceFile, ' m_slaveId(slaveId)')
- writeLine(sourceFile, '{')
- writeLine(sourceFile, ' ')
- writeLine(sourceFile, '}')
- writeLine(sourceFile)
-
- # Property get methods
- writePropertyGetSetMethodImplementationsTcp(sourceFile, className, registerJson['registers'])
-
- # Block property get methods
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- writePropertyGetSetMethodImplementationsTcp(sourceFile, className, blockDefinition['registers'])
-
- # Write init and update method implementation
- writeInitializeMethod(sourceFile, className, registerJson['registers'])
- writeUpdateMethod(sourceFile, className, registerJson['registers'])
-
- # Write update methods
- writePropertyUpdateMethodImplementationsTcp(sourceFile, className, registerJson['registers'])
-
- # Write block update method
- if 'blocks' in registerJson:
- writeBlockUpdateMethodImplementationsTcp(sourceFile, className, registerJson['blocks'])
-
- # Write internal protected property read method implementations
- writeInternalPropertyReadMethodImplementationsTcp(sourceFile, className, registerJson['registers'])
-
- writeLine(sourceFile, 'void %s::verifyInitFinished()' % (className))
- writeLine(sourceFile, '{')
- writeLine(sourceFile, ' if (m_pendingInitReplies.isEmpty()) {')
- writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s" << hostAddress().toString();' % (className, className))
- writeLine(sourceFile, ' emit initializationFinished();')
- writeLine(sourceFile, ' }')
- writeLine(sourceFile, '}')
- writeLine(sourceFile)
-
- # Write the debug print
- debugObjectParamName = className[0].lower() + className[1:]
- writeLine(sourceFile, 'QDebug operator<<(QDebug debug, %s *%s)' % (className, debugObjectParamName))
- writeLine(sourceFile, '{')
- writeLine(sourceFile, ' debug.nospace().noquote() << "%s(" << %s->hostAddress().toString() << ":" << %s->port() << ")" << "\\n";' % (className, debugObjectParamName, debugObjectParamName))
- writeRegistersDebugLine(sourceFile, debugObjectParamName, registerJson['registers'])
-
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- writeRegistersDebugLine(sourceFile, debugObjectParamName, blockDefinition['registers'])
-
- writeLine(sourceFile, ' return debug.quote().space();')
- writeLine(sourceFile, '}')
- writeLine(sourceFile)
-
- sourceFile.close()
-
-
-##########################################################################################################
-def writeRtuHeaderFile():
- print('Writing modbus TCP hader file %s' % headerFilePath)
- headerFile = open(headerFilePath, 'w')
-
- writeLicenseHeader(headerFile)
- writeLine(headerFile, '#ifndef %s_H' % className.upper())
- writeLine(headerFile, '#define %s_H' % className.upper())
- writeLine(headerFile)
- writeLine(headerFile, '#include ')
- writeLine(headerFile)
- writeLine(headerFile, '#include "../modbus/modbusdatautils.h"')
- writeLine(headerFile, '#include ')
-
- writeLine(headerFile)
-
- # Begin of class
- writeLine(headerFile, 'class %s : public QObject' % className)
- writeLine(headerFile, '{')
- writeLine(headerFile, ' Q_OBJECT')
-
- # Public members
- writeLine(headerFile, 'public:')
-
- # Write enum for all register values
- writeRegistersEnum(headerFile, registerJson)
-
- # Enum declarations
- if 'enums' in registerJson:
- for enumDefinition in registerJson['enums']:
- writeEnumDefinition(headerFile, enumDefinition)
-
- # Constructor
- writeLine(headerFile, ' explicit %s(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent = nullptr);' % className)
- writeLine(headerFile, ' ~%s() = default;' % className)
- writeLine(headerFile)
-
- writeLine(headerFile, ' ModbusRtuMaster *modbusRtuMaster() const;')
- writeLine(headerFile, ' quint16 slaveId() const;')
- writeLine(headerFile)
-
- # Write registers get/set method declarations
- writePropertyGetSetMethodDeclarationsRtu(headerFile, registerJson['registers'])
-
- # Write block get/set method declarations
- if 'blocks' in registerJson:
- writeBlocksUpdateMethodDeclarations(headerFile, registerJson['blocks'])
-
- writePropertyUpdateMethodDeclarations(headerFile, registerJson['registers'])
- writeLine(headerFile)
-
- # Write init and update method declarations
- writeLine(headerFile, ' virtual void initialize();')
- writeLine(headerFile, ' virtual void update();')
- writeLine(headerFile)
-
- # Write registers value changed signals
- writeLine(headerFile, 'signals:')
- writeLine(headerFile, ' void initializationFinished();')
- writeLine(headerFile)
- writePropertyChangedSignals(headerFile, registerJson['registers'])
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- writePropertyChangedSignals(headerFile, blockDefinition['registers'])
- writeLine(headerFile)
-
- # Protected members
- writeLine(headerFile, 'protected:')
- writeInternalPropertyReadMethodDeclarationsRtu(headerFile, registerJson['registers'])
- writeLine(headerFile)
- writePrivatePropertyMembers(headerFile, registerJson['registers'])
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- writePrivatePropertyMembers(headerFile, blockDefinition['registers'])
-
- writeLine(headerFile)
-
- # Private members
- writeLine(headerFile, 'private:')
- writeLine(headerFile, ' ModbusRtuMaster *m_modbusRtuMaster = nullptr;')
- writeLine(headerFile, ' quint16 m_slaveId = 1;')
- writeLine(headerFile, ' QVector m_pendingInitReplies;')
- writeLine(headerFile)
- writeLine(headerFile, ' void verifyInitFinished();')
- writeLine(headerFile)
-
- # End of class
- writeLine(headerFile)
- writeLine(headerFile, '};')
- writeLine(headerFile)
- writeLine(headerFile, 'QDebug operator<<(QDebug debug, %s *%s);' % (className, className[0].lower() + className[1:]))
- writeLine(headerFile)
- writeLine(headerFile, '#endif // %s_H' % className.upper())
-
- headerFile.close()
-
-
-def writeRtuSourceFile():
- print('Writing modbus RTU source file %s' % sourceFilePath)
- sourceFile = open(sourceFilePath, 'w')
- writeLicenseHeader(sourceFile)
-
- writeLine(sourceFile, '#include "%s"' % headerFileName)
- writeLine(sourceFile, '#include "loggingcategories.h"')
- writeLine(sourceFile)
- writeLine(sourceFile, 'NYMEA_LOGGING_CATEGORY(dc%s, "%s")' % (className, className))
- writeLine(sourceFile)
-
- # Constructor
- writeLine(sourceFile, '%s::%s(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent) :' % (className, className))
- writeLine(sourceFile, ' QObject(parent),')
- writeLine(sourceFile, ' m_modbusRtuMaster(modbusRtuMaster),')
- writeLine(sourceFile, ' m_slaveId(slaveId)')
- writeLine(sourceFile, '{')
- writeLine(sourceFile, ' ')
- writeLine(sourceFile, '}')
- writeLine(sourceFile)
-
- writeLine(sourceFile, 'ModbusRtuMaster *%s::modbusRtuMaster() const' % (className))
- writeLine(sourceFile, '{')
- writeLine(sourceFile, ' return m_modbusRtuMaster;')
- writeLine(sourceFile, '}')
-
- writeLine(sourceFile, 'quint16 %s::slaveId() const' % (className))
- writeLine(sourceFile, '{')
- writeLine(sourceFile, ' return m_slaveId;')
- writeLine(sourceFile, '}')
-
-
- # Property get methods
- writePropertyGetSetMethodImplementationsRtu(sourceFile, className, registerJson['registers'])
-
- # Block property get methods
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- writePropertyGetSetMethodImplementationsRtu(sourceFile, className, blockDefinition['registers'])
-
- # Write init and update method implementation
- writeInitializeMethod(sourceFile, className, registerJson['registers'])
- writeUpdateMethod(sourceFile, className, registerJson['registers'])
-
- # Write update methods
- writePropertyUpdateMethodImplementationsRtu(sourceFile, className, registerJson['registers'])
-
- # Write block update method
- if 'blocks' in registerJson:
- writeBlockUpdateMethodImplementationsRtu(sourceFile, className, registerJson['blocks'])
-
- # Write internal protected property read method implementations
- writeInternalPropertyReadMethodImplementationsRtu(sourceFile, className, registerJson['registers'])
-
- writeLine(sourceFile, 'void %s::verifyInitFinished()' % (className))
- writeLine(sourceFile, '{')
- writeLine(sourceFile, ' if (m_pendingInitReplies.isEmpty()) {')
- writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s";' % (className, className))
- writeLine(sourceFile, ' emit initializationFinished();')
- writeLine(sourceFile, ' }')
- writeLine(sourceFile, '}')
- writeLine(sourceFile)
-
- # Write the debug print
- debugObjectParamName = className[0].lower() + className[1:]
- writeLine(sourceFile, 'QDebug operator<<(QDebug debug, %s *%s)' % (className, debugObjectParamName))
- writeLine(sourceFile, '{')
- writeLine(sourceFile, ' debug.nospace().noquote() << "%s(" << %s->modbusRtuMaster()->modbusUuid().toString() << ", " << %s->modbusRtuMaster()->serialPort() << ", slave ID:" << %s->slaveId() << ")" << "\\n";' % (className, debugObjectParamName, debugObjectParamName, debugObjectParamName))
- writeRegistersDebugLine(sourceFile, debugObjectParamName, registerJson['registers'])
-
- if 'blocks' in registerJson:
- for blockDefinition in registerJson['blocks']:
- writeRegistersDebugLine(sourceFile, debugObjectParamName, blockDefinition['registers'])
-
- writeLine(sourceFile, ' return debug.quote().space();')
- writeLine(sourceFile, '}')
- writeLine(sourceFile)
-
- sourceFile.close()
-
-
-############################################################################################
-# Main
-############################################################################################
-
-parser = argparse.ArgumentParser(description='Generate modbus tcp connection class from JSON register definitions file.')
-parser.add_argument('-j', '--json', metavar='', help='The JSON file containing the register definitions.')
-parser.add_argument('-o', '--output-directory', metavar='', help='The output directory for the resulting class.')
-parser.add_argument('-c', '--class-name', metavar='', help='The name of the resulting class.')
-args = parser.parse_args()
-
-registerJson = loadJsonFile(args.json)
-scriptPath = os.path.dirname(os.path.realpath(sys.argv[0]))
-outputDirectory = os.path.realpath(args.output_directory)
-className = args.class_name
-
-headerFileName = className.lower() + '.h'
-sourceFileName = className.lower() + '.cpp'
-
-headerFilePath = os.path.join(outputDirectory, headerFileName)
-sourceFilePath = os.path.join(outputDirectory, sourceFileName)
-
-print('Scrip path: %s' % scriptPath)
-print('Output directory: %s' % outputDirectory)
-print('Class name: %s' % className)
-print('Header file: %s' % headerFileName)
-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']
-
-protocol = 'TCP'
-if 'protocol' in registerJson:
- protocol = registerJson['protocol']
-
-if 'blocks' in registerJson:
- validateBlocks(registerJson['blocks'])
-
-if protocol == 'TCP':
- writeTcpHeaderFile()
- writeTcpSourceFile()
-else:
- writeRtuHeaderFile()
- writeRtuSourceFile()
-
-
-
diff --git a/modbuscommander/integrationpluginmodbuscommander.cpp b/modbuscommander/integrationpluginmodbuscommander.cpp
index 5889534..ec597f6 100644
--- a/modbuscommander/integrationpluginmodbuscommander.cpp
+++ b/modbuscommander/integrationpluginmodbuscommander.cpp
@@ -31,12 +31,10 @@
#include "integrationpluginmodbuscommander.h"
#include "plugininfo.h"
-#include "hardwaremanager.h"
-#include "network/networkdevicediscovery.h"
-#include "hardware/modbus/modbusrtumaster.h"
-#include "hardware/modbus/modbusrtuhardwareresource.h"
-
-#include
+#include
+#include
+#include
+#include
IntegrationPluginModbusCommander::IntegrationPluginModbusCommander()
{
diff --git a/modbuscommander/integrationpluginmodbuscommander.h b/modbuscommander/integrationpluginmodbuscommander.h
index 54f6906..5736bdf 100644
--- a/modbuscommander/integrationpluginmodbuscommander.h
+++ b/modbuscommander/integrationpluginmodbuscommander.h
@@ -31,14 +31,15 @@
#ifndef INTEGRATIONPLUGINMODBUSCOMMANDER_H
#define INTEGRATIONPLUGINMODBUSCOMMANDER_H
-#include "plugintimer.h"
-#include "integrations/integrationplugin.h"
-#include "hardware/modbus/modbusrtumaster.h"
+#include
+#include
+#include
-#include "../modbus/modbustcpmaster.h"
+#include
-#include
#include
+#include
+#include
class IntegrationPluginModbusCommander: public IntegrationPlugin
{
@@ -60,7 +61,6 @@ public:
private:
PluginTimer *m_refreshTimer = nullptr;
- //QHash m_modbusRTUMasters;
QHash m_modbusTCPMasters;
QHash m_modbusRtuMasters;
QHash m_asyncActions;
diff --git a/modbuscommander/modbuscommander.pro b/modbuscommander/modbuscommander.pro
index ab4dfc1..5b2bc31 100644
--- a/modbuscommander/modbuscommander.pro
+++ b/modbuscommander/modbuscommander.pro
@@ -1,15 +1,9 @@
include(../plugins.pri)
-
-QT += \
- serialport \
- network \
- serialbus \
+include(../modbus.pri)
SOURCES += \
- integrationpluginmodbuscommander.cpp \
- ../modbus/modbustcpmaster.cpp
+ integrationpluginmodbuscommander.cpp
HEADERS += \
- integrationpluginmodbuscommander.h \
- ../modbus/modbustcpmaster.h
+ integrationpluginmodbuscommander.h
diff --git a/mtec/integrationpluginmtec.cpp b/mtec/integrationpluginmtec.cpp
index 858acd8..f0452ad 100644
--- a/mtec/integrationpluginmtec.cpp
+++ b/mtec/integrationpluginmtec.cpp
@@ -28,7 +28,8 @@
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#include "network/networkdevicediscovery.h"
+#include
+
#include "integrationpluginmtec.h"
#include "plugininfo.h"
diff --git a/mtec/integrationpluginmtec.h b/mtec/integrationpluginmtec.h
index c1302a4..7a476ad 100644
--- a/mtec/integrationpluginmtec.h
+++ b/mtec/integrationpluginmtec.h
@@ -30,8 +30,8 @@
#ifndef INTEGRATIONPLUGINMTEC_H
#define INTEGRATIONPLUGINMTEC_H
-#include "integrations/integrationplugin.h"
-#include "plugintimer.h"
+#include
+#include
#include "mtec.h"
diff --git a/mtec/mtec.h b/mtec/mtec.h
index 50f1740..197ec5f 100644
--- a/mtec/mtec.h
+++ b/mtec/mtec.h
@@ -34,7 +34,7 @@
#include
#include
-#include "../modbus/modbustcpmaster.h"
+#include
class MTec : public QObject
{
diff --git a/mtec/mtec.pro b/mtec/mtec.pro
index c68ed3b..30e501b 100644
--- a/mtec/mtec.pro
+++ b/mtec/mtec.pro
@@ -1,16 +1,11 @@
include(../plugins.pri)
-
-QT += \
- network \
- serialbus \
+include(../modbus.pri)
SOURCES += \
mtec.cpp \
- integrationpluginmtec.cpp \
- ../modbus/modbustcpmaster.cpp
+ integrationpluginmtec.cpp
HEADERS += \
mtec.h \
- integrationpluginmtec.h \
- ../modbus/modbustcpmaster.h \
+ integrationpluginmtec.h
diff --git a/mypv/integrationpluginmypv.h b/mypv/integrationpluginmypv.h
index 108feca..d5959cd 100644
--- a/mypv/integrationpluginmypv.h
+++ b/mypv/integrationpluginmypv.h
@@ -31,10 +31,10 @@
#ifndef INTEGRATIONPLUGINMYPV_H
#define INTEGRATIONPLUGINMYPV_H
-#include "integrations/integrationplugin.h"
-#include "plugintimer.h"
+#include
+#include
-#include "../modbus/modbustcpmaster.h"
+#include
#include
#include
diff --git a/mypv/mypv.pro b/mypv/mypv.pro
index 808801a..29c146b 100644
--- a/mypv/mypv.pro
+++ b/mypv/mypv.pro
@@ -1,13 +1,8 @@
include(../plugins.pri)
-
-QT += \
- network \
- serialbus \
+include(../modbus.pri)
SOURCES += \
- integrationpluginmypv.cpp \
- ../modbus/modbustcpmaster.cpp \
+ integrationpluginmypv.cpp
HEADERS += \
- integrationpluginmypv.h \
- ../modbus/modbustcpmaster.h \
+ integrationpluginmypv.h
diff --git a/nymea-plugins-modbus.pro b/nymea-plugins-modbus.pro
index 6124d5c..636d847 100644
--- a/nymea-plugins-modbus.pro
+++ b/nymea-plugins-modbus.pro
@@ -1,8 +1,8 @@
TEMPLATE = subdirs
-# Note keep it ordered so the lib will be built first
-CONFIG += ordered
-SUBDIRS += libnymea-sunspec
+# Note: In the loop at the end of this file the plugin
+# dependency on the libs will be defined
+SUBDIRS += libnymea-modbus libnymea-sunspec
PLUGIN_DIRS = \
alphainnotec \
@@ -15,6 +15,7 @@ PLUGIN_DIRS = \
mtec \
mypv \
schrack \
+ stiebeleltron \
sunspec \
unipi \
wallbe \
@@ -63,6 +64,12 @@ for(plugin, PLUGINS) {
exists($${plugin}) {
SUBDIRS*= $${plugin}
message("- $${plugin}")
+ # Make sure the libs will be built before the plugins
+ equals(plugin, "sunspec") {
+ $${plugin}.depends += libnymea-sunspec
+ } else {
+ $${plugin}.depends += libnymea-modbus
+ }
} else {
error("Invalid plugin \"$${plugin}\".")
}
diff --git a/schrack/cion-registers.json b/schrack/cion-registers.json
index 779762d..a796b9b 100644
--- a/schrack/cion-registers.json
+++ b/schrack/cion-registers.json
@@ -1,4 +1,5 @@
{
+ "className": "Cion",
"protocol": "RTU",
"endianness": "LittleEndian",
"blocks": [
diff --git a/schrack/cionmodbusrtuconnection.cpp b/schrack/cionmodbusrtuconnection.cpp
deleted file mode 100644
index 7bb4349..0000000
--- a/schrack/cionmodbusrtuconnection.cpp
+++ /dev/null
@@ -1,723 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* Copyright 2013 - 2022, 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
-*
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* WARNING
-*
-* This file has been autogenerated. Any changes in this file may be overwritten.
-* If you want to change something, update the register json or the tool.
-*
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#include "cionmodbusrtuconnection.h"
-#include "loggingcategories.h"
-#include "math.h"
-
-NYMEA_LOGGING_CATEGORY(dcCionModbusRtuConnection, "CionModbusRtuConnection")
-
-CionModbusRtuConnection::CionModbusRtuConnection(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent) :
- QObject(parent),
- m_modbusRtuMaster(modbusRtuMaster),
- m_slaveId(slaveId)
-{
-
-}
-
-ModbusRtuMaster *CionModbusRtuConnection::modbusRtuMaster() const
-{
- return m_modbusRtuMaster;
-}
-quint16 CionModbusRtuConnection::slaveId() const
-{
- return m_slaveId;
-}
-ModbusDataUtils::ByteOrder CionModbusRtuConnection::endianness() const
-{
- return m_endianness;
-}
-void CionModbusRtuConnection::setEndianness(ModbusDataUtils::ByteOrder endianness)
-{
- if (m_endianness == endianness)
- return;
-
- m_endianness = endianness;
- emit endiannessChanged(m_endianness);
-}
-quint16 CionModbusRtuConnection::chargingEnabled() const
-{
- return m_chargingEnabled;
-}
-
-ModbusRtuReply *CionModbusRtuConnection::setChargingEnabled(quint16 chargingEnabled)
-{
- QVector values = ModbusDataUtils::convertFromUInt16(chargingEnabled);
- qCDebug(dcCionModbusRtuConnection()) << "--> Write \"Charging enabled\" register:" << 100 << "size:" << 1 << values;
- return m_modbusRtuMaster->writeHoldingRegisters(m_slaveId, 100, values);
-}
-
-quint16 CionModbusRtuConnection::chargingCurrentSetpoint() const
-{
- return m_chargingCurrentSetpoint;
-}
-
-ModbusRtuReply *CionModbusRtuConnection::setChargingCurrentSetpoint(quint16 chargingCurrentSetpoint)
-{
- QVector values = ModbusDataUtils::convertFromUInt16(chargingCurrentSetpoint);
- qCDebug(dcCionModbusRtuConnection()) << "--> Write \"Charging current setpoint\" register:" << 101 << "size:" << 1 << values;
- return m_modbusRtuMaster->writeHoldingRegisters(m_slaveId, 101, values);
-}
-
-quint16 CionModbusRtuConnection::statusBits() const
-{
- return m_statusBits;
-}
-
-quint16 CionModbusRtuConnection::cpSignalState() const
-{
- return m_cpSignalState;
-}
-
-float CionModbusRtuConnection::u1Voltage() const
-{
- return m_u1Voltage;
-}
-
-float CionModbusRtuConnection::gridVoltage() const
-{
- return m_gridVoltage;
-}
-
-quint16 CionModbusRtuConnection::minChargingCurrent() const
-{
- return m_minChargingCurrent;
-}
-
-quint16 CionModbusRtuConnection::currentChargingCurrentE3() const
-{
- return m_currentChargingCurrentE3;
-}
-
-quint16 CionModbusRtuConnection::maxChargingCurrentE3() const
-{
- return m_maxChargingCurrentE3;
-}
-
-quint16 CionModbusRtuConnection::maxChargingCurrentCableE3() const
-{
- return m_maxChargingCurrentCableE3;
-}
-
-quint32 CionModbusRtuConnection::chargingDuration() const
-{
- return m_chargingDuration;
-}
-
-quint32 CionModbusRtuConnection::pluggedInDuration() const
-{
- return m_pluggedInDuration;
-}
-
-void CionModbusRtuConnection::initialize()
-{
- // No init registers defined. Nothing to be done and we are finished.
- emit initializationFinished();
-}
-
-void CionModbusRtuConnection::update()
-{
- updateChargingEnabled();
- updateChargingCurrentSetpoint();
- updateStatusBits();
- updateCpSignalState();
- updateU1Voltage();
- updateGridVoltage();
- updateMinChargingCurrent();
- updateE3Block();
- updateDurationsBlock();
-}
-
-void CionModbusRtuConnection::updateChargingEnabled()
-{
- // Update registers from Charging enabled
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Charging enabled\" register:" << 100 << "size:" << 1;
- ModbusRtuReply *reply = readChargingEnabled();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Charging enabled\" register" << 100 << "size:" << 1 << values;
- processChargingEnabledRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Charging enabled\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Charging enabled\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateChargingCurrentSetpoint()
-{
- // Update registers from Charging current setpoint
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Charging current setpoint\" register:" << 101 << "size:" << 1;
- ModbusRtuReply *reply = readChargingCurrentSetpoint();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Charging current setpoint\" register" << 101 << "size:" << 1 << values;
- processChargingCurrentSetpointRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Charging current setpoint\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Charging current setpoint\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateStatusBits()
-{
- // Update registers from Mode3-State A, B, C, D, U
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Mode3-State A, B, C, D, U\" register:" << 121 << "size:" << 1;
- ModbusRtuReply *reply = readStatusBits();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Mode3-State A, B, C, D, U\" register" << 121 << "size:" << 1 << values;
- processStatusBitsRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Mode3-State A, B, C, D, U\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Mode3-State A, B, C, D, U\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateCpSignalState()
-{
- // Update registers from Status bits
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Status bits\" register:" << 139 << "size:" << 1;
- ModbusRtuReply *reply = readCpSignalState();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Status bits\" register" << 139 << "size:" << 1 << values;
- processCpSignalStateRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Status bits\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Status bits\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateU1Voltage()
-{
- // Update registers from U1 voltage
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"U1 voltage\" register:" << 167 << "size:" << 1;
- ModbusRtuReply *reply = readU1Voltage();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"U1 voltage\" register" << 167 << "size:" << 1 << values;
- processU1VoltageRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"U1 voltage\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"U1 voltage\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateGridVoltage()
-{
- // Update registers from Voltage of the power supply grid
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Voltage of the power supply grid\" register:" << 302 << "size:" << 1;
- ModbusRtuReply *reply = readGridVoltage();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Voltage of the power supply grid\" register" << 302 << "size:" << 1 << values;
- processGridVoltageRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Voltage of the power supply grid\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Voltage of the power supply grid\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateMinChargingCurrent()
-{
- // Update registers from Minimum charging current
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Minimum charging current\" register:" << 507 << "size:" << 1;
- ModbusRtuReply *reply = readMinChargingCurrent();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Minimum charging current\" register" << 507 << "size:" << 1 << values;
- processMinChargingCurrentRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Minimum charging current\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Minimum charging current\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateCurrentChargingCurrentE3()
-{
- // Update registers from Current charging Ampere
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Current charging Ampere\" register:" << 126 << "size:" << 1;
- ModbusRtuReply *reply = readCurrentChargingCurrentE3();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Current charging Ampere\" register" << 126 << "size:" << 1 << values;
- processCurrentChargingCurrentE3RegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Current charging Ampere\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Current charging Ampere\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateMaxChargingCurrentE3()
-{
- // Update registers from Maximum charging current
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Maximum charging current\" register:" << 127 << "size:" << 1;
- ModbusRtuReply *reply = readMaxChargingCurrentE3();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Maximum charging current\" register" << 127 << "size:" << 1 << values;
- processMaxChargingCurrentE3RegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Maximum charging current\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Maximum charging current\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateMaxChargingCurrentCableE3()
-{
- // Update registers from Maximum charging current of connected cable
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Maximum charging current of connected cable\" register:" << 128 << "size:" << 1;
- ModbusRtuReply *reply = readMaxChargingCurrentCableE3();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Maximum charging current of connected cable\" register" << 128 << "size:" << 1 << values;
- processMaxChargingCurrentCableE3RegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Maximum charging current of connected cable\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Maximum charging current of connected cable\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateChargingDuration()
-{
- // Update registers from Charging duration
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Charging duration\" register:" << 151 << "size:" << 2;
- ModbusRtuReply *reply = readChargingDuration();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Charging duration\" register" << 151 << "size:" << 2 << values;
- processChargingDurationRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Charging duration\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Charging duration\" registers";
- }
-}
-
-void CionModbusRtuConnection::updatePluggedInDuration()
-{
- // Update registers from Plugged in duration
- qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Plugged in duration\" register:" << 153 << "size:" << 2;
- ModbusRtuReply *reply = readPluggedInDuration();
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector values = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Plugged in duration\" register" << 153 << "size:" << 2 << values;
- processPluggedInDurationRegisterValues(values);
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Plugged in duration\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Plugged in duration\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateE3Block()
-{
- // Update register block "e3"
- qCDebug(dcCionModbusRtuConnection()) << "--> Read block \"e3\" registers from:" << 126 << "size:" << 3;
- ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 126, 3);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from reading block \"e3\" register" << 126 << "size:" << 3 << blockValues;
- processCurrentChargingCurrentE3RegisterValues(blockValues.mid(0, 1));
- processMaxChargingCurrentE3RegisterValues(blockValues.mid(1, 1));
- processMaxChargingCurrentCableE3RegisterValues(blockValues.mid(2, 1));
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"e3\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading block \"e3\" registers";
- }
-}
-
-void CionModbusRtuConnection::updateDurationsBlock()
-{
- // Update register block "durations"
- qCDebug(dcCionModbusRtuConnection()) << "--> Read block \"durations\" registers from:" << 151 << "size:" << 4;
- ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 151, 4);
- if (reply) {
- if (!reply->isFinished()) {
- connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
- if (reply->error() == ModbusRtuReply::NoError) {
- QVector blockValues = reply->result();
- qCDebug(dcCionModbusRtuConnection()) << "<-- Response from reading block \"durations\" register" << 151 << "size:" << 4 << blockValues;
- processChargingDurationRegisterValues(blockValues.mid(0, 2));
- processPluggedInDurationRegisterValues(blockValues.mid(2, 2));
- }
- });
-
- connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
- qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"durations\" registers" << error << reply->errorString();
- emit reply->finished();
- });
- }
- } else {
- qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading block \"durations\" registers";
- }
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readChargingEnabled()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 100, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readChargingCurrentSetpoint()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 101, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readStatusBits()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 121, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readCpSignalState()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 139, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readU1Voltage()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 167, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readGridVoltage()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 302, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readMinChargingCurrent()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 507, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readCurrentChargingCurrentE3()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 126, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readMaxChargingCurrentE3()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 127, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readMaxChargingCurrentCableE3()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 128, 1);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readChargingDuration()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 151, 2);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readPluggedInDuration()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 153, 2);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readBlockE3()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 126, 3);
-}
-
-ModbusRtuReply *CionModbusRtuConnection::readBlockDurations()
-{
- return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 151, 4);
-}
-
-void CionModbusRtuConnection::processChargingEnabledRegisterValues(const QVector values)
-{
- quint16 receivedChargingEnabled = ModbusDataUtils::convertToUInt16(values);
- if (m_chargingEnabled != receivedChargingEnabled) {
- m_chargingEnabled = receivedChargingEnabled;
- emit chargingEnabledChanged(m_chargingEnabled);
- }
-}
-
-void CionModbusRtuConnection::processChargingCurrentSetpointRegisterValues(const QVector values)
-{
- quint16 receivedChargingCurrentSetpoint = ModbusDataUtils::convertToUInt16(values);
- if (m_chargingCurrentSetpoint != receivedChargingCurrentSetpoint) {
- m_chargingCurrentSetpoint = receivedChargingCurrentSetpoint;
- emit chargingCurrentSetpointChanged(m_chargingCurrentSetpoint);
- }
-}
-
-void CionModbusRtuConnection::processStatusBitsRegisterValues(const QVector values)
-{
- quint16 receivedStatusBits = ModbusDataUtils::convertToUInt16(values);
- if (m_statusBits != receivedStatusBits) {
- m_statusBits = receivedStatusBits;
- emit statusBitsChanged(m_statusBits);
- }
-}
-
-void CionModbusRtuConnection::processCpSignalStateRegisterValues(const QVector values)
-{
- quint16 receivedCpSignalState = ModbusDataUtils::convertToUInt16(values);
- if (m_cpSignalState != receivedCpSignalState) {
- m_cpSignalState = receivedCpSignalState;
- emit cpSignalStateChanged(m_cpSignalState);
- }
-}
-
-void CionModbusRtuConnection::processU1VoltageRegisterValues(const QVector values)
-{
- float receivedU1Voltage = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -2);
- if (m_u1Voltage != receivedU1Voltage) {
- m_u1Voltage = receivedU1Voltage;
- emit u1VoltageChanged(m_u1Voltage);
- }
-}
-
-void CionModbusRtuConnection::processGridVoltageRegisterValues(const QVector values)
-{
- float receivedGridVoltage = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -2);
- if (m_gridVoltage != receivedGridVoltage) {
- m_gridVoltage = receivedGridVoltage;
- emit gridVoltageChanged(m_gridVoltage);
- }
-}
-
-void CionModbusRtuConnection::processMinChargingCurrentRegisterValues(const QVector values)
-{
- quint16 receivedMinChargingCurrent = ModbusDataUtils::convertToUInt16(values);
- if (m_minChargingCurrent != receivedMinChargingCurrent) {
- m_minChargingCurrent = receivedMinChargingCurrent;
- emit minChargingCurrentChanged(m_minChargingCurrent);
- }
-}
-
-void CionModbusRtuConnection::processCurrentChargingCurrentE3RegisterValues(const QVector values)
-{
- quint16 receivedCurrentChargingCurrentE3 = ModbusDataUtils::convertToUInt16(values);
- if (m_currentChargingCurrentE3 != receivedCurrentChargingCurrentE3) {
- m_currentChargingCurrentE3 = receivedCurrentChargingCurrentE3;
- emit currentChargingCurrentE3Changed(m_currentChargingCurrentE3);
- }
-}
-
-void CionModbusRtuConnection::processMaxChargingCurrentE3RegisterValues(const QVector values)
-{
- quint16 receivedMaxChargingCurrentE3 = ModbusDataUtils::convertToUInt16(values);
- if (m_maxChargingCurrentE3 != receivedMaxChargingCurrentE3) {
- m_maxChargingCurrentE3 = receivedMaxChargingCurrentE3;
- emit maxChargingCurrentE3Changed(m_maxChargingCurrentE3);
- }
-}
-
-void CionModbusRtuConnection::processMaxChargingCurrentCableE3RegisterValues(const QVector values)
-{
- quint16 receivedMaxChargingCurrentCableE3 = ModbusDataUtils::convertToUInt16(values);
- if (m_maxChargingCurrentCableE3 != receivedMaxChargingCurrentCableE3) {
- m_maxChargingCurrentCableE3 = receivedMaxChargingCurrentCableE3;
- emit maxChargingCurrentCableE3Changed(m_maxChargingCurrentCableE3);
- }
-}
-
-void CionModbusRtuConnection::processChargingDurationRegisterValues(const QVector values)
-{
- quint32 receivedChargingDuration = ModbusDataUtils::convertToUInt32(values, m_endianness);
- if (m_chargingDuration != receivedChargingDuration) {
- m_chargingDuration = receivedChargingDuration;
- emit chargingDurationChanged(m_chargingDuration);
- }
-}
-
-void CionModbusRtuConnection::processPluggedInDurationRegisterValues(const QVector values)
-{
- quint32 receivedPluggedInDuration = ModbusDataUtils::convertToUInt32(values, m_endianness);
- if (m_pluggedInDuration != receivedPluggedInDuration) {
- m_pluggedInDuration = receivedPluggedInDuration;
- emit pluggedInDurationChanged(m_pluggedInDuration);
- }
-}
-
-void CionModbusRtuConnection::verifyInitFinished()
-{
- if (m_pendingInitReplies.isEmpty()) {
- qCDebug(dcCionModbusRtuConnection()) << "Initialization finished of CionModbusRtuConnection";
- emit initializationFinished();
- }
-}
-
-QDebug operator<<(QDebug debug, CionModbusRtuConnection *cionModbusRtuConnection)
-{
- debug.nospace().noquote() << "CionModbusRtuConnection(" << cionModbusRtuConnection->modbusRtuMaster()->modbusUuid().toString() << ", " << cionModbusRtuConnection->modbusRtuMaster()->serialPort() << ", slave ID:" << cionModbusRtuConnection->slaveId() << ")" << "\n";
- debug.nospace().noquote() << " - Charging enabled:" << cionModbusRtuConnection->chargingEnabled() << "\n";
- debug.nospace().noquote() << " - Charging current setpoint:" << cionModbusRtuConnection->chargingCurrentSetpoint() << " [A]" << "\n";
- debug.nospace().noquote() << " - Mode3-State A, B, C, D, U:" << cionModbusRtuConnection->statusBits() << "\n";
- debug.nospace().noquote() << " - Status bits:" << cionModbusRtuConnection->cpSignalState() << "\n";
- debug.nospace().noquote() << " - U1 voltage:" << cionModbusRtuConnection->u1Voltage() << " [V]" << "\n";
- debug.nospace().noquote() << " - Voltage of the power supply grid:" << cionModbusRtuConnection->gridVoltage() << " [V]" << "\n";
- debug.nospace().noquote() << " - Minimum charging current:" << cionModbusRtuConnection->minChargingCurrent() << " [A]" << "\n";
- debug.nospace().noquote() << " - Current charging Ampere:" << cionModbusRtuConnection->currentChargingCurrentE3() << " [A]" << "\n";
- debug.nospace().noquote() << " - Maximum charging current:" << cionModbusRtuConnection->maxChargingCurrentE3() << " [A]" << "\n";
- debug.nospace().noquote() << " - Maximum charging current of connected cable:" << cionModbusRtuConnection->maxChargingCurrentCableE3() << " [A]" << "\n";
- debug.nospace().noquote() << " - Charging duration:" << cionModbusRtuConnection->chargingDuration() << " [ms]" << "\n";
- debug.nospace().noquote() << " - Plugged in duration:" << cionModbusRtuConnection->pluggedInDuration() << " [ms]" << "\n";
- return debug.quote().space();
-}
-
diff --git a/schrack/cionmodbusrtuconnection.h b/schrack/cionmodbusrtuconnection.h
deleted file mode 100644
index a175aea..0000000
--- a/schrack/cionmodbusrtuconnection.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* Copyright 2013 - 2022, 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
-*
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* WARNING
-*
-* This file has been autogenerated. Any changes in this file may be overwritten.
-* If you want to change something, update the register json or the tool.
-*
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#ifndef CIONMODBUSRTUCONNECTION_H
-#define CIONMODBUSRTUCONNECTION_H
-
-#include
-
-#include "../modbus/modbusdatautils.h"
-#include
-
-class CionModbusRtuConnection : public QObject
-{
- Q_OBJECT
-public:
- enum Registers {
- RegisterChargingEnabled = 100,
- RegisterChargingCurrentSetpoint = 101,
- RegisterStatusBits = 121,
- RegisterCurrentChargingCurrentE3 = 126,
- RegisterMaxChargingCurrentE3 = 127,
- RegisterMaxChargingCurrentCableE3 = 128,
- RegisterCpSignalState = 139,
- RegisterChargingDuration = 151,
- RegisterPluggedInDuration = 153,
- RegisterU1Voltage = 167,
- RegisterGridVoltage = 302,
- RegisterMinChargingCurrent = 507
- };
- Q_ENUM(Registers)
-
- explicit CionModbusRtuConnection(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent = nullptr);
- ~CionModbusRtuConnection() = default;
-
- ModbusRtuMaster *modbusRtuMaster() const;
- quint16 slaveId() const;
-
- ModbusDataUtils::ByteOrder endianness() const;
- void setEndianness(ModbusDataUtils::ByteOrder endianness);
-
- /* Charging enabled - Address: 100, Size: 1 */
- quint16 chargingEnabled() const;
- ModbusRtuReply *setChargingEnabled(quint16 chargingEnabled);
-
- /* Charging current setpoint [A] - Address: 101, Size: 1 */
- quint16 chargingCurrentSetpoint() const;
- ModbusRtuReply *setChargingCurrentSetpoint(quint16 chargingCurrentSetpoint);
-
- /* Mode3-State A, B, C, D, U - Address: 121, Size: 1 */
- quint16 statusBits() const;
-
- /* Status bits - Address: 139, Size: 1 */
- quint16 cpSignalState() const;
-
- /* U1 voltage [V] - Address: 167, Size: 1 */
- float u1Voltage() const;
-
- /* Voltage of the power supply grid [V] - Address: 302, Size: 1 */
- float gridVoltage() const;
-
- /* Minimum charging current [A] - Address: 507, Size: 1 */
- quint16 minChargingCurrent() const;
-
- /* Current charging Ampere [A] - Address: 126, Size: 1 */
- quint16 currentChargingCurrentE3() const;
-
- /* Maximum charging current [A] - Address: 127, Size: 1 */
- quint16 maxChargingCurrentE3() const;
-
- /* Maximum charging current of connected cable [A] - Address: 128, Size: 1 */
- quint16 maxChargingCurrentCableE3() const;
-
- /* Charging duration [ms] - Address: 151, Size: 2 */
- quint32 chargingDuration() const;
-
- /* Plugged in duration [ms] - Address: 153, Size: 2 */
- quint32 pluggedInDuration() const;
-
- /* Read block from start addess 126 with size of 3 registers containing following 3 properties:
- - Current charging Ampere [A] - Address: 126, Size: 1
- - Maximum charging current [A] - Address: 127, Size: 1
- - Maximum charging current of connected cable [A] - Address: 128, Size: 1
- */
- void updateE3Block();
-
- /* Read block from start addess 151 with size of 4 registers containing following 2 properties:
- - Charging duration [ms] - Address: 151, Size: 2
- - Plugged in duration [ms] - Address: 153, Size: 2
- */
- void updateDurationsBlock();
-
- virtual void initialize();
- virtual void update();
-
- void updateChargingEnabled();
- void updateChargingCurrentSetpoint();
- void updateStatusBits();
- void updateCpSignalState();
- void updateU1Voltage();
- void updateGridVoltage();
- void updateMinChargingCurrent();
-
- void updateCurrentChargingCurrentE3();
- void updateMaxChargingCurrentE3();
- void updateMaxChargingCurrentCableE3();
- void updateChargingDuration();
- void updatePluggedInDuration();
-
- ModbusRtuReply *readChargingEnabled();
- ModbusRtuReply *readChargingCurrentSetpoint();
- ModbusRtuReply *readStatusBits();
- ModbusRtuReply *readCpSignalState();
- ModbusRtuReply *readU1Voltage();
- ModbusRtuReply *readGridVoltage();
- ModbusRtuReply *readMinChargingCurrent();
- ModbusRtuReply *readCurrentChargingCurrentE3();
- ModbusRtuReply *readMaxChargingCurrentE3();
- ModbusRtuReply *readMaxChargingCurrentCableE3();
- ModbusRtuReply *readChargingDuration();
- ModbusRtuReply *readPluggedInDuration();
-
- /* Read block from start addess 126 with size of 3 registers containing following 3 properties:
- - Current charging Ampere [A] - Address: 126, Size: 1
- - Maximum charging current [A] - Address: 127, Size: 1
- - Maximum charging current of connected cable [A] - Address: 128, Size: 1
- */
- ModbusRtuReply *readBlockE3();
-
- /* Read block from start addess 151 with size of 4 registers containing following 2 properties:
- - Charging duration [ms] - Address: 151, Size: 2
- - Plugged in duration [ms] - Address: 153, Size: 2
- */
- ModbusRtuReply *readBlockDurations();
-
-signals:
- void initializationFinished();
- void endiannessChanged(ModbusDataUtils::ByteOrder endianness);
-
- void chargingEnabledChanged(quint16 chargingEnabled);
- void chargingCurrentSetpointChanged(quint16 chargingCurrentSetpoint);
- void statusBitsChanged(quint16 statusBits);
- void cpSignalStateChanged(quint16 cpSignalState);
- void u1VoltageChanged(float u1Voltage);
- void gridVoltageChanged(float gridVoltage);
- void minChargingCurrentChanged(quint16 minChargingCurrent);
- void currentChargingCurrentE3Changed(quint16 currentChargingCurrentE3);
- void maxChargingCurrentE3Changed(quint16 maxChargingCurrentE3);
- void maxChargingCurrentCableE3Changed(quint16 maxChargingCurrentCableE3);
- void chargingDurationChanged(quint32 chargingDuration);
- void pluggedInDurationChanged(quint32 pluggedInDuration);
-
-protected:
- quint16 m_chargingEnabled = 0;
- quint16 m_chargingCurrentSetpoint = 6;
- quint16 m_statusBits = 85;
- quint16 m_cpSignalState = 0;
- float m_u1Voltage = 32;
- float m_gridVoltage = 0;
- quint16 m_minChargingCurrent = 13;
- quint16 m_currentChargingCurrentE3 = 6;
- quint16 m_maxChargingCurrentE3 = 32;
- quint16 m_maxChargingCurrentCableE3 = 32;
- quint32 m_chargingDuration = 0;
- quint32 m_pluggedInDuration = 0;
-
- void processChargingEnabledRegisterValues(const QVector values);
- void processChargingCurrentSetpointRegisterValues(const QVector values);
- void processStatusBitsRegisterValues(const QVector values);
- void processCpSignalStateRegisterValues(const QVector values);
- void processU1VoltageRegisterValues(const QVector values);
- void processGridVoltageRegisterValues(const QVector values);
- void processMinChargingCurrentRegisterValues(const QVector values);
-
- void processCurrentChargingCurrentE3RegisterValues(const QVector values);
- void processMaxChargingCurrentE3RegisterValues(const QVector values);
- void processMaxChargingCurrentCableE3RegisterValues(const QVector values);
-
- void processChargingDurationRegisterValues(const QVector values);
- void processPluggedInDurationRegisterValues(const QVector values);
-
-
-private:
- ModbusRtuMaster *m_modbusRtuMaster = nullptr;
- quint16 m_slaveId = 1;
- QVector m_pendingInitReplies;
- ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrderBigEndian;
-
- void verifyInitFinished();
-
-
-};
-
-QDebug operator<<(QDebug debug, CionModbusRtuConnection *cionModbusRtuConnection);
-
-#endif // CIONMODBUSRTUCONNECTION_H
diff --git a/schrack/schrack.pro b/schrack/schrack.pro
index 88565a9..94fae58 100644
--- a/schrack/schrack.pro
+++ b/schrack/schrack.pro
@@ -1,20 +1,13 @@
include(../plugins.pri)
-QT += serialport serialbus
+# Generate modbus connection
+MODBUS_CONNECTIONS += cion-registers.json
+#MODBUS_TOOLS_CONFIG += VERBOSE
+include(../modbus.pri)
SOURCES += \
- integrationpluginschrack.cpp \
- cionmodbusrtuconnection.cpp \
- ../modbus/modbusdatautils.cpp
+ integrationpluginschrack.cpp
HEADERS += \
- integrationpluginschrack.h \
- cionmodbusrtuconnection.h \
- ../modbus/modbusdatautils.h
+ integrationpluginschrack.h
-OTHER_FILES += cion-registers.json
-
-modbusconnection.commands = python $${top_srcdir}/modbus/tools/generate-connection.py -j $${_PRO_FILE_PWD_}/cion-registers.json -o $${_PRO_FILE_PWD_} -c CionModbusRtuConnection
-QMAKE_EXTRA_TARGETS += modbusconnection
-
-#target.depends += modbusconnection
diff --git a/stiebeleltron/README.md b/stiebeleltron/README.md
new file mode 100644
index 0000000..1187f20
--- /dev/null
+++ b/stiebeleltron/README.md
@@ -0,0 +1,21 @@
+# Stiebel Eltron
+
+Connect nymea to Stiebel Eltron heat pumps.
+
+This plugin communicates via Modbus/TCP with a Stiebel Eltron Internet-Service-Gateway (ISG). The ISG is usually connected to a WPM/WPM3/WPM3i heatpump controller which again is connected via CAN to the heatpump.
+Make sure the ISG firmware is up to date to ensure the Modbus/TCP connection is working. Contact Stiebel Eltron service for a remote update of your ISG.
+
+
+## Supported Things
+
+* Stiebel Eltron Heatpump
+
+## Requirements
+
+* The package `nymea-plugin-stiebeleltron` must be installed
+* Both devices must be in the same local area network.
+* Modbus enabled (may conflict with an installed SMA EMI).
+
+## More
+
+https://www.stiebel-eltron.de/
diff --git a/stiebeleltron/integrationpluginstiebeleltron.cpp b/stiebeleltron/integrationpluginstiebeleltron.cpp
new file mode 100644
index 0000000..086538a
--- /dev/null
+++ b/stiebeleltron/integrationpluginstiebeleltron.cpp
@@ -0,0 +1,395 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Copyright 2013 - 2021, nymea GmbH, Consolinno Energy GmbH, L. Heizinger
+ * 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 "integrationpluginstiebeleltron.h"
+#include "plugininfo.h"
+
+#include
+#include
+
+IntegrationPluginStiebelEltron::IntegrationPluginStiebelEltron() {}
+
+void IntegrationPluginStiebelEltron::discoverThings(ThingDiscoveryInfo *info) {
+ if (!hardwareManager()->networkDeviceDiscovery()->available()) {
+ qCWarning(dcStiebelEltron()) << "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(dcStiebelEltron()) << "Found" << networkDeviceInfo;
+
+ QString title;
+ if (networkDeviceInfo.hostName().isEmpty()) {
+ title = networkDeviceInfo.address().toString();
+ } else {
+ if (!networkDeviceInfo.hostName().contains("StiebelEltronISG")) continue;
+ title = networkDeviceInfo.hostName() + " (" + networkDeviceInfo.address().toString() + ")";
+ }
+
+ QString description;
+ if (networkDeviceInfo.macAddressManufacturer().isEmpty()) {
+ description = networkDeviceInfo.macAddress();
+ } else {
+ description =
+ networkDeviceInfo.macAddress() + " (" + networkDeviceInfo.macAddressManufacturer() + ")";
+ }
+
+ ThingDescriptor descriptor(stiebelEltronThingClassId, title, description);
+ ParamList params;
+ params << Param(stiebelEltronThingIpAddressParamTypeId, networkDeviceInfo.address().toString());
+ params << Param(stiebelEltronThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
+ descriptor.setParams(params);
+
+ // Check if we already have set up this device
+ Things existingThings = myThings().filterByParam(stiebelEltronThingMacAddressParamTypeId,
+ networkDeviceInfo.macAddress());
+ if (existingThings.count() == 1) {
+ qCDebug(dcStiebelEltron())
+ << "This connection already exists in the system:" << networkDeviceInfo;
+ descriptor.setThingId(existingThings.first()->id());
+ }
+
+ info->addThingDescriptor(descriptor);
+ }
+
+ info->finish(Thing::ThingErrorNoError);
+ });
+}
+
+void IntegrationPluginStiebelEltron::startMonitoringAutoThings() {}
+
+void IntegrationPluginStiebelEltron::setupThing(ThingSetupInfo *info) {
+ Thing *thing = info->thing();
+ qCDebug(dcStiebelEltron()) << "Setup" << thing << thing->params();
+
+ if (thing->thingClassId() == stiebelEltronThingClassId) {
+ QHostAddress address(thing->paramValue(stiebelEltronThingIpAddressParamTypeId).toString());
+ quint16 port = thing->paramValue(stiebelEltronThingPortParamTypeId).toUInt();
+ quint16 slaveId = thing->paramValue(stiebelEltronThingSlaveIdParamTypeId).toUInt();
+
+ StiebelEltronModbusTcpConnection *connection =
+ new StiebelEltronModbusTcpConnection(address, port, slaveId, this);
+
+ connect(connection, &StiebelEltronModbusTcpConnection::connectionStateChanged, thing,
+ [thing, connection](bool status) {
+ qCDebug(dcStiebelEltron()) << "Connected changed to" << status << "for" << thing;
+ if (status) {
+ connection->update();
+ }
+
+ thing->setStateValue(stiebelEltronConnectedStateTypeId, status);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::outdoorTemperatureChanged, thing,
+ [thing](float outdoorTemperature) {
+ qCDebug(dcStiebelEltron())
+ << thing << "outdoor temperature changed" << outdoorTemperature << "°C";
+ thing->setStateValue(stiebelEltronOutdoorTemperatureStateTypeId, outdoorTemperature);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::flowTemperatureChanged, thing,
+ [thing](float flowTemperature) {
+ qCDebug(dcStiebelEltron())
+ << thing << "flow temperature changed" << flowTemperature << "°C";
+ thing->setStateValue(stiebelEltronFlowTemperatureStateTypeId, flowTemperature);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::hotWaterTemperatureChanged, thing,
+ [thing](float hotWaterTemperature) {
+ qCDebug(dcStiebelEltron())
+ << thing << "hot water temperature changed" << hotWaterTemperature << "°C";
+ thing->setStateValue(stiebelEltronHotWaterTemperatureStateTypeId, hotWaterTemperature);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::storageTankTemperatureChanged, thing,
+ [thing](float storageTankTemperature) {
+ qCDebug(dcStiebelEltron())
+ << thing << "Storage tank temperature changed" << storageTankTemperature << "°C";
+ thing->setStateValue(stiebelEltronStorageTankTemperatureStateTypeId,
+ storageTankTemperature);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::returnTemperatureChanged, thing,
+ [thing](float returnTemperature) {
+ qCDebug(dcStiebelEltron())
+ << thing << "return temperature changed" << returnTemperature << "°C";
+ thing->setStateValue(stiebelEltronReturnTemperatureStateTypeId, returnTemperature);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::heatingEnergyChanged, thing,
+ [thing](quint32 heatingEnergy) {
+ // kWh and MWh of energy are stored in two registers an read as
+ // an uint32. The following arithmetic splits the uint32 into
+ // two uint16 and sums up the MWh and kWh values.
+ quint32 correctedEnergy = (heatingEnergy >> 16) + (heatingEnergy & 0xFFFF) * 1000;
+ qCDebug(dcStiebelEltron())
+ << thing << "Heating energy changed" << correctedEnergy << "kWh";
+ thing->setStateValue(stiebelEltronHeatingEnergyStateTypeId, correctedEnergy);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::hotWaterEnergyChanged, thing,
+ [thing](quint32 hotWaterEnergy) {
+ // see comment in heatingEnergyChanged
+ quint32 correctedEnergy = (hotWaterEnergy >> 16) + (hotWaterEnergy & 0xFFFF) * 1000;
+ qCDebug(dcStiebelEltron())
+ << thing << "Hot Water energy changed" << correctedEnergy << "kWh";
+ thing->setStateValue(stiebelEltronHotWaterEnergyStateTypeId, correctedEnergy);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::consumedEnergyHeatingChanged, thing,
+ [thing](quint32 consumedEnergyHeatingEnergy) {
+ // see comment in heatingEnergyChanged
+ quint32 correctedEnergy =
+ (consumedEnergyHeatingEnergy >> 16) + (consumedEnergyHeatingEnergy & 0xFFFF) * 1000;
+ qCDebug(dcStiebelEltron())
+ << thing << "Consumed energy Heating changed" << correctedEnergy << "kWh";
+ thing->setStateValue(stiebelEltronConsumedEnergyHeatingStateTypeId, correctedEnergy);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::consumedEnergyHotWaterChanged, thing,
+ [thing](quint32 consumedEnergyHotWaterEnergy) {
+ // see comment in heatingEnergyChanged
+ quint32 correctedEnergy =
+ (consumedEnergyHotWaterEnergy >> 16) + (consumedEnergyHotWaterEnergy & 0xFFFF) * 1000;
+ qCDebug(dcStiebelEltron())
+ << thing << "Consumed energy hot water changed" << correctedEnergy << "kWh";
+ thing->setStateValue(stiebelEltronConsumedEnergyHotWaterStateTypeId, correctedEnergy);
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::operatingModeChanged, thing,
+ [thing](StiebelEltronModbusTcpConnection::OperatingMode operatingMode) {
+ qCDebug(dcStiebelEltron()) << thing << "operating mode changed " << operatingMode;
+ switch (operatingMode) {
+ case StiebelEltronModbusTcpConnection::OperatingModeEmergency:
+ thing->setStateValue(stiebelEltronOperatingModeStateTypeId, "Emergency");
+ break;
+ case StiebelEltronModbusTcpConnection::OperatingModeStandby:
+ thing->setStateValue(stiebelEltronOperatingModeStateTypeId, "Standby");
+ break;
+ case StiebelEltronModbusTcpConnection::OperatingModeProgram:
+ thing->setStateValue(stiebelEltronOperatingModeStateTypeId, "Program");
+ break;
+ case StiebelEltronModbusTcpConnection::OperatingModeComfort:
+ thing->setStateValue(stiebelEltronOperatingModeStateTypeId, "Comfort");
+ break;
+ case StiebelEltronModbusTcpConnection::OperatingModeEco:
+ thing->setStateValue(stiebelEltronOperatingModeStateTypeId, "Eco");
+ break;
+ case StiebelEltronModbusTcpConnection::OperatingModeHotWater:
+ thing->setStateValue(stiebelEltronOperatingModeStateTypeId, "Hot water");
+ break;
+ }
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::systemStatusChanged, thing,
+ [thing](uint16_t systemStatus) {
+ qCDebug(dcStiebelEltron()) << thing << "System status changed " << systemStatus;
+ thing->setStateValue(stiebelEltronPumpOneStateTypeId, systemStatus & (1 << 0));
+ thing->setStateValue(stiebelEltronPumpTwoStateTypeId, systemStatus & (1 << 1));
+ thing->setStateValue(stiebelEltronHeatingUpStateTypeId, systemStatus & (1 << 2));
+ thing->setStateValue(stiebelEltronAuxHeatingStateTypeId, systemStatus & (1 << 3));
+ thing->setStateValue(stiebelEltronHeatingStateTypeId, systemStatus & (1 << 4));
+ thing->setStateValue(stiebelEltronHotWaterStateTypeId, systemStatus & (1 << 5));
+ thing->setStateValue(stiebelEltronCompressorStateTypeId, systemStatus & (1 << 6));
+ thing->setStateValue(stiebelEltronSummerModeStateTypeId, systemStatus & (1 << 7));
+ thing->setStateValue(stiebelEltronCoolingModeStateTypeId, systemStatus & (1 << 8));
+ thing->setStateValue(stiebelEltronDefrostingStateTypeId, systemStatus & (1 << 9));
+ thing->setStateValue(stiebelEltronSilentModeStateTypeId, systemStatus & (1 << 10));
+ thing->setStateValue(stiebelEltronSilentMode2StateTypeId, systemStatus & (1 << 11));
+ });
+
+ connect(connection, &StiebelEltronModbusTcpConnection::sgReadyStateChanged, thing,
+ [thing](StiebelEltronModbusTcpConnection::SmartGridState smartGridState) {
+ qCDebug(dcStiebelEltron()) << thing << "SG Ready mode changed" << smartGridState;
+ switch (smartGridState) {
+ case StiebelEltronModbusTcpConnection::SmartGridStateModeOne:
+ thing->setStateValue(stiebelEltronSgReadyModeStateTypeId, "Off");
+ break;
+ case StiebelEltronModbusTcpConnection::SmartGridStateModeTwo:
+ thing->setStateValue(stiebelEltronSgReadyModeStateTypeId, "Low");
+ break;
+ case StiebelEltronModbusTcpConnection::SmartGridStateModeThree:
+ thing->setStateValue(stiebelEltronSgReadyModeStateTypeId, "Standard");
+ break;
+ case StiebelEltronModbusTcpConnection::SmartGridStateModeFour:
+ thing->setStateValue(stiebelEltronSgReadyModeStateTypeId, "High");
+ break;
+ }
+ });
+ connect(connection, &StiebelEltronModbusTcpConnection::sgReadyActiveChanged, thing,
+ [thing](bool smartGridActive) {
+ qCDebug(dcStiebelEltron()) << thing << "SG Ready activation changed" << smartGridActive;
+ thing->setStateValue(stiebelEltronSgReadyActiveStateTypeId, smartGridActive);
+ });
+
+ m_connections.insert(thing, connection);
+ connection->connectDevice();
+
+ info->finish(Thing::ThingErrorNoError);
+ }
+}
+
+void IntegrationPluginStiebelEltron::postSetupThing(Thing *thing) {
+ if (thing->thingClassId() == stiebelEltronThingClassId) {
+ if (!m_pluginTimer) {
+ qCDebug(dcStiebelEltron()) << "Starting plugin timer...";
+ m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
+ connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
+ foreach (StiebelEltronModbusTcpConnection *connection, m_connections) {
+ if (connection->connected()) {
+ connection->update();
+ }
+ }
+ });
+
+ m_pluginTimer->start();
+ }
+ }
+}
+
+void IntegrationPluginStiebelEltron::thingRemoved(Thing *thing) {
+ if (thing->thingClassId() == stiebelEltronThingClassId && m_connections.contains(thing)) {
+ m_connections.take(thing)->deleteLater();
+ }
+
+ if (myThings().isEmpty() && m_pluginTimer) {
+ hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
+ m_pluginTimer = nullptr;
+ }
+}
+
+void IntegrationPluginStiebelEltron::executeAction(ThingActionInfo *info) {
+ Thing *thing = info->thing();
+ StiebelEltronModbusTcpConnection *connection = m_connections.value(thing);
+
+ if (!connection->connected()) {
+ qCWarning(dcStiebelEltron()) << "Could not execute action. The modbus connection is currently "
+ "not available.";
+ info->finish(Thing::ThingErrorHardwareNotAvailable);
+ return;
+ }
+
+ // Got this from StiebelEltron plugin, not sure if necessary
+ if (thing->thingClassId() != stiebelEltronThingClassId) {
+ info->finish(Thing::ThingErrorNoError);
+ }
+
+ if (info->action().actionTypeId() == stiebelEltronSgReadyActiveActionTypeId) {
+ bool sgReadyActiveBool =
+ info->action().paramValue(stiebelEltronSgReadyActiveActionSgReadyActiveParamTypeId).toBool();
+ qCDebug(dcStiebelEltron()) << "Execute action" << info->action().actionTypeId().toString()
+ << info->action().params();
+ qCDebug(dcStiebelEltron()) << "Value: " << sgReadyActiveBool;
+
+ QModbusReply *reply = connection->setSgReadyActive(sgReadyActiveBool);
+ if (!reply) {
+ qCWarning(dcStiebelEltron()) << "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, sgReadyActiveBool] {
+ if (reply->error() != QModbusDevice::NoError) {
+ qCWarning(dcStiebelEltron())
+ << "Set SG ready activation finished with error" << reply->errorString();
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ qCDebug(dcStiebelEltron()) << "Execute action finished successfully"
+ << info->action().actionTypeId().toString() << info->action().params();
+ info->thing()->setStateValue(stiebelEltronSgReadyActiveStateTypeId, sgReadyActiveBool);
+ info->finish(Thing::ThingErrorNoError);
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [reply](QModbusDevice::Error error) {
+ qCWarning(dcStiebelEltron())
+ << "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() == stiebelEltronSgReadyModeActionTypeId) {
+ QString sgReadyModeString =
+ info->action().paramValue(stiebelEltronSgReadyModeActionSgReadyModeParamTypeId).toString();
+ qCDebug(dcStiebelEltron()) << "Execute action" << info->action().actionTypeId().toString()
+ << info->action().params();
+ StiebelEltronModbusTcpConnection::SmartGridState sgReadyState;
+ if (sgReadyModeString == "Off") {
+ sgReadyState = StiebelEltronModbusTcpConnection::SmartGridStateModeOne;
+ } else if (sgReadyModeString == "Low") {
+ sgReadyState = StiebelEltronModbusTcpConnection::SmartGridStateModeTwo;
+ } else if (sgReadyModeString == "Standard") {
+ sgReadyState = StiebelEltronModbusTcpConnection::SmartGridStateModeThree;
+ } else if (sgReadyModeString == "High") {
+ sgReadyState = StiebelEltronModbusTcpConnection::SmartGridStateModeFour;
+ } else {
+ qCWarning(dcStiebelEltron())
+ << "Failed to set SG Ready mode. An unknown SG Ready mode was passed: " << sgReadyModeString;
+ info->finish(Thing::ThingErrorHardwareFailure); // TODO better matching error type?
+ return;
+ }
+
+ QModbusReply *reply = connection->setSgReadyState(sgReadyState);
+ if (!reply) {
+ qCWarning(dcStiebelEltron()) << "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(dcStiebelEltron())
+ << "Set SG ready mode finished with error" << reply->errorString();
+ info->finish(Thing::ThingErrorHardwareFailure);
+ return;
+ }
+
+ qCDebug(dcStiebelEltron()) << "Execute action finished successfully"
+ << info->action().actionTypeId().toString() << info->action().params();
+ info->thing()->setStateValue(stiebelEltronSgReadyModeStateTypeId, sgReadyModeString);
+ info->finish(Thing::ThingErrorNoError);
+ });
+
+ connect(reply, &QModbusReply::errorOccurred, this, [reply](QModbusDevice::Error error) {
+ qCWarning(dcStiebelEltron())
+ << "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/stiebeleltron/integrationpluginstiebeleltron.h b/stiebeleltron/integrationpluginstiebeleltron.h
new file mode 100644
index 0000000..260253d
--- /dev/null
+++ b/stiebeleltron/integrationpluginstiebeleltron.h
@@ -0,0 +1,66 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2021, nymea GmbH, Consolinno Energy GmbH, L. Heizinger
+* 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 INTEGRATIONPLUGINSTIEBELELTRON_H
+#define INTEGRATIONPLUGINSTIEBELELTRON_H
+
+#include
+#include
+
+#include "stiebeleltronmodbustcpconnection.h"
+
+class IntegrationPluginStiebelEltron: public IntegrationPlugin
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginstiebeleltron.json")
+ Q_INTERFACES(IntegrationPlugin)
+
+public:
+ explicit IntegrationPluginStiebelEltron();
+
+ 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_connections;
+
+
+};
+
+#endif // INTEGRATIONPLUGINSTIEBELELTRON_H
+
+
diff --git a/stiebeleltron/integrationpluginstiebeleltron.json b/stiebeleltron/integrationpluginstiebeleltron.json
new file mode 100644
index 0000000..299a19a
--- /dev/null
+++ b/stiebeleltron/integrationpluginstiebeleltron.json
@@ -0,0 +1,331 @@
+{
+ "name": "StiebelEltron",
+ "displayName": "Stiebel Eltron",
+ "id": "956c848b-b538-4b8f-8cdb-7bbecfc9d361",
+ "vendors": [
+ {
+ "name": "stiebelEltron",
+ "displayName": "Stiebel Eltron",
+ "id": "c8607f85-a81e-40e0-bc95-1b7199cd2d99",
+ "thingClasses": [
+ {
+ "name": "stiebelEltron",
+ "displayName": "Stiebel Eltron Heatpump",
+ "id": "e02ecf61-7d28-43c2-b87e-e7e98a48fbfd",
+ "createMethods": ["discovery", "user"],
+ "interfaces": ["smartgridheatpump", "connectable"],
+ "paramTypes": [
+ {
+ "id": "47d221fa-f6d2-400e-b80f-bb90abccb72c",
+ "name": "ipAddress",
+ "displayName": "IP address",
+ "type": "QString",
+ "inputType": "IPv4Address",
+ "defaultValue": "127.0.0.1"
+ },
+ {
+ "id": "05cd59b8-3068-460f-b0d2-6d49f27458df",
+ "name":"macAddress",
+ "displayName": "MAC address",
+ "type": "QString",
+ "inputType": "MacAddress",
+ "defaultValue": ""
+ },
+ {
+ "id": "6842321f-1f1a-47e2-b12d-59ee322eb8a6",
+ "name":"port",
+ "displayName": "Port",
+ "type": "int",
+ "defaultValue": 502
+ },
+ {
+ "id": "732de6da-bd0a-4215-b320-602117ebc75c",
+ "name":"slaveId",
+ "displayName": "Modbus slave ID",
+ "type": "int",
+ "defaultValue": 1
+ }
+ ],
+ "stateTypes": [
+ {
+ "id": "8d952a5e-87bd-492e-a213-277948521652",
+ "name": "connected",
+ "displayName": "Connected",
+ "displayNameEvent": "Connected changed",
+ "type": "bool",
+ "defaultValue": false,
+ "cached": false
+ },
+ {
+ "id": "1ec958c8-7bf1-469e-b35e-b71fa2099e91",
+ "name": "flowTemperature",
+ "displayName": "Flow temperature",
+ "displayNameEvent": "Flow temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "ce25e3fd-6544-40e9-bd39-032306553e32",
+ "name": "returnTemperature",
+ "displayName": "Return temperature",
+ "displayNameEvent": "Return temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+
+ {
+ "id": "e86cbac5-c2c3-4fcf-8caa-dbfc0df2584d",
+ "name": "outdoorTemperature",
+ "displayName": "Outdoor temperature",
+ "displayNameEvent": "Outdoor temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "27c56897-75f1-45af-9a14-b0620053d2d2",
+ "name": "hotWaterTemperature",
+ "displayName": "Hot water temperature",
+ "displayNameEvent": "Hot water changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "43dd25b3-8782-4faa-a9e0-2fb10892fa0c",
+ "name": "storageTankTemperature",
+ "displayName": "Storage tank temperature",
+ "displayNameEvent": "Storage tank temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "d0597f21-2c0e-4db6-92e0-4a3b66474f87",
+ "name": "heatingEnergy",
+ "displayName": "Heating energy",
+ "displayNameEvent": "Heating energy changed",
+ "unit": "KiloWattHour",
+ "type": "uint",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "9761060e-f364-466e-8661-d28f01b862fc",
+ "name": "hotWaterEnergy",
+ "displayName": "Hot water energy",
+ "displayNameEvent": "Hot water energy changed",
+ "unit": "KiloWattHour",
+ "type": "uint",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "11f91606-d550-4918-9fca-69e3303389c8",
+ "name": "consumedEnergyHotWater",
+ "displayName": "Consumed energy hot water",
+ "displayNameEvent": "Consumed energy hot water changed",
+ "unit": "KiloWattHour",
+ "type": "uint",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "6816dfef-3f54-4bf1-b0d5-641f06785991",
+ "name": "consumedEnergyHeating",
+ "displayName": "Consumed energy heating",
+ "displayNameEvent": "Consumed energy heating changed",
+ "unit": "KiloWattHour",
+ "type": "uint",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "932cc41e-53ae-48ae-baa2-6f385f5aa791",
+ "name": "operatingMode",
+ "displayName": "Operating mode",
+ "displayNameEvent": "Operating mode changed",
+ "displayNameAction": "Set operating mode",
+ "type": "QString",
+ "possibleValues": [
+ "Emergency",
+ "Standby",
+ "Program",
+ "Comfort",
+ "Eco",
+ "Hot water"
+ ],
+ "writable": false,
+ "defaultValue": "Standby",
+ "suggestLogging": true
+ },
+ {
+ "id": "0ad36f3e-96ff-49d0-8b12-b8c6fed1bf4b",
+ "name": "pumpOne",
+ "displayName": "Pump 1",
+ "displayNameEvent": "Pump 1 status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "1c211fb2-da78-41ad-b7d0-e404141a3dd5",
+ "name": "pumpTwo",
+ "displayName": "Pump 2",
+ "displayNameEvent": "Pump 2 status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "ad0b8df8-1eaa-409d-b5e2-a76d7c17c2b9",
+ "name": "heatingUp",
+ "displayName": "Heating up",
+ "displayNameEvent": "Heating up status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "44d5f18b-0389-4a7d-9cb8-f760ce06814e",
+ "name": "auxHeating",
+ "displayName": "Electric auxiliary heating",
+ "displayNameEvent": "Electric auxiliary heating status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "3e44e580-f515-47ae-984b-109b507a5db2",
+ "name": "heating",
+ "displayName": "Heating mode",
+ "displayNameEvent": "Heating mode status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "b6338cdb-863e-4191-adc4-bc6da5a67351",
+ "name": "hotWater",
+ "displayName": "Hot water mode",
+ "displayNameEvent": "Hot water mode status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "c957cef8-b3a7-4626-ab95-db5439fbdf7f",
+ "name": "compressor",
+ "displayName": "Compressor",
+ "displayNameEvent": "Compressor status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "7a287cfb-9088-4aad-a991-3e43714dc64e",
+ "name": "summerMode",
+ "displayName": "Summer mode",
+ "displayNameEvent": "Sommer mode status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "1bfd99ee-1477-4f70-8717-a3a2930b137f",
+ "name": "coolingMode",
+ "displayName": "Cooling mode",
+ "displayNameEvent": "Cooling mode status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "5c47d9bb-66de-48aa-b90e-caa3ca8d44a5",
+ "name": "defrosting",
+ "displayName": "Defrosting mode",
+ "displayNameEvent": "Defrosting mode status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "047fcb7d-9080-4b45-9a6e-5060fa43f7c2",
+ "name": "silentMode",
+ "displayName": "Silent mode",
+ "displayNameEvent": "Silent mode status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "d77a30d9-98f7-40ec-bc55-77c547f24145",
+ "name": "silentMode2",
+ "displayName": "Silent mode 2 (Off)",
+ "displayNameEvent": "Silent mode 2 status changed",
+ "type": "bool",
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "798458bb-d38e-4028-880a-6dcba409a2f5",
+ "name": "sgReadyActive",
+ "displayName": "SG Ready enabled",
+ "displayNameEvent": "SG Ready activation changed",
+ "displayNameAction": "Switch SG Ready on/off",
+ "type": "bool",
+ "writable": true,
+ "defaultValue": false,
+ "suggestLogging": true
+ },
+ {
+ "id": "7d474fb5-aa37-4f21-8166-b20f5bf84fb4",
+ "name": "sgReadyMode",
+ "displayName": "SG Ready mode",
+ "displayNameEvent": "SG Ready mode changed",
+ "displayNameAction": "Set SG Ready mode",
+ "type": "QString",
+ "possibleValues": [
+ "Off",
+ "Low",
+ "Standard",
+ "High"
+ ],
+ "writable": true,
+ "defaultValue": "Standard",
+ "suggestLogging": true
+ },
+ {
+ "id": "5833ceb6-5e7c-437b-a44a-e9f5eb42b6ac",
+ "name": "sourceTemperature",
+ "displayName": "Source temperature (tbd)",
+ "displayNameEvent": "Source temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ },
+ {
+ "id": "d1959819-9e56-47f7-b619-a393ce50738a",
+ "name": "roomTemperature1",
+ "displayName": "Room temperature (tbd)",
+ "displayNameEvent": "Room temperature changed",
+ "unit": "DegreeCelsius",
+ "type": "double",
+ "defaultValue": 0,
+ "suggestLogging": true
+ }
+ ],
+ "actionTypes": [ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/stiebeleltron/meta.json b/stiebeleltron/meta.json
new file mode 100644
index 0000000..80add71
--- /dev/null
+++ b/stiebeleltron/meta.json
@@ -0,0 +1,14 @@
+{
+ "title": "Stiebel Eltron",
+ "tagline": "Integrate Stiebel Eltron heat pumps into nymea.",
+ "icon": "stiebel-eltron.png",
+ "stability": "community",
+ "offline": true,
+ "technologies": [
+ "network",
+ "modbus"
+ ],
+ "categories": [
+ "heating"
+ ]
+}
diff --git a/stiebeleltron/stiebel-eltron-registers.json b/stiebeleltron/stiebel-eltron-registers.json
new file mode 100644
index 0000000..771e95b
--- /dev/null
+++ b/stiebeleltron/stiebel-eltron-registers.json
@@ -0,0 +1,325 @@
+{
+ "className": "StiebelEltron",
+ "protocol": "TCP",
+ "endianness": "BigEndian",
+ "enums": [
+ {
+ "name": "OperatingMode",
+ "values": [
+ {
+ "key": "Emergency",
+ "value": 0
+ },
+ {
+ "key": "Standby",
+ "value": 1
+ },
+ {
+ "key": "Program",
+ "value": 2
+ },
+ {
+ "key": "Comfort",
+ "value": 3
+ },
+ {
+ "key": "Eco",
+ "value": 4
+ },
+ {
+ "key": "HotWater",
+ "value": 5
+ }
+ ]
+ },
+ {
+ "name": "SmartGridState",
+ "values": [
+ {
+ "key": "ModeOne",
+ "value": 1,
+ "comment": "0x00000001"
+ },
+ {
+ "key": "ModeTwo",
+ "value": 0,
+ "comment": "0x00000000"
+ },
+ {
+ "key": "ModeThree",
+ "value": 65536,
+ "comment": "0x00010000"
+ },
+ {
+ "key": "ModeFour",
+ "value": 65537,
+ "comment": "0x00010001"
+ }
+ ]
+ }
+ ],
+ "registers": [
+ {
+ "id": "outdoorTemperature",
+ "address": 506,
+ "size": 1,
+ "type": "int16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Outdoor temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": 0,
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "flowTemperature",
+ "address": 514,
+ "size": 1,
+ "type": "int16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Flow temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": 0,
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "hotWaterTemperature",
+ "address": 521,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Hot water temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "hotGasTemperature1",
+ "address": 543,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Hot gas temperature HP 1",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "hotGasTemperature2",
+ "address": 550,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Hot gas temperature HP 2",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "SourceTemperature",
+ "address": 562,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Source temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "roomTemperatureFEK",
+ "address": 502,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Room temperature FEK",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "returnTemperature",
+ "address": 515,
+ "size": 1,
+ "type": "int16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Return temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": 0,
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "solarCollectorTemperature",
+ "address": 527,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Solar collector temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "solarStorageTankTemperature",
+ "address": 528,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Solar storage tank temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "storageTankTemperature",
+ "address": 517,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Storage tank temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "externalHeatSourceTemperature",
+ "address": 530,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "External heat source temperature",
+ "staticScaleFactor": -1,
+ "defaultValue": "0",
+ "unit": "°C",
+ "access": "RO"
+ },
+ {
+ "id": "heatingEnergy",
+ "address": 3501,
+ "size": 2,
+ "type": "uint32",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "defaultValue": "0",
+ "unit": "kWh",
+ "description": "Heating energy",
+ "access": "RO"
+ },
+ {
+ "id": "hotWaterEnergy",
+ "address": 3504,
+ "size": 2,
+ "type": "uint32",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "defaultValue": "0",
+ "unit": "kWh",
+ "description": "Hot water energy",
+ "access": "RO"
+ },
+ {
+ "id": "consumedEnergyHeating",
+ "address": 3511,
+ "size": 2,
+ "type": "uint32",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "defaultValue": "0",
+ "unit": "kWh",
+ "description": "Consumed energy heating",
+ "access": "RO"
+ },
+ {
+ "id": "consumedEnergyHotWater",
+ "address": 3514,
+ "size": 2,
+ "type": "uint32",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "defaultValue": "0",
+ "unit": "kWh",
+ "description": "Consumed energy hot water",
+ "access": "RO"
+ },
+ {
+ "id": "operatingMode",
+ "address": 1500,
+ "size": 1,
+ "type": "uint16",
+ "enum": "OperatingMode",
+ "registerType": "holdingRegister",
+ "readSchedule": "update",
+ "description": "Operating mode",
+ "defaultValue": "OperatingModeStandby",
+ "access": "RO"
+ },
+ {
+ "id": "systemStatus",
+ "address": 2500,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "System status",
+ "defaultValue": 0,
+ "access": "RO"
+ },
+ {
+ "id": "sgReadyStateRO",
+ "address": 5000,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "inputRegister",
+ "readSchedule": "update",
+ "description": "Smart grid status",
+ "defaultValue": 3,
+ "access": "RO"
+ },
+ {
+ "id": "sgReadyActive",
+ "address": 4000,
+ "size": 1,
+ "type": "uint16",
+ "registerType": "holdingRegister",
+ "readSchedule": "update",
+ "description": "SG ready active",
+ "defaultValue": 0,
+ "access": "RW"
+ },
+ {
+ "id": "sgReadyState",
+ "address": 4001,
+ "size": 2,
+ "type": "uint32",
+ "registerType": "holdingRegister",
+ "enum": "SmartGridState",
+ "readSchedule": "update",
+ "description": "SG Ready mode",
+ "defaultValue": "SmartGridStateModeThree",
+ "access": "RW"
+ }
+ ],
+ "blocks": [ ]
+}
diff --git a/stiebeleltron/stiebel-eltron.png b/stiebeleltron/stiebel-eltron.png
new file mode 100644
index 0000000..2dfbe5c
Binary files /dev/null and b/stiebeleltron/stiebel-eltron.png differ
diff --git a/stiebeleltron/stiebeleltron.pro b/stiebeleltron/stiebeleltron.pro
new file mode 100644
index 0000000..95e34d7
--- /dev/null
+++ b/stiebeleltron/stiebeleltron.pro
@@ -0,0 +1,13 @@
+include(../plugins.pri)
+
+# Generate modbus connection
+MODBUS_CONNECTIONS += stiebel-eltron-registers.json
+#MODBUS_TOOLS_CONFIG += VERBOSE
+include(../modbus.pri)
+
+HEADERS += \
+ integrationpluginstiebeleltron.h
+
+SOURCES += \
+ integrationpluginstiebeleltron.cpp
+
diff --git a/stiebeleltron/translations/956c848b-b538-4b8f-8cdb-7bbecfc9d361-en_US.ts b/stiebeleltron/translations/956c848b-b538-4b8f-8cdb-7bbecfc9d361-en_US.ts
new file mode 100644
index 0000000..a2d2764
--- /dev/null
+++ b/stiebeleltron/translations/956c848b-b538-4b8f-8cdb-7bbecfc9d361-en_US.ts
@@ -0,0 +1,477 @@
+
+
+
+
+ IntegrationPluginStiebelEltron
+
+
+ The network device discovery is not available.
+
+
+
+
+ StiebelEltron
+
+
+
+ Compressor
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: compressor, ID: {c957cef8-b3a7-4626-ab95-db5439fbdf7f})
+----------
+The name of the StateType ({c957cef8-b3a7-4626-ab95-db5439fbdf7f}) of ThingClass stiebelEltron
+
+
+
+
+ Compressor status changed
+ The name of the EventType ({c957cef8-b3a7-4626-ab95-db5439fbdf7f}) of ThingClass stiebelEltron
+
+
+
+
+
+ Connected
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: connected, ID: {8d952a5e-87bd-492e-a213-277948521652})
+----------
+The name of the StateType ({8d952a5e-87bd-492e-a213-277948521652}) of ThingClass stiebelEltron
+
+
+
+
+ Connected changed
+ The name of the EventType ({8d952a5e-87bd-492e-a213-277948521652}) of ThingClass stiebelEltron
+
+
+
+
+
+ Consumed energy heating
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: consumedEnergyHeating, ID: {6816dfef-3f54-4bf1-b0d5-641f06785991})
+----------
+The name of the StateType ({6816dfef-3f54-4bf1-b0d5-641f06785991}) of ThingClass stiebelEltron
+
+
+
+
+ Consumed energy heating changed
+ The name of the EventType ({6816dfef-3f54-4bf1-b0d5-641f06785991}) of ThingClass stiebelEltron
+
+
+
+
+
+ Consumed energy hot water
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: consumedEnergyHotWater, ID: {11f91606-d550-4918-9fca-69e3303389c8})
+----------
+The name of the StateType ({11f91606-d550-4918-9fca-69e3303389c8}) of ThingClass stiebelEltron
+
+
+
+
+ Consumed energy hot water changed
+ The name of the EventType ({11f91606-d550-4918-9fca-69e3303389c8}) of ThingClass stiebelEltron
+
+
+
+
+
+ Cooling mode
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: coolingMode, ID: {1bfd99ee-1477-4f70-8717-a3a2930b137f})
+----------
+The name of the StateType ({1bfd99ee-1477-4f70-8717-a3a2930b137f}) of ThingClass stiebelEltron
+
+
+
+
+ Cooling mode status changed
+ The name of the EventType ({1bfd99ee-1477-4f70-8717-a3a2930b137f}) of ThingClass stiebelEltron
+
+
+
+
+
+ Defrosting mode
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: defrosting, ID: {5c47d9bb-66de-48aa-b90e-caa3ca8d44a5})
+----------
+The name of the StateType ({5c47d9bb-66de-48aa-b90e-caa3ca8d44a5}) of ThingClass stiebelEltron
+
+
+
+
+ Defrosting mode status changed
+ The name of the EventType ({5c47d9bb-66de-48aa-b90e-caa3ca8d44a5}) of ThingClass stiebelEltron
+
+
+
+
+
+ Electric auxiliary heating
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: auxHeating, ID: {44d5f18b-0389-4a7d-9cb8-f760ce06814e})
+----------
+The name of the StateType ({44d5f18b-0389-4a7d-9cb8-f760ce06814e}) of ThingClass stiebelEltron
+
+
+
+
+ Electric auxiliary heating status changed
+ The name of the EventType ({44d5f18b-0389-4a7d-9cb8-f760ce06814e}) of ThingClass stiebelEltron
+
+
+
+
+
+ Flow temperature
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: flowTemperature, ID: {1ec958c8-7bf1-469e-b35e-b71fa2099e91})
+----------
+The name of the StateType ({1ec958c8-7bf1-469e-b35e-b71fa2099e91}) of ThingClass stiebelEltron
+
+
+
+
+ Flow temperature changed
+ The name of the EventType ({1ec958c8-7bf1-469e-b35e-b71fa2099e91}) of ThingClass stiebelEltron
+
+
+
+
+
+ Heating energy
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: heatingEnergy, ID: {d0597f21-2c0e-4db6-92e0-4a3b66474f87})
+----------
+The name of the StateType ({d0597f21-2c0e-4db6-92e0-4a3b66474f87}) of ThingClass stiebelEltron
+
+
+
+
+ Heating energy changed
+ The name of the EventType ({d0597f21-2c0e-4db6-92e0-4a3b66474f87}) of ThingClass stiebelEltron
+
+
+
+
+
+ Heating mode
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: heating, ID: {3e44e580-f515-47ae-984b-109b507a5db2})
+----------
+The name of the StateType ({3e44e580-f515-47ae-984b-109b507a5db2}) of ThingClass stiebelEltron
+
+
+
+
+ Heating mode status changed
+ The name of the EventType ({3e44e580-f515-47ae-984b-109b507a5db2}) of ThingClass stiebelEltron
+
+
+
+
+
+ Heating up
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: heatingUp, ID: {ad0b8df8-1eaa-409d-b5e2-a76d7c17c2b9})
+----------
+The name of the StateType ({ad0b8df8-1eaa-409d-b5e2-a76d7c17c2b9}) of ThingClass stiebelEltron
+
+
+
+
+ Heating up status changed
+ The name of the EventType ({ad0b8df8-1eaa-409d-b5e2-a76d7c17c2b9}) of ThingClass stiebelEltron
+
+
+
+
+ Hot water changed
+ The name of the EventType ({27c56897-75f1-45af-9a14-b0620053d2d2}) of ThingClass stiebelEltron
+
+
+
+
+
+ Hot water energy
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: hotWaterEnergy, ID: {9761060e-f364-466e-8661-d28f01b862fc})
+----------
+The name of the StateType ({9761060e-f364-466e-8661-d28f01b862fc}) of ThingClass stiebelEltron
+
+
+
+
+ Hot water energy changed
+ The name of the EventType ({9761060e-f364-466e-8661-d28f01b862fc}) of ThingClass stiebelEltron
+
+
+
+
+
+ Hot water mode
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: hotWater, ID: {b6338cdb-863e-4191-adc4-bc6da5a67351})
+----------
+The name of the StateType ({b6338cdb-863e-4191-adc4-bc6da5a67351}) of ThingClass stiebelEltron
+
+
+
+
+ Hot water mode status changed
+ The name of the EventType ({b6338cdb-863e-4191-adc4-bc6da5a67351}) of ThingClass stiebelEltron
+
+
+
+
+
+ Hot water temperature
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: hotWaterTemperature, ID: {27c56897-75f1-45af-9a14-b0620053d2d2})
+----------
+The name of the StateType ({27c56897-75f1-45af-9a14-b0620053d2d2}) of ThingClass stiebelEltron
+
+
+
+
+ IP address
+ The name of the ParamType (ThingClass: stiebelEltron, Type: thing, ID: {47d221fa-f6d2-400e-b80f-bb90abccb72c})
+
+
+
+
+ MAC address
+ The name of the ParamType (ThingClass: stiebelEltron, Type: thing, ID: {05cd59b8-3068-460f-b0d2-6d49f27458df})
+
+
+
+
+ Modbus slave ID
+ The name of the ParamType (ThingClass: stiebelEltron, Type: thing, ID: {732de6da-bd0a-4215-b320-602117ebc75c})
+
+
+
+
+
+ Operating mode
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: operatingMode, ID: {932cc41e-53ae-48ae-baa2-6f385f5aa791})
+----------
+The name of the StateType ({932cc41e-53ae-48ae-baa2-6f385f5aa791}) of ThingClass stiebelEltron
+
+
+
+
+ Operating mode changed
+ The name of the EventType ({932cc41e-53ae-48ae-baa2-6f385f5aa791}) of ThingClass stiebelEltron
+
+
+
+
+
+ Outdoor temperature
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: outdoorTemperature, ID: {e86cbac5-c2c3-4fcf-8caa-dbfc0df2584d})
+----------
+The name of the StateType ({e86cbac5-c2c3-4fcf-8caa-dbfc0df2584d}) of ThingClass stiebelEltron
+
+
+
+
+ Outdoor temperature changed
+ The name of the EventType ({e86cbac5-c2c3-4fcf-8caa-dbfc0df2584d}) of ThingClass stiebelEltron
+
+
+
+
+ Port
+ The name of the ParamType (ThingClass: stiebelEltron, Type: thing, ID: {6842321f-1f1a-47e2-b12d-59ee322eb8a6})
+
+
+
+
+
+ Pump 1
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: pumpOne, ID: {0ad36f3e-96ff-49d0-8b12-b8c6fed1bf4b})
+----------
+The name of the StateType ({0ad36f3e-96ff-49d0-8b12-b8c6fed1bf4b}) of ThingClass stiebelEltron
+
+
+
+
+ Pump 1 status changed
+ The name of the EventType ({0ad36f3e-96ff-49d0-8b12-b8c6fed1bf4b}) of ThingClass stiebelEltron
+
+
+
+
+
+ Pump 2
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: pumpTwo, ID: {1c211fb2-da78-41ad-b7d0-e404141a3dd5})
+----------
+The name of the StateType ({1c211fb2-da78-41ad-b7d0-e404141a3dd5}) of ThingClass stiebelEltron
+
+
+
+
+ Pump 2 status changed
+ The name of the EventType ({1c211fb2-da78-41ad-b7d0-e404141a3dd5}) of ThingClass stiebelEltron
+
+
+
+
+
+ Return temperature
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: returnTemperature, ID: {ce25e3fd-6544-40e9-bd39-032306553e32})
+----------
+The name of the StateType ({ce25e3fd-6544-40e9-bd39-032306553e32}) of ThingClass stiebelEltron
+
+
+
+
+ Return temperature changed
+ The name of the EventType ({ce25e3fd-6544-40e9-bd39-032306553e32}) of ThingClass stiebelEltron
+
+
+
+
+
+ Room temperature (tbd)
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: roomTemperature1, ID: {d1959819-9e56-47f7-b619-a393ce50738a})
+----------
+The name of the StateType ({d1959819-9e56-47f7-b619-a393ce50738a}) of ThingClass stiebelEltron
+
+
+
+
+ Room temperature changed
+ The name of the EventType ({d1959819-9e56-47f7-b619-a393ce50738a}) of ThingClass stiebelEltron
+
+
+
+
+ SG Ready activation changed
+ The name of the EventType ({798458bb-d38e-4028-880a-6dcba409a2f5}) of ThingClass stiebelEltron
+
+
+
+
+
+
+ SG Ready enabled
+ The name of the ParamType (ThingClass: stiebelEltron, ActionType: sgReadyActive, ID: {798458bb-d38e-4028-880a-6dcba409a2f5})
+----------
+The name of the ParamType (ThingClass: stiebelEltron, EventType: sgReadyActive, ID: {798458bb-d38e-4028-880a-6dcba409a2f5})
+----------
+The name of the StateType ({798458bb-d38e-4028-880a-6dcba409a2f5}) of ThingClass stiebelEltron
+
+
+
+
+
+
+ SG Ready mode
+ The name of the ParamType (ThingClass: stiebelEltron, ActionType: sgReadyMode, ID: {7d474fb5-aa37-4f21-8166-b20f5bf84fb4})
+----------
+The name of the ParamType (ThingClass: stiebelEltron, EventType: sgReadyMode, ID: {7d474fb5-aa37-4f21-8166-b20f5bf84fb4})
+----------
+The name of the StateType ({7d474fb5-aa37-4f21-8166-b20f5bf84fb4}) of ThingClass stiebelEltron
+
+
+
+
+ SG Ready mode changed
+ The name of the EventType ({7d474fb5-aa37-4f21-8166-b20f5bf84fb4}) of ThingClass stiebelEltron
+
+
+
+
+ Set SG Ready mode
+ The name of the ActionType ({7d474fb5-aa37-4f21-8166-b20f5bf84fb4}) of ThingClass stiebelEltron
+
+
+
+
+
+ Silent mode
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: silentMode, ID: {047fcb7d-9080-4b45-9a6e-5060fa43f7c2})
+----------
+The name of the StateType ({047fcb7d-9080-4b45-9a6e-5060fa43f7c2}) of ThingClass stiebelEltron
+
+
+
+
+
+ Silent mode 2 (Off)
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: silentMode2, ID: {d77a30d9-98f7-40ec-bc55-77c547f24145})
+----------
+The name of the StateType ({d77a30d9-98f7-40ec-bc55-77c547f24145}) of ThingClass stiebelEltron
+
+
+
+
+ Silent mode 2 status changed
+ The name of the EventType ({d77a30d9-98f7-40ec-bc55-77c547f24145}) of ThingClass stiebelEltron
+
+
+
+
+ Silent mode status changed
+ The name of the EventType ({047fcb7d-9080-4b45-9a6e-5060fa43f7c2}) of ThingClass stiebelEltron
+
+
+
+
+ Sommer mode status changed
+ The name of the EventType ({7a287cfb-9088-4aad-a991-3e43714dc64e}) of ThingClass stiebelEltron
+
+
+
+
+
+ Source temperature (tbd)
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: sourceTemperature, ID: {5833ceb6-5e7c-437b-a44a-e9f5eb42b6ac})
+----------
+The name of the StateType ({5833ceb6-5e7c-437b-a44a-e9f5eb42b6ac}) of ThingClass stiebelEltron
+
+
+
+
+ Source temperature changed
+ The name of the EventType ({5833ceb6-5e7c-437b-a44a-e9f5eb42b6ac}) of ThingClass stiebelEltron
+
+
+
+
+
+ Stiebel Eltron
+ The name of the vendor ({c8607f85-a81e-40e0-bc95-1b7199cd2d99})
+----------
+The name of the plugin StiebelEltron ({956c848b-b538-4b8f-8cdb-7bbecfc9d361})
+
+
+
+
+ Stiebel Eltron Heatpump
+ The name of the ThingClass ({e02ecf61-7d28-43c2-b87e-e7e98a48fbfd})
+
+
+
+
+
+ Storage tank temperature
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: storageTankTemperature, ID: {43dd25b3-8782-4faa-a9e0-2fb10892fa0c})
+----------
+The name of the StateType ({43dd25b3-8782-4faa-a9e0-2fb10892fa0c}) of ThingClass stiebelEltron
+
+
+
+
+ Storage tank temperature changed
+ The name of the EventType ({43dd25b3-8782-4faa-a9e0-2fb10892fa0c}) of ThingClass stiebelEltron
+
+
+
+
+
+ Summer mode
+ The name of the ParamType (ThingClass: stiebelEltron, EventType: summerMode, ID: {7a287cfb-9088-4aad-a991-3e43714dc64e})
+----------
+The name of the StateType ({7a287cfb-9088-4aad-a991-3e43714dc64e}) of ThingClass stiebelEltron
+
+
+
+
+ Switch SG Ready on/off
+ The name of the ActionType ({798458bb-d38e-4028-880a-6dcba409a2f5}) of ThingClass stiebelEltron
+
+
+
+
diff --git a/sunspec/integrationpluginsunspec.cpp b/sunspec/integrationpluginsunspec.cpp
index 16b14b5..c4ad08d 100644
--- a/sunspec/integrationpluginsunspec.cpp
+++ b/sunspec/integrationpluginsunspec.cpp
@@ -28,9 +28,10 @@
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#include "plugininfo.h"
#include "integrationpluginsunspec.h"
-#include "network/networkdevicediscovery.h"
+#include "plugininfo.h"
+
+#include
#include
#include
diff --git a/sunspec/integrationpluginsunspec.h b/sunspec/integrationpluginsunspec.h
index f057d19..d4a5a40 100644
--- a/sunspec/integrationpluginsunspec.h
+++ b/sunspec/integrationpluginsunspec.h
@@ -31,8 +31,8 @@
#ifndef INTEGRATIONPLUGINSUNSPEC_H
#define INTEGRATIONPLUGINSUNSPEC_H
-#include "integrations/integrationplugin.h"
-#include "plugintimer.h"
+#include
+#include
#include
#include
diff --git a/sunspec/sunspecthing.h b/sunspec/sunspecthing.h
index 211d522..ea22466 100644
--- a/sunspec/sunspecthing.h
+++ b/sunspec/sunspecthing.h
@@ -34,7 +34,8 @@
#include
#include "extern-plugininfo.h"
-#include "integrations/integrationplugin.h"
+
+#include
#include
#include
diff --git a/wallbe/integrationpluginwallbe.cpp b/wallbe/integrationpluginwallbe.cpp
index b95c67c..907aecd 100644
--- a/wallbe/integrationpluginwallbe.cpp
+++ b/wallbe/integrationpluginwallbe.cpp
@@ -30,8 +30,9 @@
#include "integrationpluginwallbe.h"
#include "plugininfo.h"
-#include "network/networkdevicediscovery.h"
-#include "types/param.h"
+
+#include
+#include
#include
#include
diff --git a/wallbe/integrationpluginwallbe.h b/wallbe/integrationpluginwallbe.h
index 4d3f545..2b24819 100644
--- a/wallbe/integrationpluginwallbe.h
+++ b/wallbe/integrationpluginwallbe.h
@@ -31,10 +31,10 @@
#ifndef INTEGRATIONPLUGINWALLBE_H
#define INTEGRATIONPLUGINWALLBE_H
-#include "integrations/integrationplugin.h"
-#include "plugintimer.h"
+#include
+#include
-#include "../modbus/modbustcpmaster.h"
+#include