X2 only accepts read requests 2 registers long

master
trinnes 2023-01-27 20:16:33 +01:00
parent 4173d9bb4a
commit 4d3f24d203
1 changed files with 210 additions and 243 deletions

View File

@ -315,317 +315,284 @@ void IntegrationPluginDrexelUndWeiss::updateStates(Thing *thing)
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::BrauchwasserSolltermperatur); readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::BrauchwasserSolltermperatur);
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Auszenluft); readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Auszenluft);
readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Summenstoerung); readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::Summenstoerung);
readX2Power(thing, modbus, slaveAddress); readHoldingRegister(thing, modbus, slaveAddress, ModbusRegisterX2::LeistungKompressor);
readX2Energy(thing, modbus, slaveAddress); 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::readX2Power(Thing *thing, ModbusRtuMaster *modbus, uint slaveAddress)
void IntegrationPluginDrexelUndWeiss::readHoldingRegister(Thing *thing, ModbusRtuMaster *modbus, uint slaveAddress, uint modbusRegister)
{ {
ModbusRtuReply *reply = modbus->readHoldingRegister(slaveAddress, ModbusRegisterX2::LeistungKompressor, 8); ModbusRtuReply *reply = modbus->readHoldingRegister(slaveAddress, modbusRegister, 2); // min 2 registers must be read
connect(reply, &ModbusRtuReply::finished, reply, &ModbusRtuReply::deleteLater); connect(reply, &ModbusRtuReply::finished, reply, &ModbusRtuReply::deleteLater);
connect(reply, &ModbusRtuReply::finished, this, [reply, thing] { connect(reply, &ModbusRtuReply::finished, this, [reply, thing, this] {
if (reply->error() != ModbusRtuReply::Error::NoError) { if (reply->error() != ModbusRtuReply::Error::NoError) {
qCWarning(dcDrexelUndWeiss()) << "Modbus error" << reply->errorString(); qCWarning(dcDrexelUndWeiss()) << "Modbus error" << reply->errorString();
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), false);
return; return;
} }
if (reply->result().length() != 8) { thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
if (reply->result().length() != 2) {
return; return;
} }
uint32_t value = (static_cast<uint32_t>(reply->result()[0])<<16 | reply->result()[1]);
if (reply->registerAddress() != ModbusRegisterX2::LeistungKompressor) { if (thing->thingClassId() == x2wpThingClassId) {
return; switch (reply->registerAddress()) {
} case ModbusRegisterX2::Waermepumpe:
thing->setStateValue(x2wpPowerStateTypeId, value);
break;
//LeistungKompressor = 4000, case ModbusRegisterX2::RaumSoll:
float value = (static_cast<uint32_t>(reply->result()[0])<<16 | reply->result()[1])/1000.00; thing->setStateValue(x2wpTargetTemperatureStateTypeId, value/1000.00);
thing->setStateValue(x2wpPowerCompressorStateTypeId, value); break;
float totalPower = value;
//LeistungRaumheizung = 4002 case ModbusRegisterX2::Raum:
value = (static_cast<uint32_t>(reply->result()[2])<<16 | reply->result()[3])/1000.00; thing->setStateValue(x2wpTemperatureStateTypeId, value/1000.00);
thing->setStateValue(x2wpPowerRoomHeatingStateTypeId, value); break;
//LeistungWarmwasser = 4004 case ModbusRegisterX2::TemperaturWarmwasserspeicherUnten:
value = (static_cast<uint32_t>(reply->result()[4])<<16 | reply->result()[5])/1000.00; thing->setStateValue(x2wpWaterTemperatureStateTypeId, value/1000.00);
thing->setStateValue(x2wpPowerWaterHeatingStateTypeId, value); break;
case ModbusRegisterX2::BrauchwasserSolltermperatur:
thing->setStateValue(x2wpTargetWaterTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::Auszenluft:
thing->setStateValue(x2wpOutsideAirTemperatureStateTypeId, value/1000.00);
break;
//LeistungLuftvorerwarrmung = 4006 case ModbusRegisterX2::Summenstoerung:
value = (static_cast<uint32_t>(reply->result()[6])<<16 | reply->result()[7])/1000.00; if (value != 0) {
thing->setStateValue(x2wpPowerAirPreheatingStateTypeId, value); //get actual error
} else {
thing->setStateValue(x2wpErrorStateTypeId, "No error");
}
break;
totalPower += value; //power compressor plus power air pre-heating case ModbusRegisterX2::StoerungAbluftventilator:
thing->setStateValue(x2wpCurrentPowerStateTypeId, totalPower); if (value != 0)
});
}
void IntegrationPluginDrexelUndWeiss::readX2Energy(Thing *thing, ModbusRtuMaster *modbus, uint slaveAddress)
{
ModbusRtuReply *reply = modbus->readHoldingRegister(slaveAddress, ModbusRegisterX2::EnergieKompressor, 8);
connect(reply, &ModbusRtuReply::finished, reply, &ModbusRtuReply::deleteLater);
connect(reply, &ModbusRtuReply::finished, this, [reply, thing] {
if (reply->error() != ModbusRtuReply::Error::NoError) {
qCWarning(dcDrexelUndWeiss()) << "Modbus error" << reply->errorString();
return;
}
if (reply->result().length() != 8) {
return;
}
if (reply->registerAddress() != ModbusRegisterX2::EnergieKompressor) {
return;
}
//EnergieKompressor = 4500
float value = (static_cast<uint32_t>(reply->result()[0])<<16 | reply->result()[1])/1000.00;
thing->setStateValue(x2wpEnergyCompressorStateTypeId, value);
float totalEnergy = value;
//EnergieRaumheizung = 4502
value = (static_cast<uint32_t>(reply->result()[2])<<16 | reply->result()[3])/1000.00;
thing->setStateValue(x2wpEnergyRoomHeatingStateTypeId, value);
//EnergieWarmwasser = 4504
value = (static_cast<uint32_t>(reply->result()[4])<<16 | reply->result()[5])/1000.00;
thing->setStateValue(x2wpEnergyWaterHeatingStateTypeId, value);
//EnergieLuftvorerwarrmung = 4506
value = (static_cast<uint32_t>(reply->result()[6])<<16 | reply->result()[7])/1000.00;
thing->setStateValue(x2wpEnergyAirPreheatingStateTypeId, value);
totalEnergy += value; //energy compressor plus energy air pre-heating
thing->setStateValue(x2wpTotalEnergyConsumedStateTypeId, totalEnergy);
});
}
void IntegrationPluginDrexelUndWeiss::readHoldingRegister(Thing *thing, ModbusRtuMaster *modbus, uint slaveAddress, uint modbusRegister)
{
ModbusRtuReply *reply = modbus->readHoldingRegister(slaveAddress, modbusRegister); // min 2 registers must be read
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);
if (reply->result().length() != 2) {
return;
}
uint32_t value = (static_cast<uint32_t>(reply->result()[0])<<16 | reply->result()[1]);
if (thing->thingClassId() == x2wpThingClassId) {
switch (reply->registerAddress()) {
case ModbusRegisterX2::Waermepumpe:
thing->setStateValue(x2wpPowerStateTypeId, value);
break;
case ModbusRegisterX2::RaumSoll:
thing->setStateValue(x2wpTargetTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::Raum:
thing->setStateValue(x2wpTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::TemperaturWarmwasserspeicherUnten:
thing->setStateValue(x2wpWaterTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::BrauchwasserSolltermperatur:
thing->setStateValue(x2wpTargetWaterTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::Auszenluft:
thing->setStateValue(x2wpOutsideAirTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::Summenstoerung:
if (value != 0) {
//get actual error
} else {
thing->setStateValue(x2wpErrorStateTypeId, "No error");
}
break;
case ModbusRegisterX2::StoerungAbluftventilator:
if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Exhaust fan"); thing->setStateValue(x2wpErrorStateTypeId, "Exhaust fan");
break; break;
case ModbusRegisterX2::StoerungBoilerfuehlerElektroheizstab: case ModbusRegisterX2::StoerungBoilerfuehlerElektroheizstab:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor electric heating element"); thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor electric heating element");
break; break;
case ModbusRegisterX2::StoerungBoilerfuehlerSolar: case ModbusRegisterX2::StoerungBoilerfuehlerSolar:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor solar"); thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor solar");
break; break;
case ModbusRegisterX2::StoerungBoilerfuehlerWaermepumpe: case ModbusRegisterX2::StoerungBoilerfuehlerWaermepumpe:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor heat pump"); thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor heat pump");
break; break;
case ModbusRegisterX2::StoerungBoileruebertemperatur: case ModbusRegisterX2::StoerungBoileruebertemperatur:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Boiler overtemperature"); thing->setStateValue(x2wpErrorStateTypeId, "Boiler overtemperature");
break; break;
case ModbusRegisterX2::StoerungCO2Sensor: case ModbusRegisterX2::StoerungCO2Sensor:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "CO2-Sensor"); thing->setStateValue(x2wpErrorStateTypeId, "CO2-Sensor");
break; break;
case ModbusRegisterX2::StoerungDruckverlustAbluftZuGrosz: case ModbusRegisterX2::StoerungDruckverlustAbluftZuGrosz:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss exhaust air too big"); thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss exhaust air too big");
break; break;
case ModbusRegisterX2::StoerungDruckverlustZuluftZuGrosz: case ModbusRegisterX2::StoerungDruckverlustZuluftZuGrosz:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss supply air too large"); thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss supply air too large");
break; break;
case ModbusRegisterX2::StoerungDurchflussmengeHeizgkreis: case ModbusRegisterX2::StoerungDurchflussmengeHeizgkreis:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate of heating circuit"); thing->setStateValue(x2wpErrorStateTypeId, "Flow rate of heating circuit");
break; break;
case ModbusRegisterX2::StoerungDurchflussmengeSolekreis: case ModbusRegisterX2::StoerungDurchflussmengeSolekreis:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate brine circuit"); thing->setStateValue(x2wpErrorStateTypeId, "Flow rate brine circuit");
break; break;
case ModbusRegisterX2::StoerungTeilnehmerNichtErreichbar: case ModbusRegisterX2::StoerungTeilnehmerNichtErreichbar:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Participant not available"); thing->setStateValue(x2wpErrorStateTypeId, "Participant not available");
break; break;
case ModbusRegisterX2::StoerungTemperaturfuehlerAuszenluft: case ModbusRegisterX2::StoerungTemperaturfuehlerAuszenluft:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor outside air"); thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor outside air");
break; break;
case ModbusRegisterX2::StoerungTemperaturfuehlerHeizkreisVorlauf: case ModbusRegisterX2::StoerungTemperaturfuehlerHeizkreisVorlauf:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor heating circuit flow"); thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor heating circuit flow");
break; break;
case ModbusRegisterX2::StoerungTemperaturfuehlerRaum: case ModbusRegisterX2::StoerungTemperaturfuehlerRaum:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor room"); thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor room");
break; break;
case ModbusRegisterX2::StoerungTemperaturfuehlerSolarkollektor: case ModbusRegisterX2::StoerungTemperaturfuehlerSolarkollektor:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor solar collector"); thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor solar collector");
break; break;
case ModbusRegisterX2::StoerungTemperaturfuehlerSole: case ModbusRegisterX2::StoerungTemperaturfuehlerSole:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine"); thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine");
break; break;
case ModbusRegisterX2::StoerungTemperaturfuehlerSoleAuszenluft: case ModbusRegisterX2::StoerungTemperaturfuehlerSoleAuszenluft:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine outside air"); thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine outside air");
break; break;
case ModbusRegisterX2::StoerungWaermepumpeHochdruck: case ModbusRegisterX2::StoerungWaermepumpeHochdruck:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump high pressure"); thing->setStateValue(x2wpErrorStateTypeId, "Heat pump high pressure");
break; break;
case ModbusRegisterX2::StoerungWaermepumpeNiederdruck: case ModbusRegisterX2::StoerungWaermepumpeNiederdruck:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump low pressure"); thing->setStateValue(x2wpErrorStateTypeId, "Heat pump low pressure");
break; break;
case ModbusRegisterX2::StoerungWertNichtZulaessig: case ModbusRegisterX2::StoerungWertNichtZulaessig:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Value not allowed"); thing->setStateValue(x2wpErrorStateTypeId, "Value not allowed");
break; break;
case ModbusRegisterX2::StoerungZuluftventilator: case ModbusRegisterX2::StoerungZuluftventilator:
if (value != 0) if (value != 0)
thing->setStateValue(x2wpErrorStateTypeId, "Supply air fan"); thing->setStateValue(x2wpErrorStateTypeId, "Supply air fan");
break; break;
default: case ModbusRegisterX2::LeistungKompressor:
break; thing->setStateValue(x2wpPowerCompressorStateTypeId, value/1000.00);
} break;
} else if (thing->thingClassId() == x2luThingClassId) {
switch (reply->registerAddress()) { case ModbusRegisterX2::LeistungWarmwasser:
case ModbusRegisterX2::Betriebsart: thing->setStateValue(x2wpPowerWaterHeatingStateTypeId, value/1000.00);
if (value == VentilationMode::ManuellStufe0) { break;
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 0");
} else if (value == VentilationMode::ManuellStufe1) { case ModbusRegisterX2::LeistungRaumheizung:
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 1"); thing->setStateValue(x2wpPowerRoomHeatingStateTypeId, value/1000.00);
} else if (value == VentilationMode::ManuellStufe2) { break;
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 2");
} else if (value == VentilationMode::ManuellStufe3) { case ModbusRegisterX2::LeistungLuftvorwaermung: {
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 3"); float power = value/1000.00;
} else if (value == VentilationMode::Automatikbetrieb) { thing->setStateValue(x2wpPowerAirPreheatingStateTypeId, power);
thing->setStateValue(x2luVentilationModeStateTypeId, "Automatic"); power += thing->stateValue(x2wpPowerCompressorStateTypeId).toFloat();
} else if (value == VentilationMode::Party) { thing->setStateValue(x2wpCurrentPowerStateTypeId, power);
thing->setStateValue(x2luVentilationModeStateTypeId, "Party"); break;
}
if (value == VentilationMode::ManuellStufe0) {
thing->setStateValue(x2luPowerStateTypeId, false);
} else {
thing->setStateValue(x2luPowerStateTypeId, true);
}
break;
case ModbusRegisterX2::AktiveLuefterstufe:
thing->setStateValue(x2luActiveVentilationLevelStateTypeId, value);
break;
case ModbusRegisterX2::CO2:
thing->setStateValue(x2luCo2StateTypeId, value);
break;
}
} }
}); case ModbusRegisterX2::EnergieKompressor:
} thing->setStateValue(x2wpEnergyCompressorStateTypeId, value/1000.00);
break;
VentilationMode IntegrationPluginDrexelUndWeiss::getVentilationModeFromString(const QString &modeString) case ModbusRegisterX2::EnergieWarmwasser:
{ thing->setStateValue(x2wpEnergyWaterHeatingStateTypeId, value/1000.00);
if (modeString == "Manual level 0") { break;
return VentilationMode::ManuellStufe0;
} else if(modeString == "Manual level 1") { case ModbusRegisterX2::EnergieRaumheizung:
return VentilationMode::ManuellStufe1; thing->setStateValue(x2wpEnergyRoomHeatingStateTypeId, value/1000.00);
} else if(modeString == "Manual level 2") { break;
return VentilationMode::ManuellStufe2;
}else if(modeString == "Manual level 3") { case ModbusRegisterX2::EnergieLuftvorerwarrmung: {
return VentilationMode::ManuellStufe3; float energy = value/1000.00;
} else if(modeString == "Automatic") { thing->setStateValue(x2wpEnergyAirPreheatingStateTypeId, energy);
return VentilationMode::Automatikbetrieb; energy += thing->stateValue(x2wpEnergyCompressorStateTypeId).toFloat();
} else if(modeString == "Party") { thing->setStateValue(x2wpTotalEnergyConsumedStateTypeId, energy);
return VentilationMode::Party; break;
} else { }
qCWarning(dcDrexelUndWeiss()) << "Unknown ventilation mode string" << modeString; default:
break;
}
} else if (thing->thingClassId() == x2luThingClassId) {
switch (reply->registerAddress()) {
case ModbusRegisterX2::Betriebsart:
if (value == VentilationMode::ManuellStufe0) {
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 0");
} else if (value == VentilationMode::ManuellStufe1) {
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 1");
} else if (value == VentilationMode::ManuellStufe2) {
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 2");
} else if (value == VentilationMode::ManuellStufe3) {
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 3");
} else if (value == VentilationMode::Automatikbetrieb) {
thing->setStateValue(x2luVentilationModeStateTypeId, "Automatic");
} else if (value == VentilationMode::Party) {
thing->setStateValue(x2luVentilationModeStateTypeId, "Party");
}
if (value == VentilationMode::ManuellStufe0) {
thing->setStateValue(x2luPowerStateTypeId, false);
} else {
thing->setStateValue(x2luPowerStateTypeId, true);
}
break;
case ModbusRegisterX2::AktiveLuefterstufe:
thing->setStateValue(x2luActiveVentilationLevelStateTypeId, value);
break;
case ModbusRegisterX2::CO2:
thing->setStateValue(x2luCo2StateTypeId, value);
break;
}
} }
});
}
VentilationMode IntegrationPluginDrexelUndWeiss::getVentilationModeFromString(const QString &modeString)
{
if (modeString == "Manual level 0") {
return VentilationMode::ManuellStufe0; 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 &paramTypeId, const QVariant &value) void IntegrationPluginDrexelUndWeiss::onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value)
{ {
// Check refresh schedule // Check refresh schedule
if (paramTypeId == drexelUndWeissPluginUpdateIntervalParamTypeId) { if (paramTypeId == drexelUndWeissPluginUpdateIntervalParamTypeId) {
if (m_refreshTimer) { if (m_refreshTimer) {
int refreshTime = value.toInt(); int refreshTime = value.toInt();
m_refreshTimer->stop(); m_refreshTimer->stop();
m_refreshTimer->startTimer(refreshTime); m_refreshTimer->startTimer(refreshTime);
}
} }
} }
}
void IntegrationPluginDrexelUndWeiss::onConnectionStateChanged(bool status) void IntegrationPluginDrexelUndWeiss::onConnectionStateChanged(bool status)
{ {
ModbusRtuMaster *modbusRtuMaster = static_cast<ModbusRtuMaster *>(sender()); ModbusRtuMaster *modbusRtuMaster = static_cast<ModbusRtuMaster *>(sender());
Thing *thing = m_modbusRtuMasters.key(modbusRtuMaster); Thing *thing = m_modbusRtuMasters.key(modbusRtuMaster);
if (!thing) if (!thing)
return; return;
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), status); thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), status);
} }