fixed sf value conversion
This commit is contained in:
parent
6383b60ce3
commit
0d91606e7d
@ -1,13 +1,11 @@
|
||||
# SunSpec
|
||||
|
||||
Connect to SunSpec devices.
|
||||
Connect to SunSpec devices over Modbus TCP
|
||||
|
||||
## Supported Things
|
||||
|
||||
* SunSpec Inverter
|
||||
* SunSpec PV Modules
|
||||
* SunSpec Meter
|
||||
* SunSpec Tracker
|
||||
* SunSpec Storage
|
||||
|
||||
## Requirements
|
||||
|
||||
@ -38,6 +38,34 @@ IntegrationPluginSunSpec::IntegrationPluginSunSpec()
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::init()
|
||||
{
|
||||
m_connectedStateTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionConnectedStateTypeId);
|
||||
m_connectedStateTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterConnectedStateTypeId);
|
||||
m_connectedStateTypeIds.insert(sunspecSplitPhaseInverterThingClassId, sunspecSplitPhaseInverterConnectedStateTypeId);
|
||||
m_connectedStateTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterConnectedStateTypeId);
|
||||
m_connectedStateTypeIds.insert(sunspecStorageThingClassId, sunspecStorageConnectedStateTypeId);
|
||||
m_connectedStateTypeIds.insert(sunspecSinglePhaseMeterThingClassId, sunspecSinglePhaseMeterConnectedStateTypeId);
|
||||
m_connectedStateTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterConnectedStateTypeId);
|
||||
m_connectedStateTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterConnectedStateTypeId);
|
||||
|
||||
m_mapIdParamTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterThingMapIdParamTypeId);
|
||||
m_mapIdParamTypeIds.insert(sunspecSplitPhaseInverterThingClassId, sunspecSplitPhaseInverterThingMapIdParamTypeId);
|
||||
m_mapIdParamTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterThingMapIdParamTypeId);
|
||||
m_mapIdParamTypeIds.insert(sunspecStorageThingClassId, sunspecStorageThingMapIdParamTypeId);
|
||||
m_mapIdParamTypeIds.insert(sunspecSinglePhaseMeterThingClassId, sunspecSinglePhaseMeterThingMapIdParamTypeId);
|
||||
m_mapIdParamTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterThingMapIdParamTypeId);
|
||||
m_mapIdParamTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterThingMapIdParamTypeId);
|
||||
|
||||
m_modbusAddressParamTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterThingModbusAddressParamTypeId);
|
||||
m_modbusAddressParamTypeIds.insert(sunspecSplitPhaseInverterThingClassId, sunspecSplitPhaseInverterThingModbusAddressParamTypeId);
|
||||
m_modbusAddressParamTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterThingModbusAddressParamTypeId);
|
||||
m_modbusAddressParamTypeIds.insert(sunspecStorageThingClassId, sunspecStorageThingModbusAddressParamTypeId);
|
||||
m_modbusAddressParamTypeIds.insert(sunspecSinglePhaseMeterThingClassId, sunspecSinglePhaseMeterThingModbusAddressParamTypeId);
|
||||
m_modbusAddressParamTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterThingModbusAddressParamTypeId);
|
||||
m_modbusAddressParamTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterThingModbusAddressParamTypeId);
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
@ -49,13 +77,13 @@ void IntegrationPluginSunSpec::setupThing(ThingSetupInfo *info)
|
||||
//int slaveId = info->thing()->paramValue(sunspecConnectionThingSlaveIdParamTypeId).toInt();
|
||||
|
||||
SunSpec *sunSpec;
|
||||
if (m_sunSpecConnections.contains(thing)) {
|
||||
if (m_sunSpecConnections.contains(thing->id())) {
|
||||
qCDebug(dcSunSpec()) << "Reconfigure SunSpec connection with new address" << address;
|
||||
sunSpec = m_sunSpecConnections.value(thing);
|
||||
sunSpec = m_sunSpecConnections.value(thing->id());
|
||||
sunSpec->setHostAddress(address);
|
||||
} else {
|
||||
sunSpec = new SunSpec(address, port, this);
|
||||
m_sunSpecConnections.insert(info->thing(), sunSpec);
|
||||
m_sunSpecConnections.insert(thing->id(), sunSpec);
|
||||
}
|
||||
|
||||
if (!sunSpec->connectModbus()) {
|
||||
@ -72,71 +100,74 @@ void IntegrationPluginSunSpec::setupThing(ThingSetupInfo *info)
|
||||
});
|
||||
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpec, &SunSpec::deleteLater);
|
||||
connect(sunSpec, &SunSpec::destroyed, [this, info] {
|
||||
m_sunSpecConnections.remove(info->thing());
|
||||
connect(sunSpec, &SunSpec::destroyed, [this, thing] {
|
||||
m_sunSpecConnections.remove(thing->id());
|
||||
});
|
||||
connect(sunSpec, &SunSpec::connectionStateChanged, this, [thing] (bool status) {
|
||||
thing->setStateValue(sunspecConnectionThingClassId, status);
|
||||
connect(sunSpec, &SunSpec::foundModbusMap, this, &IntegrationPluginSunSpec::onFoundModbusMap);
|
||||
connect(sunSpec, &SunSpec::modbusMapSearchFinished, this, &IntegrationPluginSunSpec::onModbusMapSearchFinished);
|
||||
connect(sunSpec, &SunSpec::commonMapReceived, thing, [thing] (const QString &manufacturer, const QString &deviceModel, const QString &serielNumber) {
|
||||
thing->setStateValue(sunspecConnectionConnectedStateTypeId, true);
|
||||
thing->setStateValue(sunspecConnectionManufacturerStateTypeId, manufacturer);
|
||||
thing->setStateValue(sunspecConnectionDeviceModelStateTypeId, deviceModel);
|
||||
thing->setStateValue(sunspecConnectionSerialNumberStateTypeId, serielNumber);
|
||||
});
|
||||
connect(sunSpec, &SunSpec::mapHeaderReceived, this, &IntegrationPluginSunSpec::onMapHeaderReceived);
|
||||
connect(sunSpec, &SunSpec::mapReceived, this, &IntegrationPluginSunSpec::onMapReceived);
|
||||
|
||||
} else if (thing->thingClassId() == sunspecInverterThingClassId) {
|
||||
QHostAddress address = QHostAddress(info->thing()->paramValue(sunspecInverterThingIpAddressParamTypeId).toString());
|
||||
SunSpecInverter *sunSpecInverter = new SunSpecInverter(address, 502, this);
|
||||
} else if (thing->thingClassId() == sunspecThreePhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecSinglePhaseInverterThingClassId ) {
|
||||
|
||||
if (!sunSpecInverter->connectModbus()) {
|
||||
qCWarning(dcSunSpec()) << "Error connecting to SunSpec device";
|
||||
uint mapId = thing->paramValue(m_mapIdParamTypeIds.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);
|
||||
}
|
||||
connect(sunSpecInverter, &SunSpecInverter::initFinished, info, [this, sunSpecInverter, info] {
|
||||
qCDebug(dcSunSpec()) << "Modbus Inverter init finished";
|
||||
m_sunSpecInverters.insert(info->thing(), sunSpecInverter);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
SunSpecInverter *sunSpecInverter = new SunSpecInverter(connection, SunSpec::BlockId(mapId), 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, [info, this] {m_sunSpecInverters.remove(info->thing());});
|
||||
connect(sunSpecInverter, &SunSpecInverter::destroyed, thing, [thing, this] {m_sunSpecInverters.remove(thing);});
|
||||
connect(sunSpecInverter, &SunSpecInverter::inverterDataReceived, this, &IntegrationPluginSunSpec::onInverterDataReceived);
|
||||
|
||||
} else if (thing->thingClassId() == sunspecMeterThingClassId) {
|
||||
QHostAddress address = QHostAddress(info->thing()->paramValue(sunspecMeterThingIpAddressParamTypeId).toString());
|
||||
SunSpecMeter *sunSpecMeter = new SunSpecMeter(address, 502, this);
|
||||
} else if (thing->thingClassId() == sunspecSinglePhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecThreePhaseMeterThingClassId) {
|
||||
|
||||
if (!sunSpecMeter->connectModbus()) {
|
||||
sunSpecMeter->deleteLater();
|
||||
qCDebug(dcSunSpec()) << "Could not connect";
|
||||
uint mapId = thing->paramValue(m_mapIdParamTypeIds.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);
|
||||
}
|
||||
m_sunSpecMeters.insert(info->thing(), sunSpecMeter);
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecMeter, [info, this] {
|
||||
m_sunSpecMeters.take(info->thing())->deleteLater();
|
||||
SunSpecMeter *sunSpecMeter = new SunSpecMeter(connection, SunSpec::BlockId(mapId), 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);
|
||||
}
|
||||
});
|
||||
|
||||
} else if (info->thing()->thingClassId() == sunspecTrackerThingClassId) {
|
||||
QHostAddress address = QHostAddress(info->thing()->paramValue(sunspecTrackerThingIpAddressParamTypeId).toString());
|
||||
SunSpecTracker *sunSpecTracker = new SunSpecTracker(address, 502, this);
|
||||
if (!sunSpecTracker->connectModbus()) {
|
||||
sunSpecTracker->deleteLater();
|
||||
qCDebug(dcSunSpec()) << "Could not connect";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecTracker, [info, this] {
|
||||
m_sunSpecTrackers.take(info->thing())->deleteLater();
|
||||
});
|
||||
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) {
|
||||
QHostAddress address = QHostAddress(info->thing()->paramValue(sunspecStorageThingIpAddressParamTypeId).toString());
|
||||
SunSpecStorage *sunSpecStorage = new SunSpecStorage(address, 502, this);
|
||||
if (!sunSpecStorage->connectModbus()) {
|
||||
sunSpecStorage->deleteLater();
|
||||
qCDebug(dcSunSpec()) << "Could not connect";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
m_sunSpecStorages.insert(info->thing(), sunSpecStorage);
|
||||
connect(info, &ThingSetupInfo::aborted, sunSpecStorage, [info, this] {
|
||||
m_sunSpecStorages.take(info->thing())->deleteLater();
|
||||
});
|
||||
|
||||
|
||||
} else {
|
||||
Q_ASSERT_X(false, "setupThing", QString("Unhandled thingClassId: %1").arg(info->thing()->thingClassId().toString()).toUtf8());
|
||||
@ -155,50 +186,43 @@ void IntegrationPluginSunSpec::postSetupThing(Thing *thing)
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == sunspecConnectionThingClassId) {
|
||||
SunSpec *connection = m_sunSpecConnections.take(thing);
|
||||
if (!connection)
|
||||
SunSpec *connection = m_sunSpecConnections.value(thing->id());
|
||||
if (!connection) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecConnection not found";
|
||||
return;
|
||||
}
|
||||
connection->readCommonMap();
|
||||
thing->setParamValue(sunspecConnectionManufacturerStateTypeId, connection->manufacturer());
|
||||
thing->setParamValue(sunspecInverterThingSerialNumberParamTypeId, connection->serialNumber());
|
||||
thing->setParamValue(sunspecInverterThingDeviceModelParamTypeId, connection->deviceModel());
|
||||
connection->findModbusMap(QList<SunSpec::BlockId>()); // Discover all maps, without filter
|
||||
|
||||
} else if (thing->thingClassId() == sunspecSinglePhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecThreePhaseInverterThingClassId) {
|
||||
|
||||
} else if (thing->thingClassId() == sunspecInverterThingClassId) {
|
||||
SunSpecInverter *sunSpecInverter = m_sunSpecInverters.take(thing);
|
||||
if (!sunSpecInverter)
|
||||
SunSpecInverter *sunSpecInverter = m_sunSpecInverters.value(thing);
|
||||
if (!sunSpecInverter) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter not found";
|
||||
return;
|
||||
}
|
||||
sunSpecInverter->getInverterMap();
|
||||
thing->setParamValue(sunspecInverterThingManufacturerParamTypeId, sunSpecInverter->manufacturer());
|
||||
thing->setParamValue(sunspecInverterThingSerialNumberParamTypeId, sunSpecInverter->serialNumber());
|
||||
thing->setParamValue(sunspecInverterThingDeviceModelParamTypeId, sunSpecInverter->deviceModel());
|
||||
|
||||
} else if (thing->thingClassId() == sunspecMeterThingClassId) {
|
||||
SunSpecMeter *sunSpecMeter = m_sunSpecMeters.take(thing);
|
||||
if (!sunSpecMeter)
|
||||
return;
|
||||
//TODO upate data
|
||||
thing->setParamValue(sunspecMeterThingManufacturerParamTypeId, sunSpecMeter->manufacturer());
|
||||
thing->setParamValue(sunspecMeterThingSerialNumberParamTypeId, sunSpecMeter->serialNumber());
|
||||
thing->setParamValue(sunspecMeterThingDeviceModelParamTypeId, sunSpecMeter->deviceModel());
|
||||
} else if (thing->thingClassId() == sunspecSinglePhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecThreePhaseMeterThingClassId) {
|
||||
|
||||
} else if (thing->thingClassId() == sunspecTrackerThingClassId) {
|
||||
SunSpecTracker *sunSpecTracker = m_sunSpecTrackers.take(thing);
|
||||
if (!sunSpecTracker)
|
||||
SunSpecMeter *sunSpecMeter = m_sunSpecMeters.value(thing);
|
||||
if (!sunSpecMeter) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter not found";
|
||||
return;
|
||||
//TODO upate data
|
||||
thing->setParamValue(sunspecTrackerThingManufacturerParamTypeId, sunSpecTracker->manufacturer());
|
||||
thing->setParamValue(sunspecTrackerThingSerialNumberParamTypeId, sunSpecTracker->serialNumber());
|
||||
thing->setParamValue(sunspecTrackerThingDeviceModelParamTypeId, sunSpecTracker->deviceModel());
|
||||
}
|
||||
sunSpecMeter->getMeterMap();
|
||||
|
||||
} else if (thing->thingClassId() == sunspecStorageThingClassId) {
|
||||
SunSpecStorage *sunSpecStorage = m_sunSpecStorages.take(thing);
|
||||
if (!sunSpecStorage)
|
||||
SunSpecStorage *sunSpecStorage = m_sunSpecStorages.value(thing);
|
||||
if (!sunSpecStorage) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorage not found";
|
||||
return;
|
||||
//TODO upate data
|
||||
thing->setParamValue(sunspecStorageThingManufacturerParamTypeId, sunSpecStorage->manufacturer());
|
||||
thing->setParamValue(sunspecStorageThingSerialNumberParamTypeId, sunSpecStorage->serialNumber());
|
||||
thing->setParamValue(sunspecStorageThingDeviceModelParamTypeId, sunSpecStorage->deviceModel());
|
||||
}
|
||||
sunSpecStorage->getStorageMap();
|
||||
|
||||
} else {
|
||||
Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
@ -210,21 +234,25 @@ void IntegrationPluginSunSpec::thingRemoved(Thing *thing)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "Thing removed" << thing->name();
|
||||
|
||||
if (thing->thingClassId() == sunspecInverterThingClassId) {
|
||||
if (thing->thingClassId() == sunspecConnectionThingClassId) {
|
||||
SunSpec *sunSpecConnection = m_sunSpecConnections.take(thing->id());
|
||||
if (sunSpecConnection)
|
||||
sunSpecConnection->deleteLater();
|
||||
|
||||
} else if (thing->thingClassId() == sunspecSinglePhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecThreePhaseInverterThingClassId) {
|
||||
SunSpecInverter *sunSpecInverter = m_sunSpecInverters.take(thing);
|
||||
if (sunSpecInverter)
|
||||
sunSpecInverter->deleteLater();
|
||||
|
||||
} else if (thing->thingClassId() == sunspecMeterThingClassId) {
|
||||
} else if (thing->thingClassId() == sunspecSinglePhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecThreePhaseMeterThingClassId) {
|
||||
SunSpecMeter *sunSpecMeter = m_sunSpecMeters.take(thing);
|
||||
if (sunSpecMeter)
|
||||
sunSpecMeter->deleteLater();
|
||||
|
||||
} else if (thing->thingClassId() == sunspecTrackerThingClassId) {
|
||||
SunSpecTracker *sunSpecTracker = m_sunSpecTrackers.take(thing);
|
||||
if (sunSpecTracker)
|
||||
sunSpecTracker->deleteLater();
|
||||
|
||||
} else if (thing->thingClassId() == sunspecStorageThingClassId) {
|
||||
SunSpecStorage *sunSpecStorage = m_sunSpecStorages.take(thing);
|
||||
if (sunSpecStorage)
|
||||
@ -246,7 +274,10 @@ void IntegrationPluginSunSpec::executeAction(ThingActionInfo *info)
|
||||
Thing *thing = info->thing();
|
||||
Action action = info->action();
|
||||
|
||||
if (thing->thingClassId() == sunspecInverterThingClassId) {
|
||||
if (thing->thingClassId() == sunspecSinglePhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseInverterThingClassId ||
|
||||
thing->thingClassId() == sunspecThreePhaseInverterThingClassId) {
|
||||
|
||||
SunSpecInverter *sunSpecInverter = m_sunSpecInverters.value(thing);
|
||||
if (!sunSpecInverter) {
|
||||
qWarning(dcSunSpec()) << "Could not find SunSpec inverter for thing" << thing->name();
|
||||
@ -255,10 +286,9 @@ void IntegrationPluginSunSpec::executeAction(ThingActionInfo *info)
|
||||
}
|
||||
info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||
|
||||
} else if (thing->thingClassId() == sunspecMeterThingClassId) {
|
||||
info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||
|
||||
} else if (thing->thingClassId() == sunspecTrackerThingClassId) {
|
||||
} else if (thing->thingClassId() == sunspecSinglePhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecSplitPhaseMeterThingClassId ||
|
||||
thing->thingClassId() == sunspecThreePhaseMeterThingClassId) {
|
||||
info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||
|
||||
} else if (thing->thingClassId() == sunspecStorageThingClassId) {
|
||||
@ -319,24 +349,30 @@ void IntegrationPluginSunSpec::executeAction(ThingActionInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
bool IntegrationPluginSunSpec::checkIfThingExists(uint mapId, uint modbusAddress)
|
||||
{
|
||||
Q_FOREACH(Thing *thing, myThings()) {
|
||||
if (thing->paramValue(m_mapIdParamTypeIds.value(thing->thingClassId())).toUInt() == mapId &&
|
||||
thing->paramValue(m_modbusAddressParamTypeIds.value(thing->thingClassId())).toUInt() == modbusAddress) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onRefreshTimer()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "On refresh timer";
|
||||
//get data
|
||||
foreach (SunSpec *connections, m_sunSpecConnections) {
|
||||
connections->readCommonMap();
|
||||
foreach (SunSpec *connection, m_sunSpecConnections) {
|
||||
connection->readCommonMap(); //check connection
|
||||
}
|
||||
foreach (SunSpecInverter *inverter, m_sunSpecInverters) {
|
||||
inverter->getInverterMap();
|
||||
}
|
||||
foreach (SunSpecMeter *meter, m_sunSpecMeters) {
|
||||
Q_UNUSED(meter) //TODO
|
||||
}
|
||||
foreach (SunSpecTracker *tracker, m_sunSpecTrackers) {
|
||||
Q_UNUSED(tracker) //TODO
|
||||
meter->getMeterMap();
|
||||
}
|
||||
foreach (SunSpecStorage *storage, m_sunSpecStorages) {
|
||||
Q_UNUSED(storage) //TODO
|
||||
storage->getStorageMap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,7 +393,18 @@ void IntegrationPluginSunSpec::onPluginConfigurationChanged(const ParamTypeId &p
|
||||
|
||||
void IntegrationPluginSunSpec::onConnectionStateChanged(bool status)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "Connection state changed" << status;
|
||||
SunSpec *connection = static_cast<SunSpec *>(sender());
|
||||
Thing *thing = myThings().findById(m_sunSpecConnections.key(connection));
|
||||
if (!thing)
|
||||
return;
|
||||
qCDebug(dcSunSpec()) << "Connection state changed" << status << thing->name();
|
||||
if (thing->thingClassId() == sunspecConnectionConnectedStateTypeId) {
|
||||
thing->setStateValue(sunspecConnectionConnectedStateTypeId, status);
|
||||
}
|
||||
|
||||
Q_FOREACH(Thing *child, myThings().filterByParentId(thing->id())) {
|
||||
child->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), status);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onMapHeaderReceived(uint modbusAddress, SunSpec::BlockId mapId, uint mapLength)
|
||||
@ -369,16 +416,93 @@ void IntegrationPluginSunSpec::onMapReceived(SunSpec::BlockId mapId, uint mapLen
|
||||
{
|
||||
Q_UNUSED(data)
|
||||
SunSpec *connection = static_cast<SunSpec *>(sender());
|
||||
Thing *thing = m_sunSpecConnections.key(connection);
|
||||
Thing *thing = myThings().findById(m_sunSpecConnections.key(connection));
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
qCDebug(dcSunSpec()) << "On map received" << mapId << mapLength;
|
||||
if (mapId == SunSpec::BlockIdCommon && thing->thingClassId() == sunspecConnectionThingClassId) {
|
||||
thing->setStateValue(sunspecConnectionManufacturerStateTypeId, connection->manufacturer());
|
||||
thing->setStateValue(sunspecConnectionSerialNumberStateTypeId, connection->serialNumber());
|
||||
thing->setStateValue(sunspecConnectionDeviceModelStateTypeId, connection->deviceModel());
|
||||
}
|
||||
qCDebug(dcSunSpec()) << "On map received" << mapId << "Map length" << mapLength << "Thing:" << thing->name();
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onFoundModbusMap(SunSpec::BlockId mapId, int modbusStartRegister)
|
||||
{
|
||||
SunSpec *connection = static_cast<SunSpec *>(sender());
|
||||
Thing *thing = myThings().findById(m_sunSpecConnections.key(connection));
|
||||
if (!thing) {
|
||||
qCWarning(dcSunSpec()) << "Thing not found for SunSpec connection" << connection->deviceModel() << connection->serialNumber();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSunSpec()) << "On map received" << mapId << "Map length" << modbusStartRegister << "Thing:" << thing->name();
|
||||
if (checkIfThingExists(mapId, modbusStartRegister)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mapId) {
|
||||
case SunSpec::BlockId::BlockIdInverterSinglePhase:
|
||||
case SunSpec::BlockId::BlockIdInverterSinglePhaseFloat: {
|
||||
QString model = thing->stateValue(sunspecConnectionDeviceModelStateTypeId).toString();
|
||||
ThingDescriptor descriptor(sunspecSinglePhaseInverterThingClassId, model+tr(" single phase inverter"), "", thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(sunspecSinglePhaseInverterThingMapIdParamTypeId, mapId));
|
||||
params.append(Param(sunspecSinglePhaseInverterThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared({descriptor});
|
||||
} break;
|
||||
case SunSpec::BlockId::BlockIdInverterSplitPhase:
|
||||
case SunSpec::BlockId::BlockIdInverterSplitPhaseFloat: {
|
||||
QString model = thing->stateValue(sunspecConnectionDeviceModelStateTypeId).toString();
|
||||
ThingDescriptor descriptor(sunspecSplitPhaseInverterThingClassId, model+tr(" split phase inverter"), "", thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(sunspecSplitPhaseInverterThingMapIdParamTypeId, mapId));
|
||||
params.append(Param(sunspecSplitPhaseInverterThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared({descriptor});
|
||||
} break;
|
||||
case SunSpec::BlockId::BlockIdInverterThreePhase:
|
||||
case SunSpec::BlockId::BlockIdInverterThreePhaseFloat: {
|
||||
QString model = thing->stateValue(sunspecConnectionDeviceModelStateTypeId).toString();
|
||||
ThingDescriptor descriptor(sunspecThreePhaseInverterThingClassId, model+tr(" three phase inverter"), "", thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(sunspecThreePhaseInverterThingMapIdParamTypeId, mapId));
|
||||
params.append(Param(sunspecThreePhaseInverterThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared({descriptor});
|
||||
} break;
|
||||
|
||||
case SunSpec::BlockIdSinglePhaseMeter:
|
||||
case SunSpec::BlockIdSinglePhaseMeterFloat: {
|
||||
} break;
|
||||
case SunSpec::BlockIdSplitSinglePhaseMeter:
|
||||
case SunSpec::BlockIdSplitSinglePhaseMeterFloat: {
|
||||
} break;
|
||||
case SunSpec::BlockIdWyeConnectThreePhaseMeterFloat:
|
||||
case SunSpec::BlockIdDeltaConnectThreePhaseMeterFloat: {
|
||||
} break;
|
||||
case SunSpec::BlockIdStorage: {
|
||||
QString model = thing->stateValue(sunspecConnectionDeviceModelStateTypeId).toString();
|
||||
ThingDescriptor descriptor(sunspecStorageThingClassId, model+" Storage", "Storage", thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(sunspecStorageThingMapIdParamTypeId, mapId));
|
||||
params.append(Param(sunspecThreePhaseInverterThingModbusAddressParamTypeId, modbusStartRegister));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared({descriptor});
|
||||
} break;
|
||||
default:
|
||||
qCDebug(dcSunSpec()) << "Block Id not handled";
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onModbusMapSearchFinished(const QHash<SunSpec::BlockId, int> &mapIds)
|
||||
{
|
||||
SunSpec *connection = static_cast<SunSpec *>(sender());
|
||||
Thing *thing = myThings().findById(m_sunSpecConnections.key(connection));
|
||||
if (!thing) {
|
||||
qCWarning(dcSunSpec()) << "Thing not found for SunSpec connection" << connection->deviceModel() << connection->serialNumber();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSunSpec()) << "On modbus map search finished, maps:" << mapIds.count();
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onWriteRequestExecuted(QUuid requestId, bool success)
|
||||
@ -401,95 +525,96 @@ void IntegrationPluginSunSpec::onInverterDataReceived(const SunSpecInverter::Inv
|
||||
if(!thing) {
|
||||
return;
|
||||
}
|
||||
thing->setStateValue(sunspecInverterAcPowerStateTypeId, inverterData.acPower);
|
||||
thing->setStateValue(sunspecInverterAcEnergyStateTypeId, inverterData.acEnergy/1000.00);
|
||||
thing->setStateValue(sunspecInverterLineFrequencyStateTypeId, inverterData.lineFrequency);
|
||||
thing->setStateValue(sunspecInverterTotalCurrentStateTypeId, inverterData.acCurrent);
|
||||
thing->setStateValue(sunspecInverterCabinetTemperatureStateTypeId, inverterData.cabinetTemperature);
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
|
||||
thing->setStateValue(sunspecThreePhaseInverterAcPowerStateTypeId, inverterData.acPower/1000.00);
|
||||
thing->setStateValue(sunspecThreePhaseInverterAcEnergyStateTypeId, inverterData.acEnergy/1000.00);
|
||||
thing->setStateValue(sunspecThreePhaseInverterLineFrequencyStateTypeId, inverterData.lineFrequency);
|
||||
thing->setStateValue(sunspecThreePhaseInverterTotalCurrentStateTypeId, inverterData.acCurrent);
|
||||
thing->setStateValue(sunspecThreePhaseInverterCabinetTemperatureStateTypeId, inverterData.cabinetTemperature);
|
||||
|
||||
thing->setStateValue(sunspecInverterPhaseACurrentStateTypeId, inverterData.phaseACurrent);
|
||||
thing->setStateValue(sunspecInverterPhaseBCurrentStateTypeId, inverterData.phaseBCurrent);
|
||||
thing->setStateValue(sunspecInverterPhaseCCurrentStateTypeId, inverterData.phaseCCurrent);
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseACurrentStateTypeId, inverterData.phaseACurrent);
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseBCurrentStateTypeId, inverterData.phaseBCurrent);
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseCCurrentStateTypeId, inverterData.phaseCCurrent);
|
||||
|
||||
thing->setStateValue(sunspecInverterPhaseANVoltageStateTypeId, inverterData.phaseVoltageAN);
|
||||
thing->setStateValue(sunspecInverterPhaseBNVoltageStateTypeId, inverterData.phaseVoltageBN);
|
||||
thing->setStateValue(sunspecInverterPhaseCNVoltageStateTypeId, inverterData.phaseVoltageCN);
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseANVoltageStateTypeId, inverterData.phaseVoltageAN);
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseBNVoltageStateTypeId, inverterData.phaseVoltageBN);
|
||||
thing->setStateValue(sunspecThreePhaseInverterPhaseCNVoltageStateTypeId, inverterData.phaseVoltageCN);
|
||||
|
||||
switch(inverterData.operatingState) {
|
||||
case SunSpec::SunSpecOperatingState::Off:
|
||||
thing->setStateValue(sunspecInverterOperatingStateStateTypeId, "Off");
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "Off");
|
||||
break;
|
||||
case SunSpec::SunSpecOperatingState::MPPT:
|
||||
thing->setStateValue(sunspecInverterOperatingStateStateTypeId, "MPPT");
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "MPPT");
|
||||
break;
|
||||
case SunSpec::SunSpecOperatingState::Fault:
|
||||
thing->setStateValue(sunspecInverterOperatingStateStateTypeId, "Fault");
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "Fault");
|
||||
break;
|
||||
case SunSpec::SunSpecOperatingState::Standby:
|
||||
thing->setStateValue(sunspecInverterOperatingStateStateTypeId, "Standby");
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "Standby");
|
||||
break;
|
||||
case SunSpec::SunSpecOperatingState::Sleeping:
|
||||
thing->setStateValue(sunspecInverterOperatingStateStateTypeId, "Sleeping");
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "Sleeping");
|
||||
break;
|
||||
case SunSpec::SunSpecOperatingState::Starting:
|
||||
thing->setStateValue(sunspecInverterOperatingStateStateTypeId, "Starting");
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "Starting");
|
||||
break;
|
||||
case SunSpec::SunSpecOperatingState::Throttled:
|
||||
thing->setStateValue(sunspecInverterOperatingStateStateTypeId, "Throttled");
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "Throttled");
|
||||
break;
|
||||
case SunSpec::SunSpecOperatingState::ShuttingDown:
|
||||
thing->setStateValue(sunspecInverterOperatingStateStateTypeId, "Shutting down");
|
||||
thing->setStateValue(sunspecThreePhaseInverterOperatingStateStateTypeId, "Shutting down");
|
||||
break;
|
||||
}
|
||||
|
||||
switch(inverterData.event) {
|
||||
case SunSpec::SunSpecEvent1::OVER_TEMP:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Over temperature");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Over temperature");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::UNDER_TEMP:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Under temperature");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Under temperature");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::GroundFault:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Ground fault");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Ground fault");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::MEMORY_LOSS:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Memory loss");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Memory loss");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::AC_OVER_VOLT:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "AC voltage above limit");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "AC voltage above limit");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::CABINET_OPEN:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Cabinet open");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Cabinet open");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::AC_DISCONNECT:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "AC disconnect open");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "AC disconnect open");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::AC_UNDER_VOLT:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "AC voltage under limit");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "AC voltage under limit");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::DC_DISCONNECT:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "DC disconnect open");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "DC disconnect open");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::DcOverVolatage:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "DC over voltage");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "DC over voltage");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::OVER_FREQUENCY:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Frequency above limit");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Frequency above limit");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::GRID_DISCONNECT:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Grid disconnect");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Grid disconnect");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::HW_TEST_FAILURE:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Hardware test failure");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Hardware test failure");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::MANUAL_SHUTDOWN:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Manual shutdown");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Manual shutdown");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::UNDER_FREQUENCY:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Frequency under limit");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Frequency under limit");
|
||||
break;
|
||||
case SunSpec::SunSpecEvent1::BLOWN_STRING_FUSE:
|
||||
thing->setStateValue(sunspecInverterErrorStateTypeId, "Blown string fuse on input");
|
||||
thing->setStateValue(sunspecThreePhaseInverterErrorStateTypeId, "Blown string fuse on input");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -516,15 +641,3 @@ void IntegrationPluginSunSpec::onMeterDataReceived(const SunSpecMeter::MeterData
|
||||
}
|
||||
//thing->setStateValue(sunspecMeterStorageStateStateTypeId, meterData.event);
|
||||
}
|
||||
|
||||
void IntegrationPluginSunSpec::onTrackerDataReceived(const SunSpecTracker::TrackerData &trackerData)
|
||||
{
|
||||
Q_UNUSED(trackerData)
|
||||
SunSpecTracker *tracker = static_cast<SunSpecTracker *>(sender());
|
||||
Thing *thing = m_sunSpecTrackers.key(tracker);
|
||||
|
||||
if(!thing) {
|
||||
return;
|
||||
}
|
||||
//thing->setStateValue(sunspecStorageStorageStateStateTypeId, storageData.chargingState);
|
||||
}
|
||||
|
||||
@ -52,20 +52,26 @@ class IntegrationPluginSunSpec: public IntegrationPlugin
|
||||
|
||||
public:
|
||||
explicit IntegrationPluginSunSpec();
|
||||
void init() override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void postSetupThing(Thing *thing) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
|
||||
private:
|
||||
QHash<ThingClassId, ParamTypeId> m_mapIdParamTypeIds;
|
||||
QHash<ThingClassId, ParamTypeId> m_modbusAddressParamTypeIds;
|
||||
|
||||
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIds;
|
||||
PluginTimer *m_refreshTimer = nullptr;
|
||||
QHash<QUuid, ThingActionInfo *> m_asyncActions;
|
||||
QHash<Thing *, SunSpec *> m_sunSpecConnections;
|
||||
QHash<ThingId, SunSpec *> m_sunSpecConnections;
|
||||
|
||||
QHash<Thing *, SunSpecInverter *> m_sunSpecInverters;
|
||||
QHash<Thing *, SunSpecStorage *> m_sunSpecStorages;
|
||||
QHash<Thing *, SunSpecMeter *> m_sunSpecMeters;
|
||||
QHash<Thing *, SunSpecTracker *> m_sunSpecTrackers;
|
||||
|
||||
bool checkIfThingExists(uint mapId, uint modbusAddress);
|
||||
|
||||
private slots:
|
||||
void onRefreshTimer();
|
||||
@ -77,13 +83,15 @@ private slots:
|
||||
void onMapHeaderReceived(uint modbusAddress, SunSpec::BlockId mapId, uint mapLength);
|
||||
void onMapReceived(SunSpec::BlockId mapId, uint mapLength, QVector<quint16> data);
|
||||
|
||||
void onFoundModbusMap(SunSpec::BlockId mapId, int modbusStartRegister);
|
||||
void onModbusMapSearchFinished(const QHash<SunSpec::BlockId, int> &mapIds);
|
||||
|
||||
void onWriteRequestExecuted(QUuid requestId, bool success);
|
||||
void onWriteRequestError(QUuid requestId, const QString &error);
|
||||
|
||||
void onInverterDataReceived(const SunSpecInverter::InverterData &inverterData);
|
||||
void onStorageDataReceived(const SunSpecStorage::StorageData &storageData);
|
||||
void onMeterDataReceived(const SunSpecMeter::MeterData &meterData);
|
||||
void onTrackerDataReceived(const SunSpecTracker::TrackerData &trackerData);
|
||||
};
|
||||
|
||||
#endif // INTEGRATIONPLUGINSUNSPEC_H
|
||||
|
||||
@ -46,7 +46,8 @@
|
||||
"id": "6be6abc4-e2b2-4687-9343-0e5164ed0ab2",
|
||||
"name":"ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString"
|
||||
"type": "QString",
|
||||
"defaultValue": "127.0.0.1"
|
||||
},
|
||||
{
|
||||
"id": "1fa4fc9c-f6be-47c7-928a-bcefc1142eec",
|
||||
@ -100,41 +101,96 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecInverter",
|
||||
"displayName": "SunSpec Inverter",
|
||||
"name": "sunspecSinglePhaseInverter",
|
||||
"displayName": "SunSpec single phase inverter",
|
||||
"id": "c5d5204e-3375-4b92-8128-fab77a671fed",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "41715d00-a947-4f43-a475-cea05790e01d",
|
||||
"name":"mapId",
|
||||
"displayName": "Map id",
|
||||
"type": "int",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "26ae9050-7090-453a-85a3-307bfebe6fed",
|
||||
"name":"modbusAddress",
|
||||
"displayName": "Modbus address",
|
||||
"type": "uint",
|
||||
"readOnly": true,
|
||||
"defaultValue": 0
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
{
|
||||
"id": "48bf31c4-fda7-41e5-a3ef-3011bf96e104",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecSplitPhaseInverter",
|
||||
"displayName": "SunSpec split phase inverter",
|
||||
"id": "61b38f93-d331-42bf-b1ef-d3fb16ad1230",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "c42fb50e-210f-4b53-88eb-fa216e15f88f",
|
||||
"name":"mapId",
|
||||
"displayName": "Map id",
|
||||
"type": "int",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "37582a96-f2f2-4845-abef-973c7dd0ad57",
|
||||
"name":"modbusAddress",
|
||||
"displayName": "Modbus address",
|
||||
"type": "uint",
|
||||
"readOnly": true,
|
||||
"defaultValue": 0
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
{
|
||||
"id": "27b49640-f58b-466e-a225-a4663cf3ed96",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecThreePhaseInverter",
|
||||
"displayName": "SunSpec three phase inverter",
|
||||
"id": "2e4122ea-96a5-415c-b5e2-7d6012265a83",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "6ffaa694-a4f2-4936-b043-37679449a34b",
|
||||
"name":"ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString"
|
||||
"id": "8d5b2b58-ce46-406d-844e-f53136afcf09",
|
||||
"name":"mapId",
|
||||
"displayName": "Map id",
|
||||
"type": "int",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "418d90eb-16e9-47e4-83e3-a116a8fa4de7",
|
||||
"name":"manufacturer",
|
||||
"displayName": "Manufacturer",
|
||||
"type": "QString",
|
||||
"id": "e5465ede-9d3d-4558-b614-40dda743ddae",
|
||||
"name":"modbusAddress",
|
||||
"displayName": "Modbus address",
|
||||
"type": "uint",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "edf1bc0f-d143-4b75-a11f-635339fb30bf",
|
||||
"name":"deviceModel",
|
||||
"displayName": "Device model",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "d5181377-c746-4352-8683-6d90a4a83e6e",
|
||||
"name":"serialNumber",
|
||||
"displayName": "Serial number",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
"defaultValue": 0
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
@ -162,54 +218,54 @@
|
||||
"name": "totalCurrent",
|
||||
"displayName": "Total AC current",
|
||||
"displayNameEvent": "Total AC current changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "3140ccd3-40cf-46c8-8bb2-8c3ea4582f84",
|
||||
"name": "phaseACurrent",
|
||||
"displayName": "Phase A current",
|
||||
"displayNameEvent": "Phase A current changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "7ea1a53a-6fd9-4914-8283-b57aa1aaaebf",
|
||||
"name": "phaseBCurrent",
|
||||
"displayName": "Phase B current",
|
||||
"displayNameEvent": "Phase B current changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "aa4b4cf5-43d0-4be5-9505-403918b5371d",
|
||||
"name": "phaseCCurrent",
|
||||
"displayName": "Phase C current",
|
||||
"displayNameEvent": "Phase C current changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "f08521aa-9c38-4c31-95e1-acb616f6e9c6",
|
||||
"name": "phaseANVoltage",
|
||||
"displayName": "Phase AN voltage",
|
||||
"displayNameEvent": "Phase AN volatage changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Volt",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "739b8805-d522-4406-bede-d1e4200a3aa9",
|
||||
"name": "phaseBNVoltage",
|
||||
"displayName": "Phase BN voltage",
|
||||
"displayNameEvent": "Phase BN voltage changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Volt",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "949b797d-5566-4667-8982-e430d23548e2",
|
||||
@ -225,36 +281,36 @@
|
||||
"name": "acPower",
|
||||
"displayName": "AC power",
|
||||
"displayNameEvent": "AC power changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "KiloWatt",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "faa45cae-ed28-4150-9036-fceddf9d6776",
|
||||
"name": "lineFrequency",
|
||||
"displayName": "Line frequency",
|
||||
"displayNameEvent": "Line frequency changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Hertz",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "d493880d-eb58-4530-8010-8ea4f6d63387",
|
||||
"name": "acEnergy",
|
||||
"displayName": "AC energy",
|
||||
"displayNameEvent": "AC energy changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "44b0320f-89a7-4248-bad4-288ef898a5cc",
|
||||
"name": "cabinetTemperature",
|
||||
"displayName": "Cabinet temperature",
|
||||
"displayNameEvent": "Cabinet temperature changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "DegreeCelsius",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "cebdce98-42d1-4a28-8834-8960efc0e83f",
|
||||
@ -304,41 +360,99 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecMeter",
|
||||
"displayName": "SunSpec Meter",
|
||||
"name": "sunspecSinglePhaseMeter",
|
||||
"displayName": "SunSpec single phase meter",
|
||||
"id": "7ffa43b8-b56f-4435-8509-980e9d81dfa8",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "7d6fcafb-c62e-4a21-aae2-f4041c487149",
|
||||
"name":"mapId",
|
||||
"displayName": "Map id",
|
||||
"type": "int",
|
||||
"readOnly": true,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "30b90ec0-429b-4e6c-88e9-155aa4bcad47",
|
||||
"name":"modbusAddress",
|
||||
"displayName": "Modbus address",
|
||||
"type": "uint",
|
||||
"readOnly": true,
|
||||
"defaultValue": 0
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
{
|
||||
"id": "d960e7b1-d4aa-4cab-8f54-6bcfdbb8be36",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecSplitPhaseMeter",
|
||||
"displayName": "SunSpec split phase meter",
|
||||
"id": "b8a18e45-5ff5-4f43-915f-04ee216c809d",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "89aeec6d-abeb-48b5-9594-214ad5db2d03",
|
||||
"name":"mapId",
|
||||
"displayName": "Map id",
|
||||
"type": "int",
|
||||
"readOnly": true,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "a56f198d-ed86-429f-b839-8e11a32da8c1",
|
||||
"name":"modbusAddress",
|
||||
"displayName": "Modbus address",
|
||||
"type": "uint",
|
||||
"readOnly": true,
|
||||
"defaultValue": 0
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
{
|
||||
"id": "34e34ec9-dab0-438c-9493-a3068bc401de",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecThreePhaseMeter",
|
||||
"displayName": "SunSpec three phase meter",
|
||||
"id": "68f822f9-ff30-4275-b229-39a3674fead7",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "66bdb89b-bbd4-4edf-96df-649014d94c42",
|
||||
"name":"ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString"
|
||||
"id": "a1960821-155c-4176-86fa-974429039182",
|
||||
"name":"mapId",
|
||||
"displayName": "Map id",
|
||||
"type": "int",
|
||||
"readOnly": true,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "aa1ca51d-5e9c-4a1a-a4ec-e479d4f702d5",
|
||||
"name":"manufacturer",
|
||||
"displayName": "Manufacturer",
|
||||
"type": "QString",
|
||||
"id": "6d5dbd35-1bf6-46db-bee9-90c679421b89",
|
||||
"name":"modbusAddress",
|
||||
"displayName": "Modbus address",
|
||||
"type": "uint",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "52da5388-28d7-48a2-8ad6-4c1e852a4348",
|
||||
"name":"deviceModel",
|
||||
"displayName": "Device model",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "9fa7288c-e7a1-4163-baa1-6f484e1feb55",
|
||||
"name":"serialNumber",
|
||||
"displayName": "Serial number",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
"defaultValue": 0
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
@ -442,8 +556,7 @@
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "73ebf57f-1ad2-4d19-bfd9-9e0a514c1243
|
||||
",
|
||||
"id": "73ebf57f-1ad2-4d19-bfd9-9e0a514c1243",
|
||||
"name": "energyExported",
|
||||
"displayName": "Total real energy exported",
|
||||
"displayNameEvent": "Total real energy exported changed",
|
||||
@ -462,66 +575,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecTracker",
|
||||
"displayName": "SunSpec Tracker",
|
||||
"id": "9941da30-a6d6-475d-8244-3c2145b419e6",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "ccdcca78-7efa-4253-8fdb-8731e6880e9b",
|
||||
"name":"ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString"
|
||||
},
|
||||
{
|
||||
"id": "2795052c-5d63-423d-b44e-fdf02dfaac37",
|
||||
"name":"manufacturer",
|
||||
"displayName": "Manufacturer",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "7528c840-da8c-40ba-ab82-914cfc686a49",
|
||||
"name":"deviceModel",
|
||||
"displayName": "Device model",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "ce9cc598-947c-4efc-b04f-21e784c5d2df",
|
||||
"name":"serialNumber",
|
||||
"displayName": "Serial number",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
{
|
||||
"id": "fe57e465-e49e-4d50-b880-6d9a243783ff",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "d2bbba4b-998f-444e-935f-f958927afddd",
|
||||
"name": "power",
|
||||
"displayName": "Power",
|
||||
"displayNameEvent": "Power changed",
|
||||
"displayNameAction": "Change power",
|
||||
"type": "bool",
|
||||
"defaultValue": 0,
|
||||
"writable": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecStorage",
|
||||
"displayName": "SunSpec Storage",
|
||||
@ -530,34 +583,20 @@
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "421cacb9-a94d-4ba9-923c-3bc30d8b94c8",
|
||||
"name":"ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString"
|
||||
"id": "219beb96-b9fe-4dd2-a386-ecfbbab8786d",
|
||||
"name":"mapId",
|
||||
"displayName": "Map id",
|
||||
"type": "int",
|
||||
"readOnly": true,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "1d8f1ef7-33ad-40ed-99dd-ec54f87c2f17",
|
||||
"name":"manufacturer",
|
||||
"displayName": "Manufacturer",
|
||||
"type": "QString",
|
||||
"id": "3f107844-00c5-4f39-86e5-485b3d1f5c1a",
|
||||
"name":"modbusAddress",
|
||||
"displayName": "Modbus address",
|
||||
"type": "uint",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "2a7f8464-6f03-4113-ac1d-d8ebd8705695",
|
||||
"name":"deviceModel",
|
||||
"displayName": "Device model",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "2003acdb-38ad-4184-baf8-9ef8e67fc452",
|
||||
"name":"serialNumber",
|
||||
"displayName": "Serial number",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
"defaultValue": 0
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
@ -663,56 +702,6 @@
|
||||
"displayNameAction": "Set discharging rate"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunspecStringCombiner",
|
||||
"displayName": "SunSpec String Combiner",
|
||||
"id": "7787f238-f5a3-4ba5-b3ec-7d513b87bf71",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "226697c3-37bd-49c7-8c0e-40537573c18e",
|
||||
"name":"ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString"
|
||||
},
|
||||
{
|
||||
"id": "3f126e65-05e2-46a3-aeeb-bfacc0bdd9b0",
|
||||
"name":"manufacturer",
|
||||
"displayName": "Manufacturer",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "40666030-3609-467f-b26c-3a42d1c6dca1",
|
||||
"name":"deviceModel",
|
||||
"displayName": "Device model",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
},
|
||||
{
|
||||
"id": "f5046138-9271-4a91-a3eb-c2ecfa755ef5",
|
||||
"name":"serialNumber",
|
||||
"displayName": "Serial number",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": "Unkown"
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
{
|
||||
"id": "3f791612-50fd-4a3c-ac19-27e01dd8c63a",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@ SunSpec::SunSpec(const QHostAddress &hostAddress, uint port, QObject *parent) :
|
||||
m_hostAddress(hostAddress),
|
||||
m_port(port)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Creating SunSpec connection";
|
||||
m_modbusTcpClient = new QModbusTcpClient(this);
|
||||
m_modbusTcpClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, m_port);
|
||||
m_modbusTcpClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, m_hostAddress.toString());
|
||||
@ -48,16 +49,19 @@ SunSpec::SunSpec(const QHostAddress &hostAddress, uint port, QObject *parent) :
|
||||
|
||||
SunSpec::~SunSpec()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Deleting SunSpec connection";
|
||||
}
|
||||
|
||||
bool SunSpec::connectModbus()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Connect modbus";
|
||||
return m_modbusTcpClient->connectDevice();
|
||||
}
|
||||
|
||||
void SunSpec::setHostAddress(const QHostAddress &hostAddress)
|
||||
{
|
||||
if (m_hostAddress != hostAddress) {
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Set host address" << hostAddress.toString();
|
||||
m_hostAddress = hostAddress;
|
||||
m_modbusTcpClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, m_hostAddress.toString());
|
||||
}
|
||||
@ -65,25 +69,46 @@ void SunSpec::setHostAddress(const QHostAddress &hostAddress)
|
||||
|
||||
void SunSpec::setPort(uint port)
|
||||
{
|
||||
m_port = port;
|
||||
m_modbusTcpClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
|
||||
if (port != m_port) {
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Set Port" << port;
|
||||
m_port = port;
|
||||
m_modbusTcpClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
|
||||
}
|
||||
}
|
||||
|
||||
void SunSpec::setSlaveId(uint slaveId)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Set slave id" << slaveId;
|
||||
m_slaveId = slaveId;
|
||||
}
|
||||
|
||||
void SunSpec::setTimeout(uint milliSeconds)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Set timeout" << milliSeconds << "[ms]";
|
||||
m_modbusTcpClient->setTimeout(milliSeconds);
|
||||
}
|
||||
|
||||
void SunSpec::setNumberOfRetries(uint retries)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Set number of retries" << retries;
|
||||
m_modbusTcpClient->setNumberOfRetries(retries);
|
||||
}
|
||||
|
||||
QHostAddress SunSpec::hostAddress() const
|
||||
{
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
uint SunSpec::port()
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
uint SunSpec::slaveId()
|
||||
{
|
||||
return m_slaveId;
|
||||
}
|
||||
|
||||
QString SunSpec::manufacturer()
|
||||
{
|
||||
return m_manufacturer;
|
||||
@ -101,49 +126,45 @@ QString SunSpec::serialNumber()
|
||||
|
||||
void SunSpec::findBaseRegister()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "Find base register";
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Find base register";
|
||||
QList<int> validBaseRegisters;
|
||||
validBaseRegisters.append(0);
|
||||
validBaseRegisters.append(40000);
|
||||
validBaseRegisters.append(50000);
|
||||
|
||||
Q_FOREACH (int baseRegister, validBaseRegisters) {
|
||||
qCDebug(dcSunSpec()) << " - Searching address" << baseRegister;
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, baseRegister, 2);
|
||||
if (QModbusReply *reply = m_modbusTcpClient->sendReadRequest(request, m_slaveId)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, this, [reply, this] {
|
||||
connect(reply, &QModbusReply::finished, this, [reply, baseRegister, this] {
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
uint modbusAddress = unit.startAddress();
|
||||
if ((unit.value(0) << 16 | unit.value(1)) == 0x53756e53) {
|
||||
//Well-known value. Uniquely identifies this as a SunSpec Modbus Map
|
||||
qCDebug(dcSunSpec()) << "Found start of modbus map" << modbusAddress;
|
||||
m_baseRegister = modbusAddress;
|
||||
emit foundBaseRegister(modbusAddress);
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Found start of modbus map" << baseRegister;
|
||||
m_baseRegister = baseRegister;
|
||||
emit foundBaseRegister(baseRegister);
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Got reply on base register, but value didn't mach 0x53756e53";
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Got reply on base register" << baseRegister << ", but value didn't mach 0x53756e53";
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Find base register read response error:" << reply->error();
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Find base register not found at:" << baseRegister;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Find base register eead error: " << m_modbusTcpClient->errorString();
|
||||
delete reply; // broadcast replies return immediately
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Find base register read error: " << m_modbusTcpClient->errorString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SunSpec::findModbusMap(const QList<BlockId> &ids, uint modbusAddressOffset)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "Find modbus map. Start register" << m_baseRegister+modbusAddressOffset;
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Find modbus map. Start register" << m_baseRegister+modbusAddressOffset;
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_baseRegister+modbusAddressOffset, 2);
|
||||
|
||||
if (QModbusReply *reply = m_modbusTcpClient->sendReadRequest(request, m_slaveId)) {
|
||||
@ -156,41 +177,37 @@ void SunSpec::findModbusMap(const QList<BlockId> &ids, uint modbusAddressOffset)
|
||||
uint modbusAddress = unit.startAddress();
|
||||
BlockId blockId = BlockId(unit.value(0));
|
||||
int blockLength = unit.value(1);
|
||||
if (blockId > 800 || blockId == BlockIdEnd) {
|
||||
qCDebug(dcSunSpec()) << "Block id not found, Id:" << ids;
|
||||
modbusMapSearchFinished(ids, 0, "Ids not found");
|
||||
if (blockId == BlockIdEnd) {
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Block Id End";
|
||||
modbusMapSearchFinished(m_mapList);
|
||||
return;
|
||||
}
|
||||
if (ids.contains(blockId)) {
|
||||
qCDebug(dcSunSpec()) << "Found block" << BlockId(blockId);
|
||||
|
||||
if (ids.isEmpty() || ids.contains(blockId)) {
|
||||
// If ids is empty then emit all blocks
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Found block" << BlockId(blockId) << "with block length" << blockLength;
|
||||
m_mapList.insert(BlockId(blockId), modbusAddress);
|
||||
foundModbusMap(BlockId(blockId), modbusAddress);
|
||||
} else {
|
||||
//read next block header
|
||||
qCDebug(dcSunSpec()) << "Found Block" << blockId << "with block length" << blockLength;
|
||||
findModbusMap(ids, modbusAddress+2+blockLength-m_baseRegister); //read next block
|
||||
}
|
||||
findModbusMap(ids, modbusAddress+2+blockLength-m_baseRegister); //read next block
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Read response error:" << reply->error();
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Find modbus map, read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error) {
|
||||
qCWarning(dcSunSpec()) << "Modbus replay error:" << error;
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
} else {
|
||||
delete reply; // broadcast replies return immediately
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Read error: " << m_modbusTcpClient->errorString();
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read error: " << m_modbusTcpClient->errorString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SunSpec::readMapHeader(uint modbusAddress)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "Read block header. Modbus Address:" << modbusAddress << "Slave ID" << m_slaveId;
|
||||
if (modbusAddress == 40000)
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Read map header, modbus address:" << modbusAddress << "Slave ID" << m_slaveId;
|
||||
if (modbusAddress == 0 || modbusAddress == 40000 || modbusAddress == 50000)
|
||||
modbusAddress += 2;
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, modbusAddress, 2);
|
||||
@ -228,7 +245,7 @@ void SunSpec::readMapHeader(uint modbusAddress)
|
||||
|
||||
void SunSpec::readMap(uint modbusAddress, uint modelLength)
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "Read map. Modbus Address" << modbusAddress << ", Slave ID" << m_slaveId;
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Read map, modbus address" << modbusAddress << "model length" << modelLength << ", Slave ID" << m_slaveId;
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, modbusAddress, modelLength+2);
|
||||
|
||||
@ -265,18 +282,7 @@ void SunSpec::readMap(uint modbusAddress, uint modelLength)
|
||||
|
||||
void SunSpec::readCommonMap()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "Read common block";
|
||||
|
||||
// Base and Alternate Base Register Addresses
|
||||
// DeviceModbus maps begin at one of three well-known Modbus base addresses.
|
||||
// Preferred Base Register: 40000
|
||||
// Alternate Base Register: 50000
|
||||
// Alternate Base Register: 00000
|
||||
|
||||
// Common Model model-length is 66
|
||||
// First two registers are the SunSpec Modbus Map identifier
|
||||
|
||||
qCDebug(dcSunSpec()) << "Read common block header. Modbus Address" << m_baseRegister+2 << ", Slave ID" << m_slaveId;
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Read common block header. Modbus Address" << m_baseRegister+2 << ", Slave ID" << m_slaveId;
|
||||
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_baseRegister+2, 66);
|
||||
|
||||
@ -287,27 +293,23 @@ void SunSpec::readCommonMap()
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
uint modbusAddress = unit.startAddress();
|
||||
BlockId mapId = BlockId(unit.value(0));
|
||||
int mapLength = unit.value(1);
|
||||
//uint modbusAddress = unit.startAddress();
|
||||
//BlockId mapId = BlockId(unit.value(0));
|
||||
//int mapLength = unit.value(1);
|
||||
m_manufacturer = convertModbusRegisters(unit.values(), MandatoryRegistersModel1::Manufacturer, 16);
|
||||
m_manufacturer.remove('\x00');
|
||||
m_deviceModel = convertModbusRegisters(unit.values(), MandatoryRegistersModel1::Model, 16);
|
||||
m_deviceModel.remove('\x00');
|
||||
m_serialNumber = convertModbusRegisters(unit.values(), MandatoryRegistersModel1::SerialNumber, 16);
|
||||
m_serialNumber.remove('\x00');
|
||||
qCDebug(dcSunSpec()) << "Received common block response. Manufacturer" << m_manufacturer << "Model" << m_deviceModel << "Serial number" << m_serialNumber;
|
||||
mapHeaderReceived(modbusAddress, mapId, mapLength);
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Received common block response. Manufacturer" << m_manufacturer << "Model" << m_deviceModel << "Serial number" << m_serialNumber;
|
||||
commonMapReceived(m_manufacturer, m_deviceModel, m_serialNumber);
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Read response error:" << reply->error();
|
||||
qCWarning(dcSunSpec()) << "SunSpec: Read common map, read response error:" << reply->error();
|
||||
}
|
||||
});
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error) {
|
||||
qCWarning(dcSunSpec()) << "Modbus reply error:" << error;
|
||||
reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
} else {
|
||||
qCWarning(dcSunSpec()) << "Read error: " << m_modbusTcpClient->errorString();
|
||||
qCWarning(dcSunSpec()) << "Sunspec: Read common map read error: " << m_modbusTcpClient->errorString();
|
||||
delete reply; // broadcast replies return immediately
|
||||
return;
|
||||
}
|
||||
@ -390,7 +392,7 @@ QByteArray SunSpec::convertModbusRegisters(const QVector<quint16> &modbusData, i
|
||||
float SunSpec::convertValueWithSSF(quint16 rawValue, quint16 sunssf)
|
||||
{
|
||||
float value;
|
||||
value = rawValue * (10^static_cast<qint16>(sunssf));
|
||||
value = rawValue * pow(10, static_cast<qint16>(sunssf));
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -404,26 +406,24 @@ float SunSpec::convertFloatValues(quint16 rawValue0, quint16 rawValue1)
|
||||
|
||||
void SunSpec::onModbusStateChanged(QModbusDevice::State state)
|
||||
{
|
||||
bool connected = (state != QModbusDevice::UnconnectedState);
|
||||
bool connected = (state == QModbusDevice::ConnectedState);
|
||||
if (!connected) {
|
||||
//try to reconnect in 10 seconds
|
||||
QTimer::singleShot(10000, m_modbusTcpClient, [this] {
|
||||
if (m_modbusTcpClient->connectDevice()) {
|
||||
qCDebug(dcSunSpec()) << "Could not reconnect";
|
||||
qCDebug(dcSunSpec()) << "SunSpec: Could not reconnect";
|
||||
}
|
||||
});
|
||||
} else {
|
||||
readCommonMap();
|
||||
}
|
||||
emit connectionStateChanged(connected);
|
||||
}
|
||||
|
||||
QUuid SunSpec::writeHoldingRegister(uint slaveAddress, uint registerAddress, quint16 value)
|
||||
QUuid SunSpec::writeHoldingRegister(uint registerAddress, quint16 value)
|
||||
{
|
||||
return writeHoldingRegisters(slaveAddress, registerAddress, QVector<quint16>() << value);
|
||||
return writeHoldingRegisters(registerAddress, QVector<quint16>() << value);
|
||||
}
|
||||
|
||||
QUuid SunSpec::writeHoldingRegisters(uint slaveAddress, uint registerAddress, const QVector<quint16> &values)
|
||||
QUuid SunSpec::writeHoldingRegisters(uint registerAddress, const QVector<quint16> &values)
|
||||
{
|
||||
if (!m_modbusTcpClient) {
|
||||
return "";
|
||||
@ -432,7 +432,7 @@ QUuid SunSpec::writeHoldingRegisters(uint slaveAddress, uint registerAddress, co
|
||||
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, registerAddress, values.length());
|
||||
request.setValues(values);
|
||||
|
||||
if (QModbusReply *reply = m_modbusTcpClient->sendWriteRequest(request, slaveAddress)) {
|
||||
if (QModbusReply *reply = m_modbusTcpClient->sendWriteRequest(request, m_slaveId)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, this, [reply, requestId, this] {
|
||||
|
||||
@ -178,6 +178,9 @@ public:
|
||||
void setTimeout(uint milliSeconds);
|
||||
void setNumberOfRetries(uint retries);
|
||||
|
||||
QHostAddress hostAddress() const;
|
||||
uint port();
|
||||
uint slaveId();
|
||||
QString manufacturer();
|
||||
QString deviceModel();
|
||||
QString serialNumber();
|
||||
@ -191,13 +194,14 @@ public:
|
||||
QString m_manufacturer = "Unknown";
|
||||
QString m_deviceModel = "Unknown";
|
||||
QString m_serialNumber = "Unknown";
|
||||
QHash<BlockId, int> m_mapList;
|
||||
|
||||
void findBaseRegister();
|
||||
void findModbusMap(const QList<BlockId> &mapIds, uint modbusAddressOffset = 69);
|
||||
void findModbusMap(const QList<BlockId> &mapIds, uint modbusAddressOffset = 2);
|
||||
|
||||
void readCommonMap();
|
||||
void readMapHeader(uint modbusAddress);
|
||||
void readMap(uint modbusAddress, uint modelLength); //modbusAddress = model start address, model length is without header
|
||||
void readCommonMap();
|
||||
|
||||
float convertValueWithSSF(quint16 rawValue, quint16 sunssf);
|
||||
float convertFloatValues(quint16 rawValue0, quint16 rawValue1);
|
||||
@ -205,16 +209,18 @@ public:
|
||||
QBitArray convertModbusRegisterBits(const uint16_t &modbusData);
|
||||
QByteArray convertModbusRegisters(const QVector<quint16> &modbusData, int offset, int size);
|
||||
|
||||
QUuid writeHoldingRegister(uint slaveAddress, uint registerAddress, quint16 value);
|
||||
QUuid writeHoldingRegisters(uint slaveAddress, uint registerAddress, const QVector<quint16> &values);
|
||||
QUuid writeHoldingRegister(uint registerAddress, quint16 value);
|
||||
QUuid writeHoldingRegisters(uint registerAddress, const QVector<quint16> &values);
|
||||
|
||||
signals:
|
||||
void connectionStateChanged(bool status);
|
||||
void requestExecuted(QUuid requetId, bool success);
|
||||
|
||||
void foundBaseRegister(int modbusAddress);
|
||||
void commonMapReceived(const QString &manufacturer, const QString &deviceModel, const QString &serialNumber);
|
||||
|
||||
void foundModbusMap(BlockId mapId, int modbusStartRegister);
|
||||
void modbusMapSearchFinished(const QList<BlockId> &mapIds, uint modbusStartRegister, const QString &error);
|
||||
void modbusMapSearchFinished(const QHash<BlockId, int> &mapIds);
|
||||
|
||||
void mapHeaderReceived(uint modbusAddress, BlockId mapId, uint mapLength);
|
||||
void mapReceived(BlockId mapId, uint mapLength, QVector<quint16> data);
|
||||
|
||||
@ -9,15 +9,11 @@ SOURCES += \
|
||||
sunspec.cpp \
|
||||
sunspecinverter.cpp \
|
||||
sunspecmeter.cpp \
|
||||
sunspecstorage.cpp \
|
||||
sunspectracker.cpp \
|
||||
sunspecstringcombiner.cpp \
|
||||
sunspecstorage.cpp
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginsunspec.h \
|
||||
sunspec.h \
|
||||
sunspecinverter.h \
|
||||
sunspecmeter.h \
|
||||
sunspecstorage.h \
|
||||
sunspectracker.h \
|
||||
sunspecstringcombiner.h \
|
||||
sunspecstorage.h
|
||||
|
||||
@ -31,95 +31,121 @@
|
||||
#include "sunspecinverter.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
SunSpecInverter::SunSpecInverter(const QHostAddress &hostAddress, uint port, QObject *parent) : SunSpec(hostAddress, port, parent)
|
||||
#include <QTimer>
|
||||
|
||||
SunSpecInverter::SunSpecInverter(SunSpec *sunspec, SunSpec::BlockId mapId, int modbusAddress) :
|
||||
QObject(sunspec),
|
||||
m_connection(sunspec),
|
||||
m_id(mapId),
|
||||
m_mapModbusStartRegister(modbusAddress)
|
||||
{
|
||||
connect(m_modbusTcpClient, &QModbusClient::stateChanged, this, [this] (QModbusDevice::State state) {
|
||||
if (state == QModbusDevice::ConnectedState) {
|
||||
qCDebug(dcSunSpec()) << "Inverter connected successfully";
|
||||
QList<BlockId> mapIds;
|
||||
mapIds.append(BlockIdInverterSinglePhase);
|
||||
mapIds.append(BlockIdInverterSplitPhase);
|
||||
mapIds.append(BlockIdInverterThreePhase);
|
||||
mapIds.append(BlockIdInverterSinglePhaseFloat);
|
||||
mapIds.append(BlockIdInverterSplitPhaseFloat);
|
||||
mapIds.append(BlockIdInverterThreePhaseFloat);
|
||||
findModbusMap(mapIds);
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Setting up inverter";
|
||||
connect(m_connection, &SunSpec::mapReceived, this, &SunSpecInverter::onModbusMapReceived);
|
||||
}
|
||||
|
||||
SunSpec::BlockId SunSpecInverter::blockId()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
void SunSpecInverter::init()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Init";
|
||||
m_connection->readMapHeader(m_mapModbusStartRegister);
|
||||
connect(m_connection, &SunSpec::mapHeaderReceived, this, [this] (uint modbusAddress, SunSpec::BlockId mapId, uint mapLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Map Header received, modbus address:" << modbusAddress << "map Id:" << mapId << "map length:" << mapLength;
|
||||
m_mapLength = mapLength;
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
});
|
||||
QTimer::singleShot(10000, this,[this] {
|
||||
if (!m_initFinishedSuccess) {
|
||||
emit initFinished(false);
|
||||
}
|
||||
});
|
||||
connect(this, &SunSpec::foundModbusMap, this, [this] (BlockId mapId, uint modbusRegisterAddress) {
|
||||
qCDebug(dcSunSpec()) << "Read map header for mapId" << mapId << "and modbus register" << modbusRegisterAddress;
|
||||
readMapHeader(modbusRegisterAddress);
|
||||
});
|
||||
|
||||
connect(this, &SunSpec::mapHeaderReceived, this, [this] (uint modbusAddress, BlockId mapId, uint mapLength) {
|
||||
m_id = mapId;
|
||||
m_mapLength = mapLength;
|
||||
m_mapModbusStartRegister = modbusAddress;
|
||||
readMap(modbusAddress, mapLength);
|
||||
});
|
||||
|
||||
connect(this, &SunSpec::mapReceived, this, &SunSpecInverter::onModbusMapReceived);
|
||||
}
|
||||
|
||||
void SunSpecInverter::getInverterMap()
|
||||
{
|
||||
readMap(m_mapModbusStartRegister, m_mapLength);
|
||||
// TODO check map length to modbus max value
|
||||
m_connection->readMap(m_mapModbusStartRegister, m_mapLength);
|
||||
}
|
||||
|
||||
void SunSpecInverter::readInverterBlockHeader()
|
||||
{
|
||||
readMapHeader(m_mapModbusStartRegister);
|
||||
m_connection->readMapHeader(m_mapModbusStartRegister);
|
||||
}
|
||||
|
||||
void SunSpecInverter::onModbusMapReceived(SunSpec::BlockId mapId, uint mapLength, QVector<quint16> data)
|
||||
{
|
||||
Q_UNUSED(mapLength)
|
||||
if (mapId != m_id) {
|
||||
return;
|
||||
}
|
||||
if (mapLength < m_mapLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: on modbus map received, map length ist too short" << mapLength;
|
||||
//return;
|
||||
}
|
||||
InverterData inverterData;
|
||||
|
||||
switch (mapId) {
|
||||
case BlockIdInverterSinglePhase:
|
||||
case BlockIdInverterSplitPhase:
|
||||
case BlockIdInverterThreePhase: {
|
||||
InverterData inverterData;
|
||||
inverterData.acCurrent= convertValueWithSSF(data[Model10X::Model10XAcCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.acPower = convertValueWithSSF(data[Model10X::Model10XACPower], data[Model10X::Model10XWattScaleFactor]);
|
||||
inverterData.lineFrequency = convertValueWithSSF(data[Model10X::Model10XLineFrequency], data[Model10X::Model10XHerzScaleFactor]);
|
||||
case SunSpec::BlockIdInverterSinglePhase:
|
||||
case SunSpec::BlockIdInverterSplitPhase:
|
||||
case SunSpec::BlockIdInverterThreePhase: {
|
||||
|
||||
inverterData.phaseACurrent = convertValueWithSSF(data[Model10X::Model10XPhaseACurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.phaseBCurrent = convertValueWithSSF(data[Model10X::Model10XPhaseBCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.phaseCCurrent = convertValueWithSSF(data[Model10X::Model10XPhaseCCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
qCDebug(dcSunSpec()) << "Inverter with SSF values:";
|
||||
qCDebug(dcSunSpec()) << " - AC Current:" << data[Model10X::Model10XAcCurrent];
|
||||
qCDebug(dcSunSpec()) << " - Phase A Current:" << data[Model10X::Model10XPhaseACurrent];
|
||||
qCDebug(dcSunSpec()) << " - Phase B Current:" << data[Model10X::Model10XPhaseBCurrent];
|
||||
qCDebug(dcSunSpec()) << " - Phase C Current:" << data[Model10X::Model10XPhaseCCurrent];
|
||||
qCDebug(dcSunSpec()) << " - Ampere scale factor:" << static_cast<qint16>(data[Model10X::Model10XAmpereScaleFactor]);
|
||||
|
||||
inverterData.phaseVoltageAN = convertValueWithSSF(data[Model10X::Model10XPhaseVoltageAN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
inverterData.phaseVoltageBN = convertValueWithSSF(data[Model10X::Model10XPhaseVoltageBN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
inverterData.phaseVoltageCN = convertValueWithSSF(data[Model10X::Model10XPhaseVoltageCN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
inverterData.acCurrent= m_connection->convertValueWithSSF(data[Model10X::Model10XAcCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.acPower = m_connection->convertValueWithSSF(data[Model10X::Model10XACPower], data[Model10X::Model10XWattScaleFactor]);
|
||||
inverterData.lineFrequency = m_connection->convertValueWithSSF(data[Model10X::Model10XLineFrequency], data[Model10X::Model10XHerzScaleFactor]);
|
||||
|
||||
inverterData.acEnergy = convertValueWithSSF(data[Model10X::Model10XAcEnergy], data[Model10X::Model10XWattHoursScaleFactor]);
|
||||
inverterData.phaseACurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseACurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.phaseBCurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseBCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
inverterData.phaseCCurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseCCurrent], data[Model10X::Model10XAmpereScaleFactor]);
|
||||
|
||||
inverterData.cabinetTemperature = convertValueWithSSF(data[Model10X::Model10XCabinetTemperature], data[Model10X::Model10XTemperatureScaleFactor]);
|
||||
inverterData.event = SunSpecEvent1(data[Model10X::Model10XEvent1]);
|
||||
inverterData.operatingState = SunSpecOperatingState(data[Model10X::Model10XOperatingState]);
|
||||
inverterData.phaseVoltageAN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageAN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
inverterData.phaseVoltageBN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageBN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
inverterData.phaseVoltageCN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageCN], data[Model10X::Model10XVoltageScaleFactor]);
|
||||
|
||||
qCDebug(dcSunSpec()) << "AC energy converting:";
|
||||
qCDebug(dcSunSpec()) << " - Origin" << data[Model10X::Model10XAcEnergy];
|
||||
qCDebug(dcSunSpec()) << " - SSF" << static_cast<qint16>(data[Model10X::Model10XWattHoursScaleFactor]);
|
||||
qCDebug(dcSunSpec()) << " - Converted "<< m_connection->convertValueWithSSF(data[Model10X::Model10XAcEnergy], data[Model10X::Model10XWattHoursScaleFactor]);
|
||||
inverterData.acEnergy = m_connection->convertValueWithSSF(data[Model10X::Model10XAcEnergy], data[Model10X::Model10XWattHoursScaleFactor]);
|
||||
|
||||
inverterData.cabinetTemperature = m_connection->convertValueWithSSF(data[Model10X::Model10XCabinetTemperature], data[Model10X::Model10XTemperatureScaleFactor]);
|
||||
inverterData.event = SunSpec::SunSpecEvent1(data[Model10X::Model10XEvent1]);
|
||||
inverterData.operatingState = SunSpec::SunSpecOperatingState(data[Model10X::Model10XOperatingState]);
|
||||
emit inverterDataReceived(inverterData);
|
||||
|
||||
} break;
|
||||
case BlockIdInverterSinglePhaseFloat:
|
||||
case BlockIdInverterSplitPhaseFloat:
|
||||
case BlockIdInverterThreePhaseFloat: {
|
||||
InverterData inverterData;
|
||||
inverterData.acCurrent = convertFloatValues(data[Model11X::Model11XAcCurrent], data[Model11X::Model11XAcCurrent+1]);
|
||||
case SunSpec::BlockIdInverterThreePhaseFloat:
|
||||
case SunSpec::BlockIdInverterSplitPhaseFloat:
|
||||
case SunSpec::BlockIdInverterSinglePhaseFloat: {
|
||||
|
||||
inverterData.phaseACurrent = convertFloatValues(data[Model11X::Model11XPhaseACurrent], data[Model11X::Model11XPhaseACurrent+1]);
|
||||
inverterData.phaseBCurrent = convertFloatValues(data[Model11X::Model11XPhaseBCurrent], data[Model11X::Model11XPhaseBCurrent+1]);
|
||||
inverterData.phaseCCurrent = convertFloatValues(data[Model11X::Model11XPhaseCCurrent], data[Model11X::Model11XPhaseCCurrent+1]);
|
||||
inverterData.acCurrent = m_connection->convertFloatValues(data[Model11X::Model11XAcCurrent], data[Model11X::Model11XAcCurrent+1]);
|
||||
|
||||
inverterData.phaseVoltageAN = convertFloatValues(data[Model11X::Model11XPhaseVoltageAN], data[Model11X::Model11XPhaseVoltageAN+1]);
|
||||
inverterData.phaseVoltageBN = convertFloatValues(data[Model11X::Model11XPhaseVoltageBN], data[Model11X::Model11XPhaseVoltageBN+1]);
|
||||
inverterData.phaseVoltageCN = convertFloatValues(data[Model11X::Model11XPhaseVoltageCN], data[Model11X::Model11XPhaseVoltageCN+1]);
|
||||
inverterData.phaseCCurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseCCurrent], data[Model11X::Model11XPhaseCCurrent+1]);
|
||||
inverterData.phaseVoltageCN = m_connection->convertFloatValues(data[Model11X::Model11XPhaseVoltageCN], data[Model11X::Model11XPhaseVoltageCN+1]);
|
||||
|
||||
inverterData.acPower = convertFloatValues(data[Model11X::Model11XACPower], data[Model11X::Model11XACPower+1]);
|
||||
inverterData.lineFrequency = convertFloatValues(data[Model11X::Model11XLineFrequency], data[Model11X::Model11XLineFrequency+1]);
|
||||
inverterData.phaseBCurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseBCurrent], data[Model11X::Model11XPhaseBCurrent+1]);
|
||||
inverterData.phaseVoltageBN = m_connection->convertFloatValues(data[Model11X::Model11XPhaseVoltageBN], data[Model11X::Model11XPhaseVoltageBN+1]);
|
||||
|
||||
inverterData.acEnergy = convertFloatValues(data[Model11X::Model11XAcEnergy], data[Model11X::Model11XAcEnergy+1]);
|
||||
inverterData.cabinetTemperature = convertFloatValues(data[Model11X::Model11XCabinetTemperature], data[Model11X::Model11XCabinetTemperature+1]);
|
||||
inverterData.event = SunSpecEvent1(data[Model11X::Model11XEvent1]);
|
||||
inverterData.operatingState = SunSpecOperatingState(data[Model11X::Model11XOperatingState]);
|
||||
inverterData.phaseACurrent = m_connection->convertFloatValues(data[Model11X::Model11XPhaseACurrent], data[Model11X::Model11XPhaseACurrent+1]);
|
||||
inverterData.phaseVoltageAN = m_connection->convertFloatValues(data[Model11X::Model11XPhaseVoltageAN], data[Model11X::Model11XPhaseVoltageAN+1]);
|
||||
|
||||
inverterData.acPower = m_connection->convertFloatValues(data[Model11X::Model11XACPower], data[Model11X::Model11XACPower+1]);
|
||||
inverterData.lineFrequency = m_connection->convertFloatValues(data[Model11X::Model11XLineFrequency], data[Model11X::Model11XLineFrequency+1]);
|
||||
|
||||
inverterData.acEnergy = m_connection->convertFloatValues(data[Model11X::Model11XAcEnergy], data[Model11X::Model11XAcEnergy+1]);
|
||||
inverterData.cabinetTemperature =m_connection->convertFloatValues(data[Model11X::Model11XCabinetTemperature], data[Model11X::Model11XCabinetTemperature+1]);
|
||||
inverterData.event = SunSpec::SunSpecEvent1(data[Model11X::Model11XEvent1]);
|
||||
inverterData.operatingState = SunSpec::SunSpecOperatingState(data[Model11X::Model11XOperatingState]);
|
||||
emit inverterDataReceived(inverterData);
|
||||
} break;
|
||||
default:
|
||||
|
||||
@ -34,32 +34,31 @@
|
||||
#include <QObject>
|
||||
#include "sunspec.h"
|
||||
|
||||
class SunSpecInverter : public SunSpec
|
||||
class SunSpecInverter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SunSpecInverter(const QHostAddress &hostAddress, uint port = 502, QObject *parent = 0);
|
||||
|
||||
enum Model10X { // Mandatory register
|
||||
Model10XAcCurrent = 2,
|
||||
Model10XPhaseACurrent = 3,
|
||||
Model10XPhaseBCurrent = 4,
|
||||
Model10XPhaseCCurrent = 5,
|
||||
Model10XAmpereScaleFactor = 6,
|
||||
Model10XPhaseVoltageAN = 10,
|
||||
Model10XPhaseVoltageBN = 11,
|
||||
Model10XPhaseVoltageCN = 12,
|
||||
Model10XVoltageScaleFactor = 13,
|
||||
Model10XACPower = 14,
|
||||
Model10XWattScaleFactor = 15,
|
||||
Model10XLineFrequency = 16,
|
||||
Model10XHerzScaleFactor = 17,
|
||||
Model10XAcEnergy = 24,
|
||||
Model10XWattHoursScaleFactor = 25,
|
||||
Model10XCabinetTemperature = 33,
|
||||
Model10XTemperatureScaleFactor = 37,
|
||||
Model10XOperatingState = 38,
|
||||
Model10XEvent1 = 40
|
||||
Model10XAcCurrent = 0,
|
||||
Model10XPhaseACurrent = 1,
|
||||
Model10XPhaseBCurrent = 2,
|
||||
Model10XPhaseCCurrent = 3,
|
||||
Model10XAmpereScaleFactor = 4,
|
||||
Model10XPhaseVoltageAN = 8,
|
||||
Model10XPhaseVoltageBN = 9,
|
||||
Model10XPhaseVoltageCN = 10,
|
||||
Model10XVoltageScaleFactor = 11,
|
||||
Model10XACPower = 12,
|
||||
Model10XWattScaleFactor = 13,
|
||||
Model10XLineFrequency = 14,
|
||||
Model10XHerzScaleFactor = 15,
|
||||
Model10XAcEnergy = 22,
|
||||
Model10XWattHoursScaleFactor = 24,
|
||||
Model10XCabinetTemperature = 31,
|
||||
Model10XTemperatureScaleFactor = 35,
|
||||
Model10XOperatingState = 36,
|
||||
Model10XEvent1 = 38
|
||||
};
|
||||
|
||||
enum Model11X { // Mandatory register
|
||||
@ -93,24 +92,29 @@ public:
|
||||
float lineFrequency;
|
||||
float acEnergy;
|
||||
float cabinetTemperature; // in degree Celsius
|
||||
SunSpecEvent1 event;
|
||||
SunSpecOperatingState operatingState;
|
||||
SunSpec::SunSpecEvent1 event;
|
||||
SunSpec::SunSpecOperatingState operatingState;
|
||||
};
|
||||
|
||||
SunSpecInverter(SunSpec *sunspec, SunSpec::BlockId blockId, int modbusAddress);
|
||||
SunSpec::BlockId blockId();
|
||||
void init();
|
||||
void getInverterMap();
|
||||
|
||||
private:
|
||||
BlockId m_id = BlockIdInverterThreePhase; //e.g. 103 for three phase inverter, 113 for three phase inverter with floating point representation
|
||||
SunSpec *m_connection = nullptr;
|
||||
SunSpec::BlockId m_id; //e.g. 103 for three phase inverter, 113 for three phase inverter with floating point representation
|
||||
uint m_mapLength = 0;
|
||||
uint m_mapModbusStartRegister = 40000;
|
||||
bool m_initFinishedSuccess = false;
|
||||
|
||||
void readInverterBlockHeader();
|
||||
|
||||
private slots:
|
||||
void onModbusMapReceived(BlockId mapId, uint mapLength, QVector<quint16> data);
|
||||
void onModbusMapReceived(SunSpec::BlockId mapId, uint mapLength, QVector<quint16> data);
|
||||
|
||||
signals:
|
||||
void initFinished();
|
||||
void initFinished(bool success);
|
||||
void inverterDataReceived(InverterData data);
|
||||
};
|
||||
|
||||
|
||||
@ -31,31 +31,54 @@
|
||||
#include "sunspecmeter.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
SunSpecMeter::SunSpecMeter(const QHostAddress &hostAddress, uint port, QObject *parent) : SunSpec(hostAddress, port, parent)
|
||||
SunSpecMeter::SunSpecMeter(SunSpec *sunspec, SunSpec::BlockId blockId, int modbusAddress) :
|
||||
QObject(sunspec),
|
||||
m_connection(sunspec),
|
||||
m_id(blockId),
|
||||
m_mapModbusStartRegister(modbusAddress)
|
||||
{
|
||||
connect(m_modbusTcpClient, &QModbusClient::stateChanged, this, [this] (QModbusDevice::State state) {
|
||||
if (state == QModbusDevice::ConnectedState) {
|
||||
qCDebug(dcSunSpec()) << "Meter connected successfully";
|
||||
QList<BlockId> mapIds;
|
||||
mapIds.append(BlockIdSinglePhaseMeter);
|
||||
mapIds.append(BlockIdSplitSinglePhaseMeter);
|
||||
mapIds.append(BlockIdWyeConnectThreePhaseMeter);
|
||||
mapIds.append(BlockIdDeltaConnectThreePhaseMeter);
|
||||
mapIds.append(BlockIdSinglePhaseMeterFloat);
|
||||
mapIds.append(BlockIdSplitSinglePhaseMeterFloat);
|
||||
mapIds.append(BlockIdWyeConnectThreePhaseMeterFloat);
|
||||
mapIds.append(BlockIdDeltaConnectThreePhaseMeterFloat);
|
||||
findModbusMap(mapIds);
|
||||
}
|
||||
qCDebug(dcSunSpec()) << "SunSpecMeter: Setting up meter";
|
||||
connect(m_connection, &SunSpec::mapReceived, this, &SunSpecMeter::onModbusMapReceived);
|
||||
}
|
||||
|
||||
SunSpec::BlockId SunSpecMeter::blockId()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
void SunSpecMeter::init()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Init";
|
||||
m_connection->readMapHeader(m_mapModbusStartRegister);
|
||||
connect(m_connection, &SunSpec::mapHeaderReceived, this, [this] (uint modbusAddress, SunSpec::BlockId mapId, uint mapLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Map Header received, modbus address:" << modbusAddress << "map Id:" << mapId << "map length:" << mapLength;
|
||||
m_mapLength = mapLength;
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
});
|
||||
QTimer::singleShot(10000, this,[this] {
|
||||
if (!m_initFinishedSuccess) {
|
||||
emit initFinished(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SunSpecMeter::geMeterMap()
|
||||
void SunSpecMeter::getMeterMap()
|
||||
{
|
||||
readMap(m_mapModbusStartRegister, m_mapLength);
|
||||
m_connection->readMap(m_mapModbusStartRegister, m_mapLength);
|
||||
}
|
||||
|
||||
void SunSpecMeter::readMeterBlockHeader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SunSpecMeter::onModbusMapReceived(SunSpec::BlockId mapId, uint mapLength, QVector<quint16> data)
|
||||
{
|
||||
Q_UNUSED(mapLength)
|
||||
Q_UNUSED(data)
|
||||
switch (mapId) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
#include <QObject>
|
||||
#include "sunspec.h"
|
||||
|
||||
class SunSpecMeter : public SunSpec
|
||||
class SunSpecMeter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -64,26 +64,29 @@ public:
|
||||
};
|
||||
|
||||
struct MeterData {
|
||||
SunSpecEvent1 event;
|
||||
SunSpecOperatingState operatingState;
|
||||
SunSpec::SunSpecEvent1 event;
|
||||
SunSpec::SunSpecOperatingState operatingState;
|
||||
};
|
||||
|
||||
SunSpecMeter(const QHostAddress &hostAddress, uint port = 502, QObject *parent = 0);
|
||||
|
||||
void geMeterMap();
|
||||
SunSpecMeter(SunSpec *sunspec, SunSpec::BlockId blockId, int modbusAddress);
|
||||
SunSpec::BlockId blockId();
|
||||
void init();
|
||||
void getMeterMap();
|
||||
|
||||
private:
|
||||
BlockId m_id = BlockIdDeltaConnectThreePhaseMeter;
|
||||
SunSpec *m_connection = nullptr;
|
||||
SunSpec::BlockId m_id = SunSpec::BlockIdDeltaConnectThreePhaseMeter;
|
||||
uint m_mapLength = 0;
|
||||
uint m_mapModbusStartRegister = 40000;
|
||||
bool m_initFinishedSuccess = false;
|
||||
|
||||
void readMeterBlockHeader();
|
||||
|
||||
private slots:
|
||||
// void onModbusMapReceived(BlockId mapId, uint mapLength, QVector<quint16> data);
|
||||
void onModbusMapReceived(SunSpec::BlockId mapId, uint mapLength, QVector<quint16> data);
|
||||
|
||||
signals:
|
||||
void initFinished();
|
||||
void initFinished(bool success);
|
||||
void meterDataReceived(const MeterData &data);
|
||||
};
|
||||
|
||||
|
||||
@ -31,39 +31,47 @@
|
||||
#include "sunspecstorage.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
SunSpecStorage::SunSpecStorage(const QHostAddress &hostAddress, uint port, QObject *parent) : SunSpec(hostAddress, port, parent)
|
||||
SunSpecStorage::SunSpecStorage(SunSpec *sunspec, SunSpec::BlockId blockId, int modbusAddress) :
|
||||
QObject(sunspec),
|
||||
m_connection(sunspec),
|
||||
m_id(blockId),
|
||||
m_mapModbusStartRegister(modbusAddress)
|
||||
{
|
||||
connect(m_modbusTcpClient, &QModbusClient::stateChanged, this, [this] (QModbusDevice::State state) {
|
||||
if (state == QModbusDevice::ConnectedState) {
|
||||
qCDebug(dcSunSpec()) << "Inverter connected successfully";
|
||||
QList<BlockId> mapIds;
|
||||
mapIds.append(BlockIdStorage);
|
||||
findModbusMap(mapIds);
|
||||
}
|
||||
});
|
||||
connect(this, &SunSpec::foundModbusMap, this, [this] (BlockId mapId, uint modbusRegisterAddress) {
|
||||
qCDebug(dcSunSpec()) << "Read map header for mapId" << mapId << "and modbus register" << modbusRegisterAddress;
|
||||
readMapHeader(modbusRegisterAddress);
|
||||
});
|
||||
qCDebug(dcSunSpec()) << "SunSpecStorage: Setting up storage";
|
||||
connect(m_connection, &SunSpec::mapReceived, this, &SunSpecStorage::onModbusMapReceived);
|
||||
}
|
||||
|
||||
connect(this, &SunSpec::mapHeaderReceived, this, [this] (uint modbusAddress, BlockId mapId, uint mapLength) {
|
||||
m_id = mapId;
|
||||
SunSpec::BlockId SunSpecStorage::blockId()
|
||||
{
|
||||
return m_id;
|
||||
|
||||
}
|
||||
|
||||
void SunSpecStorage::init()
|
||||
{
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Init";
|
||||
m_connection->readMapHeader(m_mapModbusStartRegister);
|
||||
connect(m_connection, &SunSpec::mapHeaderReceived, this, [this] (uint modbusAddress, SunSpec::BlockId mapId, uint mapLength) {
|
||||
qCDebug(dcSunSpec()) << "SunSpecInverter: Map Header received, modbus address:" << modbusAddress << "map Id:" << mapId << "map length:" << mapLength;
|
||||
m_mapLength = mapLength;
|
||||
m_mapModbusStartRegister = modbusAddress;
|
||||
readMap(modbusAddress, mapLength);
|
||||
emit initFinished(true);
|
||||
m_initFinishedSuccess = true;
|
||||
});
|
||||
QTimer::singleShot(10000, this,[this] {
|
||||
if (!m_initFinishedSuccess) {
|
||||
emit initFinished(false);
|
||||
}
|
||||
});
|
||||
|
||||
connect(this, &SunSpec::mapReceived, this, &SunSpecStorage::onModbusMapReceived);
|
||||
}
|
||||
|
||||
void SunSpecStorage::getStorageMap()
|
||||
{
|
||||
readMap(m_mapModbusStartRegister, m_mapLength);
|
||||
m_connection->readMap(m_mapModbusStartRegister, m_mapLength);
|
||||
}
|
||||
|
||||
void SunSpecStorage::readStorageBlockHeader()
|
||||
{
|
||||
readMapHeader(m_mapModbusStartRegister);
|
||||
m_connection->readMapHeader(m_mapModbusStartRegister);
|
||||
}
|
||||
|
||||
QUuid SunSpecStorage::setGridCharging(bool enabled)
|
||||
@ -76,7 +84,7 @@ QUuid SunSpecStorage::setGridCharging(bool enabled)
|
||||
|
||||
uint registerAddress = m_mapModbusStartRegister + Model124::Model124ChaGriSet;
|
||||
quint16 value = enabled;
|
||||
return writeHoldingRegister(m_slaveId, registerAddress, value);
|
||||
return m_connection->writeHoldingRegister(registerAddress, value);
|
||||
}
|
||||
|
||||
QUuid SunSpecStorage::setStorageControlMode(bool chargingEnabled, bool dischargingEnabled)
|
||||
@ -86,7 +94,7 @@ QUuid SunSpecStorage::setStorageControlMode(bool chargingEnabled, bool dischargi
|
||||
(static_cast<quint16>(dischargingEnabled) << StorageControlBitFieldDischarge)) ;
|
||||
|
||||
uint modbusRegister = m_mapModbusStartRegister + Model124::Model124ActivateStorageControlMode;
|
||||
return writeHoldingRegister(m_slaveId, modbusRegister, value);
|
||||
return m_connection->writeHoldingRegister(modbusRegister, value);
|
||||
}
|
||||
|
||||
QUuid SunSpecStorage::setChargingRate(int rate)
|
||||
@ -96,7 +104,7 @@ QUuid SunSpecStorage::setChargingRate(int rate)
|
||||
|
||||
uint modbusRegister = m_mapModbusStartRegister + Model124::Model124SetpointMaximumChargingRate;
|
||||
int16_t value = rate * 100;
|
||||
return writeHoldingRegister(m_slaveId, modbusRegister, value);
|
||||
return m_connection->writeHoldingRegister(modbusRegister, value);
|
||||
}
|
||||
|
||||
QUuid SunSpecStorage::setDischargingRate(int charging)
|
||||
@ -105,14 +113,14 @@ QUuid SunSpecStorage::setDischargingRate(int charging)
|
||||
/* Defines the maximum discharge rate (discharge limit). Default is 100% */
|
||||
uint modbusRegister = m_mapModbusStartRegister + Model124::Model124SetpointMaximumDischargeRate;
|
||||
quint16 value = charging * 100;
|
||||
return writeHoldingRegister(m_slaveId, modbusRegister, value);
|
||||
return m_connection->writeHoldingRegister(modbusRegister, value);
|
||||
}
|
||||
|
||||
void SunSpecStorage::onModbusMapReceived(SunSpec::BlockId mapId, uint mapLength, const QVector<quint16> &data)
|
||||
{
|
||||
Q_UNUSED(mapLength)
|
||||
switch (mapId) {
|
||||
case BlockIdStorage: {
|
||||
case SunSpec::BlockIdStorage: {
|
||||
StorageData storageData;
|
||||
storageData.chargingState = ChargingState(data[Model124::Model124ChargeStatus]);
|
||||
emit storageDataReceived(storageData);
|
||||
|
||||
@ -34,18 +34,21 @@
|
||||
#include <QObject>
|
||||
#include "sunspec.h"
|
||||
|
||||
class SunSpecStorage : public SunSpec
|
||||
class SunSpecStorage : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SunSpecStorage(const QHostAddress &hostAddress, uint port = 502, QObject *parent = 0);
|
||||
SunSpecStorage(SunSpec *sunspec, SunSpec::BlockId blockId, int modbusAddress);
|
||||
|
||||
SunSpec::BlockId blockId();
|
||||
void init();
|
||||
void getStorageMap();
|
||||
|
||||
QUuid setGridCharging(bool enabled);
|
||||
QUuid setDischargingRate(int rate);
|
||||
QUuid setChargingRate(int rate);
|
||||
QUuid setStorageControlMode(bool chargingEnabled, bool dischargingEnabled);
|
||||
|
||||
|
||||
enum StorageControlBitField {
|
||||
StorageControlBitFieldCharge = 0,
|
||||
StorageControlBitFieldDischarge = 1
|
||||
@ -88,20 +91,20 @@ public:
|
||||
bool gridChargingEnabled;
|
||||
};
|
||||
|
||||
void getStorageMap();
|
||||
|
||||
private:
|
||||
BlockId m_id = BlockIdEnergyStorageBaseModel;
|
||||
SunSpec *m_connection = nullptr;
|
||||
SunSpec::BlockId m_id = SunSpec::BlockIdEnergyStorageBaseModel;
|
||||
uint m_mapLength = 0;
|
||||
uint m_mapModbusStartRegister = 40000;
|
||||
bool m_initFinishedSuccess = false;
|
||||
|
||||
void readStorageBlockHeader();
|
||||
|
||||
private slots:
|
||||
void onModbusMapReceived(BlockId mapId, uint mapLength, const QVector<quint16> &data);
|
||||
void onModbusMapReceived(SunSpec::BlockId mapId, uint mapLength, const QVector<quint16> &data);
|
||||
|
||||
signals:
|
||||
void initFinished();
|
||||
void initFinished(bool success);
|
||||
void storageDataReceived(const StorageData &data);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user