improved sunspec storage
This commit is contained in:
parent
b536b1b16e
commit
c112e1e6a0
@ -140,81 +140,37 @@ void IntegrationPluginSunSpec::setupThing(ThingSetupInfo *info)
|
||||
thing->thingClassId() == sunspecSplitPhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecSinglePhaseInverterThingClassId ) {
|
||||
|
||||
uint modelId = thing->paramValue(m_modelIdParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
int modbusAddress = thing->paramValue(m_modbusAddressParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
SunSpec *connection = m_sunSpecConnections.value(thing->parentId());
|
||||
if (!connection) {
|
||||
qCWarning(dcSunSpec()) << "Could not find SunSpec connection";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
if (parent->setupStatus() == Thing::ThingSetupStatusComplete) {
|
||||
setupInverter(info);
|
||||
} else {
|
||||
connect(parent, &Thing::setupStatusChanged, info, [this, info] {
|
||||
setupInverter(info);
|
||||
});
|
||||
}
|
||||
SunSpecInverter *sunSpecInverter = new SunSpecInverter(connection, SunSpec::ModelId(modelId), modbusAddress);
|
||||
sunSpecInverter->init();
|
||||
connect(sunSpecInverter, &SunSpecInverter::initFinished, info, [this, sunSpecInverter, info] (bool success){
|
||||
qCDebug(dcSunSpec()) << "Modbus Inverter init finished, success:" << success;
|
||||
if (success) {
|
||||
m_sunSpecInverters.insert(info->thing(), sunSpecInverter);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
});
|
||||
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecInverter, &SunSpecInverter::deleteLater);
|
||||
connect(sunSpecInverter, &SunSpecInverter::destroyed, thing, [thing, this] {m_sunSpecInverters.remove(thing);});
|
||||
connect(sunSpecInverter, &SunSpecInverter::inverterDataReceived, this, &IntegrationPluginSunSpec::onInverterDataReceived);
|
||||
|
||||
} else if (thing->thingClassId() == sunspecSinglePhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecThreePhaseMeterThingClassId) {
|
||||
|
||||
uint modelId = thing->paramValue(m_modelIdParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
int modbusAddress = thing->paramValue(m_modbusAddressParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
SunSpec *connection = m_sunSpecConnections.value(thing->parentId());
|
||||
if (!connection) {
|
||||
qCWarning(dcSunSpec()) << "Could not find SunSpec connection";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
if (parent->setupStatus() == Thing::ThingSetupStatusComplete) {
|
||||
setupMeter(info);
|
||||
} else {
|
||||
connect(parent, &Thing::setupStatusChanged, info, [this, info] {
|
||||
setupMeter(info);
|
||||
});
|
||||
}
|
||||
SunSpecMeter *sunSpecMeter = new SunSpecMeter(connection, SunSpec::ModelId(modelId), modbusAddress);
|
||||
sunSpecMeter->init();
|
||||
connect(sunSpecMeter, &SunSpecMeter::initFinished, info, [this, sunSpecMeter, info] (bool success){
|
||||
qCDebug(dcSunSpec()) << "Modbus meter init finished, success:" << success;
|
||||
if (success) {
|
||||
m_sunSpecMeters.insert(info->thing(), sunSpecMeter);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
});
|
||||
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecMeter, &SunSpecMeter::deleteLater);
|
||||
connect(sunSpecMeter, &SunSpecMeter::destroyed, thing, [thing, this] {m_sunSpecMeters.remove(thing);});
|
||||
connect(sunSpecMeter, &SunSpecMeter::meterDataReceived, this, &IntegrationPluginSunSpec::onMeterDataReceived);
|
||||
|
||||
} else if (info->thing()->thingClassId() == sunspecStorageThingClassId) {
|
||||
|
||||
uint modelId = thing->paramValue(m_modelIdParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
int modbusAddress = thing->paramValue(m_modbusAddressParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
SunSpec *connection = m_sunSpecConnections.value(thing->parentId());
|
||||
if (!connection) {
|
||||
qCWarning(dcSunSpec()) << "Could not find SunSpec connection";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
if (parent->setupStatus() == Thing::ThingSetupStatusComplete) {
|
||||
setupStorage(info);
|
||||
} else {
|
||||
connect(parent, &Thing::setupStatusChanged, info, [this, info] {
|
||||
setupStorage(info);
|
||||
});
|
||||
}
|
||||
SunSpecStorage *sunSpecStorage = new SunSpecStorage(connection, SunSpec::ModelId(modelId), modbusAddress);
|
||||
sunSpecStorage->init();
|
||||
connect(sunSpecStorage, &SunSpecStorage::initFinished, info, [this, sunSpecStorage, info] (bool success){
|
||||
qCDebug(dcSunSpec()) << "Modbus storage init finished, success:" << success;
|
||||
if (success) {
|
||||
m_sunSpecStorages.insert(info->thing(), sunSpecStorage);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
});
|
||||
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecStorage, &SunSpecStorage::deleteLater);
|
||||
connect(sunSpecStorage, &SunSpecStorage::destroyed, thing, [thing, this] {m_sunSpecStorages.remove(thing);});
|
||||
connect(sunSpecStorage, &SunSpecStorage::storageDataReceived, this, &IntegrationPluginSunSpec::onStorageDataReceived);
|
||||
|
||||
} else {
|
||||
Q_ASSERT_X(false, "setupThing", QString("Unhandled thingClassId: %1").arg(info->thing()->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
@ -353,15 +309,16 @@ void IntegrationPluginSunSpec::executeAction(ThingActionInfo *info)
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
|
||||
}
|
||||
} else if (action.actionTypeId() == sunspecStorageEnableChargingLimitActionTypeId) {
|
||||
/*int value = (action.param(sunspecStorageEnableChargingLimitActionEnableChargingLimitParamTypeId).value().toBool() << 1) | thing->stateValue(sunspecStorageEnableDischargingLimitStateTypeId).toBool();
|
||||
QUuid requestId = sunSpecStorage->setStorageControlMode(value);
|
||||
} else if (action.actionTypeId() == sunspecStorageEnableChargingActionTypeId) {
|
||||
bool charging = action.param(sunspecStorageEnableChargingActionEnableChargingParamTypeId).value().toBool();
|
||||
bool discharging = thing->stateValue(sunspecStorageEnableDischargingStateTypeId).toBool();
|
||||
QUuid requestId = sunSpecStorage->setStorageControlMode(charging, discharging);
|
||||
if (requestId.isNull()) {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
} else {
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
|
||||
}*/
|
||||
}
|
||||
} else if (action.actionTypeId() == sunspecStorageChargingRateActionTypeId) {
|
||||
QUuid requestId = sunSpecStorage->setChargingRate(action.param(sunspecStorageChargingRateActionChargingRateParamTypeId).value().toInt());
|
||||
if (requestId.isNull()) {
|
||||
@ -370,15 +327,16 @@ void IntegrationPluginSunSpec::executeAction(ThingActionInfo *info)
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
|
||||
}
|
||||
} else if (action.actionTypeId() == sunspecStorageEnableDischargingLimitActionTypeId) {
|
||||
/*int value = (action.param(sunspecStorageEnableDischargingLimitActionEnableDischargingLimitParamTypeId).value().toBool() << 1) | thing->stateValue(sunspecStorageEnableChargingLimitStateTypeId).toBool();
|
||||
QUuid requestId = sunSpecStorage->setStorageControlMode(value);
|
||||
} else if (action.actionTypeId() == sunspecStorageEnableDischargingActionTypeId) {
|
||||
bool discharging = action.param(sunspecStorageEnableDischargingActionEnableDischargingParamTypeId).value().toBool();
|
||||
bool charging = thing->stateValue(sunspecStorageEnableChargingStateTypeId).toBool();
|
||||
QUuid requestId = sunSpecStorage->setStorageControlMode(charging, discharging);
|
||||
if (requestId.isNull()) {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
} else {
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
|
||||
}*/
|
||||
}
|
||||
} else if (action.actionTypeId() == sunspecStorageDischargingRateActionTypeId) {
|
||||
QUuid requestId = sunSpecStorage->setDischargingRate(action.param(sunspecStorageDischargingRateActionDischargingRateParamTypeId).value().toInt());
|
||||
if (requestId.isNull()) {
|
||||
@ -406,6 +364,88 @@ bool IntegrationPluginSunSpec::checkIfThingExists(uint modelId, uint modbusAddre
|
||||
return false;
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::setupInverter(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
uint modelId = thing->paramValue(m_modelIdParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
int modbusAddress = thing->paramValue(m_modbusAddressParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
SunSpec *connection = m_sunSpecConnections.value(thing->parentId());
|
||||
if (!connection) {
|
||||
qCWarning(dcSunSpec()) << "Could not find SunSpec connection";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
SunSpecInverter *sunSpecInverter = new SunSpecInverter(connection, SunSpec::ModelId(modelId), modbusAddress);
|
||||
sunSpecInverter->init();
|
||||
connect(sunSpecInverter, &SunSpecInverter::initFinished, info, [this, sunSpecInverter, info] (bool success){
|
||||
qCDebug(dcSunSpec()) << "Modbus Inverter init finished, success:" << success;
|
||||
if (success) {
|
||||
m_sunSpecInverters.insert(info->thing(), sunSpecInverter);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
});
|
||||
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecInverter, &SunSpecInverter::deleteLater);
|
||||
connect(sunSpecInverter, &SunSpecInverter::destroyed, thing, [thing, this] {m_sunSpecInverters.remove(thing);});
|
||||
connect(sunSpecInverter, &SunSpecInverter::inverterDataReceived, this, &IntegrationPluginSunSpec::onInverterDataReceived);
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::setupMeter(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
|
||||
uint modelId = thing->paramValue(m_modelIdParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
int modbusAddress = thing->paramValue(m_modbusAddressParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
SunSpec *connection = m_sunSpecConnections.value(thing->parentId());
|
||||
if (!connection) {
|
||||
qCWarning(dcSunSpec()) << "Could not find SunSpec connection";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
SunSpecMeter *sunSpecMeter = new SunSpecMeter(connection, SunSpec::ModelId(modelId), modbusAddress);
|
||||
sunSpecMeter->init();
|
||||
connect(sunSpecMeter, &SunSpecMeter::initFinished, info, [this, sunSpecMeter, info] (bool success){
|
||||
qCDebug(dcSunSpec()) << "Modbus meter init finished, success:" << success;
|
||||
if (success) {
|
||||
m_sunSpecMeters.insert(info->thing(), sunSpecMeter);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
});
|
||||
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecMeter, &SunSpecMeter::deleteLater);
|
||||
connect(sunSpecMeter, &SunSpecMeter::destroyed, thing, [thing, this] {m_sunSpecMeters.remove(thing);});
|
||||
connect(sunSpecMeter, &SunSpecMeter::meterDataReceived, this, &IntegrationPluginSunSpec::onMeterDataReceived);
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::setupStorage(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
uint modelId = thing->paramValue(m_modelIdParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
int modbusAddress = thing->paramValue(m_modbusAddressParamTypeIds.value(thing->thingClassId())).toInt();
|
||||
SunSpec *connection = m_sunSpecConnections.value(thing->parentId());
|
||||
if (!connection) {
|
||||
qCWarning(dcSunSpec()) << "Could not find SunSpec connection";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
SunSpecStorage *sunSpecStorage = new SunSpecStorage(connection, SunSpec::ModelId(modelId), modbusAddress);
|
||||
sunSpecStorage->init();
|
||||
connect(sunSpecStorage, &SunSpecStorage::initFinished, info, [this, sunSpecStorage, info] (bool success){
|
||||
qCDebug(dcSunSpec()) << "Modbus storage init finished, success:" << success;
|
||||
if (success) {
|
||||
m_sunSpecStorages.insert(info->thing(), sunSpecStorage);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
});
|
||||
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecStorage, &SunSpecStorage::deleteLater);
|
||||
connect(sunSpecStorage, &SunSpecStorage::destroyed, thing, [thing, this] {m_sunSpecStorages.remove(thing);});
|
||||
connect(sunSpecStorage, &SunSpecStorage::storageDataReceived, this, &IntegrationPluginSunSpec::onStorageDataReceived);
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onRefreshTimer()
|
||||
{
|
||||
foreach (SunSpec *connection, m_sunSpecConnections) {
|
||||
@ -437,13 +477,11 @@ void IntegrationPluginSunSpec::onPluginConfigurationChanged(const ParamTypeId &p
|
||||
Q_FOREACH(SunSpec *connection, m_sunSpecConnections) {
|
||||
connection->setNumberOfRetries(value.toUInt());
|
||||
}
|
||||
|
||||
} else if (paramTypeId == sunSpecPluginTimeoutParamTypeId) {
|
||||
qCDebug(dcSunSpec()) << "Updating timeout" << value.toUInt() << "[ms]";
|
||||
Q_FOREACH(SunSpec *connection, m_sunSpecConnections) {
|
||||
connection->setTimeout(value.toUInt());
|
||||
}
|
||||
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Unknown plugin configuration" << paramTypeId << "Value" << value;
|
||||
}
|
||||
@ -474,7 +512,7 @@ void IntegrationPluginSunSpec::onFoundSunSpecModel(SunSpec::ModelId modelId, int
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSunSpec()) << "On model received" << modelId << "length" << modbusStartRegister << "Thing:" << thing->name();
|
||||
qCDebug(dcSunSpec()) << "On model received" << modelId << "start register" << modbusStartRegister << "Thing:" << thing->name();
|
||||
if (checkIfThingExists(modelId, modbusStartRegister)) {
|
||||
return;
|
||||
}
|
||||
@ -510,7 +548,7 @@ void IntegrationPluginSunSpec::onFoundSunSpecModel(SunSpec::ModelId modelId, int
|
||||
|
||||
case SunSpec::ModelIdSinglePhaseMeter:
|
||||
case SunSpec::ModelIdSinglePhaseMeterFloat: {
|
||||
ThingDescriptor descriptor(sunspecSinglePhaseMeterThingClassId, model+tr(" Meter"), "", thing->id());
|
||||
ThingDescriptor descriptor(sunspecSinglePhaseMeterThingClassId, model+tr(" meter"), "", thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(sunspecSinglePhaseMeterThingModelIdParamTypeId, modelId));
|
||||
params.append(Param(sunspecSinglePhaseMeterThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
@ -519,7 +557,7 @@ void IntegrationPluginSunSpec::onFoundSunSpecModel(SunSpec::ModelId modelId, int
|
||||
} break;
|
||||
case SunSpec::ModelIdSplitSinglePhaseMeter:
|
||||
case SunSpec::ModelIdSplitSinglePhaseMeterFloat: {
|
||||
ThingDescriptor descriptor(sunspecSplitPhaseMeterThingClassId, model+tr(" Meter"), "", thing->id());
|
||||
ThingDescriptor descriptor(sunspecSplitPhaseMeterThingClassId, model+tr(" meter"), "", thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(sunspecSplitPhaseMeterThingModelIdParamTypeId, modelId));
|
||||
params.append(Param(sunspecSplitPhaseMeterThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
@ -528,7 +566,7 @@ void IntegrationPluginSunSpec::onFoundSunSpecModel(SunSpec::ModelId modelId, int
|
||||
} break;
|
||||
case SunSpec::ModelIdWyeConnectThreePhaseMeterFloat:
|
||||
case SunSpec::ModelIdDeltaConnectThreePhaseMeterFloat: {
|
||||
ThingDescriptor descriptor(sunspecThreePhaseMeterThingClassId, model+" Meter", "", thing->id());
|
||||
ThingDescriptor descriptor(sunspecThreePhaseMeterThingClassId, model+" meter", "", thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(sunspecThreePhaseMeterThingModelIdParamTypeId, modelId));
|
||||
params.append(Param(sunspecThreePhaseMeterThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
@ -536,10 +574,10 @@ void IntegrationPluginSunSpec::onFoundSunSpecModel(SunSpec::ModelId modelId, int
|
||||
emit autoThingsAppeared({descriptor});
|
||||
} break;
|
||||
case SunSpec::ModelIdStorage: {
|
||||
ThingDescriptor descriptor(sunspecStorageThingClassId, model+" Storage", "", thing->id());
|
||||
ThingDescriptor descriptor(sunspecStorageThingClassId, model+" storage", "", thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(sunspecStorageThingModelIdParamTypeId, modelId));
|
||||
params.append(Param(sunspecThreePhaseInverterThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
params.append(Param(sunspecStorageThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared({descriptor});
|
||||
} break;
|
||||
@ -556,9 +594,7 @@ void IntegrationPluginSunSpec::onSunSpecModelSearchFinished(const QHash<SunSpec:
|
||||
qCWarning(dcSunSpec()) << "Thing not found for SunSpec connection" << connection->deviceModel() << connection->serialNumber();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSunSpec()) << "On sunspec model search finished, models:" << modelIds.count();
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onWriteRequestExecuted(QUuid requestId, bool success)
|
||||
@ -589,7 +625,6 @@ void IntegrationPluginSunSpec::onInverterDataReceived(const SunSpecInverter::Inv
|
||||
thing->setStateValue(sunspecThreePhaseInverterTotalCurrentStateTypeId, inverterData.acCurrent);
|
||||
thing->setStateValue(sunspecThreePhaseInverterCabinetTemperatureStateTypeId, inverterData.cabinetTemperature);
|
||||
|
||||
|
||||
if (thing->thingClassId() == sunspecSplitPhaseMeterThingClassId) {
|
||||
|
||||
thing->setStateValue(sunspecSplitPhaseInverterPhaseANVoltageStateTypeId, inverterData.phaseVoltageAN);
|
||||
@ -609,7 +644,6 @@ void IntegrationPluginSunSpec::onInverterDataReceived(const SunSpecInverter::Inv
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseCCurrentStateTypeId, inverterData.phaseCCurrent);
|
||||
}
|
||||
|
||||
|
||||
switch(inverterData.operatingState) {
|
||||
case SunSpec::SunSpecOperatingState::Off:
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "Off");
|
||||
@ -689,7 +723,7 @@ void IntegrationPluginSunSpec::onInverterDataReceived(const SunSpecInverter::Inv
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onStorageDataReceived(const SunSpecStorage::StorageData &storageData)
|
||||
void IntegrationPluginSunSpec::onStorageDataReceived(const SunSpecStorage::StorageData &mandatory, const SunSpecStorage::StorageDataOptional &optional)
|
||||
{
|
||||
SunSpecStorage *storage = static_cast<SunSpecStorage *>(sender());
|
||||
Thing *thing = m_sunSpecStorages.key(storage);
|
||||
@ -698,7 +732,37 @@ void IntegrationPluginSunSpec::onStorageDataReceived(const SunSpecStorage::Stora
|
||||
return;
|
||||
}
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
|
||||
thing->setStateValue(sunspecStorageStorageStateStateTypeId, storageData.chargingState);
|
||||
|
||||
thing->setStateValue(sunspecStorageChargingRateStateTypeId, mandatory.maxChargeRate);
|
||||
thing->setStateValue(sunspecStorageDischargingRateStateTypeId, mandatory.maxDischargeRate);
|
||||
|
||||
bool charging = false;
|
||||
switch (optional.chargeSatus) {
|
||||
case SunSpecStorage::ChargingStatusOff:
|
||||
thing->setStateValue(sunspecStorageStorageStatusStateTypeId, "Off");
|
||||
break;
|
||||
case SunSpecStorage::ChargingStatusFull:
|
||||
thing->setStateValue(sunspecStorageStorageStatusStateTypeId, "Full");
|
||||
break;
|
||||
case SunSpecStorage::ChargingStatusEmpty:
|
||||
thing->setStateValue(sunspecStorageStorageStatusStateTypeId, "Empty");
|
||||
break;
|
||||
case SunSpecStorage::ChargingStatusHolding:
|
||||
thing->setStateValue(sunspecStorageStorageStatusStateTypeId, "Holding");
|
||||
break;
|
||||
case SunSpecStorage::ChargingStatusTesting:
|
||||
thing->setStateValue(sunspecStorageStorageStatusStateTypeId, "Testing");
|
||||
break;
|
||||
case SunSpecStorage::ChargingStatusCharging:
|
||||
thing->setStateValue(sunspecStorageStorageStatusStateTypeId, "Charging");
|
||||
break;
|
||||
case SunSpecStorage::ChargingStatusDischarging:
|
||||
thing->setStateValue(sunspecStorageStorageStatusStateTypeId, "Discharging");
|
||||
break;
|
||||
};
|
||||
double batteryLevel = optional.currentlyAvailableEnergy;
|
||||
thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, batteryLevel);
|
||||
thing->setStateValue(sunspecStorageBatteryCriticalStateTypeId, (batteryLevel < 5 && !charging));
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onMeterDataReceived(const SunSpecMeter::MeterData &meterData)
|
||||
|
||||
@ -79,6 +79,10 @@ private:
|
||||
|
||||
bool checkIfThingExists(uint modelId, uint modbusAddress);
|
||||
|
||||
void setupInverter(ThingSetupInfo *info);
|
||||
void setupMeter(ThingSetupInfo *info);
|
||||
void setupStorage(ThingSetupInfo *info);
|
||||
|
||||
private slots:
|
||||
void onRefreshTimer();
|
||||
|
||||
@ -93,7 +97,7 @@ private slots:
|
||||
void onWriteRequestError(QUuid requestId, const QString &error);
|
||||
|
||||
void onInverterDataReceived(const SunSpecInverter::InverterData &inverterData);
|
||||
void onStorageDataReceived(const SunSpecStorage::StorageData &storageData);
|
||||
void onStorageDataReceived(const SunSpecStorage::StorageData &mandatory, const SunSpecStorage::StorageDataOptional &optional);
|
||||
void onMeterDataReceived(const SunSpecMeter::MeterData &meterData);
|
||||
};
|
||||
#endif // INTEGRATIONPLUGINSUNSPEC_H
|
||||
|
||||
@ -998,9 +998,9 @@
|
||||
},
|
||||
{
|
||||
"id": "da2b19c5-0f48-49d1-93f0-abdc0051407d",
|
||||
"name": "storageState",
|
||||
"displayName": "State",
|
||||
"displayNameEvent": "State changed",
|
||||
"name": "storageStatus",
|
||||
"displayName": "Status",
|
||||
"displayNameEvent": "Status changed",
|
||||
"type": "QString",
|
||||
"possibleValues": [
|
||||
"Off",
|
||||
@ -1025,13 +1025,23 @@
|
||||
},
|
||||
{
|
||||
"id": "1f530f79-c0d2-466b-90e1-79149e34d92f",
|
||||
"name": "enableChargingLimit",
|
||||
"displayName": "Charging limit",
|
||||
"displayNameEvent": "Charging limit changed",
|
||||
"name": "enableCharging",
|
||||
"displayName": "Charging",
|
||||
"displayNameEvent": "Charging changed",
|
||||
"displayNameAction": "Enable charging",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true,
|
||||
"displayNameAction": "Enable Charging Limit"
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "bc99a159-815a-40ab-a6e8-b46f315305f7",
|
||||
"name": "enableDischarging",
|
||||
"displayName": "Discharging",
|
||||
"displayNameEvent": "Discharging changed",
|
||||
"displayNameAction": "Enable discharging",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "7f469bbc-64a5-4045-8d5f-9a1a85039851",
|
||||
@ -1039,30 +1049,20 @@
|
||||
"displayName": "Charging rate",
|
||||
"displayNameEvent": "Charging rate changed",
|
||||
"type": "int",
|
||||
"minValue": -100,
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"unit": "Percentage",
|
||||
"defaultValue": false,
|
||||
"writable": true,
|
||||
"displayNameAction": "Set charging rate"
|
||||
},
|
||||
{
|
||||
"id": "bc99a159-815a-40ab-a6e8-b46f315305f7",
|
||||
"name": "enableDischargingLimit",
|
||||
"displayName": "Discharging limit",
|
||||
"displayNameEvent": "Discharging limit changed",
|
||||
"displayNameAction": "Enable Discharging Limit",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "6068f030-acce-44a2-b95f-bd00dd5ca760",
|
||||
"name": "dischargingRate",
|
||||
"displayName": "Discharging rate",
|
||||
"displayNameEvent": "Discharging rate changed",
|
||||
"type": "int",
|
||||
"minValue": -100,
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"unit": "Percentage",
|
||||
"defaultValue": false,
|
||||
|
||||
@ -226,20 +226,20 @@ void SunSpec::readModelHeader(uint modbusAddress)
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Received model header response. Model ID:" << modelId << "length" << length;
|
||||
modelHeaderReceived(modbusAddress, modelId, length);
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read response error:" << reply->error();
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read model header response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error) {
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Modbus reply error:" << error;
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read model header, modbus reply error:" << error;
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read error: " << m_modbusTcpClient->errorString();
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read model header error: " << m_modbusTcpClient->errorString();
|
||||
delete reply; // broadcast replies return immediately
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read error: " << m_modbusTcpClient->errorString();
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read model header error: " << m_modbusTcpClient->errorString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -248,6 +248,11 @@ void SunSpec::readModelDataBlock(uint modbusAddress, uint length)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Read model, modbus address" << modbusAddress << "length" << length << ", Slave ID" << m_slaveId;
|
||||
|
||||
if (length > 125) { //Modbus register limit is 125
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Data block length is too long, max 125 register";
|
||||
return;
|
||||
}
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, modbusAddress, length+2);
|
||||
|
||||
if (QModbusReply *reply = m_modbusTcpClient->sendReadRequest(request, m_slaveId)) {
|
||||
|
||||
@ -53,10 +53,12 @@ void SunSpecInverter::init()
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Init";
|
||||
m_connection->readModelHeader(m_modelModbusStartRegister);
|
||||
connect(m_connection, &SunSpec::modelHeaderReceived, this, [this] (uint modbusAddress, SunSpec::ModelId modelId, uint length) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Model Header received, modbus address:" << modbusAddress << "model Id:" << modelId << "length:" << length;
|
||||
m_modelLength = length;
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
if (modelId == m_id) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Model Header received, modbus address:" << modbusAddress << "model Id:" << modelId << "length:" << length;
|
||||
m_modelLength = length;
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
}
|
||||
});
|
||||
QTimer::singleShot(10000, this,[this] {
|
||||
if (!m_initFinishedSuccess) {
|
||||
@ -67,12 +69,13 @@ void SunSpecInverter::init()
|
||||
|
||||
void SunSpecInverter::getInverterModelDataBlock()
|
||||
{
|
||||
// TODO check map length to modbus max value
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: get inverter model data block, modbus register" << m_modelModbusStartRegister << "length" << m_modelLength;
|
||||
m_connection->readModelDataBlock(m_modelModbusStartRegister, m_modelLength);
|
||||
}
|
||||
|
||||
void SunSpecInverter::getInverterModelHeader()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: get inverter model header, modbus register" << m_modelModbusStartRegister;
|
||||
m_connection->readModelHeader(m_modelModbusStartRegister);
|
||||
}
|
||||
|
||||
@ -83,7 +86,7 @@ void SunSpecInverter::onModelDataBlockReceived(SunSpec::ModelId mapId, uint mapL
|
||||
return;
|
||||
}
|
||||
if (mapLength < m_modelLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: on modbus map received, map length ist too short" << mapLength;
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: on modbus map received, map length is too short" << mapLength;
|
||||
//return;
|
||||
}
|
||||
InverterData inverterData;
|
||||
|
||||
@ -52,26 +52,30 @@ void SunSpecMeter::init()
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: Init";
|
||||
m_connection->readModelHeader(m_modelModbusStartRegister);
|
||||
connect(m_connection, &SunSpec::modelHeaderReceived, this, [this] (uint modbusAddress, SunSpec::ModelId modelId, uint length) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: Model Header received, modbus address:" << modbusAddress << "model Id:" << modelId << "length:" << length;
|
||||
m_modelLength = length;
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
if (modelId == m_id) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: Model Header received, modbus address:" << modbusAddress << "model Id:" << modelId << "length:" << length;
|
||||
m_modelLength = length;
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
}
|
||||
});
|
||||
QTimer::singleShot(10000, this,[this] {
|
||||
if (!m_initFinishedSuccess) {
|
||||
emit initFinished(false);
|
||||
}
|
||||
if (!m_initFinishedSuccess) {
|
||||
emit initFinished(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SunSpecMeter::getMeterModelDataBlock()
|
||||
{
|
||||
m_connection->readModelDataBlock(m_modelModbusStartRegister, m_modelLength);
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: get meter model data block, modbus register" << m_modelModbusStartRegister << "length" << m_modelLength;
|
||||
m_connection->readModelDataBlock(m_modelModbusStartRegister, m_modelLength);
|
||||
}
|
||||
|
||||
void SunSpecMeter::getMeterModelHeader()
|
||||
{
|
||||
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: get meter model header, modbus register" << m_modelModbusStartRegister << "length" << m_modelLength;
|
||||
m_connection->readModelHeader(m_modelModbusStartRegister);
|
||||
}
|
||||
|
||||
void SunSpecMeter::onModelDataBlockReceived(SunSpec::ModelId modelId, uint length, QVector<quint16> data)
|
||||
|
||||
@ -49,27 +49,31 @@ SunSpec::ModelId SunSpecStorage::modelId()
|
||||
void SunSpecStorage::init()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorage: Init";
|
||||
m_connection->readModelHeader(m_modelModbusStartRegister);
|
||||
getStorageModelHeader();
|
||||
connect(m_connection, &SunSpec::modelHeaderReceived, this, [this] (uint modbusAddress, SunSpec::ModelId modelId, uint length) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorager: Model header received, modbus address:" << modbusAddress << "model Id:" << modelId << "length:" << length;
|
||||
m_modelLength = length;
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
if (modelId == m_id) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorager: Model header received, modbus address:" << modbusAddress << "model Id:" << modelId << "length:" << length;
|
||||
m_modelLength = length;
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
}
|
||||
});
|
||||
QTimer::singleShot(10000, this,[this] {
|
||||
if (!m_initFinishedSuccess) {
|
||||
emit initFinished(false);
|
||||
}
|
||||
QTimer::singleShot(10000, this, [this] {
|
||||
if (!m_initFinishedSuccess) {
|
||||
emit initFinished(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SunSpecStorage::getStorageModelDataBlock()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorage: get storage model data block, modbus register" << m_modelModbusStartRegister << "length" << m_modelLength;
|
||||
m_connection->readModelDataBlock(m_modelModbusStartRegister, m_modelLength);
|
||||
}
|
||||
|
||||
void SunSpecStorage::getStorageModelHeader()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorage: get storage model header, modbus register" << m_modelModbusStartRegister << "length" << m_modelLength;
|
||||
m_connection->readModelHeader(m_modelModbusStartRegister);
|
||||
}
|
||||
|
||||
@ -81,7 +85,7 @@ QUuid SunSpecStorage::setGridCharging(bool enabled)
|
||||
PV (charging from grid 0 disabled)
|
||||
GRID (charging from 1 grid enabled*/
|
||||
|
||||
uint registerAddress = m_modelModbusStartRegister + Model124::Model124ChaGriSet;
|
||||
uint registerAddress = m_modelModbusStartRegister + Model124Optional::Model124ChargeGridSet;
|
||||
quint16 value = enabled;
|
||||
return m_connection->writeHoldingRegister(registerAddress, value);
|
||||
}
|
||||
@ -89,8 +93,8 @@ QUuid SunSpecStorage::setGridCharging(bool enabled)
|
||||
QUuid SunSpecStorage::setStorageControlMode(bool chargingEnabled, bool dischargingEnabled)
|
||||
{
|
||||
// Set charge bit to enable charge limit, set discharge bit to enable discharge limit, set both bits to enable both limits
|
||||
quint16 value = ((static_cast<quint16>(chargingEnabled) << StorageControlBitFieldCharge) |
|
||||
(static_cast<quint16>(dischargingEnabled) << StorageControlBitFieldDischarge)) ;
|
||||
quint16 value = ((static_cast<quint16>(chargingEnabled)) |
|
||||
(static_cast<quint16>(dischargingEnabled) << 1)) ;
|
||||
|
||||
uint modbusRegister = m_modelModbusStartRegister + Model124::Model124ActivateStorageControlMode;
|
||||
return m_connection->writeHoldingRegister(modbusRegister, value);
|
||||
@ -124,22 +128,38 @@ void SunSpecStorage::onModelDataBlockReceived(SunSpec::ModelId modelId, uint len
|
||||
|
||||
switch (modelId) {
|
||||
case SunSpec::ModelIdStorage: {
|
||||
StorageData storageData;
|
||||
StorageData mandatory;
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorage: Storage model received:";
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum charge" << data[Model124SetpointMaximumCharge];
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum charging rate" << data[Model124SetpointMaximumChargingRate];
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum discharge rate" << data[Model124SetpointMaximumDischargeRate];
|
||||
qCDebug(dcSunSpec()) << " - Active storage control mode" << data[Model124ActivateStorageControlMode];
|
||||
qCDebug(dcSunSpec()) << " - Currently available energy" << data[Model124CurrentlyAvailableEnergy];
|
||||
storageData.chargingState = ChargingState(data[Model124::Model124ChargeStatus]);
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum charging rate" << data[Model124ChaGriSet];
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum charging rate" << data[Model124ScaleFactorMaximumCharge];
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum charging rate" << data[Model124ScaleFactorMaximumChargeDischargeRate];
|
||||
qCDebug(dcSunSpec()) << " - Setpoint maximum charging rate" << data[Model124ScaleFactorAvailableEnergyPercent];
|
||||
emit storageDataReceived(storageData);
|
||||
qCDebug(dcSunSpec()) << " - ChaGriSet" << data[Model124ChargeGridSet];
|
||||
qCDebug(dcSunSpec()) << " - Scale factor max charge" << data[Model124ScaleFactorMaximumCharge];
|
||||
qCDebug(dcSunSpec()) << " - Scale factor max charge/discharge rate" << data[Model124ScaleFactorMaximumChargeDischargeRate];
|
||||
qCDebug(dcSunSpec()) << " - Scale factor" << data[Model124ScaleFactorAvailableEnergyPercent];
|
||||
mandatory.maxCharge = m_connection->convertValueWithSSF(data[Model124SetpointMaximumCharge], data[Model124ScaleFactorMaximumChargeDischargeRate]);
|
||||
mandatory.maxChargeRate = m_connection->convertValueWithSSF(data[Model124SetpointMaximumChargingRate], data[Model124ScaleFactorPercentChargeDischargeRate]);
|
||||
mandatory.chargingEnabled = data[Model124ActivateStorageControlMode]&0x01;
|
||||
mandatory.dischargingEnabled = data[Model124ActivateStorageControlMode]&0x02;
|
||||
mandatory.maxDischargeRate = m_connection->convertValueWithSSF(data[Model124SetpointMaximumDischargeRate], data[Model124ScaleFactorPercentChargeDischargeRate]);
|
||||
|
||||
StorageDataOptional optional;
|
||||
optional.chargeSatus = ChargingStatus(data[Model124ChargeStatus]);
|
||||
optional.batteryVoltage = m_connection->convertValueWithSSF(data[Model124InternalBatteryVoltage], data[Model124ScaleFactorBatteryVoltage]);
|
||||
optional.storageAvailable = m_connection->convertValueWithSSF(data[Model124StorageAvailableAH], data[Model124ScaleFactorMaximumChargingVA]);
|
||||
optional.gridChargingEnabled = (data[Model124ChargeGridSet] == 1);
|
||||
optional.currentlyAvailableEnergy = m_connection->convertValueWithSSF(data[Model124CurrentlyAvailableEnergyPercent], data[Model124ScaleFactorAvailableEnergyPercent]);
|
||||
//qCDebug(dcSunSpec()) << " - Currently available energy" << data[Model124CurrentlyAvailableEnergy];
|
||||
//mandatory.chargingState = ChargingStatus(data[Model124ChargeStatus]);
|
||||
//qCDebug(dcSunSpec()) << " - Charging state" << mandatory.chargingState;
|
||||
|
||||
emit storageDataReceived(mandatory, optional);
|
||||
|
||||
} break;
|
||||
case SunSpec::ModelIdBatteryBaseModel:
|
||||
case SunSpec::ModelIdBatteryBaseModel:
|
||||
case SunSpec::ModelIdLithiumIonBatteryModel: {
|
||||
qCDebug(dcSunSpec()) << "Model not yet supported";
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -50,11 +50,12 @@ public:
|
||||
QUuid setChargingRate(int rate);
|
||||
QUuid setStorageControlMode(bool chargingEnabled, bool dischargingEnabled);
|
||||
|
||||
enum StorageControlBitField {
|
||||
StorageControlBitFieldCharge = 0,
|
||||
StorageControlBitFieldDischarge = 1
|
||||
enum StorageControl {
|
||||
StorageControlHold = 0,
|
||||
StorageControlCharge = 1,
|
||||
StorageControlDischarge = 2,
|
||||
};
|
||||
Q_ENUM(StorageControlBitField)
|
||||
Q_ENUM(StorageControl)
|
||||
|
||||
enum GridCharge {
|
||||
PV = 0,
|
||||
@ -62,33 +63,69 @@ public:
|
||||
};
|
||||
Q_ENUM(GridCharge)
|
||||
|
||||
enum ChargingState {
|
||||
ChargingStateOff,
|
||||
ChargingStateEmpty,
|
||||
ChargingStateDischarging,
|
||||
ChargingStateCharging,
|
||||
ChargingStateFull,
|
||||
ChargingStateHolding,
|
||||
ChargingStateTesting
|
||||
enum ChargingStatus {
|
||||
ChargingStatusOff,
|
||||
ChargingStatusEmpty,
|
||||
ChargingStatusDischarging,
|
||||
ChargingStatusCharging,
|
||||
ChargingStatusFull,
|
||||
ChargingStatusHolding,
|
||||
ChargingStatusTesting
|
||||
};
|
||||
Q_ENUM(ChargingState)
|
||||
Q_ENUM(ChargingStatus)
|
||||
|
||||
enum Model124 { // Mandatory register
|
||||
enum Model124 { // Mandatory registers
|
||||
Model124SetpointMaximumCharge = 0,
|
||||
Model124SetpointMaximumChargingRate = 1,
|
||||
Model124SetpointMaximumDischargeRate = 2,
|
||||
Model124ActivateStorageControlMode = 3,
|
||||
Model124CurrentlyAvailableEnergy = 6,
|
||||
Model124ChargeStatus = 9,
|
||||
Model124ChaGriSet = 15,
|
||||
Model124ScaleFactorMaximumCharge = 16,
|
||||
Model124ScaleFactorMaximumChargeDischargeRate = 17,
|
||||
Model124ScaleFactorAvailableEnergyPercent = 20
|
||||
};
|
||||
Q_ENUM(Model124)
|
||||
|
||||
enum Model124Optional { // Optional registers
|
||||
Model124MaximumChargingVA = 4, // VAChaMax
|
||||
Model124MinimumReserveStoragePercent = 5, // MinRsvPct
|
||||
Model124CurrentlyAvailableEnergyPercent = 6, // ChaState
|
||||
Model124StorageAvailableAH = 7, // StorAval
|
||||
Model124InternalBatteryVoltage = 8, // InBatV
|
||||
Model124ChargeStatus = 9, // ChaSt
|
||||
Model124MaxDischargingRatePercent = 10, // OutWRte
|
||||
Model124MaxChargingRatePercent = 11,
|
||||
Model124ChargeDischargeTimeWindow = 12,
|
||||
Model124ChargeDischargeTimeout = 13,
|
||||
Model124RampTime = 14, // InOutWRte_RmpTms
|
||||
Model124ChargeGridSet = 15, // ChGriSet
|
||||
Model124ScaleFactorMaximumChargingVA = 18,
|
||||
Model124ScaleFactorMinimumReservePercentage = 19,
|
||||
Model124ScaleFactorAvailableEnergyPercent = 20,
|
||||
Model124ScaleFactorStateCharge = 21,
|
||||
Model124ScaleFactorBatteryVoltage = 22,
|
||||
Model124ScaleFactorPercentChargeDischargeRate = 23
|
||||
};
|
||||
Q_ENUM(Model124Optional)
|
||||
|
||||
struct StorageData {
|
||||
ChargingState chargingState;
|
||||
double maxCharge; // [W] Setpoint for maximum charge.
|
||||
double maxChargeRate; // [%] Setpoint for maximum charging rate. Default is MaxChaRte.
|
||||
double maxDischargeRate; // [%] Setpoint for maximum discharge rate. Default is MaxDisChaRte.
|
||||
bool chargingEnabled;
|
||||
bool dischargingEnabled;
|
||||
};
|
||||
|
||||
struct StorageDataOptional {
|
||||
// [VA] Setpoint for maximum charging VA.
|
||||
// [& ]Setpoint for minimum reserve for storage as a percentage of the nominal maximum storage.
|
||||
double currentlyAvailableEnergy; // [%] Currently available energy as a percent of the capacity rating.
|
||||
double storageAvailable; // [Ah] State of charge (ChaState) minus storage reserve (MinRsvPct) times capacity rating (AhrRtg).
|
||||
double batteryVoltage; // [V] Internal battery voltage.
|
||||
ChargingStatus chargeSatus; // Charge status of storage device. Enumerated value.
|
||||
// [%] Percent of max discharge rate.
|
||||
// [%] Percent of max charging rate.
|
||||
// [s] Time window for charge/discharge rate change.
|
||||
// [s] Timeout period for charge/discharge rate.
|
||||
// [s] Ramp time for moving from current setpoint to new setpoint.
|
||||
bool gridChargingEnabled;
|
||||
};
|
||||
|
||||
@ -104,7 +141,7 @@ private slots:
|
||||
|
||||
signals:
|
||||
void initFinished(bool success);
|
||||
void storageDataReceived(const StorageData &data);
|
||||
void storageDataReceived(const StorageData &mandatory, const StorageDataOptional &optional);
|
||||
};
|
||||
|
||||
#endif // SUNSPECSTORAGE_H
|
||||
|
||||
Reference in New Issue
Block a user