Update to latest interface requirements and add provided interfaces for the datalogger

This commit is contained in:
Simon Stürz 2021-11-12 17:21:47 +01:00
parent e7eae3711f
commit 8834286af8
6 changed files with 300 additions and 96 deletions

View File

@ -78,6 +78,8 @@ void FroniusInverter::updateThingInfo(const QByteArray &data)
QVariantMap dataMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap();
QVariantMap headMap = jsonDoc.toVariant().toMap().value("Head").toMap();
qCDebug(dcFronius()) << "Inverter data" << qUtf8Printable(QJsonDocument::fromVariant(dataMap).toJson(QJsonDocument::Indented));
// Set the inverter device state
if (dataMap.contains("PAC")) {
if(dataMap.value("PAC").toMap().values().at(0) == "W")

View File

@ -79,17 +79,63 @@ void FroniusMeter::updateThingInfo(const QByteArray &data)
//Add Smart meter with following states: „PowerReal_P_Sum“, „EnergyReal_WAC_Sum_Produced“, „EnergyReal_WAC_Sum_Consumed“
// Set the meter thing state
qCDebug(dcFronius()) << "Meter data" << qUtf8Printable(QJsonDocument::fromVariant(dataMap).toJson(QJsonDocument::Indented));
// Power
if (dataMap.contains("PowerReal_P_Sum")) {
pluginThing()->setStateValue(meterCurrentPowerStateTypeId, dataMap.value("PowerReal_P_Sum").toInt());
pluginThing()->setStateValue(meterCurrentPowerStateTypeId, dataMap.value("PowerReal_P_Sum").toDouble());
}
if (dataMap.contains("PowerReal_P_Phase_1")) {
pluginThing()->setStateValue(meterCurrentPowerPhaseAStateTypeId, dataMap.value("PowerReal_P_Phase_1").toDouble());
}
if (dataMap.contains("PowerReal_P_Phase_2")) {
pluginThing()->setStateValue(meterCurrentPowerPhaseBStateTypeId, dataMap.value("PowerReal_P_Phase_2").toDouble());
}
if (dataMap.contains("PowerReal_P_Phase_3")) {
pluginThing()->setStateValue(meterCurrentPowerPhaseCStateTypeId, dataMap.value("PowerReal_P_Phase_3").toDouble());
}
// Current
if (dataMap.contains("Current_AC_Phase_1")) {
pluginThing()->setStateValue(meterCurrentPhaseAStateTypeId, dataMap.value("Current_AC_Phase_1").toDouble());
}
if (dataMap.contains("Current_AC_Phase_2")) {
pluginThing()->setStateValue(meterCurrentPhaseBStateTypeId, dataMap.value("Current_AC_Phase_2").toDouble());
}
if (dataMap.contains("Current_AC_Phase_3")) {
pluginThing()->setStateValue(meterCurrentPhaseCStateTypeId, dataMap.value("Current_AC_Phase_3").toDouble());
}
// Voltage
if (dataMap.contains("Voltage_AC_Phase_1")) {
pluginThing()->setStateValue(meterVoltagePhaseAStateTypeId, dataMap.value("Voltage_AC_Phase_1").toDouble());
}
if (dataMap.contains("Voltage_AC_Phase_2")) {
pluginThing()->setStateValue(meterVoltagePhaseBStateTypeId, dataMap.value("Voltage_AC_Phase_2").toDouble());
}
if (dataMap.contains("Voltage_AC_Phase_3")) {
pluginThing()->setStateValue(meterVoltagePhaseCStateTypeId, dataMap.value("Voltage_AC_Phase_3").toDouble());
}
// Total energy
if (dataMap.contains("EnergyReal_WAC_Sum_Produced")) {
pluginThing()->setStateValue(meterTotalEnergyProducedStateTypeId, dataMap.value("EnergyReal_WAC_Sum_Produced").toInt()/1000.00);
pluginThing()->setStateValue(meterTotalEnergyProducedStateTypeId, dataMap.value("EnergyReal_WAC_Sum_Produced").toInt()/1000.00);
}
if (dataMap.contains("EnergyReal_WAC_Sum_Consumed")) {
pluginThing()->setStateValue(meterTotalEnergyConsumedStateTypeId, dataMap.value("EnergyReal_WAC_Sum_Consumed").toInt()/1000.00);
pluginThing()->setStateValue(meterTotalEnergyConsumedStateTypeId, dataMap.value("EnergyReal_WAC_Sum_Consumed").toInt()/1000.00);
}
// Frequency
if (dataMap.contains("Frequency_Phase_Average")) {
pluginThing()->setStateValue(meterFrequencyStateTypeId, dataMap.value("Frequency_Phase_Average").toDouble());
}
//update successful

View File

@ -78,6 +78,8 @@ void FroniusStorage::updateThingInfo(const QByteArray &data)
QVariantMap dataMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap();
// QVariantMap headMap = jsonDoc.toVariant().toMap().value("Head").toMap();
qCDebug(dcFronius()) << "Storage data" << qUtf8Printable(QJsonDocument::fromVariant(dataMap).toJson(QJsonDocument::Indented));
// create StorageInfo list map
QVariantMap storageInfoMap = dataMap.value("Controller").toMap();
@ -94,7 +96,9 @@ void FroniusStorage::updateThingInfo(const QByteArray &data)
if (storageInfoMap.contains("Temperature_Cell"))
pluginThing()->setStateValue(storageCellTemperatureStateTypeId, storageInfoMap.value("Temperature_Cell").toDouble());
//update successful
if (storageInfoMap.contains("Capacity_Maximum"))
pluginThing()->setStateValue(storageCapacityStateTypeId, storageInfoMap.value("Capacity_Maximum").toDouble());
pluginThing()->setStateValue(storageConnectedStateTypeId,true);
}
@ -120,8 +124,8 @@ void FroniusStorage::updateActivityInfo(const QByteArray &data)
// create StorageInfo list map
QVariantMap dataMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap();
float charge_akku = dataMap.value("Site").toMap().value("P_Akku").toFloat();
pluginThing()->setStateValue(storageCurrentPowerStateTypeId, charge_akku);
pluginThing()->setStateValue(storageChargingStateTypeId, charge_akku < 0);
pluginThing()->setStateValue(storageDischargingStateTypeId, charge_akku > 0);
}

