Merge PR #42: EnergyMeters: Refactor using modbus tools

pull/48/head
Jenkins nymea 2021-12-13 00:48:12 +01:00
commit 47698bcc16
21 changed files with 3822 additions and 1477 deletions

View File

@ -2,14 +2,20 @@
Connect Modbus RTU based energy meters.
## Supported Things
Once you configured in the system settings a Modbus RTU resource using the configured settings of your meter, you can start adding the energy meter to your system.
While discovering, nymea will offer you the configured modbus resources as possible connections.
## Supported things
* b+g e-tech
* SDM630Modbus
* inepro Metering
* PRO380-Mod
## Requirements
* The plugin 'nymea-plugin-energymeter' must be installed.
* The plugin 'nymea-plugin-energymeters' must be installed.
* At least one Modbus RTU interface must be setup.

View File

@ -1,50 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 BGETECHMODBUSREGISTER_H
#define BGETECHMODBUSREGISTER_H
#include "registerdescriptor.h"
static const QHash<ModbusRegisterType, ModbusRegisterDescriptor> sdm630RegisterMap {
{ModbusRegisterType::VoltageL1, ModbusRegisterDescriptor(0x00, 4, 2, "V", "float")},
{ModbusRegisterType::VoltageL2, ModbusRegisterDescriptor(0x02, 4, 2, "V", "float")},
{ModbusRegisterType::VoltageL3, ModbusRegisterDescriptor(0x04, 4, 2, "V", "float")},
{ModbusRegisterType::CurrentL1, ModbusRegisterDescriptor(0x06, 4, 2, "A", "float")},
{ModbusRegisterType::CurrentL2, ModbusRegisterDescriptor(0x08, 4, 2, "A", "float")},
{ModbusRegisterType::CurrentL3, ModbusRegisterDescriptor(0x0A, 4, 2, "A", "float")},
{ModbusRegisterType::ActivePower, ModbusRegisterDescriptor(0x34, 4, 2, "W", "float")}, //Total system power
{ModbusRegisterType::Frequency, ModbusRegisterDescriptor(0x46, 4, 2, "Hz", "float")},
{ModbusRegisterType::PowerFactor, ModbusRegisterDescriptor(0x3E, 4, 2, "", "float")}, //Total system power factor
{ModbusRegisterType::EnergyConsumed, ModbusRegisterDescriptor(0x48, 4, 2, "kWh", "float")}, //Total Import kWh
{ModbusRegisterType::EnergyProduced, ModbusRegisterDescriptor(0x4A, 4, 2, "kWh", "float")} //Total Export kWh
};
#endif // BGETECHMODBUSREGISTER_H

View File

@ -1,231 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 "energymeter.h"
#include "hardware/modbus/modbusrtureply.h"
#include "extern-plugininfo.h"
EnergyMeter::EnergyMeter(ModbusRtuMaster *modbusMaster, int slaveAddress, const QHash<ModbusRegisterType, ModbusRegisterDescriptor> &modbusRegisters, QObject *parent) :
QObject(parent),
m_modbusRtuMaster(modbusMaster),
m_slaveAddress(slaveAddress),
m_modbusRegisters(modbusRegisters)
{
qCDebug(dcEnergyMeters()) << "EnergyMeter: Creating new meter connection, address:" << slaveAddress;
}
ModbusRtuMaster *EnergyMeter::modbusMaster()
{
return m_modbusRtuMaster;
}
void EnergyMeter::setModbusMaster(ModbusRtuMaster *modbusMaster)
{
m_modbusRtuMaster = modbusMaster;
}
bool EnergyMeter::connected() const
{
return m_connected;
}
bool EnergyMeter::getVoltageL1()
{
return getRegister(ModbusRegisterType::VoltageL1);
}
bool EnergyMeter::getVoltageL2()
{
return getRegister(ModbusRegisterType::VoltageL2);
}
bool EnergyMeter::getVoltageL3()
{
return getRegister(ModbusRegisterType::VoltageL3);
}
bool EnergyMeter::getCurrentL1()
{
return getRegister(ModbusRegisterType::CurrentL1);
}
bool EnergyMeter::getCurrentL2()
{
return getRegister(ModbusRegisterType::CurrentL2);
}
bool EnergyMeter::getCurrentL3()
{
return getRegister(ModbusRegisterType::CurrentL3);
}
bool EnergyMeter::getFrequency()
{
return getRegister(ModbusRegisterType::Frequency);
}
bool EnergyMeter::getPowerFactor()
{
return getRegister(ModbusRegisterType::PowerFactor);
}
bool EnergyMeter::getActivePower()
{
return getRegister(ModbusRegisterType::ActivePower);
}
bool EnergyMeter::getEnergyProduced()
{
return getRegister(ModbusRegisterType::EnergyProduced);
}
bool EnergyMeter::getEnergyConsumed()
{
return getRegister(ModbusRegisterType::EnergyConsumed);
}
bool EnergyMeter::getRegister(ModbusRegisterType type)
{
if (!m_modbusRegisters.contains(type)) {
qCWarning(dcEnergyMeters()) << "EnergyMeter: Register type not supported" << type;
setConnectionStatus(false);
return false;
}
if (!m_modbusRtuMaster) {
qCWarning(dcEnergyMeters()) << "EnergyMeter: Modbus RTU interface not available";
setConnectionStatus(false);
return false;
}
if (!m_modbusRtuMaster->connected()) {
qCWarning(dcEnergyMeters()) << "EnergyMeter: Modbus RTU interface not connected";
setConnectionStatus(false);
return false;
}
ModbusRegisterDescriptor descriptor = m_modbusRegisters.value(type);
ModbusRtuReply *reply = nullptr;
if (descriptor.functionCode() == 3){
reply = m_modbusRtuMaster->readHoldingRegister(m_slaveAddress, descriptor.address(), descriptor.length());
} else if (descriptor.functionCode() == 4){
reply = m_modbusRtuMaster->readInputRegister(m_slaveAddress, descriptor.address(), descriptor.length());
}
connect(reply, &ModbusRtuReply::finished, reply, &ModbusRtuReply::deleteLater);
connect(reply, &ModbusRtuReply::finished, this, [reply, type, descriptor, this] {
if (reply->error() != ModbusRtuReply::NoError) {
qCWarning(dcEnergyMeters()) << "EnergyMeter: Modbus RTU reply error" << reply->errorString();
setConnectionStatus(false);
return;
}
modbus_32_t value;
value.u = 0;
if (reply->result().length() == 1) {
value.u = static_cast<float>(reply->result().at(0));
} else if (reply->result().length() == 2) {
if (descriptor.dataType() == "float") {
value.u = static_cast<float>(static_cast<uint32_t>(reply->result().at(0)) << 16 | reply->result().at(1));
} else {
qCWarning(dcEnergyMeters()) << "EnergyMeter: Data type not supported" << descriptor.dataType();
}
} else {
qCWarning(dcEnergyMeters()) << "EnergyMeter: Reply length invalid" << reply->result().length();
setConnectionStatus(false);
return;
}
if (type == ModbusRegisterType::VoltageL1) {
if (descriptor.unit() == "mV")
value.f /= 1000.00;
emit voltageL1Received(value.f);
} else if (type == ModbusRegisterType::VoltageL2) {
if (descriptor.unit() == "mV")
value.f /= 1000.00;
emit voltageL2Received(value.f);
} else if (type == ModbusRegisterType::VoltageL3) {
if (descriptor.unit() == "mV")
value.f /= 1000.00;
emit voltageL3Received(value.f);
} else if (type == ModbusRegisterType::CurrentL1) {
if (descriptor.unit() == "mA")
value.f /= 1000.00;
emit currentL1Received(value.f);
} else if (type == ModbusRegisterType::CurrentL2) {
if (descriptor.unit() == "mA")
value.f /= 1000.00;
emit currentL2Received(value.f);
} else if (type == ModbusRegisterType::CurrentL3) {
if (descriptor.unit() == "mA")
value.f /= 1000.00;
emit currentL3Received(value.f);
} else if (type == ModbusRegisterType::ActivePower) {
if (descriptor.unit() == "kW") {
value.f *= 1000;
} else if (descriptor.unit() == "mW") {
value.f /= 1000.00;
}
emit activePowerReceived(value.f);
} else if (type == ModbusRegisterType::PowerFactor) {
emit powerFactorReceived(value.f);
} else if (type == ModbusRegisterType::Frequency) {
emit frequencyReceived(value.f);
} else if (type == ModbusRegisterType::EnergyConsumed) {
if (descriptor.unit() == "Wh") {
value.f /= 1000.00;
}
emit consumedEnergyReceived(value.f);
} else if (type == ModbusRegisterType::EnergyProduced) {
if (descriptor.unit() == "Wh") {
value.f /= 1000.00;
}
emit producedEnergyReceived(value.f);
} else {
qCWarning(dcEnergyMeters()) << "EnergyMeter: Modbus register type not handled" << type;
}
});
setConnectionStatus(true);
return true;
}
void EnergyMeter::setConnectionStatus(bool connected)
{
if (connected != m_connected) {
m_connected = connected;
emit connectedChanged(m_connected);
}
}

View File

@ -1,95 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 ENERGYMETER_H
#define ENERGYMETER_H
#include <QObject>
#include <QUuid>
#include "registerdescriptor.h"
#include "hardware/modbus/modbusrtumaster.h"
class EnergyMeter : public QObject
{
Q_OBJECT
public:
explicit EnergyMeter(ModbusRtuMaster *modbusMaster, int slaveAddress, const QHash<ModbusRegisterType, ModbusRegisterDescriptor> &modbusRegisters, QObject *parent = nullptr);
ModbusRtuMaster *modbusMaster();
void setModbusMaster(ModbusRtuMaster *modbusMaster);
bool connected() const;
bool getVoltageL1();
bool getVoltageL2();
bool getVoltageL3();
bool getCurrentL1();
bool getCurrentL2();
bool getCurrentL3();
bool getFrequency();
bool getPowerFactor();
bool getActivePower();
bool getEnergyProduced();
bool getEnergyConsumed();
private:
typedef union {
int32_t s;
uint32_t u;
float f;
} modbus_32_t;
bool m_connected = false;
ModbusRtuMaster *m_modbusRtuMaster = nullptr;
int m_slaveAddress;
QHash<ModbusRegisterType, ModbusRegisterDescriptor> m_modbusRegisters;
bool getRegister(ModbusRegisterType type);
void setConnectionStatus(bool connected);
signals:
void connectedChanged(bool connected);
void voltageL1Received(double voltage);
void voltageL2Received(double voltage);
void voltageL3Received(double voltage);
void currentL1Received(double current);
void currentL2Received(double current);
void currentL3Received(double current);
void frequencyReceived(double freqeuncy);
void activePowerReceived(double power);
void powerFactorReceived(double powerFactor);
void producedEnergyReceived(double energy);
void consumedEnergyReceived(double energy);
};
#endif // ENERGYMETER_H

View File

@ -1,16 +1,16 @@
include(../plugins.pri)
QT += \
serialport \
serialbus \
SOURCES += \
energymeter.cpp \
integrationpluginenergymeters.cpp
QT += serialport serialbus
HEADERS += \
energymeter.h \
integrationpluginenergymeters.h \
inepromodbusregister.h \
bg-etechmodbusregister.h \
registerdescriptor.h
sdm630modbusrtuconnection.h \
pro380modbusrtuconnection.h \
../modbus/modbusdatautils.h
SOURCES += \
integrationpluginenergymeters.cpp \
sdm630modbusrtuconnection.cpp \
pro380modbusrtuconnection.cpp \
../modbus/modbusdatautils.cpp

View File

@ -1,49 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 INEPROMODBUSREGISTER_H
#define INEPROMODBUSREGISTER_H
#include "registerdescriptor.h"
static const QHash<ModbusRegisterType, ModbusRegisterDescriptor> pro380RegisterMap {
{ModbusRegisterType::VoltageL1, ModbusRegisterDescriptor(0x5002, 3, 2, "V", "float")}, //L1 Voltage
{ModbusRegisterType::VoltageL2, ModbusRegisterDescriptor(0x5004, 3, 2, "V", "float")}, //L2 Voltage
{ModbusRegisterType::VoltageL3, ModbusRegisterDescriptor(0x5006, 3, 2, "V", "float")}, //L3 Voltage
{ModbusRegisterType::CurrentL1, ModbusRegisterDescriptor(0x500C, 3, 2, "A", "float")}, //L1 Current
{ModbusRegisterType::CurrentL2, ModbusRegisterDescriptor(0x500E, 3, 2, "A", "float")}, //L2 Current
{ModbusRegisterType::CurrentL3, ModbusRegisterDescriptor(0x5010, 3, 2, "A", "float")}, //L3 Current
{ModbusRegisterType::ActivePower, ModbusRegisterDescriptor(0x5012, 3, 2, "kW", "float")}, //Total active power
{ModbusRegisterType::Frequency, ModbusRegisterDescriptor(0x5008, 3, 2, "Hz", "float")},
{ModbusRegisterType::PowerFactor, ModbusRegisterDescriptor(0x502A, 3, 2, "", "float")},
{ModbusRegisterType::EnergyConsumed, ModbusRegisterDescriptor(0x600C, 3, 2, "kWh", "float")}, //Forward active energy
{ModbusRegisterType::EnergyProduced, ModbusRegisterDescriptor(0x6018, 3, 2, "kWh", "float")} //Reverse active energy
};
#endif //INEPROMODBUSREGISTER_H

View File

