changed fronius to make use of QModbus
This commit is contained in:
parent
05e71c24f6
commit
bdbb239c59
@ -70,20 +70,15 @@ void IntegrationPluginDrexelUndWeiss::discoverThings(ThingDiscoveryInfo *info)
|
||||
}
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->thingClassId() == x2luThingClassId) {
|
||||
} else if (info->thingClassId() == x2luThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->thingClassId() == x2wpThingClassId) {
|
||||
} else if (info->thingClassId() == x2wpThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
} else {
|
||||
Q_ASSERT_X(false, "discoverThings", QString("Unhandled thingClassId: %1").arg(info->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::setupThing(ThingSetupInfo *info)
|
||||
@ -97,29 +92,21 @@ void IntegrationPluginDrexelUndWeiss::setupThing(ThingSetupInfo *info)
|
||||
|
||||
ModbusRTUMaster *modbus = new ModbusRTUMaster(serialPort, baudRate, QSerialPort::Parity::NoParity, 8, 1, this);
|
||||
connect(modbus, &ModbusRTUMaster::connectionStateChanged, this, &IntegrationPluginDrexelUndWeiss::onConnectionStateChanged);
|
||||
connect(modbus, &ModbusRTUMaster::receivedCoil, this, &IntegrationPluginDrexelUndWeiss::onReceivedCoil);
|
||||
connect(modbus, &ModbusRTUMaster::receivedDiscreteInput, this, &IntegrationPluginDrexelUndWeiss::onReceivedDiscreteInput);
|
||||
connect(modbus, &ModbusRTUMaster::receivedHoldingRegister, this, &IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister);
|
||||
connect(modbus, &ModbusRTUMaster::receivedInputRegister, this, &IntegrationPluginDrexelUndWeiss::onReceivedInputRegister);
|
||||
|
||||
|
||||
m_modbusRTUMasters.insert(thing, modbus);
|
||||
m_usedSerialPorts.append(serialPort);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == x2luThingClassId) {
|
||||
} else if (thing->thingClassId() == x2luThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == x2wpThingClassId) {
|
||||
} else if (thing->thingClassId() == x2wpThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
} else {
|
||||
Q_ASSERT_X(false, "setupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::postSetupThing(Thing *thing)
|
||||
@ -138,12 +125,10 @@ void IntegrationPluginDrexelUndWeiss::postSetupThing(Thing *thing)
|
||||
qCWarning(dcDrexelUndWeiss()) << "No modbus master available";
|
||||
}
|
||||
thing->setStateValue(modbusConnectionConnectedStateTypeId, true);
|
||||
}
|
||||
|
||||
if ((thing->thingClassId() == x2luThingClassId) || (thing->thingClassId() == x2wpThingClassId)) {
|
||||
} else if ((thing->thingClassId() == x2luThingClassId) || (thing->thingClassId() == x2wpThingClassId)) {
|
||||
Thing *parentThing = myThings().findById(thing->parentId());
|
||||
if (!parentThing) {
|
||||
qWarning(dcDrexelUndWeiss()) << "Could not find the parent Thing";
|
||||
qCWarning(dcDrexelUndWeiss()) << "Could not find the parent Thing";
|
||||
return;
|
||||
}
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parentThing);
|
||||
@ -152,6 +137,8 @@ void IntegrationPluginDrexelUndWeiss::postSetupThing(Thing *thing)
|
||||
}
|
||||
updateStates(thing);
|
||||
// Update states
|
||||
} else {
|
||||
Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,7 +230,7 @@ void IntegrationPluginDrexelUndWeiss::executeAction(ThingActionInfo *info)
|
||||
info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||
}
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
Q_ASSERT_X(false, "executeAction", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,24 +316,16 @@ void IntegrationPluginDrexelUndWeiss::onPluginConfigurationChanged(const ParamTy
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onConnectionStateChanged(bool status)
|
||||
{
|
||||
Q_UNUSED(status)
|
||||
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::onReceivedCoil(int slaveAddress, int modbusRegister, bool value)
|
||||
{
|
||||
Q_UNUSED(slaveAddress)
|
||||
Q_UNUSED(modbusRegister)
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onReceivedDiscreteInput(int slaveAddress, int modbusRegister, bool value)
|
||||
{
|
||||
Q_UNUSED(slaveAddress)
|
||||
Q_UNUSED(modbusRegister)
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, int value)
|
||||
void IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values)
|
||||
{
|
||||
ModbusRTUMaster *modbus = static_cast<ModbusRTUMaster *>(sender());
|
||||
|
||||
@ -357,29 +336,29 @@ void IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress
|
||||
if (thing->thingClassId() == x2luThingClassId && thing->paramValue(x2luThingSlaveAddressParamTypeId) == slaveAddress) {
|
||||
switch (modbusRegister) {
|
||||
case ModbusRegisterX2::Waermepumpe:
|
||||
thing->setStateValue(x2wpPowerStateTypeId, value);
|
||||
thing->setStateValue(x2wpPowerStateTypeId, values[0]);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::RaumSoll:
|
||||
thing->setStateValue(x2wpTargetTemperatureStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpTargetTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::Raum:
|
||||
thing->setStateValue(x2wpTemperatureStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::TemperaturWarmwasserspeicherUnten:
|
||||
thing->setStateValue(x2wpWaterTemperatureStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpWaterTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::BrauchwasserSolltermperatur:
|
||||
thing->setStateValue(x2wpTargetWaterTemperatureStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpTargetWaterTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::Auszenluft:
|
||||
thing->setStateValue(x2wpOutsideAirTemperatureStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpOutsideAirTemperatureStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::Summenstoerung:
|
||||
if (value != 0) {
|
||||
if (values[0] != 0) {
|
||||
//get actual error
|
||||
} else {
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "No Error");
|
||||
@ -387,139 +366,139 @@ void IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungAbluftventilator:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Exhaust fan");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerElektroheizstab:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor electric heating element");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerSolar:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor solar");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoilerfuehlerWaermepumpe:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor heat pump");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungBoileruebertemperatur:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Boiler overtemperature");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungCO2Sensor:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "CO2-Sensor");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDruckverlustAbluftZuGrosz:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss exhaust air too big");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDruckverlustZuluftZuGrosz:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss supply air too large");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDurchflussmengeHeizgkreis:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate of heating circuit");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungDurchflussmengeSolekreis:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate brine circuit");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTeilnehmerNichtErreichbar:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Participant not available");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerAuszenluft:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor outside air");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerHeizkreisVorlauf:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor heating circuit flow");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerRaum:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor room");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSolarkollektor:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor solar collector");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSole:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungTemperaturfuehlerSoleAuszenluft:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine outside air");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWaermepumpeHochdruck:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump high pressure");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWaermepumpeNiederdruck:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump low pressure");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungWertNichtZulaessig:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Value not allowed");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::StoerungZuluftventilator:
|
||||
if (value != 0)
|
||||
if (values[0] != 0)
|
||||
thing->setStateValue(x2wpErrorStateTypeId, "Supply air fan");
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungKompressor:
|
||||
thing->setStateValue(x2wpPowerCompressorStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpPowerCompressorStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
case ModbusRegisterX2::LeistungWarmwasser:
|
||||
thing->setStateValue(x2wpPowerWaterHeatingStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpPowerWaterHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungRaumheizung:
|
||||
thing->setStateValue(x2wpPowerRoomHeatingStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpPowerRoomHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::LeistungLuftvorwaermung:
|
||||
thing->setStateValue(x2wpPowerAirPreheatingStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpPowerAirPreheatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieKompressor:
|
||||
thing->setStateValue(x2wpEnergyCompressorStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpEnergyCompressorStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieWarmwasser:
|
||||
thing->setStateValue(x2wpEnergyWaterHeatingStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpEnergyWaterHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieRaumheizung:
|
||||
thing->setStateValue(x2wpEnergyRoomHeatingStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpEnergyRoomHeatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
|
||||
case ModbusRegisterX2::EnergieLuftvorerwarrmung:
|
||||
thing->setStateValue(x2wpEnergyAirPreheatingStateTypeId, value/1000.00);
|
||||
thing->setStateValue(x2wpEnergyAirPreheatingStateTypeId, values[0]/1000.00);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -528,32 +507,32 @@ void IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress
|
||||
|
||||
switch (modbusRegister) {
|
||||
case ModbusRegisterX2::Betriebsart:
|
||||
if (value == VentialtionMode::ManuellStufe0) {
|
||||
if (values[0] == VentialtionMode::ManuellStufe0) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 0");
|
||||
} else if (value == VentialtionMode::ManuellStufe1) {
|
||||
} else if (values[0] == VentialtionMode::ManuellStufe1) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 1");
|
||||
} else if (value == VentialtionMode::ManuellStufe2) {
|
||||
} else if (values[0] == VentialtionMode::ManuellStufe2) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 2");
|
||||
} else if (value == VentialtionMode::ManuellStufe3) {
|
||||
} else if (values[0] == VentialtionMode::ManuellStufe3) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 3");
|
||||
} else if (value == VentialtionMode::Automatikbetrieb) {
|
||||
} else if (values[0] == VentialtionMode::Automatikbetrieb) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Automatic");
|
||||
} else if (value == VentialtionMode::Party) {
|
||||
} else if (values[0] == VentialtionMode::Party) {
|
||||
thing->setStateValue(x2luVentilationModeStateTypeId, "Party");
|
||||
}
|
||||
break;
|
||||
case ModbusRegisterX2::AktiveLuefterstufe:
|
||||
thing->setStateValue(x2luActiveVentilationLevelStateTypeId, value);
|
||||
thing->setStateValue(x2luActiveVentilationLevelStateTypeId, values[0]);
|
||||
break;
|
||||
case ModbusRegisterX2::CO2:
|
||||
thing->setStateValue(x2luCo2StateTypeId, value);
|
||||
thing->setStateValue(x2luCo2StateTypeId, values[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modbusRegister == ModbusRegisterX2::Geraetetyp) {
|
||||
switch (value) {
|
||||
switch (values[0]) {
|
||||
case DeviceType::X2_WP: {
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered X2 heat pump";
|
||||
QList<ThingDescriptor> thingDescriptors;
|
||||
@ -587,29 +566,24 @@ void IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress
|
||||
qDebug(dcDrexelUndWeiss()) << "Discovered Aerosilent Bianco";
|
||||
break;
|
||||
default:
|
||||
qDebug(dcDrexelUndWeiss()) << "Unkown Thingtype" << value;
|
||||
qDebug(dcDrexelUndWeiss()) << "Unkown Thingtype" << values[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onReceivedInputRegister(int slaveAddress, int modbusRegister, int value)
|
||||
{
|
||||
Q_UNUSED(slaveAddress)
|
||||
Q_UNUSED(modbusRegister)
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
void IntegrationPluginDrexelUndWeiss::onWriteRequestFinished(QUuid requestId, bool success)
|
||||
{
|
||||
ThingActionInfo *info = m_pendingActions.take(requestId);
|
||||
if (!info)
|
||||
return;
|
||||
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);
|
||||
if (success) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "plugintimer.h"
|
||||
|
||||
#include "modbusrtumaster.h"
|
||||
#include "../modbus/modbusrtumaster.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QSerialPortInfo>
|
||||
@ -71,10 +71,9 @@ private slots:
|
||||
void onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||
|
||||
void onConnectionStateChanged(bool status);
|
||||
void onReceivedCoil(int slaveAddress, int modbusRegister, bool value);
|
||||
void onReceivedDiscreteInput(int slaveAddress, int modbusRegister, bool value);
|
||||
void onReceivedHoldingRegister(int slaveAddress, int modbusRegister, int value);
|
||||
void onReceivedInputRegister(int slaveAddress, int modbusRegister, int value);
|
||||
void onReceivedCoil(uint slaveAddress, uint modbusRegister, bool value);
|
||||
void onReceivedDiscreteInput(uint slaveAddress, uint modbusRegister, bool value);
|
||||
void onReceivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values);
|
||||
|
||||
void onWriteRequestFinished(QUuid requestId, bool success);
|
||||
};
|
||||
|
||||
@ -1,363 +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 "extern-plugininfo.h"
|
||||
|
||||
#include <QSerialPortInfo>
|
||||
|
||||
ModbusRTUMaster::ModbusRTUMaster(QString serialPort, int baudrate, QSerialPort::Parity parity, int dataBits, int 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);
|
||||
//m_modbusRtuSerialMaster->setTimeout(100);
|
||||
//m_modbusRtuSerialMaster->setNumberOfRetries(1);
|
||||
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()
|
||||
{
|
||||
qDebug(dcDrexelUndWeiss()) << "Setting up TCP connecion";
|
||||
|
||||
if (!m_modbusRtuSerialMaster)
|
||||
return false;
|
||||
|
||||
return m_modbusRtuSerialMaster->connectDevice();
|
||||
}
|
||||
|
||||
QString ModbusRTUMaster::serialPort()
|
||||
{
|
||||
return m_modbusRtuSerialMaster->connectionParameter(QModbusDevice::SerialPortNameParameter).toString();
|
||||
}
|
||||
|
||||
void ModbusRTUMaster::onReplyFinished()
|
||||
{
|
||||
QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
|
||||
if (!reply)
|
||||
return;
|
||||
reply->deleteLater();
|
||||
|
||||
int modbusAddress = 0;
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
|
||||
for (int i = 0; i < static_cast<int>(unit.valueCount()); i++) {
|
||||
//qCDebug(dcUniPi()) << "Start Address:" << unit.startAddress() << "Register Type:" << unit.registerType() << "Value:" << unit.value(i);
|
||||
modbusAddress = unit.startAddress() + i;
|
||||
|
||||
switch (unit.registerType()) {
|
||||
case QModbusDataUnit::RegisterType::Coils:
|
||||
emit receivedCoil(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::DiscreteInputs:
|
||||
emit receivedDiscreteInput(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::InputRegisters:
|
||||
emit receivedInputRegister(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::HoldingRegisters:
|
||||
emit receivedHoldingRegister(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::Invalid:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (reply->error() == QModbusDevice::ProtocolError) {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read response error:" << reply->errorString() << reply->rawResult().exceptionCode();
|
||||
} else {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read response error:" << reply->error();
|
||||
}
|
||||
}
|
||||
|
||||
void ModbusRTUMaster::onReplyErrorOccured(QModbusDevice::Error error)
|
||||
{
|
||||
qCWarning(dcDrexelUndWeiss()) << "Modbus replay error:" << error;
|
||||
QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
|
||||
if (!reply)
|
||||
return;
|
||||
reply->finished(); //to make sure it will be deleted
|
||||
}
|
||||
|
||||
void ModbusRTUMaster::onReconnectTimer()
|
||||
{
|
||||
if(!m_modbusRtuSerialMaster->connectDevice()) {
|
||||
m_reconnectTimer->start(10000);
|
||||
}
|
||||
}
|
||||
|
||||
bool ModbusRTUMaster::readCoil(int slaveAddress, int registerAddress)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster)
|
||||
return false;
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, registerAddress, 1);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendReadRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, this, &ModbusRTUMaster::onReplyFinished);
|
||||
connect(reply, &QModbusReply::errorOccurred, this, &ModbusRTUMaster::onReplyErrorOccured);
|
||||
QTimer::singleShot(200, reply, SLOT(deleteLater()));
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::writeCoil(int slaveAddress, int registerAddress, bool value)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
if (!m_modbusRtuSerialMaster)
|
||||
return requestId;
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, registerAddress, 1);
|
||||
request.setValue(0, static_cast<uint16_t>(value));
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendWriteRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, this, [requestId, this] {
|
||||
|
||||
QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
|
||||
if (!reply)
|
||||
return;
|
||||
reply->deleteLater();
|
||||
|
||||
int modbusAddress = 0;
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
emit writeRequestFinished(requestId, true);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(unit.valueCount()); i++) {
|
||||
//qCDebug(dcUniPi()) << "Start Address:" << unit.startAddress() << "Register Type:" << unit.registerType() << "Value:" << unit.value(i);
|
||||
modbusAddress = unit.startAddress() + i;
|
||||
|
||||
switch (unit.registerType()) {
|
||||
case QModbusDataUnit::RegisterType::Coils:
|
||||
emit receivedCoil(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::DiscreteInputs:
|
||||
emit receivedDiscreteInput(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::InputRegisters:
|
||||
emit receivedInputRegister(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::HoldingRegisters:
|
||||
emit receivedHoldingRegister(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::Invalid:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (reply->error() == QModbusDevice::ProtocolError) {
|
||||
emit writeRequestFinished(requestId, false);
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read response error:" << reply->errorString() << reply->rawResult().exceptionCode();
|
||||
} else {
|
||||
emit writeRequestFinished(requestId, false);
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, &ModbusRTUMaster::onReplyErrorOccured);
|
||||
QTimer::singleShot(200, reply, SLOT(deleteLater()));
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid ModbusRTUMaster::writeHoldingRegister(int slaveAddress, int registerAddress, int value)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
if (!m_modbusRtuSerialMaster){
|
||||
qCWarning(dcDrexelUndWeiss()) << "Modbus RTU interface not available";
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, registerAddress, 1);
|
||||
request.setValue(0, static_cast<uint16_t>(value));
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendWriteRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, this, [requestId, this] {
|
||||
|
||||
QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
|
||||
if (!reply)
|
||||
return;
|
||||
reply->deleteLater();
|
||||
|
||||
int modbusAddress = 0;
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
emit writeRequestFinished(requestId, true);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(unit.valueCount()); i++) {
|
||||
//qCDebug(dcUniPi()) << "Start Address:" << unit.startAddress() << "Register Type:" << unit.registerType() << "Value:" << unit.value(i);
|
||||
modbusAddress = unit.startAddress() + i;
|
||||
|
||||
switch (unit.registerType()) {
|
||||
case QModbusDataUnit::RegisterType::Coils:
|
||||
emit receivedCoil(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::DiscreteInputs:
|
||||
emit receivedDiscreteInput(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::InputRegisters:
|
||||
emit receivedInputRegister(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::HoldingRegisters:
|
||||
emit receivedHoldingRegister(reply->serverAddress(), modbusAddress, unit.value(i));
|
||||
break;
|
||||
case QModbusDataUnit::RegisterType::Invalid:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (reply->error() == QModbusDevice::ProtocolError) {
|
||||
emit writeRequestFinished(requestId, false);
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read response error:" << reply->errorString() << reply->rawResult().exceptionCode();
|
||||
} else {
|
||||
emit writeRequestFinished(requestId, false);
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, &ModbusRTUMaster::onReplyErrorOccured);
|
||||
QTimer::singleShot(200, reply, SLOT(deleteLater()));
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
bool ModbusRTUMaster::readDiscreteInput(int slaveAddress, int registerAddress)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster)
|
||||
return false;
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::DiscreteInputs, registerAddress, 1);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendReadRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, this, &ModbusRTUMaster::onReplyFinished);
|
||||
connect(reply, &QModbusReply::errorOccurred, this, &ModbusRTUMaster::onReplyErrorOccured);
|
||||
QTimer::singleShot(200, reply, SLOT(deleteLater()));
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ModbusRTUMaster::readInputRegister(int slaveAddress, int registerAddress)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster)
|
||||
return false;
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, registerAddress, 1);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendReadRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, this, &ModbusRTUMaster::onReplyFinished);
|
||||
connect(reply, &QModbusReply::errorOccurred, this, &ModbusRTUMaster::onReplyErrorOccured);
|
||||
QTimer::singleShot(200, reply, SLOT(deleteLater()));
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ModbusRTUMaster::readHoldingRegister(int slaveAddress, int registerAddress)
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster)
|
||||
return false;
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, registerAddress, 1);
|
||||
|
||||
if (QModbusReply *reply = m_modbusRtuSerialMaster->sendReadRequest(request, slaveAddress)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, this, &ModbusRTUMaster::onReplyFinished);
|
||||
connect(reply, &QModbusReply::errorOccurred, this, &ModbusRTUMaster::onReplyErrorOccured);
|
||||
QTimer::singleShot(200, reply, SLOT(deleteLater()));
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcDrexelUndWeiss()) << "Read error: " << m_modbusRtuSerialMaster->errorString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ModbusRTUMaster::onModbusErrorOccurred(QModbusDevice::Error error)
|
||||
{
|
||||
qCWarning(dcDrexelUndWeiss()) << "An error occured" << error;
|
||||
}
|
||||
|
||||
|
||||
void ModbusRTUMaster::onModbusStateChanged(QModbusDevice::State state)
|
||||
{
|
||||
bool connected = (state != QModbusDevice::UnconnectedState);
|
||||
if (!connected) {
|
||||
//try to reconnect in 10 seconds
|
||||
m_reconnectTimer->start(10000);
|
||||
}
|
||||
emit connectionStateChanged(connected);
|
||||
}
|
||||
@ -1,81 +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, int baudrate, QSerialPort::Parity parity, int dataBits, int stopBits, QObject *parent = nullptr);
|
||||
~ModbusRTUMaster();
|
||||
|
||||
bool connectDevice();
|
||||
|
||||
bool readCoil(int slaveAddress, int registerAddress);
|
||||
bool readDiscreteInput(int slaveAddress, int registerAddress);
|
||||
bool readInputRegister(int slaveAddress, int registerAddress);
|
||||
bool readHoldingRegister(int slaveAddress, int registerAddress);
|
||||
|
||||
QUuid writeCoil(int slaveAddress, int registerAddress, bool status);
|
||||
QUuid writeHoldingRegister(int slaveAddress, int registerAddress, int data);
|
||||
|
||||
QString serialPort();
|
||||
|
||||
private:
|
||||
QModbusRtuSerialMaster *m_modbusRtuSerialMaster;
|
||||
QTimer *m_reconnectTimer = nullptr;
|
||||
|
||||
private slots:
|
||||
void onReplyFinished();
|
||||
void onReplyErrorOccured(QModbusDevice::Error error);
|
||||
void onReconnectTimer();
|
||||
|
||||
void onModbusErrorOccurred(QModbusDevice::Error error);
|
||||
void onModbusStateChanged(QModbusDevice::State state);
|
||||
|
||||
signals:
|
||||
void connectionStateChanged(bool status);
|
||||
void receivedCoil(int slaveAddress, int modbusRegister, bool value);
|
||||
void receivedDiscreteInput(int slaveAddress, int modbusRegister, bool value);
|
||||
void receivedHoldingRegister(int slaveAddress, int modbusRegister, int value);
|
||||
void receivedInputRegister(int slaveAddress, int modbusRegister, int value);
|
||||
|
||||
void writeRequestFinished(QUuid requestId, bool success);
|
||||
};
|
||||
|
||||
#endif // MODBUSRTUMASTER_H
|
||||
@ -12,7 +12,7 @@ SOURCES += \
|
||||
froniusstorage.cpp \
|
||||
froniusmeter.cpp \
|
||||
sunspecthing.cpp \
|
||||
../modbus/modbustcpmaster.h \
|
||||
../modbus/modbustcpmaster.cpp \
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginfronius.h \
|
||||
|
||||
@ -265,7 +265,7 @@ void IntegrationPluginFronius::postSetupThing(Thing *thing)
|
||||
SunspecThing *sunspecThing = m_sunspecThings.key(thing);
|
||||
sunspecThing->update();
|
||||
} else {
|
||||
Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,7 +302,7 @@ void IntegrationPluginFronius::thingRemoved(Thing *thing)
|
||||
qCDebug(dcFronius()) << "Sunspec thing deleted";
|
||||
return;
|
||||
} else {
|
||||
Q_ASSERT_X(false, "thingRemoved", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
Q_ASSERT_X(false, "thingRemoved", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
|
||||
if (myThings().isEmpty()) {
|
||||
@ -335,36 +335,41 @@ void IntegrationPluginFronius::executeAction(ThingActionInfo *info)
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == sunspecStorageGridChargingActionTypeId) {
|
||||
if (sunspecThing->setGridCharging(action.param(sunspecStorageGridChargingActionGridChargingParamTypeId).value().toBool())){
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
QUuid requestId = sunspecThing->setGridCharging(action.param(sunspecStorageGridChargingActionGridChargingParamTypeId).value().toBool());
|
||||
if (requestId.isNull()) {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
} else {
|
||||
m_asyncActions.insert(requestId, info);
|
||||
}
|
||||
} else if (action.actionTypeId() == sunspecStorageEnableChargingLimitActionTypeId) {
|
||||
int value = (action.param(sunspecStorageEnableChargingLimitActionEnableChargingLimitParamTypeId).value().toBool() << 1) | thing->stateValue(sunspecStorageEnableDischargingLimitStateTypeId).toBool();
|
||||
if (sunspecThing->setStorageControlMode(value)) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
QUuid requestId = sunspecThing->setStorageControlMode(value);
|
||||
if (requestId.isNull()) {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
} else {
|
||||
m_asyncActions.insert(requestId, info);
|
||||
}
|
||||
} else if (action.actionTypeId() == sunspecStorageChargingRateActionTypeId) {
|
||||
if (sunspecThing->setChargingRate(action.param(sunspecStorageChargingRateActionChargingRateParamTypeId).value().toInt())) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
QUuid requestId = sunspecThing->setChargingRate(action.param(sunspecStorageChargingRateActionChargingRateParamTypeId).value().toInt());
|
||||
if (requestId.isNull()) {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
} else {
|
||||
m_asyncActions.insert(requestId, info);
|
||||
}
|
||||
} else if (action.actionTypeId() == sunspecStorageEnableDischargingLimitActionTypeId) {
|
||||
int value = (action.param(sunspecStorageEnableDischargingLimitActionEnableDischargingLimitParamTypeId).value().toBool() << 1) | thing->stateValue(sunspecStorageEnableChargingLimitStateTypeId).toBool();
|
||||
if (sunspecThing->setStorageControlMode(value)) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
QUuid requestId = sunspecThing->setStorageControlMode(value);
|
||||
if (requestId.isNull()) {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
} else {
|
||||
m_asyncActions.insert(requestId, info);
|
||||
}
|
||||
} else if (action.actionTypeId() == sunspecStorageDischargingRateActionTypeId) {
|
||||
if (sunspecThing->setDischargingRate(action.param(sunspecStorageDischargingRateActionDischargingRateParamTypeId).value().toInt())) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
QUuid requestId = sunspecThing->setDischargingRate(action.param(sunspecStorageDischargingRateActionDischargingRateParamTypeId).value().toInt());
|
||||
if (requestId.isNull()) {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
} else {
|
||||
m_asyncActions.insert(requestId, info);
|
||||
}
|
||||
} else {
|
||||
Q_ASSERT_X(false, "executeAction", QString("Unhandled action: %1").arg(action.actionTypeId().toString()).toUtf8());
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
#include <QHash>
|
||||
#include <QNetworkReply>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
|
||||
class PluginTimer;
|
||||
|
||||
@ -67,7 +68,7 @@ private:
|
||||
QHash<FroniusStorage *, Thing *> m_froniusStorages;
|
||||
QHash<SunspecThing *, Thing *> m_sunspecThings;
|
||||
|
||||
QHash<ThingActionInfo *, Thing *> m_asyncActions;
|
||||
QHash<QUuid, ThingActionInfo *> m_asyncActions;
|
||||
|
||||
void updateThingStates(Thing *thing);
|
||||
|
||||
|
||||
@ -37,107 +37,32 @@
|
||||
|
||||
SunspecThing::SunspecThing(Thing *thing, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_thing(thing),
|
||||
m_modbus(nullptr)
|
||||
m_thing(thing)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SunspecThing::~SunspecThing()
|
||||
{
|
||||
modbus_free(m_modbus);
|
||||
m_modbus = nullptr;
|
||||
}
|
||||
|
||||
void SunspecThing::destroyModbus()
|
||||
{
|
||||
if (m_thing)
|
||||
m_thing->setStateValue(sunspecStorageConnectedStateTypeId, false);
|
||||
|
||||
if (!m_modbus)
|
||||
return;
|
||||
|
||||
modbus_free(m_modbus);
|
||||
m_modbus = nullptr;
|
||||
}
|
||||
|
||||
void SunspecThing::readCommonBlock()
|
||||
{
|
||||
if (!m_modbus)
|
||||
if (!m_modbusTcpMaster)
|
||||
return;
|
||||
|
||||
qCDebug(dcFronius()) << "Successfully set slave to" << m_slaveId;
|
||||
|
||||
int address = 40001 - 1;
|
||||
uint16_t data[70];
|
||||
|
||||
// Read common block
|
||||
if (modbus_read_registers(m_modbus, address, 70, data) < 0) {
|
||||
qCWarning(dcFronius()) << "Could not read register address:" << modbus_strerror(errno);
|
||||
destroyModbus();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcFronius()) << "Sunspec Identification:" << convertModbusRegisters(data, 0, 2);
|
||||
|
||||
if (convertModbusRegisters(data, 0, 2) != "SunS") {
|
||||
qCWarning(dcFronius()) << "Could not find SunS value at" << address << "on" << address;
|
||||
destroyModbus();
|
||||
return;
|
||||
}
|
||||
|
||||
// ID: 40003
|
||||
qCDebug(dcFronius()) << "Id:" << data[2];
|
||||
|
||||
// Manufacturer: 40005 | 16
|
||||
qCDebug(dcFronius()) << "Manufacturer:" << QString::fromLatin1(convertModbusRegisters(data, 4, 16));
|
||||
|
||||
// Thing model: 40021 | 16
|
||||
qCDebug(dcFronius()) << "Thing model:" << QString::fromLatin1(convertModbusRegisters(data, 20, 16));
|
||||
|
||||
// Data manager version: 40037 | 8
|
||||
qCDebug(dcFronius()) << "Data manager version:" << QString::fromLatin1(convertModbusRegisters(data, 36, 8));
|
||||
|
||||
// Inverter Version: 40045 | 8
|
||||
qCDebug(dcFronius()) << "Inverter version:" << QString::fromLatin1(convertModbusRegisters(data, 44, 8));
|
||||
|
||||
// Serial Number: 40053 | 16
|
||||
qCDebug(dcFronius()) << "Serial number:" << QString::fromLatin1(convertModbusRegisters(data, 52, 16));
|
||||
|
||||
// Modbus thing address : 40069 | 1
|
||||
qCDebug(dcFronius()) << "Thing modbus address:" << data[67];
|
||||
|
||||
/*Sunspec Model Type
|
||||
zum Auswählen des Datentyps von Datenmodellen für Wechselrichter
|
||||
(3d) float
|
||||
Darstellung als Gleitkommazahlen
|
||||
SunSpec Inverter Model I111, I112 oder I113
|
||||
(3e) int+SF
|
||||
Darstellung als ganze Zahlen mit Skalierungsfaktoren
|
||||
SunSpec Inverter Model I101, I102 oder I103
|
||||
WICHTIG! Da die verschiedenen Modelle über unterschiedliche Anzahlen an Re-
|
||||
gistern verfügen, ändern sich durch den Wechsel des Datentyps auch die Regis-
|
||||
teradressen aller nachfolgenden Modelle.*/
|
||||
qCDebug(dcFronius()) << "SunSpec Inverter Modbus Map:" << data[69];
|
||||
if (data[69] > 110){
|
||||
m_floatingPointRepresentation = true;
|
||||
} else {
|
||||
m_floatingPointRepresentation = false;
|
||||
}
|
||||
|
||||
readStorageBlock();
|
||||
m_modbusTcpMaster->readHoldingRegister(m_slaveId, address, 70);
|
||||
}
|
||||
|
||||
void SunspecThing::readStorageBlock()
|
||||
{
|
||||
if (!m_modbus)
|
||||
if (!m_modbusTcpMaster)
|
||||
return;
|
||||
|
||||
|
||||
qCDebug(dcFronius()) << "Storage";
|
||||
|
||||
int address;
|
||||
|
||||
if (m_floatingPointRepresentation) {
|
||||
address = 40313;
|
||||
} else {
|
||||
@ -147,68 +72,7 @@ void SunspecThing::readStorageBlock()
|
||||
- bei Einstellung „float“: 40313
|
||||
- bei Einstellung „int+SF“: 40303
|
||||
*/
|
||||
uint16_t data[26];
|
||||
|
||||
if (modbus_read_registers(m_modbus, address, 26, data) < 0) {
|
||||
qCWarning(dcFronius()) << "Could not read register address" << address << ":" << modbus_strerror(errno);
|
||||
destroyModbus();
|
||||
return;
|
||||
}
|
||||
|
||||
// ID
|
||||
qCDebug(dcFronius()) << "Id:" << data[0];
|
||||
|
||||
if (data[0] != 124) {
|
||||
qCWarning(dcFronius()) << "Invalid id in register address" << address << ":" << data[0];
|
||||
destroyModbus();
|
||||
return;
|
||||
}
|
||||
|
||||
// L
|
||||
qCDebug(dcFronius()) << "Register count:" << data[1];
|
||||
|
||||
// WchaMax
|
||||
qCDebug(dcFronius()) << "Setpoint of maximum charge:" << data[2] << "W";
|
||||
|
||||
// WchaGra
|
||||
qCDebug(dcFronius()) << "Setpoint for maximum charge:" << data[3] << "[s]";
|
||||
|
||||
// WdisChaGra
|
||||
qCDebug(dcFronius()) << "Setpoint for maximum discharge rate:" << data[4] << "[s]";
|
||||
|
||||
// StorCtl_Mod: Activate hold/discharge/charge storage control mode. Bit0: charge, Bit 1: discharge
|
||||
QBitArray storageControlBits = convertModbusRegisterBits(data[5]);
|
||||
|
||||
qCDebug(dcFronius()) << "Charging control mode:" << (storageControlBits.testBit(0) ? "On" : "Off");
|
||||
m_thing->setStateValue(sunspecStorageEnableChargingLimitStateTypeId, storageControlBits.testBit(0));
|
||||
|
||||
qCDebug(dcFronius()) << "Discharging control mode:" << (storageControlBits.testBit(1) ? "On" : "Off");
|
||||
m_thing->setStateValue(sunspecStorageEnableDischargingLimitStateTypeId, storageControlBits.testBit(1));
|
||||
|
||||
// MinRsvPct
|
||||
qCDebug(dcFronius()) << "Setpoint for minimum reserve:" << data[7] << "[%]";
|
||||
|
||||
// ChaState
|
||||
qCDebug(dcFronius()) << "Current energy:" << ((double)data[8] / 100.0) << "[%]";
|
||||
m_thing->setStateValue(sunspecStorageEnergyStateTypeId, (double)data[8] / 100.0);
|
||||
|
||||
// ChaSt
|
||||
//Charge status of storage thing. Enumerated
|
||||
qCDebug(dcFronius()) << "Charge state" << storageStateToString(static_cast<StorageState>(data[11]));
|
||||
m_thing->setStateValue(sunspecStorageStorageStateStateTypeId, storageStateToString(static_cast<StorageState>(data[11])));
|
||||
|
||||
// OutWRte
|
||||
m_thing->setStateValue(sunspecStorageDischargingRateStateTypeId, (int16_t)data[12] / 100);
|
||||
qCDebug(dcFronius()) << "Percent of max. discharge rate:" << ((int16_t)data[12] / 100) << "[%]";
|
||||
|
||||
// InWRte
|
||||
m_thing->setStateValue(sunspecStorageChargingRateStateTypeId, (int16_t)data[13] / 100);
|
||||
qCDebug(dcFronius()) << "Percent of max. charge rate:" << ((int16_t)data[13] / 100) << "[%]";
|
||||
|
||||
// ChaGriSet
|
||||
m_thing->setStateValue(sunspecStorageGridChargingStateTypeId, data[18]);
|
||||
qCDebug(dcFronius()) << "Charging from grid:" << (data[18] == 0 ? "disabled" : "enabled");
|
||||
|
||||
m_modbusTcpMaster->readHoldingRegister(m_slaveId, address, 26);
|
||||
}
|
||||
|
||||
QByteArray SunspecThing::convertModbusRegister(const uint16_t &modbusData)
|
||||
@ -234,7 +98,7 @@ QBitArray SunspecThing::convertModbusRegisterBits(const uint16_t &modbusData)
|
||||
return bits;
|
||||
}
|
||||
|
||||
QByteArray SunspecThing::convertModbusRegisters(uint16_t *modbusData, const int &offset, const int &size)
|
||||
QByteArray SunspecThing::convertModbusRegisters(const QVector<quint16> &modbusData, int offset, int size)
|
||||
{
|
||||
QByteArray bytes;
|
||||
for (int i = offset; i < offset + size; i++)
|
||||
@ -253,60 +117,30 @@ QString SunspecThing::storageStateToString(const SunspecThing::StorageState &sta
|
||||
|
||||
bool SunspecThing::connectModbus()
|
||||
{
|
||||
if (m_modbus)
|
||||
destroyModbus();
|
||||
|
||||
if (m_thing->paramValue(sunspecStorageThingModbusHostParamTypeId).toString().isEmpty()) {
|
||||
qCWarning(dcFronius()) << "Empty ip address";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_modbus = modbus_new_tcp(m_thing->paramValue(sunspecStorageThingModbusHostParamTypeId).toString().toStdString().c_str(), 502);
|
||||
if (modbus_connect(m_modbus) == -1) {
|
||||
qCWarning(dcFronius()) << "Connection failed:" << modbus_strerror(errno);
|
||||
destroyModbus();
|
||||
return false;
|
||||
}
|
||||
m_modbusTcpMaster = new ModbusTCPMaster(QHostAddress(m_thing->paramValue(sunspecStorageThingModbusHostParamTypeId).toString()), 502, this);
|
||||
connect(m_modbusTcpMaster, &ModbusTCPMaster::connectionStateChanged, this, &SunspecThing::connectionStateChanged);
|
||||
connect(m_modbusTcpMaster, &ModbusTCPMaster::writeRequestExecuted, this, &SunspecThing::requestExecuted);
|
||||
connect(m_modbusTcpMaster, &ModbusTCPMaster::receivedHoldingRegister, this, &SunspecThing::onReceivedHoldingRegister);
|
||||
|
||||
//TODO
|
||||
//timeval response_timeout;
|
||||
//response_timeout.tv_sec = 3;
|
||||
//response_timeout.tv_usec = 0;
|
||||
|
||||
//timeval byte_timeout;
|
||||
//byte_timeout.tv_sec = 3;
|
||||
//byte_timeout.tv_usec = 0;
|
||||
//modbus_set_byte_timeout(m_modbus, &byte_timeout);
|
||||
//modbus_set_response_timeout(m_modbus, &response_timeout);
|
||||
m_modbusTcpMaster->setTimeout(3 * 1000); // 3 seconds
|
||||
m_modbusTcpMaster->setNumberOfRetries(3);
|
||||
|
||||
qCDebug(dcFronius()) << "Connected successfully" << m_thing->paramValue(sunspecStorageThingModbusHostParamTypeId).toString();
|
||||
m_thing->setStateValue(sunspecStorageConnectedStateTypeId, true);
|
||||
|
||||
|
||||
if (modbus_set_slave(m_modbus, m_slaveId) != 0) {
|
||||
qCWarning(dcFronius()) << "Could not set Slave Id to" << m_slaveId << ":" << modbus_strerror(errno);
|
||||
destroyModbus();
|
||||
return false;
|
||||
}
|
||||
|
||||
readCommonBlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SunspecThing::disconnectModbus()
|
||||
QUuid SunspecThing::setGridCharging(const bool &charging)
|
||||
{
|
||||
if (!m_modbus)
|
||||
return;
|
||||
|
||||
destroyModbus();
|
||||
}
|
||||
|
||||
bool SunspecThing::setGridCharging(const bool &charging)
|
||||
{
|
||||
if (!m_modbus) {
|
||||
connectModbus();
|
||||
return false;
|
||||
if (!m_modbusTcpMaster) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/* Start address:
|
||||
@ -327,42 +161,18 @@ bool SunspecThing::setGridCharging(const bool &charging)
|
||||
registerAddress = 40303 + 18 - 1;
|
||||
}
|
||||
|
||||
uint16_t value = 0;
|
||||
if(modbus_read_registers(m_modbus, registerAddress, 1, &value) == -1){
|
||||
qCWarning(dcFronius()) << "Could not read register address:" << registerAddress << (int16_t)value << modbus_strerror(errno);
|
||||
return false;
|
||||
}else {
|
||||
qDebug(dcFronius()) << "Succesfully read register:" << registerAddress << (int16_t)value ;
|
||||
}
|
||||
|
||||
|
||||
if (charging) {
|
||||
value = 1;
|
||||
if (modbus_write_register(m_modbus, registerAddress, value) == -1) {
|
||||
qCWarning(dcFronius()) << "Could not write register address:" << registerAddress << value << modbus_strerror(errno);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
value = 0;
|
||||
if (modbus_write_register(m_modbus, registerAddress, value) == -1) {
|
||||
qCWarning(dcFronius()) << "Could not write register address:" << registerAddress << value << modbus_strerror(errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
readStorageBlock();
|
||||
return true;
|
||||
quint16 value = charging;
|
||||
return m_modbusTcpMaster->writeHoldingRegister(m_slaveId, registerAddress, value);
|
||||
}
|
||||
|
||||
bool SunspecThing::setChargingRate(const int &charging)
|
||||
QUuid SunspecThing::setChargingRate(const int &charging)
|
||||
{
|
||||
// 40313 + Offset 14 - 1
|
||||
//Register Name InWRte
|
||||
/* Defines the maximum charge rate (charge limit). Default is 100% */
|
||||
|
||||
if (!m_modbus) {
|
||||
connectModbus();
|
||||
return false;
|
||||
if (!m_modbusTcpMaster) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int registerAddress;
|
||||
@ -373,29 +183,16 @@ bool SunspecThing::setChargingRate(const int &charging)
|
||||
}
|
||||
|
||||
int16_t value = charging * 100;
|
||||
if (modbus_write_register(m_modbus, registerAddress, value) == -1) {
|
||||
qCWarning(dcFronius()) << "Could not write register address:" << registerAddress << value << modbus_strerror(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
readStorageBlock();
|
||||
return true;
|
||||
return m_modbusTcpMaster->writeHoldingRegister(m_slaveId, registerAddress, value);
|
||||
}
|
||||
|
||||
bool SunspecThing::setStorageControlMode(const int &charging)
|
||||
QUuid SunspecThing::setStorageControlMode(const int &charging)
|
||||
{
|
||||
// 40313 + Offset 6 - 1
|
||||
// Set charge bit to enable charge limit, set discharge bit to enable discharge limit, set both bits to enable both limits
|
||||
|
||||
if (!m_modbus) {
|
||||
connectModbus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modbus_set_slave(m_modbus, m_slaveId) != 0) {
|
||||
qCWarning(dcFronius()) << "Could not set slave to" << m_slaveId << ":" << modbus_strerror(errno);
|
||||
destroyModbus();
|
||||
return false;
|
||||
if (!m_modbusTcpMaster) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int registerAddress;
|
||||
@ -406,30 +203,17 @@ bool SunspecThing::setStorageControlMode(const int &charging)
|
||||
}
|
||||
|
||||
uint16_t value = charging;
|
||||
if (modbus_write_register(m_modbus, registerAddress, value) == -1) {
|
||||
qCWarning(dcFronius()) << "Could not write register address:" << registerAddress << value << modbus_strerror(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
readStorageBlock();
|
||||
return true;
|
||||
return m_modbusTcpMaster->writeHoldingRegister(m_slaveId, registerAddress, value);
|
||||
}
|
||||
|
||||
bool SunspecThing::setDischargingRate(const int &charging)
|
||||
QUuid SunspecThing::setDischargingRate(const int &charging)
|
||||
{
|
||||
// 40313 + Offset 13 - 1
|
||||
//Register Name OutWRte
|
||||
/*Defines the maximum discharge rate (discharge limit). Default is 100% */
|
||||
|
||||
if (!m_modbus) {
|
||||
connectModbus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modbus_set_slave(m_modbus, m_slaveId) != 0) {
|
||||
qCWarning(dcFronius()) << "Could not set slave to" << m_slaveId << ":" << modbus_strerror(errno);
|
||||
destroyModbus();
|
||||
return false;
|
||||
if (!m_modbusTcpMaster) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int registerAddress;
|
||||
@ -440,22 +224,129 @@ bool SunspecThing::setDischargingRate(const int &charging)
|
||||
}
|
||||
|
||||
int16_t value = charging * 100;
|
||||
if (modbus_write_register(m_modbus, registerAddress, value) == -1) {
|
||||
qCWarning(dcFronius()) << "Could not write register address:" << registerAddress << value << modbus_strerror(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
readStorageBlock();
|
||||
return true;
|
||||
return m_modbusTcpMaster->writeHoldingRegister(m_slaveId, registerAddress, value);
|
||||
}
|
||||
|
||||
|
||||
void SunspecThing::update()
|
||||
{
|
||||
if (!m_modbus) {
|
||||
connectModbus();
|
||||
if (!m_modbusTcpMaster) {
|
||||
return;
|
||||
}
|
||||
|
||||
readCommonBlock();
|
||||
readStorageBlock();
|
||||
}
|
||||
|
||||
void SunspecThing::onReceivedHoldingRegister(quint32 slaveAddress, quint32 modbusRegister, const QVector<quint16> &data)
|
||||
{
|
||||
if (!m_thing)
|
||||
return;
|
||||
|
||||
switch (modbusRegister) {
|
||||
case 40000: {// Common block, 70 registers long
|
||||
|
||||
qCDebug(dcFronius()) << "Sunspec Identification:" << convertModbusRegisters(data, 0, 2);
|
||||
|
||||
if (convertModbusRegisters(data, 0, 2) != "SunS") {
|
||||
qCWarning(dcFronius()) << "Could not find SunS value at" << modbusRegister << "on" << slaveAddress;
|
||||
return;
|
||||
}
|
||||
|
||||
// ID: 40003
|
||||
qCDebug(dcFronius()) << "Id:" << data[2];
|
||||
|
||||
// Manufacturer: 40005 | 16
|
||||
qCDebug(dcFronius()) << "Manufacturer:" << QString::fromLatin1(convertModbusRegisters(data, 4, 16));
|
||||
|
||||
// Thing model: 40021 | 16
|
||||
qCDebug(dcFronius()) << "Thing model:" << QString::fromLatin1(convertModbusRegisters(data, 20, 16));
|
||||
|
||||
// Data manager version: 40037 | 8
|
||||
qCDebug(dcFronius()) << "Data manager version:" << QString::fromLatin1(convertModbusRegisters(data, 36, 8));
|
||||
|
||||
// Inverter Version: 40045 | 8
|
||||
qCDebug(dcFronius()) << "Inverter version:" << QString::fromLatin1(convertModbusRegisters(data, 44, 8));
|
||||
|
||||
// Serial Number: 40053 | 16
|
||||
qCDebug(dcFronius()) << "Serial number:" << QString::fromLatin1(convertModbusRegisters(data, 52, 16));
|
||||
|
||||
// Modbus thing address : 40069 | 1
|
||||
qCDebug(dcFronius()) << "Thing modbus address:" << data[67];
|
||||
|
||||
/*Sunspec Model Type
|
||||
zum Auswählen des Datentyps von Datenmodellen für Wechselrichter
|
||||
(3d) float
|
||||
Darstellung als Gleitkommazahlen
|
||||
SunSpec Inverter Model I111, I112 oder I113
|
||||
(3e) int+SF
|
||||
Darstellung als ganze Zahlen mit Skalierungsfaktoren
|
||||
SunSpec Inverter Model I101, I102 oder I103
|
||||
WICHTIG! Da die verschiedenen Modelle über unterschiedliche Anzahlen an Re-
|
||||
gistern verfügen, ändern sich durch den Wechsel des Datentyps auch die Regis-
|
||||
teradressen aller nachfolgenden Modelle.*/
|
||||
qCDebug(dcFronius()) << "SunSpec Inverter Modbus Map:" << data[69];
|
||||
if (data[69] > 110){
|
||||
m_floatingPointRepresentation = true;
|
||||
} else {
|
||||
m_floatingPointRepresentation = false;
|
||||
}
|
||||
} break;
|
||||
case 40303:
|
||||
case 40313: { //Storage Block
|
||||
// ID
|
||||
qCDebug(dcFronius()) << "Id:" << data[0];
|
||||
|
||||
if (data[0] != 124) {
|
||||
qCWarning(dcFronius()) << "Invalid id in register address" << modbusRegister << ":" << data[0];
|
||||
}
|
||||
|
||||
// L
|
||||
qCDebug(dcFronius()) << "Register count:" << data[1];
|
||||
|
||||
// WchaMax
|
||||
qCDebug(dcFronius()) << "Setpoint of maximum charge:" << data[2] << "W";
|
||||
|
||||
// WchaGra
|
||||
qCDebug(dcFronius()) << "Setpoint for maximum charge:" << data[3] << "[s]";
|
||||
|
||||
// WdisChaGra
|
||||
qCDebug(dcFronius()) << "Setpoint for maximum discharge rate:" << data[4] << "[s]";
|
||||
|
||||
// StorCtl_Mod: Activate hold/discharge/charge storage control mode. Bit0: charge, Bit 1: discharge
|
||||
QBitArray storageControlBits = convertModbusRegisterBits(data[5]);
|
||||
|
||||
qCDebug(dcFronius()) << "Charging control mode:" << (storageControlBits.testBit(0) ? "On" : "Off");
|
||||
m_thing->setStateValue(sunspecStorageEnableChargingLimitStateTypeId, storageControlBits.testBit(0));
|
||||
|
||||
qCDebug(dcFronius()) << "Discharging control mode:" << (storageControlBits.testBit(1) ? "On" : "Off");
|
||||
m_thing->setStateValue(sunspecStorageEnableDischargingLimitStateTypeId, storageControlBits.testBit(1));
|
||||
|
||||
// MinRsvPct
|
||||
qCDebug(dcFronius()) << "Setpoint for minimum reserve:" << data[7] << "[%]";
|
||||
|
||||
// ChaState
|
||||
qCDebug(dcFronius()) << "Current energy:" << ((double)data[8] / 100.0) << "[%]";
|
||||
m_thing->setStateValue(sunspecStorageEnergyStateTypeId, (double)data[8] / 100.0);
|
||||
|
||||
// ChaSt
|
||||
//Charge status of storage thing. Enumerated
|
||||
qCDebug(dcFronius()) << "Charge state" << storageStateToString(static_cast<StorageState>(data[11]));
|
||||
m_thing->setStateValue(sunspecStorageStorageStateStateTypeId, storageStateToString(static_cast<StorageState>(data[11])));
|
||||
|
||||
// OutWRte
|
||||
m_thing->setStateValue(sunspecStorageDischargingRateStateTypeId, (int16_t)data[12] / 100);
|
||||
qCDebug(dcFronius()) << "Percent of max. discharge rate:" << ((int16_t)data[12] / 100) << "[%]";
|
||||
|
||||
// InWRte
|
||||
m_thing->setStateValue(sunspecStorageChargingRateStateTypeId, (int16_t)data[13] / 100);
|
||||
qCDebug(dcFronius()) << "Percent of max. charge rate:" << ((int16_t)data[13] / 100) << "[%]";
|
||||
|
||||
// ChaGriSet
|
||||
m_thing->setStateValue(sunspecStorageGridChargingStateTypeId, data[18]);
|
||||
qCDebug(dcFronius()) << "Charging from grid:" << (data[18] == 0 ? "disabled" : "enabled");
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,9 +37,9 @@
|
||||
#include <QHostAddress>
|
||||
#include <QByteArray>
|
||||
#include <QBitArray>
|
||||
#include <QUuid>
|
||||
|
||||
#include <modbus/modbus.h>
|
||||
#include <modbus/modbus-tcp.h>
|
||||
#include "../modbus/modbustcpmaster.h"
|
||||
|
||||
class SunspecThing : public QObject
|
||||
{
|
||||
@ -61,31 +61,38 @@ public:
|
||||
|
||||
private:
|
||||
Thing *m_thing;
|
||||
modbus_t *m_modbus;
|
||||
ModbusTCPMaster *m_modbusTcpMaster = nullptr;
|
||||
int m_slaveId = 1;
|
||||
bool m_floatingPointRepresentation = false;
|
||||
|
||||
void destroyModbus();
|
||||
|
||||
void readCommonBlock();
|
||||
void readStorageBlock();
|
||||
|
||||
QByteArray convertModbusRegister(const uint16_t &modbusData);
|
||||
QBitArray convertModbusRegisterBits(const uint16_t &modbusData);
|
||||
QByteArray convertModbusRegisters(uint16_t *modbusData, const int &offset, const int &size);
|
||||
QByteArray convertModbusRegisters(const QVector<quint16> &modbusData, int offset, int size);
|
||||
|
||||
QString storageStateToString(const StorageState &state);
|
||||
|
||||
public slots:
|
||||
bool connectModbus();
|
||||
void disconnectModbus();
|
||||
|
||||
bool setGridCharging(const bool &charging);
|
||||
bool setDischargingRate(const int &charging);
|
||||
bool setChargingRate(const int &charging);
|
||||
bool setStorageControlMode(const int &charging);
|
||||
QUuid setGridCharging(const bool &charging);
|
||||
QUuid setDischargingRate(const int &charging);
|
||||
QUuid setChargingRate(const int &charging);
|
||||
QUuid setStorageControlMode(const int &charging);
|
||||
|
||||
void update();
|
||||
|
||||
signals:
|
||||
void connectionStateChanged(bool status);
|
||||
void requestExecuted(QUuid requetId, bool success);
|
||||
|
||||
private slots:
|
||||
void onConnectionStateChanged(bool status);
|
||||
void onRequestExecuted(QUuid requestId, bool success);
|
||||
void onRequestError(QUuid requestId, const QString &error);
|
||||
void onReceivedHoldingRegister(quint32 slaveAddress, quint32 modbusRegister, const QVector<quint16> &values);
|
||||
};
|
||||
|
||||
#endif // SUNSPECTHING_H
|
||||
|
||||
@ -99,9 +99,9 @@ QUuid ModbusRTUMaster::readCoil(uint slaveAddress, uint registerAddress)
|
||||
|
||||
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();
|
||||
@ -112,7 +112,6 @@ QUuid ModbusRTUMaster::readCoil(uint slaveAddress, uint registerAddress)
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
reply->deleteLater();
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
@ -145,6 +144,7 @@ QUuid ModbusRTUMaster::writeCoil(uint slaveAddress, uint registerAddress, bool v
|
||||
|
||||
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) {
|
||||
@ -157,7 +157,6 @@ QUuid ModbusRTUMaster::writeCoil(uint slaveAddress, uint registerAddress, bool v
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
reply->deleteLater();
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
@ -189,19 +188,19 @@ QUuid ModbusRTUMaster::writeHoldingRegister(uint slaveAddress, uint registerAddr
|
||||
|
||||
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.value(0));
|
||||
emit receivedHoldingRegister(reply->serverAddress(), modbusAddress, unit.values());
|
||||
|
||||
} else {
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
reply->deleteLater();
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
@ -232,6 +231,7 @@ QUuid ModbusRTUMaster::readDiscreteInput(uint slaveAddress, uint registerAddress
|
||||
|
||||
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) {
|
||||
@ -244,7 +244,6 @@ QUuid ModbusRTUMaster::readDiscreteInput(uint slaveAddress, uint registerAddress
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
reply->deleteLater();
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
@ -276,6 +275,7 @@ QUuid ModbusRTUMaster::readInputRegister(uint slaveAddress, uint registerAddress
|
||||
|
||||
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] {
|
||||
|
||||
|
||||
@ -289,7 +289,6 @@ QUuid ModbusRTUMaster::readInputRegister(uint slaveAddress, uint registerAddress
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
reply->deleteLater();
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
@ -321,19 +320,19 @@ QUuid ModbusRTUMaster::readHoldingRegister(uint slaveAddress, uint registerAddre
|
||||
|
||||
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.value(0));
|
||||
emit receivedHoldingRegister(reply->serverAddress(), modbusAddress, unit.values());
|
||||
|
||||
} else {
|
||||
requestExecuted(requestId, false);
|
||||
qCWarning(dcModbusRTU()) << "Read response error:" << reply->error();
|
||||
}
|
||||
reply->deleteLater();
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply, requestId, this] (QModbusDevice::Error error){
|
||||
|
||||
|
||||
@ -74,7 +74,7 @@ signals:
|
||||
|
||||
void receivedCoil(uint slaveAddress, uint modbusRegister, bool value);
|
||||
void receivedDiscreteInput(uint slaveAddress, uint modbusRegister, bool value);
|
||||
void receivedHoldingRegister(uint slaveAddress, uint modbusRegister, uint value);
|
||||
void receivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values);
|
||||
void receivedInputRegister(uint slaveAddress, uint modbusRegister, uint value);
|
||||
};
|
||||
|
||||
|
||||
@ -71,6 +71,16 @@ bool ModbusTCPMaster::connectDevice() {
|
||||
return m_modbusTcpClient->connectDevice();
|
||||
}
|
||||
|
||||
void ModbusTCPMaster::setNumberOfRetries(int number)
|
||||
{
|
||||
m_modbusTcpClient->setNumberOfRetries(number);
|
||||
}
|
||||
|
||||
void ModbusTCPMaster::setTimeout(int timeout)
|
||||
{
|
||||
m_modbusTcpClient->setTimeout(timeout);
|
||||
}
|
||||
|
||||
uint ModbusTCPMaster::port()
|
||||
{
|
||||
return m_modbusTcpClient->connectionParameter(QModbusDevice::NetworkPortParameter).toUInt();
|
||||
@ -143,7 +153,7 @@ QUuid ModbusTCPMaster::readCoil(uint slaveAddress, uint registerAddress)
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid ModbusTCPMaster::writeHoldingRegister(uint slaveAddress, uint registerAddress, const QVector<quint16> &values)
|
||||
QUuid ModbusTCPMaster::writeHoldingRegisters(uint slaveAddress, uint registerAddress, const QVector<quint16> &values)
|
||||
{
|
||||
if (!m_modbusTcpClient) {
|
||||
return "";
|
||||
@ -363,6 +373,11 @@ QUuid ModbusTCPMaster::writeCoil(uint slaveAddress, uint registerAddress, bool v
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid ModbusTCPMaster::writeHoldingRegister(uint slaveAddress, uint registerAddress, quint16 value)
|
||||
{
|
||||
return writeHoldingRegisters(slaveAddress, registerAddress, QVector<quint16>() << value);
|
||||
}
|
||||
|
||||
|
||||
void ModbusTCPMaster::onModbusErrorOccurred(QModbusDevice::Error error)
|
||||
{
|
||||
|
||||
@ -45,6 +45,8 @@ public:
|
||||
~ModbusTCPMaster();
|
||||
|
||||
bool connectDevice();
|
||||
void setNumberOfRetries(int number);
|
||||
void setTimeout(int timeout);
|
||||
|
||||
QUuid readCoil(uint slaveAddress, uint registerAddress);
|
||||
QUuid readDiscreteInput(uint slaveAddress, uint registerAddress);
|
||||
@ -52,7 +54,9 @@ public:
|
||||
QUuid readHoldingRegister(uint slaveAddress, uint registerAddress, uint size = 1);
|
||||
|
||||
QUuid writeCoil(uint slaveAddress, uint registerAddress, bool status);
|
||||
QUuid writeHoldingRegister(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);
|
||||
|
||||
QHostAddress hostAddress();
|
||||
uint port();
|
||||
|
||||
@ -420,7 +420,7 @@ void IntegrationPluginModbusCommander::onReceivedDiscreteInput(quint32 slaveAddr
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginModbusCommander::onReceivedHoldingRegister(quint32 slaveAddress, quint32 modbusRegister, int value)
|
||||
void IntegrationPluginModbusCommander::onReceivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values)
|
||||
{
|
||||
auto modbus = sender();
|
||||
|
||||
@ -430,7 +430,7 @@ void IntegrationPluginModbusCommander::onReceivedHoldingRegister(quint32 slaveAd
|
||||
if (thing->thingClassId() == holdingRegisterThingClassId) {
|
||||
if ((thing->paramValue(m_slaveAddressParamTypeId.value(thing->thingClassId())) == slaveAddress)
|
||||
&& (thing->paramValue(m_registerAddressParamTypeId.value(thing->thingClassId())) == modbusRegister)) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), value);
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), values[0]);
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
return;
|
||||
}
|
||||
@ -442,7 +442,7 @@ void IntegrationPluginModbusCommander::onReceivedHoldingRegister(quint32 slaveAd
|
||||
if (thing->thingClassId() == holdingRegisterThingClassId) {
|
||||
if ((thing->paramValue(m_slaveAddressParamTypeId.value(thing->thingClassId())) == slaveAddress)
|
||||
&& (thing->paramValue(m_registerAddressParamTypeId.value(thing->thingClassId())) == modbusRegister)) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), value);
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), values[0]);
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ private slots:
|
||||
void onRequestError(QUuid requestId, const QString &error);
|
||||
void onReceivedCoil(quint32 slaveAddress, quint32 modbusRegister, bool value);
|
||||
void onReceivedDiscreteInput(quint32 slaveAddress, quint32 modbusRegister, bool value);
|
||||
void onReceivedHoldingRegister(quint32 slaveAddress, quint32 modbusRegister, int value);
|
||||
void onReceivedHoldingRegister(uint slaveAddress, uint modbusRegister, const QVector<quint16> &values);
|
||||
void onReceivedInputRegister(quint32 slaveAddress, quint32 modbusRegister, int value);
|
||||
};
|
||||
|
||||
|
||||
@ -8,8 +8,10 @@ QT += \
|
||||
SOURCES += \
|
||||
integrationpluginmodbuscommander.cpp \
|
||||
../modbus/modbustcpmaster.cpp \
|
||||
../modbus/modbusrtumaster.cpp \
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginmodbuscommander.h \
|
||||
../modbus/modbustcpmaster.h \
|
||||
../modbus/modbusrtumaster.h \
|
||||
|
||||
|
||||
@ -160,12 +160,13 @@ void IntegrationPluginMyPv::executeAction(ThingActionInfo *info)
|
||||
if (action.actionTypeId() == elwaHeatingPowerActionTypeId) {
|
||||
int heatingPower = action.param(elwaHeatingPowerActionHeatingPowerParamTypeId).value().toInt();
|
||||
|
||||
QUuid requestId = modbusTCPMaster->writeHoldingRegister(0xff, ElwaModbusRegisters::Power, QVector<quint16>() << heatingPower));
|
||||
QUuid requestId = modbusTCPMaster->writeHoldingRegister(0xff, ElwaModbusRegisters::Power, heatingPower);
|
||||
m_asyncActions.insert(requestId, info);
|
||||
} else if (action.actionTypeId() == elwaPowerActionTypeId) {
|
||||
bool power = action.param(elwaHeatingPowerActionHeatingPowerParamTypeId).value().toBool();
|
||||
if(power) {
|
||||
QUuid requestId = modbusTCPMaster->writeHoldingRegister(0xff, ElwaModbusRegisters::ManuelStart, QVector<quint16>() << 1));
|
||||
QUuid requestId = modbusTCPMaster->writeHoldingRegister(0xff, ElwaModbusRegisters::ManuelStart, 1);
|
||||
m_asyncActions.insert(requestId, info);
|
||||
}
|
||||
} else {
|
||||
Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
|
||||
@ -184,7 +185,7 @@ void IntegrationPluginMyPv::onRefreshTimer(){
|
||||
|
||||
void IntegrationPluginMyPv::onConnectionStateChanged(bool status)
|
||||
{
|
||||
ModbusTCPMaster *modbusTcpMaster = sender();
|
||||
ModbusTCPMaster *modbusTcpMaster = static_cast<ModbusTCPMaster *>(sender());
|
||||
Thing *thing = m_modbusTcpMasters.key(modbusTcpMaster);
|
||||
if (!thing)
|
||||
return;
|
||||
@ -193,25 +194,32 @@ void IntegrationPluginMyPv::onConnectionStateChanged(bool status)
|
||||
|
||||
void IntegrationPluginMyPv::onWriteRequestExecuted(QUuid requestId, bool success)
|
||||
{
|
||||
|
||||
if (m_asyncActions.contains(requestId)) {
|
||||
ThingActionInfo *info = m_asyncActions.value(requestId);
|
||||
if (success) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginMyPv::onWriteRequestError(QUuid requestId, const QString &error)
|
||||
{
|
||||
Q_UNUSED(requestId)
|
||||
qCWarning(dcMypv()) << "Error "
|
||||
qCWarning(dcMypv()) << "Modbus error "<< error;
|
||||
}
|
||||
|
||||
void IntegrationPluginMyPv::onReceivedHoldingRegister(quint32 slaveAddress, quint32 modbusRegister, int value)
|
||||
void IntegrationPluginMyPv::onReceivedHoldingRegister(quint32 slaveAddress, quint32 modbusRegister, const QVector<quint16> &value)
|
||||
{
|
||||
Q_UNUSED(slaveAddress)
|
||||
ModbusTCPMaster *modbusTcpMaster = sender();
|
||||
ModbusTCPMaster *modbusTcpMaster = static_cast<ModbusTCPMaster *>(sender());
|
||||
Thing *thing = m_modbusTcpMasters.key(modbusTcpMaster);
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
if(modbusRegister == ElwaModbusRegisters::Status) {
|
||||
switch (ElwaStatus(value)) {
|
||||
switch (ElwaStatus(value[0])) {
|
||||
case ElwaStatus::Heating: {
|
||||
thing->setStateValue(elwaStatusStateTypeId, "Heating");
|
||||
thing->setStateValue(elwaPowerStateTypeId, true);
|
||||
|
||||
Reference in New Issue
Block a user