Make use of the byte order register and configure the kostal connection

master
Simon Stürz 2022-08-01 16:44:13 +02:00
parent 20b414ae10
commit 380a0ca79b
2 changed files with 67 additions and 102 deletions

View File

@ -75,44 +75,6 @@ void IntegrationPluginKostal::discoverThings(ThingDiscoveryInfo *info)
// Start the discovery process
discovery->startDiscovery();
// NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover();
// connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
// foreach (const NetworkDeviceInfo &networkDeviceInfo, discoveryReply->networkDeviceInfos()) {
// qCDebug(dcKostal()) << "Found" << networkDeviceInfo;
// QString title;
// if (networkDeviceInfo.hostName().isEmpty()) {
// title = networkDeviceInfo.address().toString();
// } else {
// title = networkDeviceInfo.hostName() + " (" + networkDeviceInfo.address().toString() + ")";
// }
// QString description;
// if (networkDeviceInfo.macAddressManufacturer().isEmpty()) {
// description = networkDeviceInfo.macAddress();
// } else {
// description = networkDeviceInfo.macAddress() + " (" + networkDeviceInfo.macAddressManufacturer() + ")";
// }
// ThingDescriptor descriptor(kostalInverterThingClassId, title, description);
// ParamList params;
// params << Param(kostalInverterThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
// descriptor.setParams(params);
// // Check if we already have set up this device
// Things existingThings = myThings().filterByParam(kostalInverterThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
// if (existingThings.count() == 1) {
// qCDebug(dcKostal()) << "This connection already exists in the system:" << networkDeviceInfo;
// descriptor.setThingId(existingThings.first()->id());
// }
// info->addThingDescriptor(descriptor);
// }
// info->finish(Thing::ThingErrorNoError);
// });
}
void IntegrationPluginKostal::setupThing(ThingSetupInfo *info)
@ -173,6 +135,7 @@ void IntegrationPluginKostal::setupThing(ThingSetupInfo *info)
}
});
}
return;
}
@ -198,71 +161,60 @@ void IntegrationPluginKostal::setupThing(ThingSetupInfo *info)
// Update the meter data from the kostal connection containing all information
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterTotalActivePowerChanged, this, [thing](float powerMeterTotalActivePower){
qCDebug(dcKostal()) << thing << "total active power changed" << powerMeterTotalActivePower << "W";
thing->setStateValue(kostalMeterCurrentPowerStateTypeId, powerMeterTotalActivePower);
});
// TODO: set toal energy consumed/produced
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterTotalActivePowerChanged, this, [thing](float powerMeterTotalActivePower){
qCDebug(dcKostal()) << thing << "total active power changed" << powerMeterTotalActivePower << "W";
thing->setStateValue(kostalMeterCurrentPowerStateTypeId, powerMeterTotalActivePower);
});
// Current
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterCurrentPhase1Changed, this, [thing](float powerMeterCurrentPhase1){
qCDebug(dcKostal()) << thing << "current phase 1 changed" << powerMeterCurrentPhase1 << "A";
thing->setStateValue(kostalMeterCurrentPhaseAStateTypeId, powerMeterCurrentPhase1);
});
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterCurrentPhase2Changed, this, [thing](float powerMeterCurrentPhase2){
qCDebug(dcKostal()) << thing << "current phase 2 changed" << powerMeterCurrentPhase2 << "A";
thing->setStateValue(kostalMeterCurrentPhaseBStateTypeId, powerMeterCurrentPhase2);
});
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterCurrentPhase3Changed, this, [thing](float powerMeterCurrentPhase3){
qCDebug(dcKostal()) << thing << "current phase 3 changed" << powerMeterCurrentPhase3 << "A";
thing->setStateValue(kostalMeterCurrentPhaseCStateTypeId, powerMeterCurrentPhase3);
});
// Voltage
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterVoltagePhase1Changed, this, [thing](float powerMeterVoltagePhase1){
qCDebug(dcKostal()) << thing << "voltage phase 1 changed" << powerMeterVoltagePhase1 << "V";
thing->setStateValue(kostalMeterVoltagePhaseAStateTypeId, powerMeterVoltagePhase1);
});
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterVoltagePhase2Changed, this, [thing](float powerMeterVoltagePhase2){
qCDebug(dcKostal()) << thing << "voltage phase 2 changed" << powerMeterVoltagePhase2 << "V";
thing->setStateValue(kostalMeterVoltagePhaseBStateTypeId, powerMeterVoltagePhase2);
});
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterVoltagePhase3Changed, this, [thing](float powerMeterVoltagePhase3){
qCDebug(dcKostal()) << thing << "voltage phase 3 changed" << powerMeterVoltagePhase3 << "V";
thing->setStateValue(kostalMeterVoltagePhaseCStateTypeId, powerMeterVoltagePhase3);
});
// Power
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterActivePowerPhase1Changed, this, [thing](float powerMeterActivePowerPhase1){
qCDebug(dcKostal()) << thing << "power phase 1 changed" << powerMeterActivePowerPhase1 << "W";
thing->setStateValue(kostalMeterCurrentPowerPhaseAStateTypeId, powerMeterActivePowerPhase1);
});
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterActivePowerPhase2Changed, this, [thing](float powerMeterActivePowerPhase2){
qCDebug(dcKostal()) << thing << "power phase 2 changed" << powerMeterActivePowerPhase2 << "W";
thing->setStateValue(kostalMeterCurrentPowerPhaseBStateTypeId, powerMeterActivePowerPhase2);
});
connect(kostalConnection, &KostalModbusTcpConnection::powerMeterActivePowerPhase3Changed, this, [thing](float powerMeterActivePowerPhase3){
qCDebug(dcKostal()) << thing << "power phase 3 changed" << powerMeterActivePowerPhase3 << "W";
thing->setStateValue(kostalMeterCurrentPowerPhaseCStateTypeId, powerMeterActivePowerPhase3);
});
connect(kostalConnection, &KostalModbusTcpConnection::gridFrequencyPowerMeterChanged, this, [thing](float gridFrequency){
qCDebug(dcKostal()) << thing << "grid frequency changed" << gridFrequency << "Hz";
thing->setStateValue(kostalMeterFrequencyStateTypeId, gridFrequency);
});
info->finish(Thing::ThingErrorNoError);
return;
}
if (thing->thingClassId() == kostalBatteryThingClassId) {
@ -284,14 +236,11 @@ void IntegrationPluginKostal::setupThing(ThingSetupInfo *info)
// Note: The connected state will be handled in the parent inverter thing
connect(kostalConnection, &KostalModbusTcpConnection::batteryStateOfChargeChanged, this, [thing](quint16 batteryStateOfCharge){
qCDebug(dcKostal()) << thing << "battery SoC changed" << batteryStateOfCharge << "%";
thing->setStateValue(kostalBatteryBatteryLevelStateTypeId, batteryStateOfCharge);
thing->setStateValue(kostalBatteryBatteryCriticalStateTypeId, batteryStateOfCharge < 5);
});
connect(kostalConnection, &KostalModbusTcpConnection::batteryActualPowerChanged, this, [thing](float batteryActualPower){
qCDebug(dcKostal()) << thing << "battery charge current changed" << batteryActualPower << "W";
thing->setStateValue(kostalBatteryCurrentPowerStateTypeId, batteryActualPower);
if (batteryActualPower == 0) {
thing->setStateValue(kostalBatteryChargingStateStateTypeId, "idle");
@ -303,11 +252,11 @@ void IntegrationPluginKostal::setupThing(ThingSetupInfo *info)
});
connect(kostalConnection, &KostalModbusTcpConnection::batteryWorkCapacityChanged, this, [thing](quint32 batteryWorkCapacity){
qCDebug(dcKostal()) << thing << "battery work capacity changed" << batteryWorkCapacity << "Wh";
thing->setStateValue(kostalBatteryCapacityStateTypeId, batteryWorkCapacity / 1000.0); // kWh
});
info->finish(Thing::ThingErrorNoError);
return;
}
}
@ -315,6 +264,20 @@ void IntegrationPluginKostal::postSetupThing(Thing *thing)
{
if (thing->thingClassId() == kostalInverterThingClassId) {
// Create the update timer if not already set up
if (!m_pluginTimer) {
qCDebug(dcKostal()) << "Starting plugin timer...";
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(2);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
foreach(KostalModbusTcpConnection *connection, m_kostalConnections) {
qCDebug(dcKostal()) << "Update connection" << connection->hostAddress().toString();
connection->update();
}
});
m_pluginTimer->start();
}
KostalModbusTcpConnection *kostalConnection = m_kostalConnections.value(thing);
// Check if we have to create the meter for the Kostal inverter
@ -376,18 +339,16 @@ void IntegrationPluginKostal::postSetupThing(Thing *thing)
emit autoThingsAppeared(ThingDescriptors() << descriptor);
}
// Create the update timer if not already set up
if (!m_pluginTimer) {
qCDebug(dcKostal()) << "Starting plugin timer...";
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(4);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
foreach(KostalModbusTcpConnection *connection, m_kostalConnections) {
if (connection->connected()) {
connection->update();
}
}
});
return;
}
if (thing->thingClassId() == kostalMeterThingClassId || thing->thingClassId() == kostalBatteryThingClassId) {
Thing *connectionThing = myThings().findById(thing->parentId());
if (connectionThing) {
thing->setStateValue("connected", connectionThing->stateValue("connected"));
}
return;
}
}
@ -437,6 +398,32 @@ void IntegrationPluginKostal::setupKostalConnection(ThingSetupInfo *info)
}
});
connect(kostalConnection, &KostalModbusTcpConnection::reachableChanged, thing, [this, thing, kostalConnection](bool reachable){
qCDebug(dcKostal()) << "Reachable changed to" << reachable << "for" << thing;
if (reachable) {
// Connected true will be set after successfull init
kostalConnection->initialize();
} else {
thing->setStateValue("connected", false);
foreach (Thing *childThing, myThings().filterByParentId(thing->id())) {
childThing->setStateValue("connected", false);
}
}
});
connect(kostalConnection, &KostalModbusTcpConnection::initializationFinished, thing, [=](bool success){
if (!thing->setupComplete())
return;
if (success) {
thing->setStateValue("connected", true);
} else {
thing->setStateValue("connected", false);
// Try once to reconnect the device
kostalConnection->reconnectDevice();
}
});
connect(kostalConnection, &KostalModbusTcpConnection::initializationFinished, info, [=](bool success){
if (!success) {
qCWarning(dcKostal()) << "Connection init finished with errors" << thing->name() << kostalConnection->hostAddress().toString();
@ -456,66 +443,68 @@ void IntegrationPluginKostal::setupKostalConnection(ThingSetupInfo *info)
childThing->setStateValue("connected", true);
}
// Make sure we use the same endianness as the inverter (register size 1, so independent from endianess)
switch (kostalConnection->modbusByteOrder()) {
case KostalModbusTcpConnection::ByteOrderBigEndian:
kostalConnection->setEndianness(ModbusDataUtils::ByteOrderBigEndian);
break;
case KostalModbusTcpConnection::ByteOrderLittleEndian:
kostalConnection->setEndianness(ModbusDataUtils::ByteOrderLittleEndian);
break;
}
connect(kostalConnection, &KostalModbusTcpConnection::updateFinished, thing, [=](){
qCDebug(dcKostal()) << "Updated" << kostalConnection;
});
connect(kostalConnection, &KostalModbusTcpConnection::totalAcPowerChanged, thing, [thing](float totalAcPower){
qCDebug(dcKostal()) << thing << "total AC power changed" << totalAcPower << "W";
thing->setStateValue(kostalInverterCurrentPowerStateTypeId, - totalAcPower);
});
connect(kostalConnection, &KostalModbusTcpConnection::totalYieldChanged, thing, [thing](float totalYield){
qCDebug(dcKostal()) << thing << "total yeald changed" << totalYield << "Wh";
thing->setStateValue(kostalInverterTotalEnergyProducedStateTypeId, totalYield / 1000.0); // kWh
});
// Current
connect(kostalConnection, &KostalModbusTcpConnection::currentPhase1Changed, thing, [thing](float currentPhase1){
qCDebug(dcKostal()) << thing << "current phase 1 changed" << currentPhase1 << "A";
thing->setStateValue(kostalInverterPhaseACurrentStateTypeId, currentPhase1); // A
});
connect(kostalConnection, &KostalModbusTcpConnection::currentPhase2Changed, thing, [thing](float currentPhase2){
qCDebug(dcKostal()) << thing << "current phase 2 changed" << currentPhase2 << "A";
thing->setStateValue(kostalInverterPhaseBCurrentStateTypeId, currentPhase2); // A
});
connect(kostalConnection, &KostalModbusTcpConnection::currentPhase3Changed, thing, [thing](float currentPhase3){
qCDebug(dcKostal()) << thing << "current phase 3 changed" << currentPhase3 << "A";
thing->setStateValue(kostalInverterPhaseCCurrentStateTypeId, currentPhase3); // A
});
// Voltage
connect(kostalConnection, &KostalModbusTcpConnection::voltagePhase1Changed, thing, [thing](float voltagePhase1){
qCDebug(dcKostal()) << thing << "voltage phase 1 changed" << voltagePhase1 << "V";
thing->setStateValue(kostalInverterVoltagePhaseAStateTypeId, voltagePhase1);
});
connect(kostalConnection, &KostalModbusTcpConnection::voltagePhase2Changed, thing, [thing](float voltagePhase2){
qCDebug(dcKostal()) << thing << "voltage phase 2 changed" << voltagePhase2 << "V";
thing->setStateValue(kostalInverterVoltagePhaseBStateTypeId, voltagePhase2);
});
connect(kostalConnection, &KostalModbusTcpConnection::voltagePhase3Changed, thing, [thing](float voltagePhase3){
qCDebug(dcKostal()) << thing << "voltage phase 3 changed" << voltagePhase3 << "V";
thing->setStateValue(kostalInverterVoltagePhaseCStateTypeId, voltagePhase3);
});
// Current power
connect(kostalConnection, &KostalModbusTcpConnection::activePowerPhase1Changed, thing, [thing](float activePowerPhase1){
qCDebug(dcKostal()) << thing << "active power phase 1 changed" << activePowerPhase1 << "W";
thing->setStateValue(kostalInverterCurrentPowerPhaseAStateTypeId, activePowerPhase1);
});
connect(kostalConnection, &KostalModbusTcpConnection::activePowerPhase2Changed, thing, [thing](float activePowerPhase2){
qCDebug(dcKostal()) << thing << "active power phase 2 changed" << activePowerPhase2 << "W";
thing->setStateValue(kostalInverterCurrentPowerPhaseBStateTypeId, activePowerPhase2);
});
connect(kostalConnection, &KostalModbusTcpConnection::activePowerPhase3Changed, thing, [thing](float activePowerPhase3){
qCDebug(dcKostal()) << thing << "active power phase 3 changed" << activePowerPhase3 << "W";
thing->setStateValue(kostalInverterCurrentPowerPhaseCStateTypeId, activePowerPhase3);
});
connect(kostalConnection, &KostalModbusTcpConnection::gridFrequencyInverterChanged, thing, [thing](float gridFrequencyInverter){
qCDebug(dcKostal()) << thing << "grid frequency changed" << gridFrequencyInverter << "Hz";
thing->setStateValue(kostalInverterFrequencyStateTypeId, gridFrequencyInverter);
});
@ -523,29 +512,5 @@ void IntegrationPluginKostal::setupKostalConnection(ThingSetupInfo *info)
kostalConnection->update();
});
connect(kostalConnection, &KostalModbusTcpConnection::reachableChanged, thing, [this, thing, kostalConnection](bool reachable){
qCDebug(dcKostal()) << "Reachable changed to" << reachable << "for" << thing;
if (reachable) {
// Connected true will be set after successfull init
kostalConnection->initialize();
} else {
thing->setStateValue("connected", false);
foreach (Thing *childThing, myThings().filterByParentId(thing->id())) {
childThing->setStateValue("connected", false);
}
}
});
connect(kostalConnection, &KostalModbusTcpConnection::initializationFinished, info, [=](bool success){
if (success) {
thing->setStateValue("connected", true);
} else {
thing->setStateValue("connected", false);
// Try once to reconnect the device
kostalConnection->reconnectDevice();
}
});
kostalConnection->connectDevice();
}

View File

@ -157,7 +157,7 @@
"enum": "ByteOrder",
"registerType": "holdingRegister",
"description": "MODBUS Byte Order Note",
"defaultValue": "ByteOrderLittleEndian",
"defaultValue": "ByteOrderBigEndian",
"access": "RO"
},
{