View File

@ -51,6 +51,6 @@ public:
private:
QString m_charging_state;
int m_charge;
int m_charge;
};
#endif // FRONIUSSTORAGE_H

View File

@ -390,9 +390,8 @@ void IntegrationPluginFronius::searchNewThings(FroniusLogger *logger)
if (!loggerThing)
return;
QByteArray data = reply->readAll();
// Convert the rawdata to a json document
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
@ -409,9 +408,9 @@ void IntegrationPluginFronius::searchNewThings(FroniusLogger *logger)
// Parse reply for inverters at the host address
QVariantMap inverterMap = bodyMap.value("Data").toMap().value("Inverter").toMap();
foreach (QString inverterId, inverterMap.keys()) {
foreach (const QString &inverterId, inverterMap.keys()) {
//check if thing already connected to logger
if (!thingExists(inverterThingIdParamTypeId,inverterId)) {
if (!thingExists(inverterThingIdParamTypeId, inverterId)) {
QString thingName = loggerThing->name() + " Inverter " + inverterId;
ThingDescriptor descriptor(inverterThingClassId, thingName, "Fronius Solar Inverter", loggerThing->id());
ParamList params;
@ -423,31 +422,111 @@ void IntegrationPluginFronius::searchNewThings(FroniusLogger *logger)
// parse reply for meter things at the host address
QVariantMap meterMap = bodyMap.value("Data").toMap().value("Meter").toMap();
foreach (QString meterId, meterMap.keys()) {
foreach (const QString &meterId, meterMap.keys()) {
//check if thing already connected to logger
if(!thingExists(meterThingIdParamTypeId, meterId)) {
QString thingName = loggerThing->name() + " Meter " + meterId;
ThingDescriptor descriptor(meterThingClassId, thingName, "Fronius Solar Meter", loggerThing->id());
ParamList params;
params.append(Param(meterThingIdParamTypeId, meterId));
descriptor.setParams(params);
thingDescriptors.append(descriptor);
if (!thingExists(meterThingIdParamTypeId, meterId)) {
// get meter infos
///solar_api/v1/GetMeterRealtimeData.cgi?Scope=Device&DeviceId=0
QUrl requestUrl;
requestUrl.setScheme("http");
requestUrl.setHost(logger->hostAddress());
requestUrl.setPath(logger->baseUrl() + "GetMeterRealtimeData.cgi");
QUrlQuery query;
query.addQueryItem("Scope", "Device");
query.addQueryItem("DeviceId", meterId);
requestUrl.setQuery(query);
qCDebug(dcFronius()) << "Get meter information before setup";
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(requestUrl));
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, this, [=]() {
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcFronius()) << "Network request error:" << reply->error() << reply->errorString();
return;
}
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcFronius()) << "Failed to parse JSON data" << data << ":" << error.errorString();
return;
}
QVariantMap dataMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap();
QString thingName;
QString serialNumber;
if (dataMap.contains("Details")) {
QVariantMap details = dataMap.value("Details").toMap();
thingName = details.value("Manufacturer", "Fronius").toString() + " " + details.value("Model", "Smart Meter").toString();
serialNumber = details.value("Serial").toString();
} else {
thingName = loggerThing->name() + " Meter " + meterId;
}
ThingDescriptor descriptor(meterThingClassId, thingName, QString(), loggerThing->id());
ParamList params;
params.append(Param(meterThingIdParamTypeId, meterId));
params.append(Param(meterThingSerialNumberParamTypeId, serialNumber));
descriptor.setParams(params);
emit autoThingsAppeared(ThingDescriptors() << descriptor);
});
}
}
// parse reply for storage things at the host address
QVariantMap storageMap = bodyMap.value("Data").toMap().value("Storage").toMap();
foreach (QString storageId, storageMap.keys()) {
foreach (const QString &storageId, storageMap.keys()) {
//check if thing already connected to logger
if(!thingExists(storageThingIdParamTypeId,storageId)) {
QString thingName = loggerThing->name() + " Storage " + storageId;
ThingDescriptor descriptor(storageThingClassId, thingName, "Fronius Solar Storage", loggerThing->id());
ParamList params;
params.append(Param(storageThingManufacturerParamTypeId, ""));
params.append(Param(storageThingCapacityParamTypeId, ""));
params.append(Param(storageThingIdParamTypeId, storageId));
descriptor.setParams(params);
thingDescriptors.append(descriptor);
if (!thingExists(storageThingIdParamTypeId, storageId)) {
QUrlQuery query;
QUrl requestUrl;
requestUrl.setScheme("http");
requestUrl.setHost(logger->hostAddress());
requestUrl.setPath(logger->baseUrl() + "GetStorageRealtimeData.cgi");
query.addQueryItem("Scope","Device");
query.addQueryItem("DeviceId", storageId);
requestUrl.setQuery(query);
qCDebug(dcFronius()) << "Get storage information before setup" << requestUrl.toString();
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(requestUrl));
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, this, [=]() {
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcFronius()) << "Network request error:" << reply->error() << reply->errorString();
return;
}
// Convert the rawdata to a json document
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcFronius()) << "Failed to parse JSON data" << data << ":" << error.errorString();
return;
}
QVariantMap dataMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap().value("Controller").toMap();
QString thingName;
QString serialNumber;
if (dataMap.contains("Details")) {
QVariantMap details = dataMap.value("Details").toMap();
thingName = details.value("Manufacturer", "Fronius").toString() + " " + details.value("Model", "Energy Storage").toString();
serialNumber = details.value("Serial").toString();
} else {
thingName = loggerThing->name() + " Storage " + storageId;
}
ThingDescriptor descriptor(storageThingClassId, thingName, QString(), loggerThing->id());
ParamList params;
params.append(Param(storageThingIdParamTypeId, storageId));
params.append(Param(storageThingSerialNumberParamTypeId, serialNumber));
descriptor.setParams(params);
emit autoThingsAppeared(ThingDescriptors() << descriptor);
});
}
}
@ -475,7 +554,7 @@ void IntegrationPluginFronius::searchNewThings(FroniusLogger *logger)
bool IntegrationPluginFronius::thingExists(const ParamTypeId &thingParamId, QString thingId)
{
foreach(Thing *thing, myThings()) {
foreach (Thing *thing, myThings()) {
if (thing->paramValue(thingParamId).toString() == thingId) {
return true;
}
@ -486,59 +565,13 @@ bool IntegrationPluginFronius::thingExists(const ParamTypeId &thingParamId, QStr
void IntegrationPluginFronius::setupChild(ThingSetupInfo *info, Thing *loggerThing)
{
Thing *thing = info->thing();
if (thing->thingClassId() == storageThingClassId) {
FroniusStorage *newStorage = new FroniusStorage(thing, this);
newStorage->setDeviceId(thing->paramValue(storageThingIdParamTypeId).toString());
newStorage->setBaseUrl(m_froniusLoggers.key(loggerThing)->baseUrl());
newStorage->setHostAddress(m_froniusLoggers.key(loggerThing)->hostAddress());
// Get storage manufacturer and maximum capacity
QUrlQuery query;
QUrl requestUrl;
requestUrl.setScheme("http");
requestUrl.setHost(newStorage->hostAddress());
requestUrl.setPath(newStorage->baseUrl() + "GetStorageRealtimeData.cgi");
query.addQueryItem("Scope","Device");
query.addQueryItem("DeviceId", newStorage->deviceId());
requestUrl.setQuery(query);
qCDebug(dcFronius()) << "Get Storage Data at address" << requestUrl.toString();
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(requestUrl));
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, info, [this, info, newStorage, reply]() {
QByteArray data = reply->readAll();
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcFronius()) << "Network request error:" << reply->error() << reply->errorString();
info->finish(Thing::ThingErrorNoError);
return;
}
// Convert the rawdata to a json document
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcFronius()) << "Failed to parse JSON data" << data << ":" << error.errorString();
info->finish(Thing::ThingErrorHardwareFailure, tr("Please try again"));
return;
}
// Create StorageInfo list map
QVariantMap storageInfoMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap().value("Controller").toMap();
newStorage->pluginThing()->setParamValue(storageThingManufacturerParamTypeId, storageInfoMap.value("Details").toMap().value("Manufacturer").toString());
newStorage->pluginThing()->setParamValue(storageThingCapacityParamTypeId, storageInfoMap.value("Capacity_Maximum").toInt());
m_froniusStorages.insert(newStorage, info->thing());
info->finish(Thing::ThingErrorNoError);
});
} else if (thing->thingClassId() == inverterThingClassId) {
if (thing->thingClassId() == inverterThingClassId) {
FroniusInverter *newInverter = new FroniusInverter(thing,this);
newInverter->setDeviceId(thing->paramValue(inverterThingIdParamTypeId).toString());
newInverter->setBaseUrl(m_froniusLoggers.key(loggerThing)->baseUrl());
newInverter->setHostAddress(m_froniusLoggers.key(loggerThing)->hostAddress());
// get inverter unique ID
// Get inverter unique ID
QUrl requestUrl;
requestUrl.setScheme("http");
requestUrl.setHost(newInverter->hostAddress());
@ -577,6 +610,7 @@ void IntegrationPluginFronius::setupChild(ThingSetupInfo *info, Thing *loggerThi
m_froniusInverters.insert(newInverter, info->thing());
info->finish(Thing::ThingErrorNoError);
});
} else if (thing->thingClassId() == meterThingClassId) {
FroniusMeter *newMeter = new FroniusMeter(thing, this);;
newMeter->setDeviceId(thing->paramValue(meterThingIdParamTypeId).toString());
@ -585,5 +619,14 @@ void IntegrationPluginFronius::setupChild(ThingSetupInfo *info, Thing *loggerThi
m_froniusMeters.insert(newMeter, thing);
info->finish(Thing::ThingErrorNoError);
} else if (thing->thingClassId() == storageThingClassId) {
FroniusStorage *newStorage = new FroniusStorage(thing, this);
newStorage->setDeviceId(thing->paramValue(storageThingIdParamTypeId).toString());
newStorage->setBaseUrl(m_froniusLoggers.key(loggerThing)->baseUrl());
newStorage->setHostAddress(m_froniusLoggers.key(loggerThing)->hostAddress());
m_froniusStorages.insert(newStorage, info->thing());
info->finish(Thing::ThingErrorNoError);
}
}

