diff --git a/libnymea-sunspec/sunspecconnection.cpp b/libnymea-sunspec/sunspecconnection.cpp index b672554..2017879 100644 --- a/libnymea-sunspec/sunspecconnection.cpp +++ b/libnymea-sunspec/sunspecconnection.cpp @@ -30,6 +30,7 @@ #include "sunspecconnection.h" #include "sunspecmodel.h" +#include "models/sunspeccommonmodel.h" #include "models/sunspecmodelfactory.h" Q_LOGGING_CATEGORY(dcSunSpec, "SunSpec") @@ -254,17 +255,35 @@ void SunSpecConnection::processDiscoveryResult() } if (m_uninitializedModels.isEmpty()) { - // Sort the models according to their modbus start address to get the common model for each model + // Sort the models according to their modbus start address in order to set the common model for each model std::sort(m_models.begin(), m_models.end(), [](const SunSpecModel* a, const SunSpecModel* b) -> bool { return a->modbusStartRegister() < b->modbusStartRegister(); }); + // Set common model information to each model (until the next common model shows up) qCDebug(dcSunSpec()) << "Sorted model list:"; + SunSpecCommonModel *currentCommonModel = nullptr; + SunSpecModel::CommonModelInfo commonModelInfo; for (int i = 0; i < m_models.count(); i++) { - qCDebug(dcSunSpec()) << "-->" << m_models.at(i); + SunSpecModel *model = m_models.at(i); + qCDebug(dcSunSpec()) << "-->" << model; + if (model->modelId() == SunSpecModelFactory::ModelIdCommon) { + SunSpecCommonModel *commonModel = qobject_cast(model); + if (commonModel != currentCommonModel) { + currentCommonModel = commonModel; + commonModelInfo.manufacturerName = currentCommonModel->manufacturer(); + commonModelInfo.modelName = currentCommonModel->model(); + commonModelInfo.serialNumber = currentCommonModel->serialNumber(); + commonModelInfo.versionString = currentCommonModel->version(); + } + continue; + } + + if (currentCommonModel && model->modelId() != SunSpecModelFactory::ModelIdCommon) { + model->m_commonModelInfo = commonModelInfo; + } } - // Set common model information to each model qCDebug(dcSunSpec()) << "All models initialized. Discovery finished successfully."; setDiscoveryRunning(false); emit discoveryFinished(true); diff --git a/libnymea-sunspec/sunspecmodel.cpp b/libnymea-sunspec/sunspecmodel.cpp index 72afb7b..027c085 100644 --- a/libnymea-sunspec/sunspecmodel.cpp +++ b/libnymea-sunspec/sunspecmodel.cpp @@ -84,6 +84,11 @@ QVector SunSpecModel::blockData() const return m_blockData; } +SunSpecModel::CommonModelInfo SunSpecModel::commonModelInfo() const +{ + return m_commonModelInfo; +} + void SunSpecModel::init() { m_initialized = false; diff --git a/libnymea-sunspec/sunspecmodel.h b/libnymea-sunspec/sunspecmodel.h index 66f1caa..3a1229f 100644 --- a/libnymea-sunspec/sunspecmodel.h +++ b/libnymea-sunspec/sunspecmodel.h @@ -45,6 +45,9 @@ class SunSpecConnection; class SunSpecModel : public QObject { Q_OBJECT + + friend class SunSpecConnection; + public: enum ModelBlockType { ModelBlockTypeFixed, @@ -53,6 +56,13 @@ public: }; Q_ENUM(ModelBlockType) + typedef struct CommonModelInfo { + QString manufacturerName; + QString modelName; + QString serialNumber; + QString versionString; + } CommonModelInfo; + explicit SunSpecModel(SunSpecConnection *connection, quint16 modbusStartRegister, quint16 modelId, quint16 modelLength, QObject *parent = nullptr); virtual ~SunSpecModel() = default; @@ -60,6 +70,7 @@ public: bool initialized() const; + // Model information virtual QString name() const = 0; virtual QString description() const = 0; virtual QString label() const = 0; @@ -72,6 +83,8 @@ public: QVector blockData() const; + CommonModelInfo commonModelInfo() const; + virtual void init(); virtual void readBlockData(); @@ -92,6 +105,8 @@ protected: QVector m_blockData; QHash m_dataPoints; + CommonModelInfo m_commonModelInfo; + void setInitializedFinished(); virtual void processBlockData() = 0; diff --git a/sunspec/integrationpluginsunspec.cpp b/sunspec/integrationpluginsunspec.cpp index 2fe9a64..ee1248d 100644 --- a/sunspec/integrationpluginsunspec.cpp +++ b/sunspec/integrationpluginsunspec.cpp @@ -63,7 +63,7 @@ IntegrationPluginSunSpec::IntegrationPluginSunSpec() void IntegrationPluginSunSpec::init() { - // Connection params + // SunSpec connection params m_connectionIpParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingIpAddressParamTypeId); m_connectionIpParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingIpAddressParamTypeId); @@ -76,20 +76,6 @@ void IntegrationPluginSunSpec::init() m_connectionSlaveIdParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingSlaveIdParamTypeId); m_connectionSlaveIdParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingSlaveIdParamTypeId); - // Connection states - m_connectionManufacturerStateTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionManufacturerStateTypeId); - m_connectionManufacturerStateTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionManufacturerStateTypeId); - - m_connectionDeviceModelStateTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionDeviceModelStateTypeId); - m_connectionDeviceModelStateTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionDeviceModelStateTypeId); - - m_connectionVersionStateTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionVersionStateTypeId); - m_connectionVersionStateTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionVersionStateTypeId); - - m_connectionSerialNumberStateTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionSerialNumberStateTypeId); - m_connectionSerialNumberStateTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionSerialNumberStateTypeId); - - // Connected state for all things m_connectedStateTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionConnectedStateTypeId); m_connectedStateTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionConnectedStateTypeId); @@ -103,7 +89,16 @@ void IntegrationPluginSunSpec::init() m_connectedStateTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterConnectedStateTypeId); m_connectedStateTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterConnectedStateTypeId); - // Model id params for sunspec things + // Version states for all sunspec things + m_versionStateTypeIds.insert(solarEdgeBatteryThingClassId, solarEdgeBatteryVersionStateTypeId); + m_versionStateTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterVersionStateTypeId); + m_versionStateTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterVersionStateTypeId); + m_versionStateTypeIds.insert(sunspecStorageThingClassId, sunspecStorageVersionStateTypeId); + m_versionStateTypeIds.insert(sunspecSinglePhaseMeterThingClassId, sunspecSinglePhaseMeterVersionStateTypeId); + m_versionStateTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterVersionStateTypeId); + m_versionStateTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterVersionStateTypeId); + + // Params for sunspec things m_modelIdParamTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterThingModelIdParamTypeId); m_modelIdParamTypeIds.insert(sunspecSplitPhaseInverterThingClassId, sunspecSplitPhaseInverterThingModelIdParamTypeId); m_modelIdParamTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterThingModelIdParamTypeId); @@ -112,6 +107,7 @@ void IntegrationPluginSunSpec::init() m_modelIdParamTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterThingModelIdParamTypeId); m_modelIdParamTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterThingModelIdParamTypeId); + m_modbusAddressParamTypeIds.insert(solarEdgeBatteryThingClassId, solarEdgeBatteryThingModbusAddressParamTypeId); m_modbusAddressParamTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterThingModbusAddressParamTypeId); m_modbusAddressParamTypeIds.insert(sunspecSplitPhaseInverterThingClassId, sunspecSplitPhaseInverterThingModbusAddressParamTypeId); m_modbusAddressParamTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterThingModbusAddressParamTypeId); @@ -120,6 +116,32 @@ void IntegrationPluginSunSpec::init() m_modbusAddressParamTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterThingModbusAddressParamTypeId); m_modbusAddressParamTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterThingModbusAddressParamTypeId); + m_manufacturerParamTypeIds.insert(solarEdgeBatteryThingClassId, solarEdgeBatteryThingManufacturerParamTypeId); + m_manufacturerParamTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterThingManufacturerParamTypeId); + m_manufacturerParamTypeIds.insert(sunspecSplitPhaseInverterThingClassId, sunspecSplitPhaseInverterThingManufacturerParamTypeId); + m_manufacturerParamTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterThingManufacturerParamTypeId); + m_manufacturerParamTypeIds.insert(sunspecStorageThingClassId, sunspecStorageThingManufacturerParamTypeId); + m_manufacturerParamTypeIds.insert(sunspecSinglePhaseMeterThingClassId, sunspecSinglePhaseMeterThingManufacturerParamTypeId); + m_manufacturerParamTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterThingManufacturerParamTypeId); + m_manufacturerParamTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterThingManufacturerParamTypeId); + + m_deviceModelParamTypeIds.insert(solarEdgeBatteryThingClassId, solarEdgeBatteryThingDeviceModelParamTypeId); + m_deviceModelParamTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterThingDeviceModelParamTypeId); + m_deviceModelParamTypeIds.insert(sunspecSplitPhaseInverterThingClassId, sunspecSplitPhaseInverterThingDeviceModelParamTypeId); + m_deviceModelParamTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterThingDeviceModelParamTypeId); + m_deviceModelParamTypeIds.insert(sunspecStorageThingClassId, sunspecStorageThingDeviceModelParamTypeId); + m_deviceModelParamTypeIds.insert(sunspecSinglePhaseMeterThingClassId, sunspecSinglePhaseMeterThingDeviceModelParamTypeId); + m_deviceModelParamTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterThingDeviceModelParamTypeId); + m_deviceModelParamTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterThingDeviceModelParamTypeId); + + m_serialNumberParamTypeIds.insert(solarEdgeBatteryThingClassId, solarEdgeBatteryThingSerialNumberParamTypeId); + m_serialNumberParamTypeIds.insert(sunspecSinglePhaseInverterThingClassId, sunspecSinglePhaseInverterThingSerialNumberParamTypeId); + m_serialNumberParamTypeIds.insert(sunspecSplitPhaseInverterThingClassId, sunspecSplitPhaseInverterThingSerialNumberParamTypeId); + m_serialNumberParamTypeIds.insert(sunspecThreePhaseInverterThingClassId, sunspecThreePhaseInverterThingSerialNumberParamTypeId); + m_serialNumberParamTypeIds.insert(sunspecStorageThingClassId, sunspecStorageThingSerialNumberParamTypeId); + m_serialNumberParamTypeIds.insert(sunspecSinglePhaseMeterThingClassId, sunspecSinglePhaseMeterThingSerialNumberParamTypeId); + m_serialNumberParamTypeIds.insert(sunspecSplitPhaseMeterThingClassId, sunspecSplitPhaseMeterThingSerialNumberParamTypeId); + m_serialNumberParamTypeIds.insert(sunspecThreePhaseMeterThingClassId, sunspecThreePhaseMeterThingSerialNumberParamTypeId); } void IntegrationPluginSunSpec::discoverThings(ThingDiscoveryInfo *info) @@ -261,9 +283,13 @@ void IntegrationPluginSunSpec::postSetupThing(Thing *thing) if (thing->thingClassId() == solarEdgeConnectionThingClassId) { searchSolarEdgeBatteries(connection); } + } else if (m_sunspecThings.contains(thing)) { SunSpecThing *sunSpecThing = m_sunspecThings.value(thing); sunSpecThing->readBlockData(); + + // Update the version state + thing->setStateValue(m_versionStateTypeIds.value(thing->thingClassId()), sunSpecThing->model()->commonModelInfo().versionString); } else { Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8()); } @@ -338,19 +364,6 @@ void IntegrationPluginSunSpec::processDiscoveryResult(Thing *thing, SunSpecConne { qCDebug(dcSunSpec()) << "Processing discovery result from" << thing->name() << connection; - // First process the common model - foreach (SunSpecModel *model, connection->models()) { - if (model->modelId() == SunSpecModelFactory::ModelIdCommon) { - SunSpecCommonModel *common = qobject_cast(model); - qCDebug(dcSunSpec()) << common; - thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true); - thing->setStateValue(m_connectionManufacturerStateTypeIds.value(thing->thingClassId()), common->manufacturer()); - thing->setStateValue(m_connectionDeviceModelStateTypeIds.value(thing->thingClassId()), common->model()); - thing->setStateValue(m_connectionVersionStateTypeIds.value(thing->thingClassId()), common->version()); - thing->setStateValue(m_connectionSerialNumberStateTypeIds.value(thing->thingClassId()), common->serialNumber()); - } - } - // Now process the other models and check if we can create any auto device if not already added foreach (SunSpecModel *model, connection->models()) { // Make sure we have not added this model yet @@ -364,76 +377,34 @@ void IntegrationPluginSunSpec::processDiscoveryResult(Thing *thing, SunSpecConne // Skip the common model, we already handled this one for each thing model break; case SunSpecModelFactory::ModelIdInverterSinglePhase: - case SunSpecModelFactory::ModelIdInverterSinglePhaseFloat: { - ThingDescriptor descriptor(sunspecSinglePhaseInverterThingClassId, thing->stateValue(m_connectionDeviceModelStateTypeIds.value(thing->thingClassId())).toString() + " " + QT_TR_NOOP("Single Phase Inverter"), "", thing->id()); - ParamList params; - params.append(Param(sunspecSinglePhaseInverterThingModelIdParamTypeId, model->modelId())); - params.append(Param(sunspecSinglePhaseInverterThingModbusAddressParamTypeId, model->modbusStartRegister())); - descriptor.setParams(params); - emit autoThingsAppeared({descriptor}); + case SunSpecModelFactory::ModelIdInverterSinglePhaseFloat: + autocreateSunSpecModelThing(sunspecSinglePhaseInverterThingClassId, QT_TR_NOOP("Single Phase Inverter"), thing->id(), model); break; - } case SunSpecModelFactory::ModelIdInverterSplitPhase: - case SunSpecModelFactory::ModelIdInverterSplitPhaseFloat: { - ThingDescriptor descriptor(sunspecSplitPhaseInverterThingClassId, thing->stateValue(m_connectionDeviceModelStateTypeIds.value(thing->thingClassId())).toString() + " " + QT_TR_NOOP("Split Phase Inverter"), "", thing->id()); - ParamList params; - params.append(Param(sunspecSplitPhaseInverterThingModelIdParamTypeId, model->modelId())); - params.append(Param(sunspecSplitPhaseInverterThingModbusAddressParamTypeId, model->modbusStartRegister())); - descriptor.setParams(params); - emit autoThingsAppeared({descriptor}); + case SunSpecModelFactory::ModelIdInverterSplitPhaseFloat: + autocreateSunSpecModelThing(sunspecSplitPhaseInverterThingClassId, QT_TR_NOOP("Split Phase Inverter"), thing->id(), model); break; - } case SunSpecModelFactory::ModelIdInverterThreePhase: - case SunSpecModelFactory::ModelIdInverterThreePhaseFloat: { - ThingDescriptor descriptor(sunspecThreePhaseInverterThingClassId, thing->stateValue(m_connectionDeviceModelStateTypeIds.value(thing->thingClassId())).toString() + " " + QT_TR_NOOP("Three Phase Inverter"), "", thing->id()); - ParamList params; - params.append(Param(sunspecThreePhaseInverterThingModelIdParamTypeId, model->modelId())); - params.append(Param(sunspecThreePhaseInverterThingModbusAddressParamTypeId, model->modbusStartRegister())); - descriptor.setParams(params); - emit autoThingsAppeared({descriptor}); + case SunSpecModelFactory::ModelIdInverterThreePhaseFloat: + autocreateSunSpecModelThing(sunspecThreePhaseInverterThingClassId, QT_TR_NOOP("Three Phase Inverter"), thing->id(), model); break; - } case SunSpecModelFactory::ModelIdMeterSinglePhase: - case SunSpecModelFactory::ModelIdMeterSinglePhaseFloat: { - ThingDescriptor descriptor(sunspecSinglePhaseMeterThingClassId, thing->stateValue(m_connectionDeviceModelStateTypeIds.value(thing->thingClassId())).toString() + " " + QT_TR_NOOP("Single Phase Meter"), "", thing->id()); - ParamList params; - params.append(Param(sunspecSinglePhaseMeterThingModelIdParamTypeId, model->modelId())); - params.append(Param(sunspecSinglePhaseMeterThingModbusAddressParamTypeId, model->modbusStartRegister())); - descriptor.setParams(params); - emit autoThingsAppeared({descriptor}); + case SunSpecModelFactory::ModelIdMeterSinglePhaseFloat: + autocreateSunSpecModelThing(sunspecSinglePhaseMeterThingClassId, QT_TR_NOOP("Single Phase Meter"), thing->id(), model); break; - } case SunSpecModelFactory::ModelIdMeterSplitSinglePhaseAbn: - case SunSpecModelFactory::ModelIdMeterSplitSinglePhaseFloat: { - ThingDescriptor descriptor(sunspecSplitPhaseMeterThingClassId, thing->stateValue(m_connectionDeviceModelStateTypeIds.value(thing->thingClassId())).toString() + " " + QT_TR_NOOP("Split Phase Meter"), "", thing->id()); - ParamList params; - params.append(Param(sunspecSplitPhaseMeterThingModelIdParamTypeId, model->modelId())); - params.append(Param(sunspecSplitPhaseMeterThingModbusAddressParamTypeId, model->modbusStartRegister())); - descriptor.setParams(params); - emit autoThingsAppeared({descriptor}); + case SunSpecModelFactory::ModelIdMeterSplitSinglePhaseFloat: + autocreateSunSpecModelThing(sunspecSplitPhaseMeterThingClassId, QT_TR_NOOP("Split Phase Meter"), thing->id(), model); break; - } case SunSpecModelFactory::ModelIdMeterThreePhase: case SunSpecModelFactory::ModelIdDeltaConnectThreePhaseAbcMeter: case SunSpecModelFactory::ModelIdMeterThreePhaseWyeConnect: - case SunSpecModelFactory::ModelIdMeterThreePhaseDeltaConnect: { - ThingDescriptor descriptor(sunspecThreePhaseMeterThingClassId, thing->stateValue(m_connectionDeviceModelStateTypeIds.value(thing->thingClassId())).toString() + " " + QT_TR_NOOP("Three Phase Meter"), "", thing->id()); - ParamList params; - params.append(Param(sunspecThreePhaseMeterThingModelIdParamTypeId, model->modelId())); - params.append(Param(sunspecThreePhaseMeterThingModbusAddressParamTypeId, model->modbusStartRegister())); - descriptor.setParams(params); - emit autoThingsAppeared({descriptor}); + case SunSpecModelFactory::ModelIdMeterThreePhaseDeltaConnect: + autocreateSunSpecModelThing(sunspecThreePhaseMeterThingClassId, QT_TR_NOOP("Three Phase Meter"), thing->id(), model); break; - } - case SunSpecModelFactory::ModelIdStorage: { - ThingDescriptor descriptor(sunspecStorageThingClassId, thing->stateValue(m_connectionDeviceModelStateTypeIds.value(thing->thingClassId())).toString() + " " + QT_TR_NOOP("Storage"), "", thing->id()); - ParamList params; - params.append(Param(sunspecStorageThingModelIdParamTypeId, model->modelId())); - params.append(Param(sunspecStorageThingModbusAddressParamTypeId, model->modbusStartRegister())); - descriptor.setParams(params); - emit autoThingsAppeared({descriptor}); + case SunSpecModelFactory::ModelIdStorage: + autocreateSunSpecModelThing(sunspecStorageThingClassId, QT_TR_NOOP("Storage"), thing->id(), model); break; - } default: qCWarning(dcSunSpec()) << "Plugin has no implementation for detected" << model; break; @@ -664,6 +635,8 @@ void IntegrationPluginSunSpec::searchSolarEdgeBattery(SunSpecConnection *connect ThingDescriptor descriptor(solarEdgeBatteryThingClassId, battery->batteryData().manufacturerName + " - " + battery->batteryData().model, QString(), parentThingId); ParamList params; params.append(Param(solarEdgeBatteryThingModbusAddressParamTypeId, startRegister)); + params.append(Param(solarEdgeBatteryThingManufacturerParamTypeId, battery->batteryData().manufacturerName)); + params.append(Param(solarEdgeBatteryThingDeviceModelParamTypeId, battery->batteryData().model)); params.append(Param(solarEdgeBatteryThingSerialNumberParamTypeId, battery->batteryData().serialNumber)); descriptor.setParams(params); emit autoThingsAppeared({descriptor}); @@ -681,6 +654,30 @@ void IntegrationPluginSunSpec::searchSolarEdgeBattery(SunSpecConnection *connect } } +void IntegrationPluginSunSpec::autocreateSunSpecModelThing(const ThingClassId &thingClassId, const QString &thingName, const ThingId &parentId, SunSpecModel *model) +{ + ThingDescriptor descriptor(thingClassId); + descriptor.setParentId(parentId); + + QString finalThingName; + if (model->commonModelInfo().manufacturerName.isEmpty()) { + finalThingName = thingName; + } else { + finalThingName = model->commonModelInfo().manufacturerName + " " + thingName; + } + + descriptor.setTitle(finalThingName); + + ParamList params; + params.append(Param(m_modelIdParamTypeIds.value(descriptor.thingClassId()), model->modelId())); + params.append(Param(m_modbusAddressParamTypeIds.value(descriptor.thingClassId()), model->modbusStartRegister())); + params.append(Param(m_manufacturerParamTypeIds.value(descriptor.thingClassId()), model->commonModelInfo().manufacturerName)); + params.append(Param(m_deviceModelParamTypeIds.value(descriptor.thingClassId()), model->commonModelInfo().modelName)); + params.append(Param(m_serialNumberParamTypeIds.value(descriptor.thingClassId()), model->commonModelInfo().serialNumber)); + descriptor.setParams(params); + emit autoThingsAppeared({descriptor}); +} + void IntegrationPluginSunSpec::onRefreshTimer() { // Update all sunspec thing blocks diff --git a/sunspec/integrationpluginsunspec.h b/sunspec/integrationpluginsunspec.h index 11f6080..bab9f7e 100644 --- a/sunspec/integrationpluginsunspec.h +++ b/sunspec/integrationpluginsunspec.h @@ -69,15 +69,15 @@ private: QHash m_connectionMacAddressParamTypeIds; QHash m_connectionSlaveIdParamTypeIds; - // SunSpec Connection states map - QHash m_connectionManufacturerStateTypeIds; - QHash m_connectionDeviceModelStateTypeIds; - QHash m_connectionVersionStateTypeIds; - QHash m_connectionSerialNumberStateTypeIds; + // SunSpec thing common state map + QHash m_versionStateTypeIds; // SunSpec thing params map QHash m_modelIdParamTypeIds; QHash m_modbusAddressParamTypeIds; + QHash m_manufacturerParamTypeIds; + QHash m_deviceModelParamTypeIds; + QHash m_serialNumberParamTypeIds; PluginTimer *m_refreshTimer = nullptr; @@ -100,6 +100,7 @@ private: void searchSolarEdgeBatteries(SunSpecConnection *connection); void searchSolarEdgeBattery(SunSpecConnection *connection, const ThingId &parentThingId, quint16 startRegister); + void autocreateSunSpecModelThing(const ThingClassId &thingClassId, const QString &thingName, const ThingId &parentId, SunSpecModel *model); private slots: void onRefreshTimer(); diff --git a/sunspec/integrationpluginsunspec.json b/sunspec/integrationpluginsunspec.json index eb6eb55..8cd3e9b 100644 --- a/sunspec/integrationpluginsunspec.json +++ b/sunspec/integrationpluginsunspec.json @@ -80,38 +80,6 @@ "type": "bool", "defaultValue": false, "cached": false - }, - { - "id": "04970315-ed3a-45ce-98fc-35ae3c4eb27b", - "name":"manufacturer", - "displayName": "Manufacturer", - "displayNameEvent": "Manufacturer changed", - "type": "QString", - "defaultValue": "Unkown" - }, - { - "id": "58146c26-17d3-458e-a13f-d7f306c20c44", - "name":"deviceModel", - "displayName": "Device model", - "displayNameEvent": "Device model changed", - "type": "QString", - "defaultValue": "Unkown" - }, - { - "id": "d95757de-b52d-418b-9404-ac3d7202d897", - "name":"version", - "displayName": "Version", - "displayNameEvent": "Version changed", - "type": "QString", - "defaultValue": "" - }, - { - "id": "6ed498e1-37ca-4bb7-bac7-463509c7784e", - "name":"serialNumber", - "displayName": "Serial number", - "displayNameEvent": "Serial number changed", - "type": "QString", - "defaultValue": "Unkown" } ] }, @@ -136,6 +104,27 @@ "type": "uint", "readOnly": true, "defaultValue": 0 + }, + { + "id": "5fbb0b62-e0f9-4aee-aba7-fd00ae8b0a5d", + "name":"manufacturer", + "displayName": "Manufacturer", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "12f1b02c-033d-423f-a217-955ddb995dd5", + "name":"deviceModel", + "displayName": "Device model", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "59b85218-f144-4ce8-95f7-19a1dc2e2a8d", + "name":"serialNumber", + "displayName": "Serial number", + "type": "QString", + "defaultValue": "Unkown" } ], "stateTypes":[ @@ -227,6 +216,14 @@ "displayNameEvent": "Error changed", "type": "QString", "defaultValue": "" + }, + { + "id": "f4439de3-a461-42d6-b4c9-aa35f696a420", + "name": "version", + "displayName": "Version", + "displayNameEvent": "Version changed", + "type": "QString", + "defaultValue": "" } ] }, @@ -251,6 +248,27 @@ "type": "uint", "readOnly": true, "defaultValue": 0 + }, + { + "id": "c2c35b68-1c0f-47cc-b09f-49d9cf67c0ff", + "name":"manufacturer", + "displayName": "Manufacturer", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "d40b1b9d-994d-422c-8a41-b98cf03c1678", + "name":"deviceModel", + "displayName": "Device model", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "8afdd256-0393-4610-9477-7c4541c92ffe", + "name":"serialNumber", + "displayName": "Serial number", + "type": "QString", + "defaultValue": "Unkown" } ], "stateTypes":[ @@ -369,6 +387,14 @@ "displayNameEvent": "Error changed", "type": "QString", "defaultValue": "" + }, + { + "id": "2986cac4-f4ac-4299-ac9e-48339e2a54ef", + "name": "version", + "displayName": "Version", + "displayNameEvent": "Version changed", + "type": "QString", + "defaultValue": "" } ] }, @@ -393,6 +419,27 @@ "type": "uint", "readOnly": true, "defaultValue": 0 + }, + { + "id": "640b71ba-2ccd-40d6-bf45-8271a9046f81", + "name":"manufacturer", + "displayName": "Manufacturer", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "938b6555-e0af-4222-b85b-90bc1bc78c8f", + "name":"deviceModel", + "displayName": "Device model", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "ee169df5-475c-4dfb-870a-0785899b7dc1", + "name":"serialNumber", + "displayName": "Serial number", + "type": "QString", + "defaultValue": "Unkown" } ], "stateTypes":[ @@ -529,6 +576,14 @@ "displayNameEvent": "Error changed", "type": "QString", "defaultValue": "" + }, + { + "id": "3b543b60-d8f6-4bc0-a79f-cb9cb20e4bb8", + "name": "version", + "displayName": "Version", + "displayNameEvent": "Version changed", + "type": "QString", + "defaultValue": "" } ] }, @@ -554,6 +609,27 @@ "type": "uint", "readOnly": true, "defaultValue": 0 + }, + { + "id": "811de380-848a-448c-8446-daa0e0fd8e50", + "name":"manufacturer", + "displayName": "Manufacturer", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "e31333c8-746d-4955-af0a-ae18d7100de7", + "name":"deviceModel", + "displayName": "Device model", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "581fa623-0005-448f-a5b1-8db1043795a3", + "name":"serialNumber", + "displayName": "Serial number", + "type": "QString", + "defaultValue": "Unkown" } ], "stateTypes":[ @@ -637,6 +713,14 @@ "type": "double", "unit": "KiloWattHour", "defaultValue": 0.00 + }, + { + "id": "94adff6f-f672-4e4e-a72c-cd6cd7e8721a", + "name": "version", + "displayName": "Version", + "displayNameEvent": "Version changed", + "type": "QString", + "defaultValue": "" } ] }, @@ -662,6 +746,27 @@ "type": "uint", "readOnly": true, "defaultValue": 0 + }, + { + "id": "ecbdee01-8be7-42bf-9e1a-a0f700669b09", + "name":"manufacturer", + "displayName": "Manufacturer", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "6bc978cb-a779-4f5f-87a4-3cbbe2a55ca8", + "name":"deviceModel", + "displayName": "Device model", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "fb7cc04b-91cb-4f3d-a444-201cca57934a", + "name":"serialNumber", + "displayName": "Serial number", + "type": "QString", + "defaultValue": "Unkown" } ], "stateTypes":[ @@ -763,6 +868,14 @@ "type": "double", "unit": "KiloWattHour", "defaultValue": 0.00 + }, + { + "id": "85c5087c-77b4-4ac8-bdff-020f6242bd57", + "name": "version", + "displayName": "Version", + "displayNameEvent": "Version changed", + "type": "QString", + "defaultValue": "" } ] }, @@ -788,6 +901,27 @@ "type": "uint", "readOnly": true, "defaultValue": 0 + }, + { + "id": "462552de-af84-4893-9132-81c1adce67ad", + "name":"manufacturer", + "displayName": "Manufacturer", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "00d308dc-e9a3-40e4-acad-3cad2ca3590f", + "name":"deviceModel", + "displayName": "Device model", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "97bbcc98-f4ec-4060-bac2-31b40720862c", + "name":"serialNumber", + "displayName": "Serial number", + "type": "QString", + "defaultValue": "Unkown" } ], "stateTypes":[ @@ -907,6 +1041,14 @@ "type": "double", "unit": "KiloWattHour", "defaultValue": 0.00 + }, + { + "id": "3b8f53d2-4c80-48a6-8c0b-381e93872811", + "name": "version", + "displayName": "Version", + "displayNameEvent": "Version changed", + "type": "QString", + "defaultValue": "" } ] }, @@ -932,6 +1074,27 @@ "type": "uint", "readOnly": true, "defaultValue": 0 + }, + { + "id": "7ee31b97-caec-4cdb-80c9-71e232c5fb22", + "name":"manufacturer", + "displayName": "Manufacturer", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "2abf786d-18be-46cb-b4a3-7e0934a4c3fd", + "name":"deviceModel", + "displayName": "Device model", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "5cf43b80-3e65-4f69-8bf5-91810da0ead4", + "name":"serialNumber", + "displayName": "Serial number", + "type": "QString", + "defaultValue": "Unkown" } ], "stateTypes":[ @@ -1051,6 +1214,14 @@ "defaultValue": false, "writable": true, "displayNameAction": "Set discharging rate" + }, + { + "id": "fca0c151-d8fa-4d6e-a5d7-b3bc965abc09", + "name": "version", + "displayName": "Version", + "displayNameEvent": "Version changed", + "type": "QString", + "defaultValue": "" } ] } @@ -1106,38 +1277,6 @@ "type": "bool", "defaultValue": false, "cached": false - }, - { - "id": "3f783971-ba6f-498d-8e31-1ecfc6efa0a3", - "name":"manufacturer", - "displayName": "Manufacturer", - "displayNameEvent": "Manufacturer changed", - "type": "QString", - "defaultValue": "Unkown" - }, - { - "id": "ce075b2c-12c8-4279-99ef-7ba39aba4d53", - "name":"deviceModel", - "displayName": "Device model", - "displayNameEvent": "Device model changed", - "type": "QString", - "defaultValue": "Unkown" - }, - { - "id": "bf2c53dc-be30-4177-b3ab-119c49e8a994", - "name":"version", - "displayName": "Version", - "displayNameEvent": "Version changed", - "type": "QString", - "defaultValue": "" - }, - { - "id": "a71286ed-1851-4324-bd72-567696c2aebb", - "name":"serialNumber", - "displayName": "Serial number", - "displayNameEvent": "Serial number changed", - "type": "QString", - "defaultValue": "Unkown" } ] }, @@ -1156,12 +1295,25 @@ "readOnly": true, "defaultValue": 0 }, + { + "id": "8a4b19a9-ee14-42aa-9146-fa84e15970ee", + "name":"manufacturer", + "displayName": "Manufacturer", + "type": "QString", + "defaultValue": "Unkown" + }, + { + "id": "e90a3833-1eb6-43ed-a72a-0cf7cb8015ca", + "name":"deviceModel", + "displayName": "Device model", + "type": "QString", + "defaultValue": "Unkown" + }, { "id": "efd99fe4-3a48-4208-829d-14e062015ee7", "name":"serialNumber", "displayName": "Serial number", "type": "QString", - "readOnly": true, "defaultValue": "" } ], @@ -1302,9 +1454,9 @@ }, { "id": "db2e0304-4f0e-461f-8bab-c63fcb5deb1b", - "name": "firmwareVersion", - "displayName": "Firmware version", - "displayNameEvent": "Firmware version changed", + "name": "version", + "displayName": "Version", + "displayNameEvent": "Version changed", "type": "QString", "defaultValue": "" } diff --git a/sunspec/solaredgebattery.cpp b/sunspec/solaredgebattery.cpp index da20a7a..c492fe4 100644 --- a/sunspec/solaredgebattery.cpp +++ b/sunspec/solaredgebattery.cpp @@ -252,7 +252,7 @@ void SolarEdgeBattery::onBlockDataUpdated() m_thing->setStateValue(solarEdgeBatteryMaxEnergyStateTypeId, m_batteryData.maxEnergy); m_thing->setStateValue(solarEdgeBatteryAvailableEnergyStateTypeId, m_batteryData.availableEnergy); m_thing->setStateValue(solarEdgeBatteryStateOfHealthStateTypeId, m_batteryData.stateOfHealth); - m_thing->setStateValue(solarEdgeBatteryFirmwareVersionStateTypeId, m_batteryData.firmwareVersion); + m_thing->setStateValue(solarEdgeBatteryVersionStateTypeId, m_batteryData.firmwareVersion); } QDebug operator<<(QDebug debug, const SolarEdgeBattery::BatteryData &batteryData)