switched to modbus rtu resource
This commit is contained in:
parent
47b661c2c9
commit
4d5911a098
@ -6,9 +6,7 @@ QT += \
|
||||
|
||||
SOURCES += \
|
||||
integrationplugindrexelundweiss.cpp \
|
||||
../modbus/modbusrtumaster.cpp \
|
||||
|
||||
HEADERS += \
|
||||
integrationplugindrexelundweiss.h \
|
||||
modbusdegisterdefinition.h \
|
||||
../modbus/modbusrtumaster.h \
|
||||
modbusdegisterdefinition.h
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -30,50 +30,39 @@
|
||||
|
||||
#include "integrationplugindrexelundweiss.h"
|
||||
#include "plugininfo.h"
|
||||
#include "modbusdegisterdefinition.h"
|
||||
|
||||
#include "hardwaremanager.h"
|
||||
#include "hardware/modbus/modbusrtumaster.h"
|
||||
#include "hardware/modbus/modbusrtuhardwareresource.h"
|
||||
|
||||
IntegrationPluginDrexelUndWeiss::IntegrationPluginDrexelUndWeiss()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IntegrationPluginDrexelUndWeiss::~IntegrationPluginDrexelUndWeiss()
|
||||
{
|
||||
|
||||
m_connectedStateTypeIds.insert(x2luThingClassId, x2luConnectedStateTypeId);
|
||||
m_connectedStateTypeIds.insert(x2wpThingClassId, x2wpConnectedStateTypeId);
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::init()
|
||||
{
|
||||
connect(this, &IntegrationPluginDrexelUndWeiss::configValueChanged, this, &IntegrationPluginDrexelUndWeiss::onPluginConfigurationChanged);
|
||||
|
||||
connect(hardwareManager()->modbusRtuResource(), &ModbusRtuHardwareResource::modbusRtuMasterRemoved, this, [=](const QUuid &modbusUuid){
|
||||
qCDebug(dcDrexelUndWeiss()) << "Modbus RTU master has been removed" << modbusUuid.toString();
|
||||
|
||||
// Check if there is any device using this resource
|
||||
foreach (Thing *thing, m_modbusRtuMasters.keys()) {
|
||||
if (m_modbusRtuMasters.value(thing)->modbusUuid() == modbusUuid) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Hardware resource removed for" << thing << ". The thing will not be functional any more until a new resource has been configured for it.";
|
||||
m_modbusRtuMasters.remove(thing);
|
||||
thing->setStateValue(m_connectedStateTypeIds[thing->thingClassId()], false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
// Create the list of available serial interfaces
|
||||
QList<ThingDescriptor> thingDescriptors;
|
||||
|
||||
if (info->thingClassId() == modbusConnectionThingClassId) {
|
||||
Q_FOREACH(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
|
||||
if (m_usedSerialPorts.contains(port.systemLocation())){
|
||||
//Thing already in use
|
||||
qCDebug(dcDrexelUndWeiss()) << "Found serial port that is already used:" << port.portName();
|
||||
} else {
|
||||
//Serial port is not yet used, create now a new one
|
||||
qCDebug(dcDrexelUndWeiss()) << "Found serial port:" << port.portName();
|
||||
QString description = port.manufacturer() + " " + port.description();
|
||||
ThingDescriptor descriptor(info->thingClassId(), port.portName(), description);
|
||||
ParamList parameters;
|
||||
parameters.append(Param(modbusConnectionThingSerialPortParamTypeId, port.systemLocation()));
|
||||
descriptor.setParams(parameters);
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
} else if (info->thingClassId() == x2luThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
} else if (info->thingClassId() == x2wpThingClassId) {
|
||||
if (info->thingClassId() == x2luThingClassId || info->thingClassId() == x2wpThingClassId) {
|
||||
QList<ThingDescriptor> thingDescriptors;
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
} else {
|
||||
@ -84,26 +73,79 @@ void IntegrationPluginDrexelUndWeiss::discoverThings(ThingDiscoveryInfo *info)
|
||||
void IntegrationPluginDrexelUndWeiss::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
qCDebug(dcDrexelUndWeiss()) << "Setup thing" << thing->name();
|
||||
|
||||
if (thing->thingClassId() == modbusConnectionThingClassId) {
|
||||
if (thing->thingClassId() == x2luThingClassId) {
|
||||
|
||||
QString serialPort = thing->paramValue(modbusConnectionThingSerialPortParamTypeId).toString();
|
||||
int baudRate = thing->paramValue(modbusConnectionThingBaudRateParamTypeId).toInt();
|
||||
QUuid modbusMasterUuid = thing->paramValue(x2luThingModbusMasterUuidParamTypeId).toUuid();
|
||||
uint slaveAddress = thing->paramValue(x2luThingSlaveAddressParamTypeId).toUInt();
|
||||
|
||||
ModbusRTUMaster *modbus = new ModbusRTUMaster(serialPort, baudRate, QSerialPort::Parity::NoParity, 8, 1, this);
|
||||
connect(modbus, &ModbusRTUMaster::connectionStateChanged, this, &IntegrationPluginDrexelUndWeiss::onConnectionStateChanged);
|
||||
connect(modbus, &ModbusRTUMaster::receivedHoldingRegister, this, &IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister);
|
||||
if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(modbusMasterUuid)) {
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable, tr("Modbus RTU interface not available."));
|
||||
}
|
||||
ModbusRtuMaster *modbus = hardwareManager()->modbusRtuResource()->getModbusRtuMaster(modbusMasterUuid);
|
||||
if (!modbus->connected()) {
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable, tr("Modbus RTU interface is not connected."));
|
||||
}
|
||||
|
||||
m_modbusRTUMasters.insert(thing, modbus);
|
||||
m_usedSerialPorts.append(serialPort);
|
||||
ModbusRtuReply *reply = modbus->readHoldingRegister(slaveAddress, ModbusRegisterX2::Geraetetyp);
|
||||
connect(reply, &ModbusRtuReply::finished, reply, &ModbusRtuReply::deleteLater);
|
||||
connect(reply, &ModbusRtuReply::finished, info, [reply, modbus, info, thing, this] {
|
||||
if (reply->error() != ModbusRtuReply::Error::NoError) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Setup failed, received modbus error" << reply->errorString();
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
|
||||
if (reply->result().length() != 1) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Setup failed, received reply has an illegal length";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
if (reply->result().first() != DeviceType::X2_LU) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Device on slave addresss" << reply->slaveAddress() << "is not a X2 ventilation unit";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
m_modbusRtuMasters.insert(thing, modbus);
|
||||
});
|
||||
connect(modbus, &ModbusRtuMaster::connectedChanged, this, &IntegrationPluginDrexelUndWeiss::onConnectionStateChanged);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
} else if (thing->thingClassId() == x2luThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
|
||||
} else if (thing->thingClassId() == x2wpThingClassId) {
|
||||
|
||||
QUuid modbusMasterUuid = thing->paramValue(x2wpThingModbusMasterUuidParamTypeId).toUuid();
|
||||
uint slaveAddress = thing->paramValue(x2wpThingSlaveAddressParamTypeId).toUInt();
|
||||
|
||||
if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(modbusMasterUuid)) {
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable, tr("Modbus RTU interface not available."));
|
||||
}
|
||||
ModbusRtuMaster *modbus = hardwareManager()->modbusRtuResource()->getModbusRtuMaster(modbusMasterUuid);
|
||||
if (!modbus->connected()) {
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable, tr("Modbus RTU interface is not connected."));
|
||||
}
|
||||
ModbusRtuReply *reply = modbus->readHoldingRegister(slaveAddress, ModbusRegisterX2::Geraetetyp);
|
||||
connect(reply, &ModbusRtuReply::finished, reply, &ModbusRtuReply::deleteLater);
|
||||
connect(reply, &ModbusRtuReply::finished, info, [reply, modbus, info, thing, this] {
|
||||
if (reply->error() != ModbusRtuReply::Error::NoError) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Setup failed, received modbus error" << reply->errorString();
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
|
||||
if (reply->result().length() != 1) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Setup failed, received reply has an illegal length";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
if (reply->result().first() != DeviceType::X2_WP) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Device on slave addresss" << reply->slaveAddress() << "is not a X2 heat pump";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
m_modbusRtuMasters.insert(thing, modbus);
|
||||
});
|
||||
connect(modbus, &ModbusRtuMaster::connectedChanged, this, &IntegrationPluginDrexelUndWeiss::onConnectionStateChanged);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
|
||||
} else {
|
||||
Q_ASSERT_X(false, "setupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
@ -111,27 +153,21 @@ void IntegrationPluginDrexelUndWeiss::setupThing(ThingSetupInfo *info)
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::postSetupThing(Thing *thing)
|
||||
{
|
||||
qCDebug(dcDrexelUndWeiss()) << "Post setup thing" << thing->name();
|
||||
if (!m_refreshTimer) {
|
||||
// Refresh timer for TCP read
|
||||
qCDebug(dcDrexelUndWeiss()) << "Creating refresh timer";
|
||||
int refreshTime = configValue(drexelUndWeissPluginUpdateIntervalParamTypeId).toInt();
|
||||
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(refreshTime);
|
||||
connect(m_refreshTimer, &PluginTimer::timeout, this, &IntegrationPluginDrexelUndWeiss::onRefreshTimer);
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == modbusConnectionThingClassId) {
|
||||
// read Register 5000 and emit auto-Thing
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(thing);
|
||||
if (!modbus){
|
||||
qCWarning(dcDrexelUndWeiss()) << "No modbus master available";
|
||||
}
|
||||
thing->setStateValue(modbusConnectionConnectedStateTypeId, true);
|
||||
} else if ((thing->thingClassId() == x2luThingClassId) || (thing->thingClassId() == x2wpThingClassId)) {
|
||||
if ((thing->thingClassId() == x2luThingClassId) || (thing->thingClassId() == x2wpThingClassId)) {
|
||||
Thing *parentThing = myThings().findById(thing->parentId());
|
||||
if (!parentThing) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Could not find the parent Thing";
|
||||
return;
|
||||
}
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parentThing);
|
||||
ModbusRtuMaster *modbus = m_modbusRtuMasters.value(parentThing);
|
||||
if (!modbus){
|
||||
qCWarning(dcDrexelUndWeiss()) << "No modbus interface available";
|
||||
}
|
||||
@ -147,86 +183,40 @@ void IntegrationPluginDrexelUndWeiss::executeAction(ThingActionInfo *info)
|
||||
Thing *thing = info->thing();
|
||||
Action action = info->action();
|
||||
|
||||
if (thing->thingClassId() == modbusConnectionThingClassId) {
|
||||
if (thing->thingClassId() == x2luThingClassId) {
|
||||
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(thing);
|
||||
if (!modbus){
|
||||
qCWarning(dcDrexelUndWeiss()) << "No modbus interface available";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == modbusConnectionDiscoverDevicesActionTypeId) {
|
||||
int slave = action.param(modbusConnectionDiscoverDevicesActionSlaveAddressParamTypeId).value().toInt();
|
||||
discoverModbusSlaves(modbus, slave);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
} else {
|
||||
Q_ASSERT_X(false, "executeAction", QString("Unhandled ActionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
|
||||
}
|
||||
|
||||
} else if (thing->thingClassId() == x2luThingClassId) {
|
||||
Thing *parentThing = myThings().findById(thing->parentId());
|
||||
if (!parentThing) {
|
||||
qWarning(dcDrexelUndWeiss()) << "Could not find the parent thing";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parentThing);
|
||||
int slave = thing->paramValue(x2luThingSlaveAddressParamTypeId).toInt();
|
||||
if (!modbus){
|
||||
qCWarning(dcDrexelUndWeiss()) << "No modbus interface available";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == x2luVentilationModeActionTypeId) {
|
||||
QString mode = action.param(x2luVentilationModeActionVentilationModeParamTypeId).value().toString();
|
||||
int data = 0;
|
||||
|
||||
if (mode == "Manual level 0") {
|
||||
data = VentialtionMode::ManuellStufe0;
|
||||
} else if(mode == "Manual level 1") {
|
||||
data = VentialtionMode::ManuellStufe1;
|
||||
} else if(mode == "Manual level 2") {
|
||||
data = VentialtionMode::ManuellStufe2;
|
||||
}else if(mode == "Manual level 3") {
|
||||
data = VentialtionMode::ManuellStufe3;
|
||||
} else if(mode == "Automatic") {
|
||||
data = VentialtionMode::Automatikbetrieb;
|
||||
} else if(mode == "Party") {
|
||||
data = VentialtionMode::Party;
|
||||
uint slaveAddress = thing->paramValue(x2luThingSlaveAddressParamTypeId).toUInt();
|
||||
if (action.actionTypeId() == x2luPowerActionTypeId) {
|
||||
bool power = action.paramValue(x2luPowerActionPowerParamTypeId).toBool();
|
||||
uint16_t data = 0;
|
||||
if (power) {
|
||||
data = getVentilationModeFromString(thing->stateValue(x2luVentilationModeStateTypeId).toString());
|
||||
} else {
|
||||
data = VentilationMode::ManuellStufe0;
|
||||
}
|
||||
m_pendingActions.insert(modbus->writeHoldingRegister(slave, ModbusRegisterX2::Betriebsart, data), info);
|
||||
return;
|
||||
sendWriteRequest(info, slaveAddress, ModbusRegisterX2::Betriebsart, data);
|
||||
|
||||
} else if (action.actionTypeId() == x2luVentilationModeActionTypeId) {
|
||||
QString mode = action.param(x2luVentilationModeActionVentilationModeParamTypeId).value().toString();
|
||||
uint16_t data = getVentilationModeFromString(mode);
|
||||
sendWriteRequest(info, slaveAddress, ModbusRegisterX2::Betriebsart, data);
|
||||
|
||||
} else {
|
||||
Q_ASSERT_X(false, "executeAction", QString("Unhandled ActionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
|
||||
}
|
||||
} else if (thing->thingClassId() == x2wpThingClassId) {
|
||||
Thing *parentThing = myThings().findById(thing->parentId());
|
||||
if (!parentThing) {
|
||||
qWarning(dcDrexelUndWeiss()) << "Could not find modbus interface";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parentThing);
|
||||
int slave = thing->paramValue(x2wpThingSlaveAddressParamTypeId).toInt();
|
||||
if (!modbus){
|
||||
qCWarning(dcDrexelUndWeiss()) << "No modbus master available";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
uint slaveAddress = thing->paramValue(x2wpThingSlaveAddressParamTypeId).toUInt();
|
||||
if (action.actionTypeId() == x2wpTargetTemperatureActionTypeId) {
|
||||
qreal targetTemp = (action.param(x2wpTargetTemperatureActionTargetTemperatureParamTypeId).value().toDouble());
|
||||
int data = static_cast<int>(qRound(targetTemp * 1000));
|
||||
m_pendingActions.insert(modbus->writeHoldingRegister(slave,ModbusRegisterX2::RaumSoll, data), info);
|
||||
return;
|
||||
uint16_t data = static_cast<uint16_t>(qRound(targetTemp * 1000));
|
||||
sendWriteRequest(info, slaveAddress, ModbusRegisterX2::RaumSoll, data);
|
||||
|
||||
} else if (action.actionTypeId() == x2wpTargetWaterTemperatureActionTypeId) {
|
||||
qreal targetWaterTemp = action.param(x2wpTargetWaterTemperatureActionTargetWaterTemperatureParamTypeId).value().toDouble();
|
||||
int data = static_cast<int>(qRound(targetWaterTemp * 1000));
|
||||
m_pendingActions.insert(modbus->writeHoldingRegister(slave, ModbusRegisterX2::BrauchwasserSolltermperatur, data), info);
|
||||
return;
|
||||
sendWriteRequest(info, slaveAddress, ModbusRegisterX2::BrauchwasserSolltermperatur, data);
|
||||
|
||||
} else {
|
||||
Q_ASSERT_X(false, "executeAction", QString("Unhandled ActionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
|
||||
}
|
||||
@ -235,18 +225,40 @@ void IntegrationPluginDrexelUndWeiss::executeAction(ThingActionInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::sendWriteRequest(ThingActionInfo *info, uint slaveAddress, uint modbusRegister, uint16_t value)
|
||||
{
|
||||
ModbusRtuMaster *modbus = m_modbusRtuMasters.value(info->thing());
|
||||
|
||||
if (!modbus){
|
||||
qCWarning(dcDrexelUndWeiss()) << "Modbus RTU interface available";
|
||||
info->finish(Thing::ThingErrorHardwareFailure, tr("Modbus RTU interface not available."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!modbus->connected()) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Modbus RTU interface not connected";
|
||||
info->finish(Thing::ThingErrorHardwareFailure, tr("Modbus RTU interface not connected."));
|
||||
return;
|
||||
}
|
||||
|
||||
ModbusRtuReply *reply = modbus->writeHoldingRegisters(slaveAddress, modbusRegister, QVector<uint16_t>() << value);
|
||||
connect(reply, &ModbusRtuReply::finished, reply, &ModbusRtuReply::deleteLater);
|
||||
connect(reply, &ModbusRtuReply::finished, info, [info, reply] {
|
||||
|
||||
if (reply->error() != ModbusRtuReply::Error::NoError) {
|
||||
return info->finish(Thing::ThingErrorHardwareFailure);
|
||||
}
|
||||
//TODO update thing state after successfull write requests
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::thingRemoved(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == modbusConnectionThingClassId) {
|
||||
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.take(thing);
|
||||
if (!modbus){
|
||||
qCWarning(dcDrexelUndWeiss()) << "No modbus interface available";
|
||||
return;
|
||||
}
|
||||
m_usedSerialPorts.removeAll(modbus->serialPort());
|
||||
modbus->deleteLater();
|
||||
if (thing->thingClassId() == x2luThingClassId || thing->thingClassId() == x2luThingClassId) {
|
||||
m_modbusRtuMasters.remove(thing);
|
||||
}
|
||||
|
||||
if (myThings().isEmpty()) {
|
||||
@ -258,15 +270,7 @@ void IntegrationPluginDrexelUndWeiss::thingRemoved(Thing *thing)
|
||||
void IntegrationPluginDrexelUndWeiss::onRefreshTimer()
|
||||
{
|
||||
foreach (Thing *thing, myThings()) {
|
||||
|
||||
if (thing->thingClassId() == modbusConnectionThingClassId) {
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(thing);
|
||||
|
||||
if (!modbus) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "No modbus master available";
|
||||
return;
|
||||
}
|
||||
} else if (thing->thingClassId() == x2luThingClassId || thing->thingClassId() == x2wpThingClassId){
|
||||
if (thing->thingClassId() == x2luThingClassId || thing->thingClassId() == x2wpThingClassId){
|
||||
updateStates(thing);
|
||||
}
|
||||
}
|
||||
@ -275,38 +279,279 @@ void IntegrationPluginDrexelUndWeiss::onRefreshTimer()
|
||||
void IntegrationPluginDrexelUndWeiss::updateStates(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == x2luThingClassId) {
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parent);
|
||||
int slave = thing->paramValue(x2luThingSlaveAddressParamTypeId).toInt();
|
||||
ModbusRtuMaster *modbus = m_modbusRtuMasters.value(thing);
|
||||
if (!modbus) {
|
||||
return;
|
||||
}
|
||||
uint slaveAddress = thing->paramValue(x2luThingSlaveAddressParamTypeId).toUInt();
|
||||
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::AktiveLuefterstufe);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::Betriebsart); // Ventilation mode
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::CO2);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::AktiveLuefterstufe);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Betriebsart); // Ventilation mode
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::CO2);
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == x2wpThingClassId) {
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parent);
|
||||
int slave = thing->paramValue(x2wpThingSlaveAddressParamTypeId).toInt();
|
||||
ModbusRtuMaster *modbus = m_modbusRtuMasters.value(thing);
|
||||
if (!modbus) {
|
||||
return;
|
||||
}
|
||||
int slaveAddress = thing->paramValue(x2wpThingSlaveAddressParamTypeId).toUInt();
|
||||
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::Waermepumpe);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::RaumSoll);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::Raum);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::TemperaturWarmwasserspeicherUnten);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::BrauchwasserSolltermperatur);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::Auszenluft);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::Summenstoerung);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::LeistungKompressor);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::LeistungWarmwasser);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::LeistungRaumheizung);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::LeistungLuftvorwaermung);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::EnergieKompressor);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::EnergieWarmwasser);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::EnergieRaumheizung);
|
||||
modbus->readHoldingRegister(slave, ModbusRegisterX2::EnergieLuftvorerwarrmung);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Waermepumpe);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::RaumSoll);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Raum);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::TemperaturWarmwasserspeicherUnten);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::BrauchwasserSolltermperatur);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Auszenluft);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Summenstoerung);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::LeistungKompressor);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::LeistungWarmwasser);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::LeistungRaumheizung);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::LeistungLuftvorwaermung);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::EnergieKompressor);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::EnergieWarmwasser);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::EnergieRaumheizung);
|
||||
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::EnergieLuftvorerwarrmung);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::readHoldingRegister(Thing *thing, ModbusRtuMaster *modbus, uint slaveAddress, uint modbusRegister)
|
||||
{
|
||||
ModbusRtuReply *reply = modbus->readHoldingRegister(slaveAddress, modbusRegister);
|
||||
connect(reply, &ModbusRtuReply::finished, reply, &ModbusRtuReply::deleteLater);
|
||||
connect(reply, &ModbusRtuReply::finished, this, [reply, thing, this] {
|
||||
if (reply->error() != ModbusRtuReply::Error::NoError) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Modbus error" << reply->errorString();
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), false);
|
||||
return;
|
||||
}
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
|
||||
QVector<uint16_t> values = reply->result();
|
||||
|
||||
if (thing->thingClassId() == x2luThingClassId) {
|
||||
switch (reply->registerAddress()) {
|
||||
case ModbusRegisterX2::Waermepumpe:
|
||||
thing->setStateValue(x2wpPowerStateTypeId, values[0]);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::RaumSoll:
|
||||
thing->setStateValue(x2wpTargetTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::Raum:
|
||||
thing->setStateValue(x2wpTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::TemperaturWarmwasserspeicherUnten:
|
||||
thing->setStateValue(x2wpWaterTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::BrauchwasserSolltermperatur:
|
||||
thing->setStateValue(x2wpTargetWaterTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::Auszenluft:
|
||||
thing->setStateValue(x2wpOutsideAirTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::Summenstoerung:
|
||||
if (values[0] != 0) {
|
||||
//get actual error
|
||||
} else {
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "No Error");
|
||||
}
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungAbluftventilator:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Exhaust fan");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerElektroheizstab:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor electric heating element");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerSolar:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor solar");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerWaermepumpe:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor heat pump");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoileruebertemperatur:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler overtemperature");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungCO2Sensor:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "CO2-Sensor");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDruckverlustAbluftZuGrosz:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss exhaust air too big");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDruckverlustZuluftZuGrosz:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss supply air too large");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDurchflussmengeHeizgkreis:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate of heating circuit");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDurchflussmengeSolekreis:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate brine circuit");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTeilnehmerNichtErreichbar:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Participant not available");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerAuszenluft:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor outside air");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerHeizkreisVorlauf:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor heating circuit flow");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerRaum:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor room");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSolarkollektor:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor solar collector");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSole:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSoleAuszenluft:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine outside air");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWaermepumpeHochdruck:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump high pressure");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWaermepumpeNiederdruck:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump low pressure");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWertNichtZulaessig:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Value not allowed");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungZuluftventilator:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Supply air fan");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungKompressor:
|
||||
thing->setStateValue(x2wpPowerCompressorStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::LeistungWarmwasser:
|
||||
thing->setStateValue(x2wpPowerWaterHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungRaumheizung:
|
||||
thing->setStateValue(x2wpPowerRoomHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungLuftvorwaermung:
|
||||
thing->setStateValue(x2wpPowerAirPreheatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieKompressor:
|
||||
thing->setStateValue(x2wpEnergyCompressorStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieWarmwasser:
|
||||
thing->setStateValue(x2wpEnergyWaterHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieRaumheizung:
|
||||
thing->setStateValue(x2wpEnergyRoomHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieLuftvorerwarrmung:
|
||||
thing->setStateValue(x2wpEnergyAirPreheatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (thing->thingClassId() == x2wpThingClassId) {
|
||||
|
||||
switch (reply->registerAddress()) {
|
||||
case ModbusRegisterX2::Betriebsart:
|
||||
if (values[0] == VentilationMode::ManuellStufe0) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 0");
|
||||
} else if (values[0] == VentilationMode::ManuellStufe1) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 1");
|
||||
} else if (values[0] == VentilationMode::ManuellStufe2) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 2");
|
||||
} else if (values[0] == VentilationMode::ManuellStufe3) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 3");
|
||||
} else if (values[0] == VentilationMode::Automatikbetrieb) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Automatic");
|
||||
} else if (values[0] == VentilationMode::Party) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Party");
|
||||
}
|
||||
if (values[0] == VentilationMode::ManuellStufe0) {
|
||||
thing->setStateValue(x2luPowerStateTypeId, false);
|
||||
} else {
|
||||
thing->setStateValue(x2luPowerStateTypeId, true);
|
||||
}
|
||||
break;
|
||||
case ModbusRegisterX2::AktiveLuefterstufe:
|
||||
thing->setStateValue(x2luActiveVentilationLevelStateTypeId, values[0]);
|
||||
break;
|
||||
case ModbusRegisterX2::CO2:
|
||||
thing->setStateValue(x2luCo2StateTypeId, values[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
VentilationMode IntegrationPluginDrexelUndWeiss::getVentilationModeFromString(const QString &modeString)
|
||||
{
|
||||
if (modeString == "Manual level 0") {
|
||||
return VentilationMode::ManuellStufe0;
|
||||
} else if(modeString == "Manual level 1") {
|
||||
return VentilationMode::ManuellStufe1;
|
||||
} else if(modeString == "Manual level 2") {
|
||||
return VentilationMode::ManuellStufe2;
|
||||
}else if(modeString == "Manual level 3") {
|
||||
return VentilationMode::ManuellStufe3;
|
||||
} else if(modeString == "Automatic") {
|
||||
return VentilationMode::Automatikbetrieb;
|
||||
} else if(modeString == "Party") {
|
||||
return VentilationMode::Party;
|
||||
} else {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Unknown ventilation mode string" << modeString;
|
||||
}
|
||||
return VentilationMode::ManuellStufe0;
|
||||
}
|
||||
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, const QVariant &value)
|
||||
{
|
||||
@ -322,318 +567,9 @@ void IntegrationPluginDrexelUndWeiss::onPluginConfigurationChanged(const ParamTy
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onConnectionStateChanged(bool status)
|
||||
{
|
||||
ModbusRTUMaster *modbusRtuMaster = static_cast<ModbusRTUMaster *>(sender());
|
||||
Thing *thing = m_modbusRTUMasters.key(modbusRtuMaster);
|
||||
ModbusRtuMaster *modbusRtuMaster = static_cast<ModbusRtuMaster *>(sender());
|
||||
Thing *thing = m_modbusRtuMasters.key(modbusRtuMaster);
|
||||
if (!thing)
|
||||
return;
|
||||
if (thing->thingClassId() == modbusConnectionThingClassId) {
|
||||
thing->setStateValue(modbusConnectionConnectedStateTypeId, status);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values)
|
||||
{
|
||||
ModbusRTUMaster *modbus = static_cast<ModbusRTUMaster *>(sender());
|
||||
|
||||
if (m_modbusRTUMasters.values().contains(modbus) ){
|
||||
Thing *parentThing = m_modbusRTUMasters.key(static_cast<ModbusRTUMaster *>(modbus));
|
||||
|
||||
foreach(Thing *thing, myThings().filterByParentId(parentThing->id())) {
|
||||
if (thing->thingClassId() == x2luThingClassId && thing->paramValue(x2luThingSlaveAddressParamTypeId) == slaveAddress) {
|
||||
switch (modbusRegister) {
|
||||
case ModbusRegisterX2::Waermepumpe:
|
||||
thing->setStateValue(x2wpPowerStateTypeId, values[0]);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::RaumSoll:
|
||||
thing->setStateValue(x2wpTargetTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::Raum:
|
||||
thing->setStateValue(x2wpTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::TemperaturWarmwasserspeicherUnten:
|
||||
thing->setStateValue(x2wpWaterTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::BrauchwasserSolltermperatur:
|
||||
thing->setStateValue(x2wpTargetWaterTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::Auszenluft:
|
||||
thing->setStateValue(x2wpOutsideAirTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::Summenstoerung:
|
||||
if (values[0] != 0) {
|
||||
//get actual error
|
||||
} else {
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "No Error");
|
||||
}
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungAbluftventilator:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Exhaust fan");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerElektroheizstab:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor electric heating element");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerSolar:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor solar");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerWaermepumpe:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor heat pump");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoileruebertemperatur:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler overtemperature");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungCO2Sensor:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "CO2-Sensor");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDruckverlustAbluftZuGrosz:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss exhaust air too big");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDruckverlustZuluftZuGrosz:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss supply air too large");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDurchflussmengeHeizgkreis:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate of heating circuit");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDurchflussmengeSolekreis:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate brine circuit");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTeilnehmerNichtErreichbar:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Participant not available");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerAuszenluft:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor outside air");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerHeizkreisVorlauf:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor heating circuit flow");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerRaum:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor room");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSolarkollektor:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor solar collector");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSole:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSoleAuszenluft:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine outside air");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWaermepumpeHochdruck:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump high pressure");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWaermepumpeNiederdruck:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump low pressure");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWertNichtZulaessig:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Value not allowed");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungZuluftventilator:
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Supply air fan");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungKompressor:
|
||||
thing->setStateValue(x2wpPowerCompressorStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::LeistungWarmwasser:
|
||||
thing->setStateValue(x2wpPowerWaterHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungRaumheizung:
|
||||
thing->setStateValue(x2wpPowerRoomHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungLuftvorwaermung:
|
||||
thing->setStateValue(x2wpPowerAirPreheatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieKompressor:
|
||||
thing->setStateValue(x2wpEnergyCompressorStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieWarmwasser:
|
||||
thing->setStateValue(x2wpEnergyWaterHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieRaumheizung:
|
||||
thing->setStateValue(x2wpEnergyRoomHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieLuftvorerwarrmung:
|
||||
thing->setStateValue(x2wpEnergyAirPreheatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (thing->thingClassId() == x2wpThingClassId && thing->paramValue(x2wpThingSlaveAddressParamTypeId) == slaveAddress) {
|
||||
|
||||
switch (modbusRegister) {
|
||||
case ModbusRegisterX2::Betriebsart:
|
||||
if (values[0] == VentialtionMode::ManuellStufe0) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 0");
|
||||
} else if (values[0] == VentialtionMode::ManuellStufe1) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 1");
|
||||
} else if (values[0] == VentialtionMode::ManuellStufe2) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 2");
|
||||
} else if (values[0] == VentialtionMode::ManuellStufe3) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 3");
|
||||
} else if (values[0] == VentialtionMode::Automatikbetrieb) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Automatic");
|
||||
} else if (values[0] == VentialtionMode::Party) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Party");
|
||||
}
|
||||
break;
|
||||
case ModbusRegisterX2::AktiveLuefterstufe:
|
||||
thing->setStateValue(x2luActiveVentilationLevelStateTypeId, values[0]);
|
||||
break;
|
||||
case ModbusRegisterX2::CO2:
|
||||
thing->setStateValue(x2luCo2StateTypeId, values[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modbusRegister == ModbusRegisterX2::Geraetetyp) {
|
||||
switch (values[0]) {
|
||||
case DeviceType::X2_WP: {
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered X2 heat pump";
|
||||
QList<ThingDescriptor> thingDescriptors;
|
||||
ThingDescriptor descriptor(x2wpThingClassId, "X2 WP", "Drexel und Weiss", parentThing->id());
|
||||
ParamList params;
|
||||
|
||||
params.append(Param(x2wpThingSlaveAddressParamTypeId, slaveAddress));
|
||||
descriptor.setParams(params);
|
||||
thingDescriptors.append(descriptor);
|
||||
emit autoThingsAppeared(thingDescriptors);
|
||||
break;
|
||||
}
|
||||
case DeviceType::X2_LU: {
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered X2 ventilation unit";
|
||||
QList<ThingDescriptor> thingDescriptors;
|
||||
ThingDescriptor descriptor(x2luThingClassId, "X2 LU", "Drexel und Weiss", parentThing->id());
|
||||
ParamList params;
|
||||
|
||||
params.append(Param(x2luThingSlaveAddressParamTypeId, slaveAddress));
|
||||
descriptor.setParams(params);
|
||||
thingDescriptors.append(descriptor);
|
||||
emit autoThingsAppeared(thingDescriptors);
|
||||
break;
|
||||
}
|
||||
case DeviceType::AerosilentBianco:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosilent Bianco";
|
||||
break;
|
||||
case DeviceType::AerosilentBusiness:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosilent Business";
|
||||
break;
|
||||
case DeviceType::AerosilentCentro:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosilent Centro";
|
||||
break;
|
||||
case DeviceType::AerosilentMicro:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosilent Micro";
|
||||
break;
|
||||
case DeviceType::AerosilentPrimus:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosilent Primus";
|
||||
break;
|
||||
case DeviceType::AerosilentStratos:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosilent Stratos";
|
||||
break;
|
||||
case DeviceType::AerosilentTopo:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosmart Topo";
|
||||
break;
|
||||
case DeviceType::AerosmartL:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosmart L";
|
||||
break;
|
||||
case DeviceType::AerosmartM:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosmart M";
|
||||
break;
|
||||
case DeviceType::AerosmartMono:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosmart Mono";
|
||||
break;
|
||||
case DeviceType::AerosmartS:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosmart S";
|
||||
break;
|
||||
case DeviceType::AerosmartXls:
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosmart Xls";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onWriteRequestFinished(QUuid requestId, bool success)
|
||||
{
|
||||
if (m_pendingActions.contains(requestId)) {
|
||||
ThingActionInfo *info = m_pendingActions.take(requestId);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
if (success) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::discoverModbusSlaves(ModbusRTUMaster *modbus, int slaveAddress)
|
||||
{
|
||||
foreach (Thing *thing, myThings()) {
|
||||
if (thing->thingClassId() == x2luThingClassId) {
|
||||
if (thing->paramValue(x2luThingSlaveAddressParamTypeId).toInt() == slaveAddress) {
|
||||
qWarning(dcDrexelUndWeiss()) << "Thing with slave address" << slaveAddress << "already added";
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (thing->thingClassId() == x2wpThingClassId) {
|
||||
if (thing->paramValue(x2wpThingSlaveAddressParamTypeId).toInt() == slaveAddress) {
|
||||
qWarning(dcDrexelUndWeiss()) << "Thing with slave address" << slaveAddress << "already added";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
modbus->readHoldingRegister(slaveAddress, ModbusRegisterX2::Geraetetyp);
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), status);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -32,12 +32,11 @@
|
||||
#define INTEGRATIONPLUGINDREXELUNDWEISS_H
|
||||
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "hardware/modbus/modbusrtumaster.h"
|
||||
#include "plugintimer.h"
|
||||
|
||||
#include "../modbus/modbusrtumaster.h"
|
||||
#include "modbusdegisterdefinition.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QSerialPortInfo>
|
||||
|
||||
class IntegrationPluginDrexelUndWeiss : public IntegrationPlugin
|
||||
{
|
||||
@ -48,9 +47,8 @@ class IntegrationPluginDrexelUndWeiss : public IntegrationPlugin
|
||||
|
||||
public:
|
||||
explicit IntegrationPluginDrexelUndWeiss();
|
||||
~IntegrationPluginDrexelUndWeiss() override;
|
||||
void init() override;
|
||||
|
||||
void init() override;
|
||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void postSetupThing(Thing *thing) override;
|
||||
@ -58,21 +56,21 @@ public:
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
|
||||
private:
|
||||
QList<QString> m_usedSerialPorts;
|
||||
QHash<Thing *, ModbusRTUMaster *> m_modbusRTUMasters;
|
||||
QHash<Thing *, ModbusRtuMaster *> m_modbusRtuMasters;
|
||||
PluginTimer *m_refreshTimer = nullptr;
|
||||
QHash<QUuid, ThingActionInfo *> m_pendingActions;
|
||||
|
||||
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIds;
|
||||
void sendWriteRequest(ThingActionInfo *info, uint slaveAddress, uint modbusRegister, uint16_t value);
|
||||
void updateStates(Thing *thing);
|
||||
void discoverModbusSlaves(ModbusRTUMaster *modbus, int slaveAddress);
|
||||
void discoverModbusSlaves(ModbusRtuMaster *modbus, uint slaveAddress);
|
||||
void readHoldingRegister(Thing *thing, ModbusRtuMaster *modbus, uint slaveAddress, uint modbusRegister);
|
||||
|
||||
VentilationMode getVentilationModeFromString(const QString &modeString);
|
||||
|
||||
private slots:
|
||||
void onRefreshTimer();
|
||||
void onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||
|
||||
void onConnectionStateChanged(bool status);
|
||||
void onReceivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values);
|
||||
void onWriteRequestFinished(QUuid requestId, bool success);
|
||||
};
|
||||
|
||||
#endif // INTEGRATIONPLUGINDREXELUNDWEISS_H
|
||||
|
||||
@ -18,81 +18,37 @@
|
||||
"displayName": "Drexel und Weiss",
|
||||
"id": "9f476e8b-7e95-448e-b03b-874747e8fb1f",
|
||||
"thingClasses": [
|
||||
{
|
||||
"name": "modbusConnection",
|
||||
"displayName": "Modbus connection",
|
||||
"id": "06d04eec-ab5d-479a-b9e6-8c89efc18a8b",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"interfaces": ["gateway"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "ed49f7d8-ab18-4c37-9b80-1004b75dcb91",
|
||||
"name": "serialPort",
|
||||
"displayName": "Serial port",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": "ttyAMA0"
|
||||
},
|
||||
{
|
||||
"id": "d0c04612-cc3e-4d38-b4c9-708e28dc4eb3",
|
||||
"name": "baudRate",
|
||||
"displayName": "Baud rate",
|
||||
"type": "int",
|
||||
"defaultValue": 9600
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "181ce6e2-9c55-45c6-b329-adf379679e07a",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "b9a24ecc-4433-4f31-99ba-596033bda421",
|
||||
"name": "discoverDevices",
|
||||
"displayName": "Discover devices",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "22413a22-31d4-4b8c-b855-8a29da5946bc",
|
||||
"name": "slaveAddress",
|
||||
"displayName": "Slave address",
|
||||
"type": "int",
|
||||
"minValue": 0,
|
||||
"maxValue": 250,
|
||||
"defaultValue": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x2lu",
|
||||
"displayName": "X2 LU",
|
||||
"id": "0de8e21e-392a-4790-a78a-b1a7eaa7571b",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": ["co2sensor", "connectable"],
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": ["ventilation", "co2sensor", "connectable"],
|
||||
"discoveryParamTypes": [
|
||||
{
|
||||
"id": "8dd4ba9f-51f6-4711-a917-abac5e1aa82b",
|
||||
"name": "slaveAddress",
|
||||
"displayName": "Slave address",
|
||||
"type": "int",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "28a72cb7-3cd0-4704-b604-44fb090d5a88",
|
||||
"name": "slaveAddress",
|
||||
"displayName": "Slave address",
|
||||
"type": "int",
|
||||
"type": "uint",
|
||||
"minValue": 0,
|
||||
"maxValue": 250,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "91ef76cf-6c53-4a8a-a278-6f6e2ef68cc6",
|
||||
"name": "sofwareVersion",
|
||||
"displayName": "Software version",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": "-"
|
||||
"id": "d25197d1-b1b9-45a9-b6fa-60583ed469fb",
|
||||
"name": "modbusMasterUuid",
|
||||
"displayName": "Modbus RTU master",
|
||||
"type": "QUuid",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
@ -104,6 +60,16 @@
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "c9df6349-2bf6-46cc-bce3-d4155836dbe5",
|
||||
"name": "power",
|
||||
"displayName": "Power",
|
||||
"displayNameAction": "Set power",
|
||||
"displayNameEvent": "Power changed",
|
||||
"type": "bool",
|
||||
"writable": true,
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "0a6b44c8-e7af-4148-92ff-682ae717f3a8",
|
||||
"name": "co2",
|
||||
@ -145,25 +111,33 @@
|
||||
"name": "x2wp",
|
||||
"displayName": "X2 WP",
|
||||
"id": "e548f962-92db-4110-8279-10fbcde35f93",
|
||||
"createMethods": ["auto"],
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": ["thermostat", "heating", "temperaturesensor", "connectable"],
|
||||
"discoveryParamTypes": [
|
||||
{
|
||||
"id": "d4923c90-22c8-477e-a37a-341858e59dcb",
|
||||
"name": "slaveAddress",
|
||||
"displayName": "Slave address",
|
||||
"type": "int",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "b551d138-b006-4290-bfef-97072ff677c6",
|
||||
"name": "slaveAddress",
|
||||
"displayName": "Slave address",
|
||||
"type": "int",
|
||||
"type": "uint",
|
||||
"minValue": 0,
|
||||
"maxValue": 250,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "1ffd72a9-7b3f-4287-b671-7f22e159f9b8",
|
||||
"name": "sofwareVersion",
|
||||
"displayName": "Software version",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": "-"
|
||||
"id": "db8358f3-f573-44e3-b024-c4613ee3a270",
|
||||
"name": "modbusMasterUuid",
|
||||
"displayName": "Modbus RTU master",
|
||||
"type": "QUuid",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -33,6 +33,8 @@
|
||||
|
||||
#endif // MODBUSDEGISTERDEFINITION
|
||||
|
||||
#include <QObject>
|
||||
|
||||
enum ModbusRegisterX2 {
|
||||
AbsenkungderLuefterstufe1 = 5328,
|
||||
AktiveLuefterstufe = 1066,
|
||||
@ -241,7 +243,7 @@ enum HeatPumpStatus {
|
||||
NachAbtauenAbtropfen
|
||||
};
|
||||
|
||||
enum VentialtionMode {
|
||||
enum VentilationMode {
|
||||
ManuellStufe0 = 0,
|
||||
ManuellStufe1,
|
||||
ManuellStufe2,
|
||||
|
||||
@ -35,11 +35,6 @@ The name of the StateType ({0a6b44c8-e7af-4148-92ff-682ae717f3a8}) of ThingClass
|
||||
<extracomment>The name of the ActionType ({fb021cac-1236-4324-a45c-8d89ad069052}) of ThingClass x2wp</extracomment>
|
||||
<translation>Setze Zielwassertemperatur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Discover devices</source>
|
||||
<extracomment>The name of the ActionType ({b9a24ecc-4433-4f31-99ba-596033bda421}) of ThingClass modbusConnection</extracomment>
|
||||
<translation>Suche Geräte</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Drexel und Weiss</source>
|
||||
<extracomment>The name of the vendor ({9f476e8b-7e95-448e-b03b-874747e8fb1f})
|
||||
@ -137,12 +132,20 @@ The name of the StateType ({32378843-5478-4b86-9c0e-ccbf978c02be}) of ThingClass
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2wp, EventType: power, ID: {f2ce8389-c33f-4f10-8484-f2e993841762})
|
||||
----------
|
||||
The name of the StateType ({f2ce8389-c33f-4f10-8484-f2e993841762}) of ThingClass x2wp</extracomment>
|
||||
The name of the StateType ({f2ce8389-c33f-4f10-8484-f2e993841762}) of ThingClass x2wp
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, ActionType: power, ID: {c9df6349-2bf6-46cc-bce3-d4155836dbe5})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, EventType: power, ID: {c9df6349-2bf6-46cc-bce3-d4155836dbe5})
|
||||
----------
|
||||
The name of the StateType ({c9df6349-2bf6-46cc-bce3-d4155836dbe5}) of ThingClass x2lu</extracomment>
|
||||
<translation>Eingeschalten</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Power changed</source>
|
||||
<extracomment>The name of the EventType ({f2ce8389-c33f-4f10-8484-f2e993841762}) of ThingClass x2wp</extracomment>
|
||||
<extracomment>The name of the EventType ({f2ce8389-c33f-4f10-8484-f2e993841762}) of ThingClass x2wp
|
||||
----------
|
||||
The name of the EventType ({c9df6349-2bf6-46cc-bce3-d4155836dbe5}) of ThingClass x2lu</extracomment>
|
||||
<translation>Eingeschalten geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
@ -205,27 +208,17 @@ The name of the StateType ({3ab2d609-1686-4fd7-84e3-580c8e0537d0}) of ThingClass
|
||||
<extracomment>The name of the EventType ({3ab2d609-1686-4fd7-84e3-580c8e0537d0}) of ThingClass x2wp</extracomment>
|
||||
<translation>Raumtemperatur geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Serial port</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: modbusConnection, Type: thing, ID: {ed49f7d8-ab18-4c37-9b80-1004b75dcb91})</extracomment>
|
||||
<translation>Serielle Schnittstelle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Slave address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, Type: thing, ID: {b551d138-b006-4290-bfef-97072ff677c6})
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, Type: discovery, ID: {d4923c90-22c8-477e-a37a-341858e59dcb})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, Type: thing, ID: {28a72cb7-3cd0-4704-b604-44fb090d5a88})
|
||||
The name of the ParamType (ThingClass: x2wp, Type: thing, ID: {b551d138-b006-4290-bfef-97072ff677c6})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: modbusConnection, ActionType: discoverDevices, ID: {22413a22-31d4-4b8c-b855-8a29da5946bc})</extracomment>
|
||||
The name of the ParamType (ThingClass: x2lu, Type: discovery, ID: {8dd4ba9f-51f6-4711-a917-abac5e1aa82b})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, Type: thing, ID: {28a72cb7-3cd0-4704-b604-44fb090d5a88})</extracomment>
|
||||
<translation>Slave-Adresse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Software version</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, Type: thing, ID: {1ffd72a9-7b3f-4287-b671-7f22e159f9b8})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, Type: thing, ID: {91ef76cf-6c53-4a8a-a278-6f6e2ef68cc6})</extracomment>
|
||||
<translation>Softwareversion</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Target room temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, ActionType: targetTemperature, ID: {fb98754d-0fba-4163-9b74-3e5a07d71421})
|
||||
@ -307,11 +300,6 @@ The name of the StateType ({77a96b57-fa0a-4946-af5b-39c3b66d9422}) of ThingClass
|
||||
<extracomment>The name of the ThingClass ({e548f962-92db-4110-8279-10fbcde35f93})</extracomment>
|
||||
<translation>X2 WP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Baud rate</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: modbusConnection, Type: thing, ID: {d0c04612-cc3e-4d38-b4c9-708e28dc4eb3})</extracomment>
|
||||
<translation>Baudrate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, EventType: connected, ID: {baf203be-a391-4bfc-8198-53b4ecbcce80})
|
||||
@ -320,26 +308,42 @@ The name of the StateType ({baf203be-a391-4bfc-8198-53b4ecbcce80}) of ThingClass
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, EventType: connected, ID: {b4c4726f-d3d7-46e8-badb-0d590e7f5fac})
|
||||
----------
|
||||
The name of the StateType ({b4c4726f-d3d7-46e8-badb-0d590e7f5fac}) of ThingClass x2lu
|
||||
----------
|
||||
The name of the ParamType (ThingClass: modbusConnection, EventType: connected, ID: {181ce6e2-9c55-45c6-b329-adf379679e07})
|
||||
----------
|
||||
The name of the StateType ({181ce6e2-9c55-45c6-b329-adf379679e07}) of ThingClass modbusConnection</extracomment>
|
||||
The name of the StateType ({b4c4726f-d3d7-46e8-badb-0d590e7f5fac}) of ThingClass x2lu</extracomment>
|
||||
<translation>Verbunden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connected changed</source>
|
||||
<extracomment>The name of the EventType ({baf203be-a391-4bfc-8198-53b4ecbcce80}) of ThingClass x2wp
|
||||
----------
|
||||
The name of the EventType ({b4c4726f-d3d7-46e8-badb-0d590e7f5fac}) of ThingClass x2lu
|
||||
----------
|
||||
The name of the EventType ({181ce6e2-9c55-45c6-b329-adf379679e07}) of ThingClass modbusConnection</extracomment>
|
||||
The name of the EventType ({b4c4726f-d3d7-46e8-badb-0d590e7f5fac}) of ThingClass x2lu</extracomment>
|
||||
<translation>Verbunden geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Modbus connection</source>
|
||||
<extracomment>The name of the ThingClass ({06d04eec-ab5d-479a-b9e6-8c89efc18a8b})</extracomment>
|
||||
<translation>Modbusverbindung</translation>
|
||||
<source>Modbus RTU master</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, Type: thing, ID: {db8358f3-f573-44e3-b024-c4613ee3a270})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, Type: thing, ID: {d25197d1-b1b9-45a9-b6fa-60583ed469fb})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set power</source>
|
||||
<extracomment>The name of the ActionType ({c9df6349-2bf6-46cc-bce3-d4155836dbe5}) of ThingClass x2lu</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IntegrationPluginDrexelUndWeiss</name>
|
||||
<message>
|
||||
<source>Modbus RTU interface not available.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Modbus RTU interface is not connected.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Modbus RTU interface not connected.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
||||
@ -35,11 +35,6 @@ The name of the StateType ({0a6b44c8-e7af-4148-92ff-682ae717f3a8}) of ThingClass
|
||||
<extracomment>The name of the ActionType ({fb021cac-1236-4324-a45c-8d89ad069052}) of ThingClass x2wp</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Discover devices</source>
|
||||
<extracomment>The name of the ActionType ({b9a24ecc-4433-4f31-99ba-596033bda421}) of ThingClass modbusConnection</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Drexel und Weiss</source>
|
||||
<extracomment>The name of the vendor ({9f476e8b-7e95-448e-b03b-874747e8fb1f})
|
||||
@ -137,12 +132,20 @@ The name of the StateType ({32378843-5478-4b86-9c0e-ccbf978c02be}) of ThingClass
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2wp, EventType: power, ID: {f2ce8389-c33f-4f10-8484-f2e993841762})
|
||||
----------
|
||||
The name of the StateType ({f2ce8389-c33f-4f10-8484-f2e993841762}) of ThingClass x2wp</extracomment>
|
||||
The name of the StateType ({f2ce8389-c33f-4f10-8484-f2e993841762}) of ThingClass x2wp
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, ActionType: power, ID: {c9df6349-2bf6-46cc-bce3-d4155836dbe5})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, EventType: power, ID: {c9df6349-2bf6-46cc-bce3-d4155836dbe5})
|
||||
----------
|
||||
The name of the StateType ({c9df6349-2bf6-46cc-bce3-d4155836dbe5}) of ThingClass x2lu</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Power changed</source>
|
||||
<extracomment>The name of the EventType ({f2ce8389-c33f-4f10-8484-f2e993841762}) of ThingClass x2wp</extracomment>
|
||||
<extracomment>The name of the EventType ({f2ce8389-c33f-4f10-8484-f2e993841762}) of ThingClass x2wp
|
||||
----------
|
||||
The name of the EventType ({c9df6349-2bf6-46cc-bce3-d4155836dbe5}) of ThingClass x2lu</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
@ -205,25 +208,15 @@ The name of the StateType ({3ab2d609-1686-4fd7-84e3-580c8e0537d0}) of ThingClass
|
||||
<extracomment>The name of the EventType ({3ab2d609-1686-4fd7-84e3-580c8e0537d0}) of ThingClass x2wp</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Serial port</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: modbusConnection, Type: thing, ID: {ed49f7d8-ab18-4c37-9b80-1004b75dcb91})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Slave address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, Type: thing, ID: {b551d138-b006-4290-bfef-97072ff677c6})
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, Type: discovery, ID: {d4923c90-22c8-477e-a37a-341858e59dcb})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, Type: thing, ID: {28a72cb7-3cd0-4704-b604-44fb090d5a88})
|
||||
The name of the ParamType (ThingClass: x2wp, Type: thing, ID: {b551d138-b006-4290-bfef-97072ff677c6})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: modbusConnection, ActionType: discoverDevices, ID: {22413a22-31d4-4b8c-b855-8a29da5946bc})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Software version</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, Type: thing, ID: {1ffd72a9-7b3f-4287-b671-7f22e159f9b8})
|
||||
The name of the ParamType (ThingClass: x2lu, Type: discovery, ID: {8dd4ba9f-51f6-4711-a917-abac5e1aa82b})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, Type: thing, ID: {91ef76cf-6c53-4a8a-a278-6f6e2ef68cc6})</extracomment>
|
||||
The name of the ParamType (ThingClass: x2lu, Type: thing, ID: {28a72cb7-3cd0-4704-b604-44fb090d5a88})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
@ -307,11 +300,6 @@ The name of the StateType ({77a96b57-fa0a-4946-af5b-39c3b66d9422}) of ThingClass
|
||||
<extracomment>The name of the ThingClass ({e548f962-92db-4110-8279-10fbcde35f93})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Baud rate</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: modbusConnection, Type: thing, ID: {d0c04612-cc3e-4d38-b4c9-708e28dc4eb3})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, EventType: connected, ID: {baf203be-a391-4bfc-8198-53b4ecbcce80})
|
||||
@ -320,25 +308,41 @@ The name of the StateType ({baf203be-a391-4bfc-8198-53b4ecbcce80}) of ThingClass
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, EventType: connected, ID: {b4c4726f-d3d7-46e8-badb-0d590e7f5fac})
|
||||
----------
|
||||
The name of the StateType ({b4c4726f-d3d7-46e8-badb-0d590e7f5fac}) of ThingClass x2lu
|
||||
----------
|
||||
The name of the ParamType (ThingClass: modbusConnection, EventType: connected, ID: {181ce6e2-9c55-45c6-b329-adf379679e07})
|
||||
----------
|
||||
The name of the StateType ({181ce6e2-9c55-45c6-b329-adf379679e07}) of ThingClass modbusConnection</extracomment>
|
||||
The name of the StateType ({b4c4726f-d3d7-46e8-badb-0d590e7f5fac}) of ThingClass x2lu</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connected changed</source>
|
||||
<extracomment>The name of the EventType ({baf203be-a391-4bfc-8198-53b4ecbcce80}) of ThingClass x2wp
|
||||
----------
|
||||
The name of the EventType ({b4c4726f-d3d7-46e8-badb-0d590e7f5fac}) of ThingClass x2lu
|
||||
----------
|
||||
The name of the EventType ({181ce6e2-9c55-45c6-b329-adf379679e07}) of ThingClass modbusConnection</extracomment>
|
||||
The name of the EventType ({b4c4726f-d3d7-46e8-badb-0d590e7f5fac}) of ThingClass x2lu</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Modbus connection</source>
|
||||
<extracomment>The name of the ThingClass ({06d04eec-ab5d-479a-b9e6-8c89efc18a8b})</extracomment>
|
||||
<source>Modbus RTU master</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: x2wp, Type: thing, ID: {db8358f3-f573-44e3-b024-c4613ee3a270})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: x2lu, Type: thing, ID: {d25197d1-b1b9-45a9-b6fa-60583ed469fb})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set power</source>
|
||||
<extracomment>The name of the ActionType ({c9df6349-2bf6-46cc-bce3-d4155836dbe5}) of ThingClass x2lu</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IntegrationPluginDrexelUndWeiss</name>
|
||||
<message>
|
||||
<source>Modbus RTU interface not available.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Modbus RTU interface is not connected.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Modbus RTU interface not connected.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
|
||||
@ -1,410 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <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 "modbusrtumaster.h"
|
||||
|
||||
#include <QSerialPortInfo>
|
||||
|
||||
#include <loggingcategories.h>
|
||||
|
||||
NYMEA_LOGGING_CATEGORY(dcModbusRTU, "ModbusRTU")
|
||||
|
||||
ModbusRTUMaster::ModbusRTUMaster(QString serialPort, uint baudrate, QSerialPort::Parity parity, uint dataBits, uint stopBits, QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_modbusRtuSerialMaster = new QModbusRtuSerialMaster(this);
|
||||
m_modbusRtuSerialMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter, serialPort);
|
||||
m_modbusRtuSerialMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, baudrate);
|
||||
m_modbusRtuSerialMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, dataBits);
|
||||
m_modbusRtuSerialMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, stopBits);
|
||||
m_modbusRtuSerialMaster->setConnectionParameter(QModbusDevice::SerialParityParameter, parity);
|
||||
|
||||
connect(m_modbusRtuSerialMaster, &QModbusTcpClient::stateChanged, this, &ModbusRTUMaster::onModbusStateChanged);
|
||||
connect(m_modbusRtuSerialMaster, &QModbusRtuSerialMaster::errorOccurred, this, &ModbusRTUMaster::onModbusErrorOccurred);
|
||||
|
||||
m_reconnectTimer = new QTimer(this);
|
||||
m_reconnectTimer->setSingleShot(true);
|
||||
connect(m_reconnectTimer, &QTimer::timeout, this, &ModbusRTUMaster::onReconnectTimer);
|
||||
}
|
||||
|
||||
ModbusRTUMaster::~ModbusRTUMaster()
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster) {
|
||||
m_modbusRtuSerialMaster->disconnectDevice();
|
||||
m_modbusRtuSerialMaster->deleteLater();
|
||||
}
|
||||
if (!m_reconnectTimer) {
|
||||
m_reconnectTimer->stop();
|
||||
m_reconnectTimer->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
bool ModbusRTUMaster::connectDevice()
|
||||
{
|
||||
qCDebug(dcModbusRTU()) << "Setting up RTU client connecion";
|
||||
|
||||
if (!m_modbusRtuSerialMaster)
|
||||
return false;
|
||||
|
||||
return m_modbusRtuSerialMaster->connectDevice();
|
||||
}
|
||||
|
||||
bool ModbusRTUMaster::connected()
|
||||
{
|
||||
return (m_modbusRtuSerialMaster->state() == QModbusDevice::State::ConnectedState);
|
||||
}
|
||||
|
||||
void ModbusRTUMaster::setNumberOfRetries(int number)
|
||||
{
|
||||
m_modbusRtuSerialMaster->setNumberOfRetries(number);
|
||||
}
|
||||
|
||||
void ModbusRTUMaster::setTimeout(int timeout)
|
||||
{
|
||||
m_modbusRtuSerialMaster->setTimeout(timeout);
|
||||
}
|
||||
|
||||
int ModbusRTUMaster::timeout()
|
||||
{
|
||||
return m_modbusRtuSerialMaster->timeout();
|
||||
}
|
||||
|
||||
int ModbusRTUMaster::numberOfRetries()
|
||||
{
|
||||
return m_modbusRtuSerialMaster->numberOfRetries();
|
||||
}
|
||||
|
||||
QString ModbusRTUMaster::serialPort()
|
||||
{
|
||||
return m_modbusRtuSerialMaster->connectionParameter(QModbusDevice::SerialPortNameParameter).toString();
|
||||
}
|
||||
|
||||
void ModbusRTUMaster::onReconnectTimer()
|
||||
{
|
||||
if(!m_modbusRtuSerialMaster->connectDevice()) {
|
||||
m_reconnectTimer->start(10000);
|
||||
}
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::readCoil(uint slaveAddress, uint registerAddress, uint size)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster) {
|
||||
return "";
|
||||
}
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, registerAddress, size);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendReadRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, this, [reply, requestId, this] {
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
requestExecuted(requestId, true);
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
uint modbusAddress = unit.startAddress();
|
||||
emit receivedCoil(reply->serverAddress(), modbusAddress, unit.values());
|
||||
|
||||
} else {
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
qCWarning(dcModbusRTU()) << "Modbus replay error:" << error;
|
||||
|
||||
emit requestError(requestId, reply->errorString());
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
QTimer::singleShot(200, reply, &QModbusReply::deleteLater);
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcModbusRTU()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
return "";
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::writeCoil(uint slaveAddress, uint registerAddress, bool value)
|
||||
{
|
||||
return writeCoils(slaveAddress, registerAddress, QVector<quint16>() << static_cast<quint16>(value));
|
||||
}
|
||||
|
||||
|
||||
QUuid ModbusRTUMaster::writeCoils(uint slaveAddress, uint registerAddress, const QVector<quint16> &values)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster) {
|
||||
return "";
|
||||
}
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, registerAddress, values.length());
|
||||
request.setValues(values);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendWriteRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, this, [reply, requestId, this] {
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
requestExecuted(requestId, true);
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
uint modbusAddress = unit.startAddress();
|
||||
emit receivedCoil(reply->serverAddress(), modbusAddress, unit.values());
|
||||
|
||||
} else {
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
qCWarning(dcModbusRTU()) << "Modbus replay error:" << error;
|
||||
emit requestError(requestId, reply->errorString());
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
QTimer::singleShot(200, reply, &QModbusReply::deleteLater);
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcModbusRTU()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
return "";
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::writeHoldingRegister(uint slaveAddress, uint registerAddress, quint16 value)
|
||||
{
|
||||
return writeHoldingRegisters(slaveAddress, registerAddress, QVector<quint16>() << value);
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::writeHoldingRegisters(uint slaveAddress, uint registerAddress, const QVector<quint16> &values)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster) {
|
||||
return "";
|
||||
}
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, registerAddress, values.length());
|
||||
request.setValues(values);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendWriteRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, this, [reply, requestId, this] {
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
requestExecuted(requestId, true);
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
uint modbusAddress = unit.startAddress();
|
||||
emit receivedHoldingRegister(reply->serverAddress(), modbusAddress, unit.values());
|
||||
|
||||
} else {
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
qCWarning(dcModbusRTU()) << "Modbus replay error:" << error;
|
||||
emit requestError(requestId, reply->errorString());
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
QTimer::singleShot(200, reply, &QModbusReply::deleteLater);
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcModbusRTU()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
return "";
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::readDiscreteInput(uint slaveAddress, uint registerAddress, uint size)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster) {
|
||||
return "";
|
||||
}
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::DiscreteInputs, registerAddress, size);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendReadRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, this, [reply, requestId, this] {
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
requestExecuted(requestId, true);
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
uint modbusAddress = unit.startAddress();
|
||||
emit receivedDiscreteInput(reply->serverAddress(), modbusAddress, unit.values());
|
||||
|
||||
} else {
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
qCWarning(dcModbusRTU()) << "Modbus replay error:" << error;
|
||||
|
||||
emit requestError(requestId, reply->errorString());
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
QTimer::singleShot(200, reply, &QModbusReply::deleteLater);
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcModbusRTU()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
return "";
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::readInputRegister(uint slaveAddress, uint registerAddress, uint size)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster) {
|
||||
return "";
|
||||
}
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, registerAddress, size);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendReadRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, this, [reply, requestId, this] {
|
||||
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
requestExecuted(requestId, true);
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
uint modbusAddress = unit.startAddress();
|
||||
emit receivedInputRegister(reply->serverAddress(), modbusAddress, unit.values());
|
||||
|
||||
} else {
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
qCWarning(dcModbusRTU()) << "Modbus replay error:" << error;
|
||||
|
||||
emit requestError(requestId, reply->errorString());
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
QTimer::singleShot(200, reply, &QModbusReply::deleteLater);
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcModbusRTU()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
return "";
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::readHoldingRegister(uint slaveAddress, uint registerAddress, uint size)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster) {
|
||||
return "";
|
||||
}
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, registerAddress, size);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendReadRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, this, [reply, requestId, this] {
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
requestExecuted(requestId, true);
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
uint modbusAddress = unit.startAddress();
|
||||
emit receivedHoldingRegister(reply->serverAddress(), modbusAddress, unit.values());
|
||||
|
||||
} else {
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
qCWarning(dcModbusRTU()) << "Modbus replay error:" << error;
|
||||
|
||||
emit requestError(requestId, reply->errorString());
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
QTimer::singleShot(200, reply, &QModbusReply::deleteLater);
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcModbusRTU()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
return "";
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
|
||||
void ModbusRTUMaster::onModbusErrorOccurred(QModbusDevice::Error error)
|
||||
{
|
||||
qCWarning(dcModbusRTU()) << "An error occured" << error;
|
||||
if (error == QModbusDevice::Error::ConnectionError) {
|
||||
emit connectionStateChanged(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ModbusRTUMaster::onModbusStateChanged(QModbusDevice::State state)
|
||||
{
|
||||
qCWarning(dcModbusRTU()) << "State changed" << state;
|
||||
if (state == QModbusDevice::UnconnectedState) {
|
||||
//try to reconnect in 10 seconds
|
||||
m_reconnectTimer->start(10000);
|
||||
}
|
||||
emit connectionStateChanged(state == QModbusDevice::ConnectedState);
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <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 MODBUSRTUMASTER_H
|
||||
#define MODBUSRTUMASTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtSerialBus>
|
||||
#include <QSerialPort>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
|
||||
class ModbusRTUMaster : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ModbusRTUMaster(QString serialPort, uint baudrate, QSerialPort::Parity parity, uint dataBits, uint stopBits, QObject *parent = nullptr);
|
||||
~ModbusRTUMaster();
|
||||
|
||||
bool connectDevice();
|
||||
bool connected();
|
||||
void setNumberOfRetries(int number);
|
||||
void setTimeout(int timeout);
|
||||
|
||||
int timeout();
|
||||
int numberOfRetries();
|
||||
|
||||
QUuid readCoil(uint slaveAddress, uint registerAddress, uint size = 1);
|
||||
QUuid readDiscreteInput(uint slaveAddress, uint registerAddress, uint size = 1);
|
||||
QUuid readInputRegister(uint slaveAddress, uint registerAddress, uint size = 1);
|
||||
QUuid readHoldingRegister(uint slaveAddress, uint registerAddress, uint size = 1);
|
||||
|
||||
QUuid writeCoil(uint slaveAddress, uint registerAddress, bool status);
|
||||
QUuid writeCoils(uint slaveAddress, uint registerAddress, const QVector<quint16> &values);
|
||||
|
||||
QUuid writeHoldingRegister(uint slaveAddress, uint registerAddress, quint16 value);
|
||||
QUuid writeHoldingRegisters(uint slaveAddress, uint registerAddress, const QVector<quint16> &values);
|
||||
|
||||
QString serialPort();
|
||||
|
||||
private:
|
||||
QModbusRtuSerialMaster *m_modbusRtuSerialMaster;
|
||||
QTimer *m_reconnectTimer = nullptr;
|
||||
|
||||
private slots:
|
||||
void onReconnectTimer();
|
||||
|
||||
void onModbusErrorOccurred(QModbusDevice::Error error);
|
||||
void onModbusStateChanged(QModbusDevice::State state);
|
||||
|
||||
signals:
|
||||
void connectionStateChanged(bool status);
|
||||
|
||||
void requestExecuted(QUuid requestId, bool success);
|
||||
void requestError(QUuid requestId, const QString &error);
|
||||
|
||||
void receivedCoil(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values);
|
||||
void receivedDiscreteInput(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values);
|
||||
void receivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values);
|
||||
void receivedInputRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values);
|
||||
};
|
||||
|
||||
#endif // MODBUSRTUMASTER_H
|
||||
Reference in New Issue
Block a user