View File

@ -11,9 +11,10 @@
{
"id": "4fd79fed-42f1-4df9-be64-3df7b2e0bda2",
"name": "datalogger",
"displayName": "Fronius Solar Connection",
"displayName": "Fronius Solar",
"createMethods": ["discovery", "user"],
"interfaces": ["gateway"],
"providedInterfaces": ["energymeter", "solarinverter", "energystorage"],
"paramTypes": [
{
"id": "52da0197-4b78-4fec-aa72-70f949e26edc",
@ -230,7 +231,7 @@
"name": "meter",
"displayName": "Fronius smart meter",
"createMethods": ["auto"],
"interfaces": [ "smartmeterconsumer", "smartmeterproducer", "connectable" ],
"interfaces": [ "energymeter", "connectable" ],
"paramTypes": [
{
"id": "cf3a7025-d368-475a-8f48-efc1344a8409",
@ -239,6 +240,14 @@
"type": "QString",
"inputType": "TextLine",
"readOnly": true
},
{
"id": "dfc2eeef-38b2-4089-9953-48186aaee060",
"name": "serialNumber",
"displayName": "Serial number",
"type": "QString",
"inputType": "TextLine",
"readOnly": true
}
],
"stateTypes": [
@ -251,6 +260,60 @@
"defaultValue": false,
"cached": false
},
{
"id": "267bc59f-1113-4aff-a502-4618a591aa16",
"name": "voltagePhaseA",
"displayName": "Voltage phase A",
"displayNameEvent": "Voltage phase A changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "bbcedb80-30f1-493e-81f0-5f77f2847353",
"name": "voltagePhaseB",
"displayName": "Voltage phase B",
"displayNameEvent": "Voltage phase B changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "8037557b-40dc-411b-8937-bcd1695f898a",
"name": "voltagePhaseC",
"displayName": "Voltage phase C",
"displayNameEvent": "Voltage phase C changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0
},
{
"id": "a9673688-d84a-4848-8583-a70739130252",
"name": "currentPhaseA",
"displayName": "Current phase A",
"displayNameEvent": "Current phase A changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
},
{
"id": "15632e49-95f9-496d-830c-53a31ca6d98e",
"name": "currentPhaseB",
"displayName": "Current phase B",
"displayNameEvent": "Current phase B changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
},
{
"id": "10a24ba9-a57a-48a9-98f3-52671c09e855",
"name": "currentPhaseC",
"displayName": "Current phase C",
"displayNameEvent": "Current phase C changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0
},
{
"id": "e5056ea1-88a2-410b-9c5e-6322aca4cb17",
"name": "currentPower",
@ -277,6 +340,42 @@
"type": "double",
"unit": "KiloWattHour",
"defaultValue": "0"
},
{
"id": "6dbbb062-447b-47d6-b2e4-dceac9aff795",
"name": "currentPowerPhaseA",
"displayName": "Current power phase A",
"displayNameEvent": "Current power phase A changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "f230e78e-15b0-47a4-b494-bae65be00755",
"name": "currentPowerPhaseB",
"displayName": "Current power phase B",
"displayNameEvent": "Current power phase B changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "56b5d550-d902-4c33-9288-8ee972735a75",
"name": "currentPowerPhaseC",
"displayName": "Current power phase C",
"displayNameEvent": "Current power phase C changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "9ff64b29-e023-4395-abd4-b6c366acfd9e",
"name": "frequency",
"displayName": "Frequency",
"displayNameEvent": "Frequency changed",
"type": "double",
"unit": "Hertz",
"defaultValue": 0.00
}
]
},
@ -287,22 +386,6 @@
"createMethods": ["auto"],
"interfaces": [ "battery", "connectable" ],
"paramTypes": [
{
"id": "9665c38b-c13a-428f-b741-1470239c63dc",
"name": "manufacturer",
"displayName": "Manufacturer",
"type": "QString",
"defaultValue": "TextLine",
"readOnly": true
},
{
"id": "59a68e91-1aad-46b7-b351-03b7b2216366",
"name": "capacity",
"displayName": "Maxmimum capacity",
"type": "QString",
"defaultValue": "TextLine",
"readOnly": true
},
{
"id": "49087f31-abf5-4bb8-946b-a3626ee80566",
"name": "id",
@ -310,6 +393,14 @@
"type": "QString",
"inputType": "TextLine",
"readOnly": true
},
{
"id": "8b6c7053-5ba5-4808-8ff4-9024c624d77d",
"name": "serialNumber",
"displayName": "Serial number",
"type": "QString",
"inputType": "TextLine",
"readOnly": true
}
],
"stateTypes": [
@ -338,6 +429,24 @@
"type": "bool",
"defaultValue": false
},
{
"id": "5a89cd3f-3abf-4f51-ab2b-4039f1d211d9",
"name": "currentPower",
"displayName": "Current power",
"displayNameEvent": "Current power changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "3b163deb-67a2-41d1-8441-b2d53ad846ef",
"name": "capacity",
"displayName": "Capacity",
"displayNameEvent": "Capacity changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0
},
{
"id": "5c6da672-9662-41bc-8c8c-aa0f32481251",
"name": "batteryLevel",