@ -31,63 +31,19 @@
#include "integrationpluginenergymeters.h"
#include "plugininfo.h"
#include "bg-etechmodbusregister.h"
#include "inepromodbusregister.h"
IntegrationPluginEnergyMeters::IntegrationPluginEnergyMeters()
{
/*
* NOTE:
* To add an new device model, the integrationplugin json file must be extended with the new model and vendor.
* Then add the new states and params to the lists here, also add the modbus register configuration file
*/
m_slaveIdParamTypeIds.insert(pro380ThingClassId, pro380ThingSlaveAddressParamTypeId);
m_slaveIdParamTypeIds.insert(sdm630ThingClassId, sdm630ThingSlaveAddressParamTypeId);
m_modbusUuidParamTypeIds.insert(pro380ThingClassId, pro380ThingModbusMasterUuidParamTypeId);
m_modbusUuidParamTypeIds.insert(sdm630ThingClassId, sdm630ThingModbusMasterUuidParamTypeId);
m_connectionStateTypeIds.insert(pro380ThingClassId, pro380ConnectedStateTypeId);
m_connectionStateTypeIds.insert(sdm630ThingClassId, sdm630ConnectedStateTypeId);
m_voltageL1StateTypeIds.insert(pro380ThingClassId, pro380VoltageL1StateTypeId);
m_voltageL1StateTypeIds.insert(sdm630ThingClassId, sdm630VoltageL1StateTypeId);
m_voltageL2StateTypeIds.insert(pro380ThingClassId, pro380VoltageL2StateTypeId);
m_voltageL2StateTypeIds.insert(sdm630ThingClassId, sdm630VoltageL2StateTypeId);
m_voltageL3StateTypeIds.insert(pro380ThingClassId, pro380VoltageL3StateTypeId);
m_voltageL3StateTypeIds.insert(sdm630ThingClassId, sdm630VoltageL3StateTypeId);
m_currentL1StateTypeIds.insert(pro380ThingClassId, pro380CurrentL1StateTypeId);
m_currentL1StateTypeIds.insert(sdm630ThingClassId, sdm630CurrentL1StateTypeId);
m_currentL2StateTypeIds.insert(pro380ThingClassId, pro380CurrentL2StateTypeId);
m_currentL2StateTypeIds.insert(sdm630ThingClassId, sdm630CurrentL2StateTypeId);
m_currentL3StateTypeIds.insert(pro380ThingClassId, pro380CurrentL3StateTypeId);
m_currentL3StateTypeIds.insert(sdm630ThingClassId, sdm630CurrentL3StateTypeId);
m_activePowerStateTypeIds.insert(pro380ThingClassId, pro380CurrentPowerEventTypeId);
m_activePowerStateTypeIds.insert(sdm630ThingClassId, sdm630CurrentPowerStateTypeId);
m_frequencyStateTypeIds.insert(pro380ThingClassId, pro380FrequencyStateTypeId);
m_frequencyStateTypeIds.insert(sdm630ThingClassId, sdm630FrequencyStateTypeId);
m_powerFactorStateTypeIds.insert(pro380ThingClassId, pro380PowerFactorStateTypeId);
m_powerFactorStateTypeIds.insert(sdm630ThingClassId, sdm630PowerFactorStateTypeId);
m_totalEnergyConsumedStateTypeIds.insert(pro380ThingClassId, pro380TotalEnergyConsumedEventTypeId);
m_totalEnergyConsumedStateTypeIds.insert(sdm630ThingClassId, sdm630TotalEnergyConsumedEventTypeId);
m_totalEnergyProducedStateTypeIds.insert(pro380ThingClassId, pro380TotalEnergyProducedStateTypeId);
m_totalEnergyProducedStateTypeIds.insert(sdm630ThingClassId, sdm630TotalEnergyProducedStateTypeId);
m_discoverySlaveAddressParamTypeIds.insert(pro380ThingClassId, pro380DiscoverySlaveAddressParamTypeId);
m_discoverySlaveAddressParamTypeIds.insert(sdm630ThingClassId, sdm630DiscoverySlaveAddressParamTypeId);
m_registerMaps.insert(pro380ThingClassId, pro380RegisterMap);
m_registerMaps.insert(sdm630ThingClassId, sdm630RegisterMap);
m_connectionStateTypeIds.insert(pro380ThingClassId, pro380ConnectedStateTypeId);
m_connectionStateTypeIds.insert(sdm630ThingClassId, sdm630ConnectedStateTypeId);
}
void IntegrationPluginEnergyMeters::init()
@ -95,16 +51,17 @@ void IntegrationPluginEnergyMeters::init()
connect(hardwareManager()->modbusRtuResource(), &ModbusRtuHardwareResource::modbusRtuMasterRemoved, this, [=] (const QUuid &modbusUuid){
qCDebug(dcEnergyMeters()) << "Modbus RTU master has been removed" << modbusUuid.toString();
Q_FOREACH(Thing *thing, myThings()) {
foreach (Thing *thing, myThings()) {
if (m_modbusUuidParamTypeIds.contains(thing->thingClassId())) {
if (thing->paramValue(m_modbusUuidParamTypeIds.value(thing->thingClassId())) == modbusUuid) {
qCWarning(dcEnergyMeters()) << "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(m_connectionStateTypeIds[thing->thingClassId()], false);
EnergyMeter *meter = m_energyMeters.value(thing);
if (!meter)
return;
meter->setModbusMaster(nullptr);
if (thing->thingClassId() == sdm630ThingClassId) {
delete m_sdmConnections.take(thing);
} else if (thing->thingClassId() == pro380ThingClassId) {
delete m_ineproConnections.take(thing);
}
}
}
}
@ -113,34 +70,33 @@ void IntegrationPluginEnergyMeters::init()
void IntegrationPluginEnergyMeters::discoverThings(ThingDiscoveryInfo *info)
{
qCDebug(dcEnergyMeters()) << "Discover things";
QList<ThingDescriptor> thingDescriptors;
qCDebug(dcEnergyMeters()) << "Discover modbus RTU resources...";
if (hardwareManager()->modbusRtuResource()->modbusRtuMasters().isEmpty()) {
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("No Modbus RTU interface available."));
return;
}
if (!m_connectionStateTypeIds.contains(info->thingClassId())) {
Q_ASSERT_X(false, "discoverThings", QString("Unhandled thingClassId: %1").arg(info->thingClassId().toString()).toUtf8());
}
Q_ASSERT_X(m_connectionStateTypeIds.contains(info->thingClassId()), "discoverThings", QString("Unhandled thingClassId: %1").arg(info->thingClassId().toString()).toUtf8());
uint slaveAddress = info->params().paramValue(m_discoverySlaveAddressParamTypeIds.value(info->thingClassId())).toUInt();
if (slaveAddress > 254 || slaveAddress == 0) {
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("Modbus slave address must be between 1 and 254"));
return;
}
Q_FOREACH(ModbusRtuMaster *modbusMaster, hardwareManager()->modbusRtuResource()->modbusRtuMasters()) {
foreach (ModbusRtuMaster *modbusMaster, hardwareManager()->modbusRtuResource()->modbusRtuMasters()) {
qCDebug(dcEnergyMeters()) << "Found RTU master resource" << modbusMaster << "connected" << modbusMaster->connected();
if (!modbusMaster->connected()) {
if (!modbusMaster->connected())
continue;
}
ThingDescriptor descriptor(info->thingClassId(), QT_TR_NOOP("Energy meter"), QT_TR_NOOP("Slave address ") +QString::number(slaveAddress)+" "+modbusMaster->serialPort());
ThingDescriptor descriptor(info->thingClassId(), QT_TR_NOOP("Energy meter"), QT_TR_NOOP("Slave address ") + QString::number(slaveAddress) + " " + modbusMaster->serialPort());
ParamList params;
params << Param(m_slaveIdParamTypeIds.value(info->thingClassId()), slaveAddress);
params << Param(m_modbusUuidParamTypeIds.value(info->thingClassId()), modbusMaster->modbusUuid());
descriptor.setParams(params);
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
return;
}
@ -148,84 +104,235 @@ void IntegrationPluginEnergyMeters::discoverThings(ThingDiscoveryInfo *info)
void IntegrationPluginEnergyMeters::setupThing(ThingSetupInfo *info)
{
Thing *thing = info->thing();
qCDebug(dcEnergyMeters()) << "Setup thing" << thing->name();
qCDebug(dcEnergyMeters()) << "Setup thing" << thing << thing->params();
Q_ASSERT_X(m_connectionStateTypeIds.contains(thing->thingClassId()), "setupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
if (!m_connectionStateTypeIds.contains(thing->thingClassId())) {
Q_ASSERT_X(false, "setupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
}
if (m_energyMeters.contains(thing)) {
qCDebug(dcEnergyMeters()) << "Setup after rediscovery, cleaning up ...";
m_energyMeters.take(thing)->deleteLater();
}
uint address = thing->paramValue(m_slaveIdParamTypeIds.value(thing->thingClassId())).toUInt();
if (address > 254 || address == 0) {
qCWarning(dcEnergyMeters()) << "Setup failed, slave address is not valid" << address;
info->finish(Thing::ThingErrorSetupFailed, tr("Slave address not valid, must be between 1 and 254"));
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("Slave address not valid, must be between 1 and 254"));
return;
}
QUuid uuid = thing->paramValue(m_modbusUuidParamTypeIds.value(thing->thingClassId())).toUuid();
if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(uuid)) {
qCWarning(dcEnergyMeters()) << "Setup failed, hardware manager not available";
info->finish(Thing::ThingErrorSetupFailed, tr("Modbus RTU resource not available."));
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("Modbus RTU resource not available."));
return;
}
EnergyMeter *meter = new EnergyMeter(hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), address, m_registerMaps.value(thing->thingClassId()), this);
connect(info, &ThingSetupInfo::aborted, meter, &EnergyMeter::deleteLater);
connect(meter, &EnergyMeter::consumedEnergyReceived, info, [this, info, meter] (double energy) {
qCDebug(dcEnergyMeters()) << "Consumed energy received" << energy << "Setup finished";
connect(meter, &EnergyMeter::connectedChanged, this, &IntegrationPluginEnergyMeters::onConnectionStateChanged);
connect(meter, &EnergyMeter::voltageL1Received, this, &IntegrationPluginEnergyMeters::onVoltageL1Received);
connect(meter, &EnergyMeter::voltageL2Received, this, &IntegrationPluginEnergyMeters::onVoltageL2Received);
connect(meter, &EnergyMeter::voltageL3Received, this, &IntegrationPluginEnergyMeters::onVoltageL3Received);
connect(meter, &EnergyMeter::currentL1Received, this, &IntegrationPluginEnergyMeters::onCurrentL1Received);
connect(meter, &EnergyMeter::currentL2Received, this, &IntegrationPluginEnergyMeters::onCurrentL2Received);
connect(meter, &EnergyMeter::currentL3Received, this, &IntegrationPluginEnergyMeters::onCurrentL3Received);
connect(meter, &EnergyMeter::activePowerReceived, this, &IntegrationPluginEnergyMeters::onActivePowerReceived);
connect(meter, &EnergyMeter::powerFactorReceived, this, &IntegrationPluginEnergyMeters::onPowerFactorReceived);
connect(meter, &EnergyMeter::frequencyReceived, this, &IntegrationPluginEnergyMeters::onFrequencyReceived);
connect(meter, &EnergyMeter::producedEnergyReceived, this, &IntegrationPluginEnergyMeters::onProducedEnergyReceived);
connect(meter, &EnergyMeter::consumedEnergyReceived, this, &IntegrationPluginEnergyMeters::onConsumedEnergyReceived);
if (thing->thingClassId() == sdm630ThingClassId) {
if (m_sdmConnections.contains(thing)) {
qCDebug(dcEnergyMeters()) << "Setup after rediscovery, cleaning up ...";
m_sdmConnections.take(thing)->deleteLater();
}
m_energyMeters.insert(info->thing(), meter);
Sdm630ModbusRtuConnection *sdmConnection = new Sdm630ModbusRtuConnection(hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), address, this);
connect(sdmConnection->modbusRtuMaster(), &ModbusRtuMaster::connectedChanged, this, [=](bool connected){
if (connected) {
qCDebug(dcEnergyMeters()) << "Modbus RTU resource connected" << thing << sdmConnection->modbusRtuMaster()->serialPort();
} else {
qCWarning(dcEnergyMeters()) << "Modbus RTU resource disconnected" << thing << sdmConnection->modbusRtuMaster()->serialPort();
}
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::currentPhaseAChanged, this, [=](float currentPhaseA){
thing->setStateValue(sdm630CurrentPhaseAStateTypeId, currentPhaseA);
thing->setStateValue(sdm630ConnectedStateTypeId, true);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::currentPhaseBChanged, this, [=](float currentPhaseB){
thing->setStateValue(sdm630CurrentPhaseBStateTypeId, currentPhaseB);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::currentPhaseCChanged, this, [=](float currentPhaseC){
thing->setStateValue(sdm630CurrentPhaseCStateTypeId, currentPhaseC);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::voltagePhaseAChanged, this, [=](float voltagePhaseA){
thing->setStateValue(sdm630VoltagePhaseAStateTypeId, voltagePhaseA);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::voltagePhaseBChanged, this, [=](float voltagePhaseB){
thing->setStateValue(sdm630VoltagePhaseBStateTypeId, voltagePhaseB);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::voltagePhaseCChanged, this, [=](float voltagePhaseC){
thing->setStateValue(sdm630VoltagePhaseCStateTypeId, voltagePhaseC);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::totalCurrentPowerChanged, this, [=](float currentPower){
thing->setStateValue(sdm630CurrentPowerStateTypeId, currentPower);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::powerPhaseAChanged, this, [=](float powerPhaseA){
thing->setStateValue(sdm630CurrentPowerPhaseAStateTypeId, powerPhaseA);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::powerPhaseBChanged, this, [=](float powerPhaseB){
thing->setStateValue(sdm630CurrentPowerPhaseBStateTypeId, powerPhaseB);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::powerPhaseCChanged, this, [=](float powerPhaseC){
thing->setStateValue(sdm630CurrentPowerPhaseCStateTypeId, powerPhaseC);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::frequencyChanged, this, [=](float frequency){
thing->setStateValue(sdm630FrequencyStateTypeId, frequency);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::totalEnergyConsumedChanged, this, [=](float totalEnergyConsumed){
thing->setStateValue(sdm630TotalEnergyConsumedStateTypeId, totalEnergyConsumed);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::totalEnergyProducedChanged, this, [=](float totalEnergyProduced){
thing->setStateValue(sdm630TotalEnergyProducedStateTypeId, totalEnergyProduced);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::energyProducedPhaseAChanged, this, [=](float energyProducedPhaseA){
thing->setStateValue(sdm630EnergyProducedPhaseAStateTypeId, energyProducedPhaseA);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::energyProducedPhaseBChanged, this, [=](float energyProducedPhaseB){
thing->setStateValue(sdm630EnergyProducedPhaseBStateTypeId, energyProducedPhaseB);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::energyProducedPhaseCChanged, this, [=](float energyProducedPhaseC){
thing->setStateValue(sdm630EnergyProducedPhaseCStateTypeId, energyProducedPhaseC);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::energyConsumedPhaseAChanged, this, [=](float energyConsumedPhaseA){
thing->setStateValue(sdm630EnergyConsumedPhaseAStateTypeId, energyConsumedPhaseA);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::energyConsumedPhaseBChanged, this, [=](float energyConsumedPhaseB){
thing->setStateValue(sdm630EnergyConsumedPhaseBStateTypeId, energyConsumedPhaseB);
});
connect(sdmConnection, &Sdm630ModbusRtuConnection::energyConsumedPhaseCChanged, this, [=](float energyConsumedPhaseC){
thing->setStateValue(sdm630EnergyConsumedPhaseCStateTypeId, energyConsumedPhaseC);
});
// FIXME: try to read before setup success
m_sdmConnections.insert(thing, sdmConnection);
info->finish(Thing::ThingErrorNoError);
});
meter->getEnergyConsumed();
return;
} else if (thing->thingClassId() == pro380ThingClassId) {
if (m_ineproConnections.contains(thing)) {
qCDebug(dcEnergyMeters()) << "Setup after rediscovery, cleaning up ...";
m_ineproConnections.take(thing)->deleteLater();
}
Pro380ModbusRtuConnection *proConnection = new Pro380ModbusRtuConnection(hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), address, this);
connect(proConnection->modbusRtuMaster(), &ModbusRtuMaster::connectedChanged, this, [=](bool connected){
if (connected) {
qCDebug(dcEnergyMeters()) << "Modbus RTU resource connected" << thing << proConnection->modbusRtuMaster()->serialPort();
} else {
qCWarning(dcEnergyMeters()) << "Modbus RTU resource disconnected" << thing << proConnection->modbusRtuMaster()->serialPort();
}
});
connect(proConnection, &Pro380ModbusRtuConnection::currentPhaseAChanged, this, [=](float currentPhaseA){
thing->setStateValue(pro380CurrentPhaseAStateTypeId, currentPhaseA);
thing->setStateValue(pro380ConnectedStateTypeId, true);
});
connect(proConnection, &Pro380ModbusRtuConnection::currentPhaseBChanged, this, [=](float currentPhaseB){
thing->setStateValue(pro380CurrentPhaseBStateTypeId, currentPhaseB);
});
connect(proConnection, &Pro380ModbusRtuConnection::currentPhaseCChanged, this, [=](float currentPhaseC){
thing->setStateValue(pro380CurrentPhaseCStateTypeId, currentPhaseC);
});
connect(proConnection, &Pro380ModbusRtuConnection::voltagePhaseAChanged, this, [=](float voltagePhaseA){
thing->setStateValue(pro380VoltagePhaseAStateTypeId, voltagePhaseA);
});
connect(proConnection, &Pro380ModbusRtuConnection::voltagePhaseBChanged, this, [=](float voltagePhaseB){
thing->setStateValue(pro380VoltagePhaseBStateTypeId, voltagePhaseB);
});
connect(proConnection, &Pro380ModbusRtuConnection::voltagePhaseCChanged, this, [=](float voltagePhaseC){
thing->setStateValue(pro380VoltagePhaseCStateTypeId, voltagePhaseC);
});
connect(proConnection, &Pro380ModbusRtuConnection::totalCurrentPowerChanged, this, [=](float currentPower){
thing->setStateValue(pro380CurrentPowerStateTypeId, currentPower * 1000); // kW
});
connect(proConnection, &Pro380ModbusRtuConnection::powerPhaseAChanged, this, [=](float powerPhaseA){
thing->setStateValue(pro380CurrentPowerPhaseAStateTypeId, powerPhaseA * 1000); // kW
});
connect(proConnection, &Pro380ModbusRtuConnection::powerPhaseBChanged, this, [=](float powerPhaseB){
thing->setStateValue(pro380CurrentPowerPhaseBStateTypeId, powerPhaseB * 1000); // kW
});
connect(proConnection, &Pro380ModbusRtuConnection::powerPhaseCChanged, this, [=](float powerPhaseC){
thing->setStateValue(pro380CurrentPowerPhaseCStateTypeId, powerPhaseC * 1000); // kW
});
connect(proConnection, &Pro380ModbusRtuConnection::frequencyChanged, this, [=](float frequency){
thing->setStateValue(pro380FrequencyStateTypeId, frequency);
});
connect(proConnection, &Pro380ModbusRtuConnection::totalEnergyConsumedChanged, this, [=](float totalEnergyConsumed){
thing->setStateValue(pro380TotalEnergyConsumedStateTypeId, totalEnergyConsumed);
});
connect(proConnection, &Pro380ModbusRtuConnection::totalEnergyProducedChanged, this, [=](float totalEnergyProduced){
thing->setStateValue(pro380TotalEnergyProducedStateTypeId, totalEnergyProduced);
});
connect(proConnection, &Pro380ModbusRtuConnection::energyProducedPhaseAChanged, this, [=](float energyProducedPhaseA){
thing->setStateValue(pro380EnergyProducedPhaseAStateTypeId, energyProducedPhaseA);
});
connect(proConnection, &Pro380ModbusRtuConnection::energyProducedPhaseBChanged, this, [=](float energyProducedPhaseB){
thing->setStateValue(pro380EnergyProducedPhaseBStateTypeId, energyProducedPhaseB);
});
connect(proConnection, &Pro380ModbusRtuConnection::energyProducedPhaseCChanged, this, [=](float energyProducedPhaseC){
thing->setStateValue(pro380EnergyProducedPhaseCStateTypeId, energyProducedPhaseC);
});
connect(proConnection, &Pro380ModbusRtuConnection::energyConsumedPhaseAChanged, this, [=](float energyConsumedPhaseA){
thing->setStateValue(pro380EnergyConsumedPhaseAStateTypeId, energyConsumedPhaseA);
});
connect(proConnection, &Pro380ModbusRtuConnection::energyConsumedPhaseBChanged, this, [=](float energyConsumedPhaseB){
thing->setStateValue(pro380EnergyConsumedPhaseBStateTypeId, energyConsumedPhaseB);
});
connect(proConnection, &Pro380ModbusRtuConnection::energyConsumedPhaseCChanged, this, [=](float energyConsumedPhaseC){
thing->setStateValue(pro380EnergyConsumedPhaseCStateTypeId, energyConsumedPhaseC);
});
// FIXME: try to read before setup success
m_ineproConnections.insert(thing, proConnection);
info->finish(Thing::ThingErrorNoError);
}
}
void IntegrationPluginEnergyMeters::postSetupThing(Thing *thing)
{
qCDebug(dcEnergyMeters) << "Post setup thing" << thing->name();
if (m_connectionStateTypeIds.contains(thing->thingClassId())) {
thing->setStateValue(m_connectionStateTypeIds.value(thing->thingClassId()), true);
if (!m_refreshTimer) {
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(2);
connect(m_refreshTimer, &PluginTimer::timeout, this, [this] {
foreach (Thing *thing, myThings().filterByThingClassId(sdm630ThingClassId)) {
m_sdmConnections.value(thing)->update();
}
if (m_energyMeters.contains(thing)) {
startUpdateCycle(m_energyMeters.value(thing));
} else {
qCWarning(dcEnergyMeters()) << "Thing has no energy meter connection and will not work properly";
}
}
if (!m_reconnectTimer) {
qCDebug(dcEnergyMeters()) << "Starting reconnect timer";
m_reconnectTimer = hardwareManager()->pluginTimerManager()->registerTimer(5);
connect(m_reconnectTimer, &PluginTimer::timeout, this, [this] {
foreach (Thing *thing, myThings()) {
if (m_connectionStateTypeIds.contains(thing->thingClassId())) {
if (!thing->stateValue(m_connectionStateTypeIds.value(thing->thingClassId())).toBool()) {
EnergyMeter *meter = m_energyMeters.value(thing);
if (!meter) {
qCWarning(dcEnergyMeters()) << "On reconnect timer, could not find any EnergyMeter connection for" << thing->name();
continue;
}
qCDebug(dcEnergyMeters()) << "On reconnect timer, restarting update cycle for" << thing->name();
startUpdateCycle(meter);
}
}
foreach (Thing *thing, myThings().filterByThingClassId(pro380ThingClassId)) {
m_sdmConnections.value(thing)->update();
}
});
qCDebug(dcEnergyMeters()) << "Starting refresh timer...";
m_refreshTimer->start();
}
}
@ -233,171 +340,15 @@ void IntegrationPluginEnergyMeters::thingRemoved(Thing *thing)
{
qCDebug(dcEnergyMeters()) << "Thing removed" << thing->name();
if (m_energyMeters.contains(thing)) {
EnergyMeter *meter = m_energyMeters.take(thing);
m_updateCycleInProgress.remove(meter);
meter->deleteLater();
}
if (m_sdmConnections.contains(thing))
m_sdmConnections.take(thing)->deleteLater();
if (myThings().isEmpty() && m_reconnectTimer) {
if (m_ineproConnections.contains(thing))
m_ineproConnections.take(thing)->deleteLater();
if (myThings().isEmpty() && m_refreshTimer) {
qCDebug(dcEnergyMeters()) << "Stopping reconnect timer";
hardwareManager()->pluginTimerManager()->unregisterTimer(m_reconnectTimer);
m_reconnectTimer = nullptr;
hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer);
m_refreshTimer = nullptr;
}
}
void IntegrationPluginEnergyMeters::startUpdateCycle(EnergyMeter *meter)
{
if (m_updateCycleInProgress.contains(meter)) {
if (m_updateCycleInProgress.value(meter)) {
qCWarning(dcEnergyMeters()) << "Update cycle not startet, update cycle already in progress";
return;
}
}
m_updateCycleInProgress.insert(meter, true);
meter->getVoltageL1();
}
void IntegrationPluginEnergyMeters::updateCycleFinished(EnergyMeter *meter)
{
m_updateCycleInProgress.insert(meter, false);
int updateInterval = configValue(energyMetersPluginUpdateIntervalParamTypeId).toInt();
QTimer::singleShot(updateInterval, meter, [this, meter] {
startUpdateCycle(meter); // restart update cycle
});
}
void IntegrationPluginEnergyMeters::onConnectionStateChanged(bool status)
{
EnergyMeter *meter = static_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
if (!status) {
updateCycleFinished(meter);
}
qCDebug(dcEnergyMeters()) << "Connection status changed" << thing->name() << status;
thing->setStateValue(m_connectionStateTypeIds.value(thing->thingClassId()), status);
}
void IntegrationPluginEnergyMeters::onVoltageL1Received(double voltage)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getVoltageL2();
thing->setStateValue(m_voltageL1StateTypeIds.value(thing->thingClassId()), voltage);
}
void IntegrationPluginEnergyMeters::onVoltageL2Received(double voltage)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getVoltageL3();
thing->setStateValue(m_voltageL2StateTypeIds.value(thing->thingClassId()), voltage);
}
void IntegrationPluginEnergyMeters::onVoltageL3Received(double voltage)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getCurrentL1();
thing->setStateValue(m_voltageL3StateTypeIds.value(thing->thingClassId()), voltage);
}
void IntegrationPluginEnergyMeters::onCurrentL1Received(double current)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getCurrentL2();
thing->setStateValue(m_currentL1StateTypeIds.value(thing->thingClassId()), current);
}
void IntegrationPluginEnergyMeters::onCurrentL2Received(double current)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getCurrentL3();
thing->setStateValue(m_currentL2StateTypeIds.value(thing->thingClassId()), current);
}
void IntegrationPluginEnergyMeters::onCurrentL3Received(double current)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getActivePower();
thing->setStateValue(m_currentL3StateTypeIds.value(thing->thingClassId()), current);
}
void IntegrationPluginEnergyMeters::onActivePowerReceived(double power)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getFrequency();
thing->setStateValue(m_activePowerStateTypeIds.value(thing->thingClassId()), power);
}
void IntegrationPluginEnergyMeters::onFrequencyReceived(double frequency)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getPowerFactor();
thing->setStateValue(m_frequencyStateTypeIds.value(thing->thingClassId()), frequency);
}
void IntegrationPluginEnergyMeters::onPowerFactorReceived(double powerFactor)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getEnergyProduced();
thing->setStateValue(m_powerFactorStateTypeIds.value(thing->thingClassId()), powerFactor);
}
void IntegrationPluginEnergyMeters::onProducedEnergyReceived(double energy)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
meter->getEnergyConsumed();
thing->setStateValue(m_totalEnergyProducedStateTypeIds.value(thing->thingClassId()), energy);
}
void IntegrationPluginEnergyMeters::onConsumedEnergyReceived(double energy)
{
EnergyMeter *meter = qobject_cast<EnergyMeter *>(sender());
Thing *thing = m_energyMeters.key(meter);
if (!thing)
return;
updateCycleFinished(meter);
thing->setStateValue(m_totalEnergyConsumedStateTypeIds.value(thing->thingClassId()), energy);
}

View File

@ -31,11 +31,12 @@
#ifndef INTEGRATIONPLUGINENERGYMETERS_H
#define INTEGRATIONPLUGINENERGYMETERS_H
#include "integrations/integrationplugin.h"
#include "hardware/modbus/modbusrtuhardwareresource.h"
#include "plugintimer.h"
#include <integrations/integrationplugin.h>
#include <hardware/modbus/modbusrtuhardwareresource.h>
#include <plugintimer.h>
#include "energymeter.h"
#include "sdm630modbusrtuconnection.h"
#include "pro380modbusrtuconnection.h"
#include <QObject>
#include <QTimer>
@ -56,45 +57,16 @@ public:
void thingRemoved(Thing *thing) override;
private:
PluginTimer *m_reconnectTimer = nullptr;
QHash<ThingClassId, StateTypeId> m_connectionStateTypeIds;
QHash<ThingClassId, StateTypeId> m_voltageL1StateTypeIds;
QHash<ThingClassId, StateTypeId> m_voltageL2StateTypeIds;
QHash<ThingClassId, StateTypeId> m_voltageL3StateTypeIds;
QHash<ThingClassId, StateTypeId> m_currentL1StateTypeIds;
QHash<ThingClassId, StateTypeId> m_currentL2StateTypeIds;
QHash<ThingClassId, StateTypeId> m_currentL3StateTypeIds;
QHash<ThingClassId, StateTypeId> m_activePowerStateTypeIds;
QHash<ThingClassId, StateTypeId> m_frequencyStateTypeIds;
QHash<ThingClassId, StateTypeId> m_powerFactorStateTypeIds;
QHash<ThingClassId, StateTypeId> m_totalEnergyConsumedStateTypeIds;
QHash<ThingClassId, StateTypeId> m_totalEnergyProducedStateTypeIds;
PluginTimer *m_refreshTimer = nullptr;
QHash<Thing *, Sdm630ModbusRtuConnection *> m_sdmConnections; // sdm 630
QHash<Thing *, Pro380ModbusRtuConnection *> m_ineproConnections; // pro 380
QHash<ThingClassId, ParamTypeId> m_discoverySlaveAddressParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_slaveIdParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_modbusUuidParamTypeIds;
QHash<ThingClassId, StateTypeId> m_connectionStateTypeIds;
QHash<ThingClassId, QHash<ModbusRegisterType, ModbusRegisterDescriptor>> m_registerMaps;
QHash<Thing *, EnergyMeter *> m_energyMeters;
QHash<EnergyMeter *, bool> m_updateCycleInProgress;
void startUpdateCycle(EnergyMeter *meter);
void updateCycleFinished(EnergyMeter *meter);
private slots:
void onConnectionStateChanged(bool status);
void onVoltageL1Received(double voltage);
void onVoltageL2Received(double voltage);
void onVoltageL3Received(double voltage);
void onCurrentL1Received(double current);
void onCurrentL2Received(double current);
void onCurrentL3Received(double current);
void onActivePowerReceived(double power);
void onFrequencyReceived(double frequency);
void onPowerFactorReceived(double powerFactor);
void onProducedEnergyReceived(double energy);
void onConsumedEnergyReceived(double energy);
};
#endif // INTEGRATIONPLUGINENERGYMETERS_H

View File

@ -2,17 +2,7 @@
"name": "EnergyMeters",
"displayName": "EnergyMeters",
"id": "56e95111-fb6b-4f63-9a0a-a5ee001e89ed",
"paramTypes":[
{
"id": "eaa84c3c-06b8-4642-a40b-c2efbe6aae66",
"name": "updateInterval",
"displayName": "Update interval",
"type": "uint",
"unit": "MilliSeconds",
"defaultValue": 300,
"minValue": 200
}
],
"paramTypes":[ ],
"vendors": [
{
"name": "ineproMetering",
@ -24,7 +14,7 @@
"displayName": "PRO380-Mod",
"id": "d7c6440b-54f9-4cc0-a96b-9bb7304b3e77",
"createMethods": ["discovery"],
"interfaces": ["smartmeterconsumer", "smartmeterproducer"],
"interfaces": ["energymeter", "connectable"],
"discoveryParamTypes": [
{
"id": "a29f37f6-b344-4628-8ab4-8f4c18fada4a",
@ -63,54 +53,54 @@
},
{
"id": "04dba21a-7447-46b9-b9ae-095e5769e511",
"name": "voltageL1",
"displayName": "Voltage L1",
"displayNameEvent": "Voltage L1 changed",
"name": "voltagePhaseA",
"displayName": "Voltage phase A",
"displayNameEvent": "Voltage phase A changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "270d0c34-0a0c-4655-985f-faad6efd1afd",
"name": "voltageL2",
"displayName": "Voltage L2",
"displayNameEvent": "Voltage L2 changed",
"name": "voltagePhaseB",
"displayName": "Voltage phase B",
"displayNameEvent": "Voltage phase B changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "a1da8cfd-37cc-4c87-b857-e942cd90daec",
"name": "voltageL3",
"displayName": "Voltage L3",
"displayNameEvent": "Voltage L3 changed",
"name": "voltagePhaseC",
"displayName": "Voltage phase C",
"displayNameEvent": "Voltage phase C changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "1e077a3b-2dab-4ec4-ae96-ab49a564fe31",
"name": "currentL1",
"displayName": "Current L1",
"displayNameEvent": "Current L1 changed",
"name": "currentPhaseA",
"displayName": "Current phase A",
"displayNameEvent": "Current phase A changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
},
{
"id": "d2f54061-0807-47de-944c-68c8118ece91",
"name": "currentL2",
"displayName": "Current L2",
"displayNameEvent": "Current L2 changed",
"name": "currentPhaseB",
"displayName": "Current phase B",
"displayNameEvent": "Current phase B changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
},
{
"id": "610b20fb-2718-4f02-ac6e-12a9ef8c7615",
"name": "currentL3",
"displayName": "Current L3",
"displayNameEvent": "Current L3 changed",
"name": "currentPhaseC",
"displayName": "Current phase C",
"displayNameEvent": "Current phase C changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
@ -118,19 +108,38 @@
{
"id": "464eff60-11c2-46b7-98f5-1aa8172e5a2d",
"name": "currentPower",
"displayName": "Active power",
"displayNameEvent": "Active power changed",
"displayName": "Current power",
"displayNameEvent": "Current power changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "cdb34487-3d9b-492a-8c33-802f32a2e90e",
"name": "powerFactor",
"displayName": "Power factor",
"displayNameEvent": "Power factor changed",
"id": "55283773-0a4e-4574-b21a-d4a3f287eab1",
"name": "currentPowerPhaseA",
"displayName": "Current power phase A",
"displayNameEvent": "Current power phase A changed",
"type": "double",
"defaultValue": 0.00
"unit": "Watt",
"defaultValue": 0
},
{
"id": "8f15d104-5ff7-4c33-9cf9-fdbef4b6f721",
"name": "currentPowerPhaseB",
"displayName": "Current power phase B",
"displayNameEvent": "Current power phase B changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "86c0f968-ee70-4f56-bdfc-33b8e2b134a4",
"name": "currentPowerPhaseC",
"displayName": "Current power phase C",
"displayNameEvent": "Current power phase C changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "bb6fd00c-3bbb-4977-bb8a-96787bb6f5c5",
@ -158,6 +167,60 @@
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "b16b3b0c-82d9-4b3c-a172-0e6631c8ce16",
"name": "energyConsumedPhaseA",
"displayName": "Energy consumed phase A",
"displayNameEvent": "Energy consumed phase A changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "64225f7f-9b2f-4bfc-87b2-38758804a28b",
"name": "energyConsumedPhaseB",
"displayName": "Energy consumed phase B",
"displayNameEvent": "Energy consumed phase B changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "a6e82d61-e837-4ec8-b14a-af0d49bea9d2",
"name": "energyConsumedPhaseC",
"displayName": "Energy consumed phase C",
"displayNameEvent": "Energy consumed phase C changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "95bd476e-c247-4f7d-ab01-d9f1b7c0d996",
"name": "energyProducedPhaseA",
"displayName": "Energy produced phase A",
"displayNameEvent": "Energy produced phase A changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "f0a0bd81-708c-48d6-b5c9-165464a5b309",
"name": "energyProducedPhaseB",
"displayName": "Energy produced phase B",
"displayNameEvent": "Energy produced phase B changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "c33fcd11-b4a9-44b2-9e30-40dfa2e4c9b1",
"name": "energyProducedPhaseC",
"displayName": "Energy produced phase C",
"displayNameEvent": "Energy produced phase C changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
}
]
}
@ -170,10 +233,10 @@
"thingClasses": [
{
"name": "sdm630",
"displayName": "SDM630Modbus",
"displayName": "SDM630 Modbus",
"id": "f37597bb-35fe-48f2-9617-343dd54c0903",
"createMethods": ["discovery"],
"interfaces": ["smartmeterconsumer", "smartmeterproducer"],
"interfaces": ["energymeter", "connectable"],
"discoveryParamTypes": [
{
"id": "6ab43559-53ec-47ba-b8a0-8d3b7f8d90c2",
@ -212,54 +275,54 @@
},
{
"id": "db018146-0441-4dc0-9834-6d43ebaf8311",
"name": "voltageL1",
"displayName": "Voltage L1",
"displayNameEvent": "Voltage L1 changed",
"name": "voltagePhaseA",
"displayName": "Voltage phase A",
"displayNameEvent": "Voltage phase A changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "406f6d02-d5eb-49b3-87da-3247568e6054",
"name": "voltageL2",
"displayName": "Voltage L2",
"displayNameEvent": "Voltage L2 changed",
"name": "voltagePhaseB",
"displayName": "Voltage phase B",
"displayNameEvent": "Voltage phase B changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "ace6294d-deaa-4d9a-af78-d64379bcb229",
"name": "voltageL3",
"displayName": "Voltage L3",
"displayNameEvent": "Voltage L3 changed",
"name": "voltagePhaseC",
"displayName": "Voltage phase C",
"displayNameEvent": "Voltage phase C changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "4baf1d08-5ffa-49cf-95ef-9527b0c6f081",
"name": "currentL1",
"displayName": "Current L1",
"displayNameEvent": "Current L1 changed",
"name": "currentPhaseA",
"displayName": "Current phase A",
"displayNameEvent": "Current phase A changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
},
{
"id": "99e47d06-0a6a-4bfd-b164-61ecb6ba2818",
"name": "currentL2",
"displayName": "Current L2",
"displayNameEvent": "Current L2 changed",
"name": "currentPhaseB",
"displayName": "Current phase B",
"displayNameEvent": "Current phase B changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
},
{
"id": "4a092a66-352d-4d60-90ab-6ac5f58b92fe",
"name": "currentL3",
"displayName": "Current L3",
"displayNameEvent": "Current L3 changed",
"name": "currentPhaseC",
"displayName": "Current phase C",
"displayNameEvent": "Current phase C changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
@ -267,19 +330,38 @@
{
"id": "c824e97b-a6d1-4030-9d7a-00af6fb8e1c3",
"name": "currentPower",
"displayName": "Active power",
"displayNameEvent": "Active power changed",
"displayName": "Current power",
"displayNameEvent": "Current power changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "31b9032f-f994-472b-94bd-44f9fb094801",
"name": "powerFactor",
"displayName": "Power factor",
"displayNameEvent": "Power factor changed",
"id": "3982fb12-b179-40f7-9b27-36adb1cadd37",
"name": "currentPowerPhaseA",
"displayName": "Current power phase A",
"displayNameEvent": "Current power phase A changed",
"type": "double",
"defaultValue": 0.00
"unit": "Watt",
"defaultValue": 0
},
{
"id": "2a231c58-b095-4037-8394-a730431e70b8",
"name": "currentPowerPhaseB",
"displayName": "Current power phase B",
"displayNameEvent": "Current power phase B changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "ee8c4f0c-2b69-4210-9966-1553a592b06d",
"name": "currentPowerPhaseC",
"displayName": "Current power phase C",
"displayNameEvent": "Current power phase C changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "ab24f26c-dc15-4ec3-8d76-06a48285440b",
@ -307,6 +389,60 @@
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "6ca06c81-fe75-4448-a22f-47c303421440",
"name": "energyConsumedPhaseA",
"displayName": "Energy consumed phase A",
"displayNameEvent": "Energy consumed phase A changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "fa2b879b-2a81-4bc8-9577-98082c4d9330",
"name": "energyConsumedPhaseB",
"displayName": "Energy consumed phase B",
"displayNameEvent": "Energy consumed phase B changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "4c084c9e-7a5d-42d1-96b2-a8a4b4a25713",
"name": "energyConsumedPhaseC",
"displayName": "Energy consumed phase C",
"displayNameEvent": "Energy consumed phase C changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "308fa88e-6054-4c79-b12a-be2d0a404ef6",
"name": "energyProducedPhaseA",
"displayName": "Energy produced phase A",
"displayNameEvent": "Energy produced phase A changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "48ab6e61-dfb4-4f85-b5cc-9d89e53c6b39",
"name": "energyProducedPhaseB",
"displayName": "Energy produced phase B",
"displayNameEvent": "Energy produced phase B changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "6b3ddf15-3d4b-4dc1-8e5a-84fbf90b49ff",
"name": "energyProducedPhaseC",
"displayName": "Energy produced phase C",
"displayNameEvent": "Energy produced phase C changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
}
]
}

View File

@ -1,11 +1,13 @@
{
"title": "Energy Meters",
"tagline": "Connect Modbus RTU energy meters.",
"icon": "energymeter.svg",
"icon": "",
"stability": "consumer",
"offline": true,
"technologies": [
"modbus"
],
"categories": [
"energy"
]
}

View File

@ -0,0 +1,266 @@
{
"protocol": "RTU",
"endianness": "BigEndian",
"blocks": [
{
"id": "phasesVoltage",
"readSchedule": "update",
"registers": [
{
"id": "voltagePhaseA",
"address": 20482,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Voltage phase L1",
"unit": "V",
"defaultValue": "0",
"access": "RO"
},
{
"id": "voltagePhaseB",
"address": 20484,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Voltage phase L2",
"unit": "V",
"defaultValue": "0",
"access": "RO"
},
{
"id": "voltagePhaseC",
"address": 20486,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Voltage phase L3",
"unit": "V",
"defaultValue": "0",
"access": "RO"
}
]
},
{
"id": "phasesCurrent",
"readSchedule": "update",
"registers": [
{
"id": "currentPhaseA",
"address": 20492,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Current phase L1",
"unit": "A",
"defaultValue": "0",
"access": "RO"
},
{
"id": "currentPhaseB",
"address": 20494,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Current phase L2",
"unit": "A",
"defaultValue": "0",
"access": "RO"
},
{
"id": "currentPhaseC",
"address": 20496,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Current phase L3",
"unit": "A",
"defaultValue": "0",
"access": "RO"
}
]
},
{
"id": "currentPower",
"readSchedule": "update",
"registers": [
{
"id": "totalCurrentPower",
"address": 20498,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Total system power",
"unit": "kW",
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerPhaseA",
"address": 20500,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Power phase L1",
"unit": "kW",
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerPhaseB",
"address": 20502,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Power phase L2",
"unit": "kW",
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerPhaseC",
"address": 20504,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Power phase L3",
"unit": "kW",
"defaultValue": "0",
"access": "RO"
}
]
},
{
"id": "phasesEnergyConsumed",
"readSchedule": "update",
"registers": [
{
"id": "energyConsumedPhaseA",
"address": 24594,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Energy consumed phase A",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyConsumedPhaseB",
"address": 24596,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Energy consumed phase B",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyConsumedPhaseC",
"address": 24598,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Energy consumed phase C",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
}
]
},
{
"id": "phasesEnergyProduced",
"readSchedule": "update",
"registers": [
{
"id": "energyProducedPhaseA",
"address": 24606,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Energy produced phase A",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyProducedPhaseB",
"address": 24608,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Energy produced phase B",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyProducedPhaseC",
"address": 24610,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Energy produced phase C",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
}
]
}
],
"registers": [
{
"id": "frequency",
"address": 20488,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Frequency",
"unit": "Hz",
"defaultValue": "0",
"access": "RO"
},
{
"id": "totalEnergyConsumed",
"address": 24588,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Total energy consumed (Forward active energy)",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "totalEnergyProduced",
"address": 24600,
"size": 2,
"type": "float",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Total energy produced (Reverse active energy)",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
}
]
}

View File

@ -0,0 +1,537 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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<quint16> 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<quint16> 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<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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();
}

View File

@ -0,0 +1,204 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 <QObject>
#include "../modbus/modbusdatautils.h"
#include <hardware/modbus/modbusrtumaster.h>
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<ModbusRtuReply *> 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

View File

@ -1,87 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 REGISTERDESCRIPTOR_H
#define REGISTERDESCRIPTOR_H
#include <QObject>
#include <QHash>
enum ModbusRegisterType {
VoltageL1,
VoltageL2,
VoltageL3,
CurrentL1,
CurrentL2,
CurrentL3,
ActivePower,
Frequency,
PowerFactor,
EnergyProduced,
EnergyConsumed
};
class ModbusRegisterDescriptor
{
public:
ModbusRegisterDescriptor() {}
ModbusRegisterDescriptor(int address, int functionCode, int length, QString unit, QString dataType) :
m_address(address),
m_functionCode(functionCode),
m_length(length),
m_unit(unit),
m_dataType(dataType)
{}
int address() const
{ return m_address;}
int functionCode() const
{ return m_functionCode;}
int length() const
{ return m_length;}
QString unit() const
{ return m_unit;}
QString dataType() const
{ return m_dataType;}
private:
int m_address;
int m_functionCode;
int m_length;
QString m_unit;
QString m_dataType;
};
#endif // REGISTERDESCRIPTOR_H

View File

@ -0,0 +1,260 @@
{
"protocol": "RTU",
"endianness": "BigEndian",
"registers": [
{
"id": "totalCurrentPower",
"address": 52,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Total system power",
"unit": "W",
"defaultValue": "0",
"access": "RO"
}
],
"blocks": [
{
"id": "phaseVoltageAndCurrent",
"readSchedule": "update",
"registers": [
{
"id": "voltagePhaseA",
"address": 0,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Voltage phase L1",
"unit": "V",
"defaultValue": "0",
"access": "RO"
},
{
"id": "voltagePhaseB",
"address": 2,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Voltage phase L2",
"unit": "V",
"defaultValue": "0",
"access": "RO"
},
{
"id": "voltagePhaseC",
"address": 4,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Voltage phase L3",
"unit": "V",
"defaultValue": "0",
"access": "RO"
},
{
"id": "currentPhaseA",
"address": 6,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Current phase L1",
"unit": "A",
"defaultValue": "0",
"access": "RO"
},
{
"id": "currentPhaseB",
"address": 8,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Current phase L2",
"unit": "A",
"defaultValue": "0",
"access": "RO"
},
{
"id": "currentPhaseC",
"address": 10,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Current phase L3",
"unit": "A",
"defaultValue": "0",
"access": "RO"
}
]
},
{
"id": "phasePower",
"readSchedule": "update",
"registers": [
{
"id": "powerPhaseA",
"address": 12,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Power phase L1",
"unit": "W",
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerPhaseB",
"address": 14,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Power phase L2",
"unit": "W",
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerPhaseC",
"address": 16,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Power phase L3",
"unit": "W",
"defaultValue": "0",
"access": "RO"
}
]
},
{
"id": "frequencyAndTotalEnergy",
"readSchedule": "update",
"registers": [
{
"id": "frequency",
"address": 70,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Frequency",
"unit": "Hz",
"defaultValue": "0",
"access": "RO"
},
{
"id": "totalEnergyConsumed",
"address": 72,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Total energy consumed",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "totalEnergyProduced",
"address": 74,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Total energy produced",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
}
]
},
{
"id": "phaseEnergyEnergy",
"readSchedule": "update",
"registers": [
{
"id": "energyProducedPhaseA",
"address": 346,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Energy produced phase A",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyProducedPhaseB",
"address": 348,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Energy produced phase B",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyProducedPhaseC",
"address": 350,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Energy produced phase C",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyConsumedPhaseA",
"address": 352,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Energy consumed phase A",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyConsumedPhaseB",
"address": 354,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Energy consumed phase B",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
},
{
"id": "energyConsumedPhaseC",
"address": 356,
"size": 2,
"type": "float",
"registerType": "inputRegister",
"readSchedule": "update",
"description": "Energy consumed phase C",
"unit": "kWh",
"defaultValue": "0",
"access": "RO"
}
]
}
]
}

View File

@ -0,0 +1,455 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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<quint16> blockValues = reply->result();
QVector<quint16> 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();
}

View File

@ -0,0 +1,199 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 <QObject>
#include "../modbus/modbusdatautils.h"
#include <hardware/modbus/modbusrtumaster.h>
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<ModbusRtuReply *> 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

View File

@ -4,40 +4,16 @@
<context>
<name>EnergyMeters</name>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="109"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="112"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="115"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="118"/>
<source>Active power</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPower, ID: {c824e97b-a6d1-4030-9d7a-00af6fb8e1c3})
----------
The name of the StateType ({c824e97b-a6d1-4030-9d7a-00af6fb8e1c3}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPower, ID: {464eff60-11c2-46b7-98f5-1aa8172e5a2d})
----------
The name of the StateType ({464eff60-11c2-46b7-98f5-1aa8172e5a2d}) of ThingClass pro380</extracomment>
<translation>Leistung</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="121"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="124"/>
<source>Active power changed</source>
<extracomment>The name of the EventType ({c824e97b-a6d1-4030-9d7a-00af6fb8e1c3}) of ThingClass sdm630
----------
The name of the EventType ({464eff60-11c2-46b7-98f5-1aa8172e5a2d}) of ThingClass pro380</extracomment>
<translation>Leistung geändert</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="127"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="156"/>
<source>B+G e-tech</source>
<extracomment>The name of the vendor ({215035fe-95e8-43d8-a52e-0a31b787d902})</extracomment>
<translation>B+G e-tech</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="130"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="133"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="136"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="139"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="159"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="162"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="165"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="168"/>
<source>Connected</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: connected, ID: {8050bd0b-1dad-4a7e-b632-c71ead3c9f8b})
----------
@ -49,8 +25,8 @@ The name of the StateType ({7f9bc504-0882-4b86-83b1-42fa345acfd9}) of ThingClass
<translation>Verbunden</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="142"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="145"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="171"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="174"/>
<source>Connected changed</source>
<extracomment>The name of the EventType ({8050bd0b-1dad-4a7e-b632-c71ead3c9f8b}) of ThingClass sdm630
----------
@ -58,88 +34,328 @@ The name of the EventType ({7f9bc504-0882-4b86-83b1-42fa345acfd9}) of ThingClass
<translation>Verbunden</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="148"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="151"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="154"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="157"/>
<source>Current L1</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentL1, ID: {4baf1d08-5ffa-49cf-95ef-9527b0c6f081})
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="177"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="180"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="183"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="186"/>
<source>Current phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPhaseA, ID: {4baf1d08-5ffa-49cf-95ef-9527b0c6f081})
----------
The name of the StateType ({4baf1d08-5ffa-49cf-95ef-9527b0c6f081}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentL1, ID: {1e077a3b-2dab-4ec4-ae96-ab49a564fe31})
The name of the ParamType (ThingClass: pro380, EventType: currentPhaseA, ID: {1e077a3b-2dab-4ec4-ae96-ab49a564fe31})
----------
The name of the StateType ({1e077a3b-2dab-4ec4-ae96-ab49a564fe31}) of ThingClass pro380</extracomment>
<translation>Strom L1</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="160"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="163"/>
<source>Current L1 changed</source>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="189"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="192"/>
<source>Current phase A changed</source>
<extracomment>The name of the EventType ({4baf1d08-5ffa-49cf-95ef-9527b0c6f081}) of ThingClass sdm630
----------
The name of the EventType ({1e077a3b-2dab-4ec4-ae96-ab49a564fe31}) of ThingClass pro380</extracomment>
<translation>Strom L1 geändert</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="166"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="169"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="172"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="175"/>
<source>Current L2</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentL2, ID: {99e47d06-0a6a-4bfd-b164-61ecb6ba2818})
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="195"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="198"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="201"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="204"/>
<source>Current phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPhaseB, ID: {99e47d06-0a6a-4bfd-b164-61ecb6ba2818})
----------
The name of the StateType ({99e47d06-0a6a-4bfd-b164-61ecb6ba2818}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentL2, ID: {d2f54061-0807-47de-944c-68c8118ece91})
The name of the ParamType (ThingClass: pro380, EventType: currentPhaseB, ID: {d2f54061-0807-47de-944c-68c8118ece91})
----------
The name of the StateType ({d2f54061-0807-47de-944c-68c8118ece91}) of ThingClass pro380</extracomment>
<translation>Strom L2</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="178"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="181"/>
<source>Current L2 changed</source>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="207"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="210"/>
<source>Current phase B changed</source>
<extracomment>The name of the EventType ({99e47d06-0a6a-4bfd-b164-61ecb6ba2818}) of ThingClass sdm630
----------
The name of the EventType ({d2f54061-0807-47de-944c-68c8118ece91}) of ThingClass pro380</extracomment>
<translation>Strom L2 geändert</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="184"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="187"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="190"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="193"/>
<source>Current L3</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentL3, ID: {4a092a66-352d-4d60-90ab-6ac5f58b92fe})
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="213"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="216"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="219"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="222"/>
<source>Current phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPhaseC, ID: {4a092a66-352d-4d60-90ab-6ac5f58b92fe})
----------
The name of the StateType ({4a092a66-352d-4d60-90ab-6ac5f58b92fe}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentL3, ID: {610b20fb-2718-4f02-ac6e-12a9ef8c7615})
The name of the ParamType (ThingClass: pro380, EventType: currentPhaseC, ID: {610b20fb-2718-4f02-ac6e-12a9ef8c7615})
----------
The name of the StateType ({610b20fb-2718-4f02-ac6e-12a9ef8c7615}) of ThingClass pro380</extracomment>
<translation>Strom L3</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="196"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="199"/>
<source>Current L3 changed</source>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="225"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="228"/>
<source>Current phase C changed</source>
<extracomment>The name of the EventType ({4a092a66-352d-4d60-90ab-6ac5f58b92fe}) of ThingClass sdm630
----------
The name of the EventType ({610b20fb-2718-4f02-ac6e-12a9ef8c7615}) of ThingClass pro380</extracomment>
<translation>Strom L3 geändert</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="202"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="231"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="234"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="237"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="240"/>
<source>Current power</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPower, ID: {c824e97b-a6d1-4030-9d7a-00af6fb8e1c3})
----------
The name of the StateType ({c824e97b-a6d1-4030-9d7a-00af6fb8e1c3}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPower, ID: {464eff60-11c2-46b7-98f5-1aa8172e5a2d})
----------
The name of the StateType ({464eff60-11c2-46b7-98f5-1aa8172e5a2d}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="243"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="246"/>
<source>Current power changed</source>
<extracomment>The name of the EventType ({c824e97b-a6d1-4030-9d7a-00af6fb8e1c3}) of ThingClass sdm630
----------
The name of the EventType ({464eff60-11c2-46b7-98f5-1aa8172e5a2d}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="249"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="252"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="255"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="258"/>
<source>Current power phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPowerPhaseA, ID: {3982fb12-b179-40f7-9b27-36adb1cadd37})
----------
The name of the StateType ({3982fb12-b179-40f7-9b27-36adb1cadd37}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPowerPhaseA, ID: {55283773-0a4e-4574-b21a-d4a3f287eab1})
----------
The name of the StateType ({55283773-0a4e-4574-b21a-d4a3f287eab1}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="261"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="264"/>
<source>Current power phase A changed</source>
<extracomment>The name of the EventType ({3982fb12-b179-40f7-9b27-36adb1cadd37}) of ThingClass sdm630
----------
The name of the EventType ({55283773-0a4e-4574-b21a-d4a3f287eab1}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="267"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="270"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="273"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="276"/>
<source>Current power phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPowerPhaseB, ID: {2a231c58-b095-4037-8394-a730431e70b8})
----------
The name of the StateType ({2a231c58-b095-4037-8394-a730431e70b8}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPowerPhaseB, ID: {8f15d104-5ff7-4c33-9cf9-fdbef4b6f721})
----------
The name of the StateType ({8f15d104-5ff7-4c33-9cf9-fdbef4b6f721}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="279"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="282"/>
<source>Current power phase B changed</source>
<extracomment>The name of the EventType ({2a231c58-b095-4037-8394-a730431e70b8}) of ThingClass sdm630
----------
The name of the EventType ({8f15d104-5ff7-4c33-9cf9-fdbef4b6f721}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="285"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="288"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="291"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="294"/>
<source>Current power phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPowerPhaseC, ID: {ee8c4f0c-2b69-4210-9966-1553a592b06d})
----------
The name of the StateType ({ee8c4f0c-2b69-4210-9966-1553a592b06d}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPowerPhaseC, ID: {86c0f968-ee70-4f56-bdfc-33b8e2b134a4})
----------
The name of the StateType ({86c0f968-ee70-4f56-bdfc-33b8e2b134a4}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="297"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="300"/>
<source>Current power phase C changed</source>
<extracomment>The name of the EventType ({ee8c4f0c-2b69-4210-9966-1553a592b06d}) of ThingClass sdm630
----------
The name of the EventType ({86c0f968-ee70-4f56-bdfc-33b8e2b134a4}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="303"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="306"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="309"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="312"/>
<source>Energy consumed phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyConsumedPhaseA, ID: {6ca06c81-fe75-4448-a22f-47c303421440})
----------
The name of the StateType ({6ca06c81-fe75-4448-a22f-47c303421440}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyConsumedPhaseA, ID: {b16b3b0c-82d9-4b3c-a172-0e6631c8ce16})
----------
The name of the StateType ({b16b3b0c-82d9-4b3c-a172-0e6631c8ce16}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="315"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="318"/>
<source>Energy consumed phase A changed</source>
<extracomment>The name of the EventType ({6ca06c81-fe75-4448-a22f-47c303421440}) of ThingClass sdm630
----------
The name of the EventType ({b16b3b0c-82d9-4b3c-a172-0e6631c8ce16}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="321"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="324"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="327"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="330"/>
<source>Energy consumed phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyConsumedPhaseB, ID: {fa2b879b-2a81-4bc8-9577-98082c4d9330})
----------
The name of the StateType ({fa2b879b-2a81-4bc8-9577-98082c4d9330}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyConsumedPhaseB, ID: {64225f7f-9b2f-4bfc-87b2-38758804a28b})
----------
The name of the StateType ({64225f7f-9b2f-4bfc-87b2-38758804a28b}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="333"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="336"/>
<source>Energy consumed phase B changed</source>
<extracomment>The name of the EventType ({fa2b879b-2a81-4bc8-9577-98082c4d9330}) of ThingClass sdm630
----------
The name of the EventType ({64225f7f-9b2f-4bfc-87b2-38758804a28b}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="339"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="342"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="345"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="348"/>
<source>Energy consumed phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyConsumedPhaseC, ID: {4c084c9e-7a5d-42d1-96b2-a8a4b4a25713})
----------
The name of the StateType ({4c084c9e-7a5d-42d1-96b2-a8a4b4a25713}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyConsumedPhaseC, ID: {a6e82d61-e837-4ec8-b14a-af0d49bea9d2})
----------
The name of the StateType ({a6e82d61-e837-4ec8-b14a-af0d49bea9d2}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="351"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="354"/>
<source>Energy consumed phase C changed</source>
<extracomment>The name of the EventType ({4c084c9e-7a5d-42d1-96b2-a8a4b4a25713}) of ThingClass sdm630
----------
The name of the EventType ({a6e82d61-e837-4ec8-b14a-af0d49bea9d2}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="357"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="360"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="363"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="366"/>
<source>Energy produced phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyProducedPhaseA, ID: {308fa88e-6054-4c79-b12a-be2d0a404ef6})
----------
The name of the StateType ({308fa88e-6054-4c79-b12a-be2d0a404ef6}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyProducedPhaseA, ID: {95bd476e-c247-4f7d-ab01-d9f1b7c0d996})
----------
The name of the StateType ({95bd476e-c247-4f7d-ab01-d9f1b7c0d996}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="369"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="372"/>
<source>Energy produced phase A changed</source>
<extracomment>The name of the EventType ({308fa88e-6054-4c79-b12a-be2d0a404ef6}) of ThingClass sdm630
----------
The name of the EventType ({95bd476e-c247-4f7d-ab01-d9f1b7c0d996}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="375"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="378"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="381"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="384"/>
<source>Energy produced phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyProducedPhaseB, ID: {48ab6e61-dfb4-4f85-b5cc-9d89e53c6b39})
----------
The name of the StateType ({48ab6e61-dfb4-4f85-b5cc-9d89e53c6b39}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyProducedPhaseB, ID: {f0a0bd81-708c-48d6-b5c9-165464a5b309})
----------
The name of the StateType ({f0a0bd81-708c-48d6-b5c9-165464a5b309}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="387"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="390"/>
<source>Energy produced phase B changed</source>
<extracomment>The name of the EventType ({48ab6e61-dfb4-4f85-b5cc-9d89e53c6b39}) of ThingClass sdm630
----------
The name of the EventType ({f0a0bd81-708c-48d6-b5c9-165464a5b309}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="393"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="396"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="399"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="402"/>
<source>Energy produced phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyProducedPhaseC, ID: {6b3ddf15-3d4b-4dc1-8e5a-84fbf90b49ff})
----------
The name of the StateType ({6b3ddf15-3d4b-4dc1-8e5a-84fbf90b49ff}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyProducedPhaseC, ID: {c33fcd11-b4a9-44b2-9e30-40dfa2e4c9b1})
----------
The name of the StateType ({c33fcd11-b4a9-44b2-9e30-40dfa2e4c9b1}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="405"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="408"/>
<source>Energy produced phase C changed</source>
<extracomment>The name of the EventType ({6b3ddf15-3d4b-4dc1-8e5a-84fbf90b49ff}) of ThingClass sdm630
----------
The name of the EventType ({c33fcd11-b4a9-44b2-9e30-40dfa2e4c9b1}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="411"/>
<source>EnergyMeters</source>
<extracomment>The name of the plugin EnergyMeters ({56e95111-fb6b-4f63-9a0a-a5ee001e89ed})</extracomment>
<translation>Energiezähler</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="205"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="208"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="211"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="214"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="414"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="417"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="420"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="423"/>
<source>Frequency</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: frequency, ID: {ab24f26c-dc15-4ec3-8d76-06a48285440b})
----------
@ -151,8 +367,8 @@ The name of the StateType ({bb6fd00c-3bbb-4977-bb8a-96787bb6f5c5}) of ThingClass
<translation>Frequenz</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="217"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="220"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="426"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="429"/>
<source>Frequency changed</source>
<extracomment>The name of the EventType ({ab24f26c-dc15-4ec3-8d76-06a48285440b}) of ThingClass sdm630
----------
@ -160,8 +376,8 @@ The name of the EventType ({bb6fd00c-3bbb-4977-bb8a-96787bb6f5c5}) of ThingClass
<translation>Frequenz geändert</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="223"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="226"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="432"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="435"/>
<source>Modbus RTU master</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, Type: thing, ID: {d90e9292-d03c-4f2a-957e-5d965018c9c9})
----------
@ -169,8 +385,8 @@ The name of the ParamType (ThingClass: pro380, Type: thing, ID: {6cdbec8c-21b9-4
<translation>Modbus RTU Master</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="229"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="232"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="438"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="441"/>
<source>Modbus slave address</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, Type: thing, ID: {ac77ea98-b006-486e-a3e8-b30a483f26c1})
----------
@ -178,44 +394,92 @@ The name of the ParamType (ThingClass: pro380, Type: thing, ID: {c75b2c31-6ec3-4
<translation>Modbus Slave-Adresse</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="235"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="444"/>
<source>PRO380-Mod</source>
<extracomment>The name of the ThingClass ({d7c6440b-54f9-4cc0-a96b-9bb7304b3e77})</extracomment>
<translation>PRO380-Mod</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="238"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="241"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="244"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="247"/>
<source>Power factor</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: powerFactor, ID: {31b9032f-f994-472b-94bd-44f9fb094801})
----------
The name of the StateType ({31b9032f-f994-472b-94bd-44f9fb094801}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: powerFactor, ID: {cdb34487-3d9b-492a-8c33-802f32a2e90e})
----------
The name of the StateType ({cdb34487-3d9b-492a-8c33-802f32a2e90e}) of ThingClass pro380</extracomment>
<translation>Leistungsfaktor</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="250"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="253"/>
<source>Power factor changed</source>
<extracomment>The name of the EventType ({31b9032f-f994-472b-94bd-44f9fb094801}) of ThingClass sdm630
----------
The name of the EventType ({cdb34487-3d9b-492a-8c33-802f32a2e90e}) of ThingClass pro380</extracomment>
<translation>Leistungsfaktor geändert</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="256"/>
<source>SDM630Modbus</source>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="447"/>
<source>SDM630 Modbus</source>
<extracomment>The name of the ThingClass ({f37597bb-35fe-48f2-9617-343dd54c0903})</extracomment>
<translation>SDM630Modbus</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="259"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="262"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="492"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="495"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="498"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="501"/>
<source>Voltage phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltagePhaseA, ID: {db018146-0441-4dc0-9834-6d43ebaf8311})
----------
The name of the StateType ({db018146-0441-4dc0-9834-6d43ebaf8311}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltagePhaseA, ID: {04dba21a-7447-46b9-b9ae-095e5769e511})
----------
The name of the StateType ({04dba21a-7447-46b9-b9ae-095e5769e511}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="504"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="507"/>
<source>Voltage phase A changed</source>
<extracomment>The name of the EventType ({db018146-0441-4dc0-9834-6d43ebaf8311}) of ThingClass sdm630
----------
The name of the EventType ({04dba21a-7447-46b9-b9ae-095e5769e511}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="510"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="513"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="516"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="519"/>
<source>Voltage phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltagePhaseB, ID: {406f6d02-d5eb-49b3-87da-3247568e6054})
----------
The name of the StateType ({406f6d02-d5eb-49b3-87da-3247568e6054}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltagePhaseB, ID: {270d0c34-0a0c-4655-985f-faad6efd1afd})
----------
The name of the StateType ({270d0c34-0a0c-4655-985f-faad6efd1afd}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="522"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="525"/>
<source>Voltage phase B changed</source>
<extracomment>The name of the EventType ({406f6d02-d5eb-49b3-87da-3247568e6054}) of ThingClass sdm630
----------
The name of the EventType ({270d0c34-0a0c-4655-985f-faad6efd1afd}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="528"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="531"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="534"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="537"/>
<source>Voltage phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltagePhaseC, ID: {ace6294d-deaa-4d9a-af78-d64379bcb229})
----------
The name of the StateType ({ace6294d-deaa-4d9a-af78-d64379bcb229}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltagePhaseC, ID: {a1da8cfd-37cc-4c87-b857-e942cd90daec})
----------
The name of the StateType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="540"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="543"/>
<source>Voltage phase C changed</source>
<extracomment>The name of the EventType ({ace6294d-deaa-4d9a-af78-d64379bcb229}) of ThingClass sdm630
----------
The name of the EventType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="450"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="453"/>
<source>Slave address</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, Type: discovery, ID: {6ab43559-53ec-47ba-b8a0-8d3b7f8d90c2})
----------
@ -223,10 +487,10 @@ The name of the ParamType (ThingClass: pro380, Type: discovery, ID: {a29f37f6-b3
<translation>Slave-Adresse</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="265"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="268"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="271"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="274"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="456"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="459"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="462"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="465"/>
<source>Total energy consumed</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: totalEnergyConsumed, ID: {98d858a8-22e8-4262-b5c7-25bb027942ad})
----------
@ -238,8 +502,8 @@ The name of the StateType ({f18fd596-b47f-44be-a0f0-6ca44369ebf5}) of ThingClass
<translation>Gesamte verbrauchte Energy</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="277"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="280"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="468"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="471"/>
<source>Total energy consumed changed</source>
<extracomment>The name of the EventType ({98d858a8-22e8-4262-b5c7-25bb027942ad}) of ThingClass sdm630
----------
@ -247,10 +511,10 @@ The name of the EventType ({f18fd596-b47f-44be-a0f0-6ca44369ebf5}) of ThingClass
<translation>Gesamte verbrauchte Energie geändert</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="283"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="286"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="289"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="292"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="474"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="477"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="480"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="483"/>
<source>Total energy produced</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: totalEnergyProduced, ID: {e469b3ff-a4c2-42da-af35-ccafaef214af})
----------
@ -262,8 +526,8 @@ The name of the StateType ({112911c9-14e0-4c83-ac92-f2ceb3bdecdf}) of ThingClass
<translation>Gesamte produzierte Energie</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="295"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="298"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="486"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="489"/>
<source>Total energy produced changed</source>
<extracomment>The name of the EventType ({e469b3ff-a4c2-42da-af35-ccafaef214af}) of ThingClass sdm630
----------
@ -271,85 +535,7 @@ The name of the EventType ({112911c9-14e0-4c83-ac92-f2ceb3bdecdf}) of ThingClass
<translation>Gesamte produzierte Energie geändert</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="301"/>
<source>Update interval</source>
<extracomment>The name of the ParamType (ThingClass: energyMeters, Type: plugin, ID: {eaa84c3c-06b8-4642-a40b-c2efbe6aae66})</extracomment>
<translation>Updateintervall</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="304"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="307"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="310"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="313"/>
<source>Voltage L1</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltageL1, ID: {db018146-0441-4dc0-9834-6d43ebaf8311})
----------
The name of the StateType ({db018146-0441-4dc0-9834-6d43ebaf8311}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltageL1, ID: {04dba21a-7447-46b9-b9ae-095e5769e511})
----------
The name of the StateType ({04dba21a-7447-46b9-b9ae-095e5769e511}) of ThingClass pro380</extracomment>
<translation>Spannung L1</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="316"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="319"/>
<source>Voltage L1 changed</source>
<extracomment>The name of the EventType ({db018146-0441-4dc0-9834-6d43ebaf8311}) of ThingClass sdm630
----------
The name of the EventType ({04dba21a-7447-46b9-b9ae-095e5769e511}) of ThingClass pro380</extracomment>
<translation>Spannung L1 geändert</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="322"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="325"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="328"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="331"/>
<source>Voltage L2</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltageL2, ID: {406f6d02-d5eb-49b3-87da-3247568e6054})
----------
The name of the StateType ({406f6d02-d5eb-49b3-87da-3247568e6054}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltageL2, ID: {270d0c34-0a0c-4655-985f-faad6efd1afd})
----------
The name of the StateType ({270d0c34-0a0c-4655-985f-faad6efd1afd}) of ThingClass pro380</extracomment>
<translation>Spannung L2</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="334"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="337"/>
<source>Voltage L2 changed</source>
<extracomment>The name of the EventType ({406f6d02-d5eb-49b3-87da-3247568e6054}) of ThingClass sdm630
----------
The name of the EventType ({270d0c34-0a0c-4655-985f-faad6efd1afd}) of ThingClass pro380</extracomment>
<translation>Spannung L2 geändert</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="340"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="343"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="346"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="349"/>
<source>Voltage L3</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltageL3, ID: {ace6294d-deaa-4d9a-af78-d64379bcb229})
----------
The name of the StateType ({ace6294d-deaa-4d9a-af78-d64379bcb229}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltageL3, ID: {a1da8cfd-37cc-4c87-b857-e942cd90daec})
----------
The name of the StateType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass pro380</extracomment>
<translation>Spannung L3</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="352"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="355"/>
<source>Voltage L3 changed</source>
<extracomment>The name of the EventType ({ace6294d-deaa-4d9a-af78-d64379bcb229}) of ThingClass sdm630
----------
The name of the EventType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass pro380</extracomment>
<translation>Spannung L3 geändert</translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="358"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="546"/>
<source>inepro Metering</source>
<extracomment>The name of the vendor ({64f4df0f-18ce-409c-bf32-84a086c691ca})</extracomment>
<translation>inepro Metering</translation>
@ -358,32 +544,32 @@ The name of the EventType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass
<context>
<name>IntegrationPluginEnergyMeters</name>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="116"/>
<location filename="../integrationpluginenergymeters.cpp" line="75"/>
<source>No Modbus RTU interface available.</source>
<translation>Keine Modbus RTU Schnittstelle verfügbar</translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="123"/>
<location filename="../integrationpluginenergymeters.cpp" line="83"/>
<source>Modbus slave address must be between 1 and 254</source>
<translation>Die Modbus-Slave-Adresse muss zwischen 1 und 254 liegen</translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="131"/>
<location filename="../integrationpluginenergymeters.cpp" line="92"/>
<source>Energy meter</source>
<translation>Energiezähler</translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="131"/>
<location filename="../integrationpluginenergymeters.cpp" line="92"/>
<source>Slave address </source>
<translation>Slave-Adresse</translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="159"/>
<location filename="../integrationpluginenergymeters.cpp" line="113"/>
<source>Slave address not valid, must be between 1 and 254</source>
<translation>Die Slave-Adresse ist ungültig, sie muss zwischen 1 und 254 liegen</translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="165"/>
<location filename="../integrationpluginenergymeters.cpp" line="120"/>
<source>Modbus RTU resource not available.</source>
<translation>Modbus RTU Schnittstelle nicht verfügbar</translation>
</message>

View File

@ -4,40 +4,16 @@
<context>
<name>EnergyMeters</name>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="109"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="112"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="115"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="118"/>
<source>Active power</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPower, ID: {c824e97b-a6d1-4030-9d7a-00af6fb8e1c3})
----------
The name of the StateType ({c824e97b-a6d1-4030-9d7a-00af6fb8e1c3}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPower, ID: {464eff60-11c2-46b7-98f5-1aa8172e5a2d})
----------
The name of the StateType ({464eff60-11c2-46b7-98f5-1aa8172e5a2d}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="121"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="124"/>
<source>Active power changed</source>
<extracomment>The name of the EventType ({c824e97b-a6d1-4030-9d7a-00af6fb8e1c3}) of ThingClass sdm630
----------
The name of the EventType ({464eff60-11c2-46b7-98f5-1aa8172e5a2d}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="127"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="156"/>
<source>B+G e-tech</source>
<extracomment>The name of the vendor ({215035fe-95e8-43d8-a52e-0a31b787d902})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="130"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="133"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="136"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="139"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="159"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="162"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="165"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="168"/>
<source>Connected</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: connected, ID: {8050bd0b-1dad-4a7e-b632-c71ead3c9f8b})
----------
@ -49,8 +25,8 @@ The name of the StateType ({7f9bc504-0882-4b86-83b1-42fa345acfd9}) of ThingClass
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="142"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="145"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="171"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="174"/>
<source>Connected changed</source>
<extracomment>The name of the EventType ({8050bd0b-1dad-4a7e-b632-c71ead3c9f8b}) of ThingClass sdm630
----------
@ -58,88 +34,328 @@ The name of the EventType ({7f9bc504-0882-4b86-83b1-42fa345acfd9}) of ThingClass
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="148"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="151"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="154"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="157"/>
<source>Current L1</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentL1, ID: {4baf1d08-5ffa-49cf-95ef-9527b0c6f081})
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="177"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="180"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="183"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="186"/>
<source>Current phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPhaseA, ID: {4baf1d08-5ffa-49cf-95ef-9527b0c6f081})
----------
The name of the StateType ({4baf1d08-5ffa-49cf-95ef-9527b0c6f081}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentL1, ID: {1e077a3b-2dab-4ec4-ae96-ab49a564fe31})
The name of the ParamType (ThingClass: pro380, EventType: currentPhaseA, ID: {1e077a3b-2dab-4ec4-ae96-ab49a564fe31})
----------
The name of the StateType ({1e077a3b-2dab-4ec4-ae96-ab49a564fe31}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="160"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="163"/>
<source>Current L1 changed</source>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="189"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="192"/>
<source>Current phase A changed</source>
<extracomment>The name of the EventType ({4baf1d08-5ffa-49cf-95ef-9527b0c6f081}) of ThingClass sdm630
----------
The name of the EventType ({1e077a3b-2dab-4ec4-ae96-ab49a564fe31}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="166"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="169"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="172"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="175"/>
<source>Current L2</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentL2, ID: {99e47d06-0a6a-4bfd-b164-61ecb6ba2818})
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="195"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="198"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="201"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="204"/>
<source>Current phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPhaseB, ID: {99e47d06-0a6a-4bfd-b164-61ecb6ba2818})
----------
The name of the StateType ({99e47d06-0a6a-4bfd-b164-61ecb6ba2818}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentL2, ID: {d2f54061-0807-47de-944c-68c8118ece91})
The name of the ParamType (ThingClass: pro380, EventType: currentPhaseB, ID: {d2f54061-0807-47de-944c-68c8118ece91})
----------
The name of the StateType ({d2f54061-0807-47de-944c-68c8118ece91}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="178"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="181"/>
<source>Current L2 changed</source>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="207"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="210"/>
<source>Current phase B changed</source>
<extracomment>The name of the EventType ({99e47d06-0a6a-4bfd-b164-61ecb6ba2818}) of ThingClass sdm630
----------
The name of the EventType ({d2f54061-0807-47de-944c-68c8118ece91}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="184"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="187"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="190"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="193"/>
<source>Current L3</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentL3, ID: {4a092a66-352d-4d60-90ab-6ac5f58b92fe})
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="213"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="216"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="219"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="222"/>
<source>Current phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPhaseC, ID: {4a092a66-352d-4d60-90ab-6ac5f58b92fe})
----------
The name of the StateType ({4a092a66-352d-4d60-90ab-6ac5f58b92fe}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentL3, ID: {610b20fb-2718-4f02-ac6e-12a9ef8c7615})
The name of the ParamType (ThingClass: pro380, EventType: currentPhaseC, ID: {610b20fb-2718-4f02-ac6e-12a9ef8c7615})
----------
The name of the StateType ({610b20fb-2718-4f02-ac6e-12a9ef8c7615}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="196"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="199"/>
<source>Current L3 changed</source>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="225"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="228"/>
<source>Current phase C changed</source>
<extracomment>The name of the EventType ({4a092a66-352d-4d60-90ab-6ac5f58b92fe}) of ThingClass sdm630
----------
The name of the EventType ({610b20fb-2718-4f02-ac6e-12a9ef8c7615}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="202"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="231"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="234"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="237"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="240"/>
<source>Current power</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPower, ID: {c824e97b-a6d1-4030-9d7a-00af6fb8e1c3})
----------
The name of the StateType ({c824e97b-a6d1-4030-9d7a-00af6fb8e1c3}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPower, ID: {464eff60-11c2-46b7-98f5-1aa8172e5a2d})
----------
The name of the StateType ({464eff60-11c2-46b7-98f5-1aa8172e5a2d}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="243"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="246"/>
<source>Current power changed</source>
<extracomment>The name of the EventType ({c824e97b-a6d1-4030-9d7a-00af6fb8e1c3}) of ThingClass sdm630
----------
The name of the EventType ({464eff60-11c2-46b7-98f5-1aa8172e5a2d}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="249"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="252"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="255"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="258"/>
<source>Current power phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPowerPhaseA, ID: {3982fb12-b179-40f7-9b27-36adb1cadd37})
----------
The name of the StateType ({3982fb12-b179-40f7-9b27-36adb1cadd37}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPowerPhaseA, ID: {55283773-0a4e-4574-b21a-d4a3f287eab1})
----------
The name of the StateType ({55283773-0a4e-4574-b21a-d4a3f287eab1}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="261"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="264"/>
<source>Current power phase A changed</source>
<extracomment>The name of the EventType ({3982fb12-b179-40f7-9b27-36adb1cadd37}) of ThingClass sdm630
----------
The name of the EventType ({55283773-0a4e-4574-b21a-d4a3f287eab1}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="267"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="270"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="273"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="276"/>
<source>Current power phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPowerPhaseB, ID: {2a231c58-b095-4037-8394-a730431e70b8})
----------
The name of the StateType ({2a231c58-b095-4037-8394-a730431e70b8}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPowerPhaseB, ID: {8f15d104-5ff7-4c33-9cf9-fdbef4b6f721})
----------
The name of the StateType ({8f15d104-5ff7-4c33-9cf9-fdbef4b6f721}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="279"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="282"/>
<source>Current power phase B changed</source>
<extracomment>The name of the EventType ({2a231c58-b095-4037-8394-a730431e70b8}) of ThingClass sdm630
----------
The name of the EventType ({8f15d104-5ff7-4c33-9cf9-fdbef4b6f721}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="285"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="288"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="291"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="294"/>
<source>Current power phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: currentPowerPhaseC, ID: {ee8c4f0c-2b69-4210-9966-1553a592b06d})
----------
The name of the StateType ({ee8c4f0c-2b69-4210-9966-1553a592b06d}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: currentPowerPhaseC, ID: {86c0f968-ee70-4f56-bdfc-33b8e2b134a4})
----------
The name of the StateType ({86c0f968-ee70-4f56-bdfc-33b8e2b134a4}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="297"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="300"/>
<source>Current power phase C changed</source>
<extracomment>The name of the EventType ({ee8c4f0c-2b69-4210-9966-1553a592b06d}) of ThingClass sdm630
----------
The name of the EventType ({86c0f968-ee70-4f56-bdfc-33b8e2b134a4}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="303"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="306"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="309"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="312"/>
<source>Energy consumed phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyConsumedPhaseA, ID: {6ca06c81-fe75-4448-a22f-47c303421440})
----------
The name of the StateType ({6ca06c81-fe75-4448-a22f-47c303421440}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyConsumedPhaseA, ID: {b16b3b0c-82d9-4b3c-a172-0e6631c8ce16})
----------
The name of the StateType ({b16b3b0c-82d9-4b3c-a172-0e6631c8ce16}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="315"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="318"/>
<source>Energy consumed phase A changed</source>
<extracomment>The name of the EventType ({6ca06c81-fe75-4448-a22f-47c303421440}) of ThingClass sdm630
----------
The name of the EventType ({b16b3b0c-82d9-4b3c-a172-0e6631c8ce16}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="321"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="324"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="327"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="330"/>
<source>Energy consumed phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyConsumedPhaseB, ID: {fa2b879b-2a81-4bc8-9577-98082c4d9330})
----------
The name of the StateType ({fa2b879b-2a81-4bc8-9577-98082c4d9330}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyConsumedPhaseB, ID: {64225f7f-9b2f-4bfc-87b2-38758804a28b})
----------
The name of the StateType ({64225f7f-9b2f-4bfc-87b2-38758804a28b}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="333"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="336"/>
<source>Energy consumed phase B changed</source>
<extracomment>The name of the EventType ({fa2b879b-2a81-4bc8-9577-98082c4d9330}) of ThingClass sdm630
----------
The name of the EventType ({64225f7f-9b2f-4bfc-87b2-38758804a28b}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="339"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="342"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="345"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="348"/>
<source>Energy consumed phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyConsumedPhaseC, ID: {4c084c9e-7a5d-42d1-96b2-a8a4b4a25713})
----------
The name of the StateType ({4c084c9e-7a5d-42d1-96b2-a8a4b4a25713}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyConsumedPhaseC, ID: {a6e82d61-e837-4ec8-b14a-af0d49bea9d2})
----------
The name of the StateType ({a6e82d61-e837-4ec8-b14a-af0d49bea9d2}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="351"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="354"/>
<source>Energy consumed phase C changed</source>
<extracomment>The name of the EventType ({4c084c9e-7a5d-42d1-96b2-a8a4b4a25713}) of ThingClass sdm630
----------
The name of the EventType ({a6e82d61-e837-4ec8-b14a-af0d49bea9d2}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="357"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="360"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="363"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="366"/>
<source>Energy produced phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyProducedPhaseA, ID: {308fa88e-6054-4c79-b12a-be2d0a404ef6})
----------
The name of the StateType ({308fa88e-6054-4c79-b12a-be2d0a404ef6}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyProducedPhaseA, ID: {95bd476e-c247-4f7d-ab01-d9f1b7c0d996})
----------
The name of the StateType ({95bd476e-c247-4f7d-ab01-d9f1b7c0d996}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="369"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="372"/>
<source>Energy produced phase A changed</source>
<extracomment>The name of the EventType ({308fa88e-6054-4c79-b12a-be2d0a404ef6}) of ThingClass sdm630
----------
The name of the EventType ({95bd476e-c247-4f7d-ab01-d9f1b7c0d996}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="375"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="378"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="381"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="384"/>
<source>Energy produced phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyProducedPhaseB, ID: {48ab6e61-dfb4-4f85-b5cc-9d89e53c6b39})
----------
The name of the StateType ({48ab6e61-dfb4-4f85-b5cc-9d89e53c6b39}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyProducedPhaseB, ID: {f0a0bd81-708c-48d6-b5c9-165464a5b309})
----------
The name of the StateType ({f0a0bd81-708c-48d6-b5c9-165464a5b309}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="387"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="390"/>
<source>Energy produced phase B changed</source>
<extracomment>The name of the EventType ({48ab6e61-dfb4-4f85-b5cc-9d89e53c6b39}) of ThingClass sdm630
----------
The name of the EventType ({f0a0bd81-708c-48d6-b5c9-165464a5b309}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="393"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="396"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="399"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="402"/>
<source>Energy produced phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: energyProducedPhaseC, ID: {6b3ddf15-3d4b-4dc1-8e5a-84fbf90b49ff})
----------
The name of the StateType ({6b3ddf15-3d4b-4dc1-8e5a-84fbf90b49ff}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: energyProducedPhaseC, ID: {c33fcd11-b4a9-44b2-9e30-40dfa2e4c9b1})
----------
The name of the StateType ({c33fcd11-b4a9-44b2-9e30-40dfa2e4c9b1}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="405"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="408"/>
<source>Energy produced phase C changed</source>
<extracomment>The name of the EventType ({6b3ddf15-3d4b-4dc1-8e5a-84fbf90b49ff}) of ThingClass sdm630
----------
The name of the EventType ({c33fcd11-b4a9-44b2-9e30-40dfa2e4c9b1}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="411"/>
<source>EnergyMeters</source>
<extracomment>The name of the plugin EnergyMeters ({56e95111-fb6b-4f63-9a0a-a5ee001e89ed})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="205"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="208"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="211"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="214"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="414"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="417"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="420"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="423"/>
<source>Frequency</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: frequency, ID: {ab24f26c-dc15-4ec3-8d76-06a48285440b})
----------
@ -151,8 +367,8 @@ The name of the StateType ({bb6fd00c-3bbb-4977-bb8a-96787bb6f5c5}) of ThingClass
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="217"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="220"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="426"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="429"/>
<source>Frequency changed</source>
<extracomment>The name of the EventType ({ab24f26c-dc15-4ec3-8d76-06a48285440b}) of ThingClass sdm630
----------
@ -160,8 +376,8 @@ The name of the EventType ({bb6fd00c-3bbb-4977-bb8a-96787bb6f5c5}) of ThingClass
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="223"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="226"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="432"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="435"/>
<source>Modbus RTU master</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, Type: thing, ID: {d90e9292-d03c-4f2a-957e-5d965018c9c9})
----------
@ -169,8 +385,8 @@ The name of the ParamType (ThingClass: pro380, Type: thing, ID: {6cdbec8c-21b9-4
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="229"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="232"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="438"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="441"/>
<source>Modbus slave address</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, Type: thing, ID: {ac77ea98-b006-486e-a3e8-b30a483f26c1})
----------
@ -178,44 +394,92 @@ The name of the ParamType (ThingClass: pro380, Type: thing, ID: {c75b2c31-6ec3-4
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="235"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="444"/>
<source>PRO380-Mod</source>
<extracomment>The name of the ThingClass ({d7c6440b-54f9-4cc0-a96b-9bb7304b3e77})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="238"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="241"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="244"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="247"/>
<source>Power factor</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: powerFactor, ID: {31b9032f-f994-472b-94bd-44f9fb094801})
----------
The name of the StateType ({31b9032f-f994-472b-94bd-44f9fb094801}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: powerFactor, ID: {cdb34487-3d9b-492a-8c33-802f32a2e90e})
----------
The name of the StateType ({cdb34487-3d9b-492a-8c33-802f32a2e90e}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="250"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="253"/>
<source>Power factor changed</source>
<extracomment>The name of the EventType ({31b9032f-f994-472b-94bd-44f9fb094801}) of ThingClass sdm630
----------
The name of the EventType ({cdb34487-3d9b-492a-8c33-802f32a2e90e}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="256"/>
<source>SDM630Modbus</source>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="447"/>
<source>SDM630 Modbus</source>
<extracomment>The name of the ThingClass ({f37597bb-35fe-48f2-9617-343dd54c0903})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="259"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="262"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="492"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="495"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="498"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="501"/>
<source>Voltage phase A</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltagePhaseA, ID: {db018146-0441-4dc0-9834-6d43ebaf8311})
----------
The name of the StateType ({db018146-0441-4dc0-9834-6d43ebaf8311}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltagePhaseA, ID: {04dba21a-7447-46b9-b9ae-095e5769e511})
----------
The name of the StateType ({04dba21a-7447-46b9-b9ae-095e5769e511}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="504"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="507"/>
<source>Voltage phase A changed</source>
<extracomment>The name of the EventType ({db018146-0441-4dc0-9834-6d43ebaf8311}) of ThingClass sdm630
----------
The name of the EventType ({04dba21a-7447-46b9-b9ae-095e5769e511}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="510"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="513"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="516"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="519"/>
<source>Voltage phase B</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltagePhaseB, ID: {406f6d02-d5eb-49b3-87da-3247568e6054})
----------
The name of the StateType ({406f6d02-d5eb-49b3-87da-3247568e6054}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltagePhaseB, ID: {270d0c34-0a0c-4655-985f-faad6efd1afd})
----------
The name of the StateType ({270d0c34-0a0c-4655-985f-faad6efd1afd}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="522"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="525"/>
<source>Voltage phase B changed</source>
<extracomment>The name of the EventType ({406f6d02-d5eb-49b3-87da-3247568e6054}) of ThingClass sdm630
----------
The name of the EventType ({270d0c34-0a0c-4655-985f-faad6efd1afd}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="528"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="531"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="534"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="537"/>
<source>Voltage phase C</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltagePhaseC, ID: {ace6294d-deaa-4d9a-af78-d64379bcb229})
----------
The name of the StateType ({ace6294d-deaa-4d9a-af78-d64379bcb229}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltagePhaseC, ID: {a1da8cfd-37cc-4c87-b857-e942cd90daec})
----------
The name of the StateType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="540"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="543"/>
<source>Voltage phase C changed</source>
<extracomment>The name of the EventType ({ace6294d-deaa-4d9a-af78-d64379bcb229}) of ThingClass sdm630
----------
The name of the EventType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="450"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="453"/>
<source>Slave address</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, Type: discovery, ID: {6ab43559-53ec-47ba-b8a0-8d3b7f8d90c2})
----------
@ -223,10 +487,10 @@ The name of the ParamType (ThingClass: pro380, Type: discovery, ID: {a29f37f6-b3
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="265"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="268"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="271"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="274"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="456"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="459"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="462"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="465"/>
<source>Total energy consumed</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: totalEnergyConsumed, ID: {98d858a8-22e8-4262-b5c7-25bb027942ad})
----------
@ -238,8 +502,8 @@ The name of the StateType ({f18fd596-b47f-44be-a0f0-6ca44369ebf5}) of ThingClass
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="277"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="280"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="468"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="471"/>
<source>Total energy consumed changed</source>
<extracomment>The name of the EventType ({98d858a8-22e8-4262-b5c7-25bb027942ad}) of ThingClass sdm630
----------
@ -247,10 +511,10 @@ The name of the EventType ({f18fd596-b47f-44be-a0f0-6ca44369ebf5}) of ThingClass
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="283"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="286"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="289"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="292"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="474"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="477"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="480"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="483"/>
<source>Total energy produced</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: totalEnergyProduced, ID: {e469b3ff-a4c2-42da-af35-ccafaef214af})
----------
@ -262,8 +526,8 @@ The name of the StateType ({112911c9-14e0-4c83-ac92-f2ceb3bdecdf}) of ThingClass
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="295"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="298"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="486"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="489"/>
<source>Total energy produced changed</source>
<extracomment>The name of the EventType ({e469b3ff-a4c2-42da-af35-ccafaef214af}) of ThingClass sdm630
----------
@ -271,85 +535,7 @@ The name of the EventType ({112911c9-14e0-4c83-ac92-f2ceb3bdecdf}) of ThingClass
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="301"/>
<source>Update interval</source>
<extracomment>The name of the ParamType (ThingClass: energyMeters, Type: plugin, ID: {eaa84c3c-06b8-4642-a40b-c2efbe6aae66})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="304"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="307"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="310"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="313"/>
<source>Voltage L1</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltageL1, ID: {db018146-0441-4dc0-9834-6d43ebaf8311})
----------
The name of the StateType ({db018146-0441-4dc0-9834-6d43ebaf8311}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltageL1, ID: {04dba21a-7447-46b9-b9ae-095e5769e511})
----------
The name of the StateType ({04dba21a-7447-46b9-b9ae-095e5769e511}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="316"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="319"/>
<source>Voltage L1 changed</source>
<extracomment>The name of the EventType ({db018146-0441-4dc0-9834-6d43ebaf8311}) of ThingClass sdm630
----------
The name of the EventType ({04dba21a-7447-46b9-b9ae-095e5769e511}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="322"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="325"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="328"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="331"/>
<source>Voltage L2</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltageL2, ID: {406f6d02-d5eb-49b3-87da-3247568e6054})
----------
The name of the StateType ({406f6d02-d5eb-49b3-87da-3247568e6054}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltageL2, ID: {270d0c34-0a0c-4655-985f-faad6efd1afd})
----------
The name of the StateType ({270d0c34-0a0c-4655-985f-faad6efd1afd}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="334"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="337"/>
<source>Voltage L2 changed</source>
<extracomment>The name of the EventType ({406f6d02-d5eb-49b3-87da-3247568e6054}) of ThingClass sdm630
----------
The name of the EventType ({270d0c34-0a0c-4655-985f-faad6efd1afd}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="340"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="343"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="346"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="349"/>
<source>Voltage L3</source>
<extracomment>The name of the ParamType (ThingClass: sdm630, EventType: voltageL3, ID: {ace6294d-deaa-4d9a-af78-d64379bcb229})
----------
The name of the StateType ({ace6294d-deaa-4d9a-af78-d64379bcb229}) of ThingClass sdm630
----------
The name of the ParamType (ThingClass: pro380, EventType: voltageL3, ID: {a1da8cfd-37cc-4c87-b857-e942cd90daec})
----------
The name of the StateType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="352"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="355"/>
<source>Voltage L3 changed</source>
<extracomment>The name of the EventType ({ace6294d-deaa-4d9a-af78-d64379bcb229}) of ThingClass sdm630
----------
The name of the EventType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass pro380</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="358"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/energymeters/plugininfo.h" line="546"/>
<source>inepro Metering</source>
<extracomment>The name of the vendor ({64f4df0f-18ce-409c-bf32-84a086c691ca})</extracomment>
<translation type="unfinished"></translation>
@ -358,32 +544,32 @@ The name of the EventType ({a1da8cfd-37cc-4c87-b857-e942cd90daec}) of ThingClass
<context>
<name>IntegrationPluginEnergyMeters</name>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="116"/>
<location filename="../integrationpluginenergymeters.cpp" line="75"/>
<source>No Modbus RTU interface available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="123"/>
<location filename="../integrationpluginenergymeters.cpp" line="83"/>
<source>Modbus slave address must be between 1 and 254</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="131"/>
<location filename="../integrationpluginenergymeters.cpp" line="92"/>
<source>Energy meter</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="131"/>
<location filename="../integrationpluginenergymeters.cpp" line="92"/>
<source>Slave address </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="159"/>
<location filename="../integrationpluginenergymeters.cpp" line="113"/>
<source>Slave address not valid, must be between 1 and 254</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginenergymeters.cpp" line="165"/>
<location filename="../integrationpluginenergymeters.cpp" line="120"/>
<source>Modbus RTU resource not available.</source>
<translation type="unfinished"></translation>
</message>

View File

@ -65,7 +65,7 @@ The basic structure of the modbus register JSON looks like following example:
},
...
]
}
}
```
@ -78,6 +78,15 @@ 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`
## Protocol
Depending on the communication protocol, a different base class will be used for the resulting output class.
There are 2 possibilities:
* `RTU`: a communication based on the RS485 serial RTU transport protocol
* `TCP`: a communication based on the TCP transport protocol
## 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 `<EnumName><EnumValueName> = <value>`.
@ -120,6 +129,50 @@ Earch register will be defined as a property in the resulting class modbus TCP c
* `staticScaleFactor`: Optional. Use this static scale factor to convert this register value to float. `floatValue = registerValue * 10^staticScaleFactor`. The scale factor value is normally a `int16` value, i.e. -10 or 10
* `defaultValue`: Optional. The value for initializing the property.
# Register blocks
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!
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.
* `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:
* `init`: The register will be fetched during initialization. Once all `init `registers have been fetched, the `initializationFinished()` signal will be emitted.
* `update`: The register will be feched each time the `update()` method will be called.
* `registers`: Mandatory. The list of registers within the block. Please see the [Registers](#register) definition for more details about registers. The must be from the same register type, the same access type and there are no gaps allowed.
Example block:
"blocks": [
{
"id": "meaningFullName",
"readSchedule": "update",
"registers": [
{
"id": "registerOne",
"address": 0,
"size": 2,
...
},
{
"id": "registerTwo",
"address": 2,
"size": 1,
...
},
{
"id": "registerThree",
"address": 3,
"size": 2,
...
},
]
}
]
# Example
Change into your plugin sub directory.

View File

@ -230,56 +230,56 @@ def getValueConversionMethod(registerDefinition):
if 'enum' in registerDefinition:
enumName = registerDefinition['enum']
if registerDefinition['type'] == 'uint16':
return ('static_cast<%s>(ModbusDataUtils::convertToUInt16(unit.values()))' % (enumName))
return ('static_cast<%s>(ModbusDataUtils::convertToUInt16(values))' % (enumName))
elif registerDefinition['type'] == 'int16':
return ('static_cast<%s>(ModbusDataUtils::convertToInt16(unit.values()))' % (enumName))
return ('static_cast<%s>(ModbusDataUtils::convertToInt16(values))' % (enumName))
elif registerDefinition['type'] == 'uint32':
return ('static_cast<%s>(ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
return ('static_cast<%s>(ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
elif registerDefinition['type'] == 'int32':
return ('static_cast<%s>(ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
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(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
return ('ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
elif registerDefinition['type'] == 'int16':
return ('ModbusDataUtils::convertToInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
return ('ModbusDataUtils::convertToInt16(values) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
elif registerDefinition['type'] == 'uint32':
return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactorProperty))
return ('ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactorProperty))
elif registerDefinition['type'] == 'int32':
return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactorProperty))
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(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactor))
return ('ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, %s)' % (scaleFactor))
elif registerDefinition['type'] == 'int16':
return ('ModbusDataUtils::convertToInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactor))
return ('ModbusDataUtils::convertToInt16(values) * 1.0 * pow(10, %s)' % (scaleFactor))
elif registerDefinition['type'] == 'uint32':
return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
return ('ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
elif registerDefinition['type'] == 'int32':
return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
return ('ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
# Handle default types
elif registerDefinition['type'] == 'uint16':
return ('ModbusDataUtils::convertToUInt16(unit.values())')
return ('ModbusDataUtils::convertToUInt16(values)')
elif registerDefinition['type'] == 'int16':
return ('ModbusDataUtils::convertToInt16(unit.values())')
return ('ModbusDataUtils::convertToInt16(values)')
elif registerDefinition['type'] == 'uint32':
return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
return ('ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'int32':
return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
return ('ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'uint64':
return ('ModbusDataUtils::convertToUInt64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
return ('ModbusDataUtils::convertToUInt64(values, ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'int64':
return ('ModbusDataUtils::convertToInt64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
return ('ModbusDataUtils::convertToInt64(values, ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'float':
return ('ModbusDataUtils::convertToFloat32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
return ('ModbusDataUtils::convertToFloat32(values, ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'float64':
return ('ModbusDataUtils::convertToFloat64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
return ('ModbusDataUtils::convertToFloat64(values, ModbusDataUtils::ByteOrder%s)' % endianness)
elif registerDefinition['type'] == 'string':
return ('ModbusDataUtils::convertToString(unit.values())')
return ('ModbusDataUtils::convertToString(values)')
def writePropertyGetSetMethodDeclarations(fileDescriptor, registerDefinitions):
@ -300,7 +300,7 @@ def writePropertyGetSetMethodDeclarations(fileDescriptor, registerDefinitions):
writeLine(fileDescriptor)
def writePropertyGetSetMethodImplementations(fileDescriptor, className, registerDefinitions):
def writePropertyGetSetMethodImplementationsTcp(fileDescriptor, className, registerDefinitions):
for registerDefinition in registerDefinitions:
propertyName = registerDefinition['id']
propertyTyp = getCppDataType(registerDefinition)
@ -324,8 +324,11 @@ def writePropertyGetSetMethodImplementations(fileDescriptor, className, register
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Write \\"%s\\" register:" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
if registerDefinition['registerType'] == 'holdingRegister':
writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, %s, values.count());' % (registerDefinition['address']))
# TODO: other write methods
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);')
@ -333,6 +336,39 @@ def writePropertyGetSetMethodImplementations(fileDescriptor, className, register
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<quint16> 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:
@ -344,7 +380,76 @@ def writePropertyUpdateMethodDeclarations(fileDescriptor, registerDefinitions):
writeLine(fileDescriptor, ' void update%s();' % (propertyName[0].upper() + propertyName[1:]))
def writePropertyUpdateMethodImplementations(fileDescriptor, className, registerDefinitions):
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
writePropertyGetSetMethodDeclarations(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
@ -362,9 +467,8 @@ def writePropertyUpdateMethodImplementations(fileDescriptor, className, register
writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){')
writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {')
writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();')
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
# FIXME: introduce bool and check register type for parsing
writeLine(fileDescriptor, ' const QVector<quint16> 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:]))
@ -387,13 +491,132 @@ def writePropertyUpdateMethodImplementations(fileDescriptor, className, register
writeLine(fileDescriptor)
def writeInternalPropertyReadMethodDeclarations(fileDescriptor, registerDefinitions):
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<quint16> 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<quint16> blockValues = reply->result();')
writeLine(fileDescriptor, ' QVector<quint16> 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 writeInternalPropertyReadMethodDeclarationsTcp(fileDescriptor, registerDefinitions):
for registerDefinition in registerDefinitions:
propertyName = registerDefinition['id']
writeLine(fileDescriptor, ' QModbusReply *read%s();' % (propertyName[0].upper() + propertyName[1:]))
def writeInternalPropertyReadMethodImplementations(fileDescriptor, className, registerDefinitions):
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:]))
@ -415,6 +638,28 @@ def writeInternalPropertyReadMethodImplementations(fileDescriptor, className, re
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']
@ -447,6 +692,7 @@ def writeInitializeMethod(fileDescriptor, className, registerDefinitions):
break
if initRequired:
# FIXME: distinguish between RTU and TCP
writeLine(fileDescriptor, ' QModbusReply *reply = nullptr;')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' if (!m_pendingInitReplies.isEmpty()) {')
@ -508,10 +754,332 @@ def writeUpdateMethod(fileDescriptor, className, registerDefinitions):
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 <QObject>')
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:')
# 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
writePropertyGetSetMethodDeclarations(headerFile, registerJson['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)
# Write registers value changed signals
writeLine(headerFile, 'signals:')
writeLine(headerFile, ' void initializationFinished();')
writeLine(headerFile)
writePropertyChangedSignals(headerFile, registerJson['registers'])
for blockDefinition in registerJson['blocks']:
writePropertyChangedSignals(headerFile, blockDefinition['registers'])
writeLine(headerFile)
# Private members
writeLine(headerFile, 'private:')
writeLine(headerFile, ' quint16 m_slaveId = 1;')
writeLine(headerFile, ' QVector<QModbusReply *> m_pendingInitReplies;')
writeLine(headerFile)
writePrivatePropertyMembers(headerFile, registerJson['registers'])
for blockDefinition in registerJson['blocks']:
writePrivatePropertyMembers(headerFile, blockDefinition['registers'])
writeLine(headerFile)
writeLine(headerFile, ' void verifyInitFinished();')
writeLine(headerFile)
writeInternalPropertyReadMethodDeclarationsTcp(headerFile, registerJson['registers'])
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'])
# 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 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'])
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 <QObject>')
writeLine(headerFile)
writeLine(headerFile, '#include "../modbus/modbusdatautils.h"')
writeLine(headerFile, '#include <hardware/modbus/modbusrtumaster.h>')
writeLine(headerFile)
# Begin of class
writeLine(headerFile, 'class %s : public QObject' % className)
writeLine(headerFile, '{')
writeLine(headerFile, ' Q_OBJECT')
# Public members
writeLine(headerFile, 'public:')
# 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
writePropertyGetSetMethodDeclarations(headerFile, registerJson['registers'])
# Write block get/set method declarations
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'])
for blockDefinition in registerJson['blocks']:
writePropertyChangedSignals(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<ModbusRtuReply *> m_pendingInitReplies;')
writeLine(headerFile)
writePrivatePropertyMembers(headerFile, registerJson['registers'])
for blockDefinition in registerJson['blocks']:
writePrivatePropertyMembers(headerFile, blockDefinition['registers'])
writeLine(headerFile)
writeLine(headerFile, ' void verifyInitFinished();')
writeLine(headerFile)
writeInternalPropertyReadMethodDeclarationsRtu(headerFile, registerJson['registers'])
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
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
writeBlockUpdateMethodImplementationsRtu(sourceFile, className, registerJson['blocks'])
# Write 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'])
for blockDefinition in registerJson['blocks']:
writeRegistersDebugLine(sourceFile, debugObjectParamName, blockDefinition['registers'])
writeLine(sourceFile, ' return debug.quote().space();')
writeLine(sourceFile, '}')
writeLine(sourceFile)
sourceFile.close()
############################################################################################
# Main
############################################################################################
@ -545,142 +1113,18 @@ endianness = 'BigEndian'
if 'endianness' in registerJson:
endianness = registerJson['endianness']
protocol = 'TCP'
if 'protocol' in registerJson:
protocol = registerJson['protocol']
#############################################################################
# Write header file
#############################################################################
validateBlocks(registerJson['blocks'])
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 <QObject>')
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:')
# Enum declarations
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
writePropertyGetSetMethodDeclarations(headerFile, registerJson['registers'])
# 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'])
writeLine(headerFile)
# Private members
writeLine(headerFile, 'private:')
writeLine(headerFile, ' quint16 m_slaveId = 1;')
writeLine(headerFile, ' QVector<QModbusReply *> m_pendingInitReplies;')
writeLine(headerFile)
writePrivatePropertyMembers(headerFile, registerJson['registers'])
writeLine(headerFile)
writeLine(headerFile, ' void verifyInitFinished();')
writeLine(headerFile)
writeInternalPropertyReadMethodDeclarations(headerFile, registerJson['registers'])
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()
if protocol == 'TCP':
writeTcpHeaderFile()
writeTcpSourceFile()
else:
writeRtuHeaderFile()
writeRtuSourceFile()
#############################################################################
# Write source file
#############################################################################
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
writePropertyGetSetMethodImplementations(sourceFile, className, registerJson['registers'])
# Write init and update method implementation
writeInitializeMethod(sourceFile, className, registerJson['registers'])
writeUpdateMethod(sourceFile, className, registerJson['registers'])
# Write update methods
writePropertyUpdateMethodImplementations(sourceFile, className, registerJson['registers'])
# Write property read method implementations
writeInternalPropertyReadMethodImplementations(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))
for registerDefinition in registerJson['registers']:
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(sourceFile, ' debug.nospace().noquote() << %s << "\\n";' % (line))
writeLine(sourceFile, ' return debug.quote().space();')
writeLine(sourceFile, '}')
writeLine(sourceFile)
sourceFile.close()