Skip to content

Commit

Permalink
App Manager: bugfix + new Fronius PV-Inverter App (OpenEMS#1867)
Browse files Browse the repository at this point in the history
Bugfix: setting app as dependency with specific instanceid without properties
Added Fronius PvInverter

Co-authored-by: Michael Grill <michael.grill@fenecon.de>
  • Loading branch information
michaelgrill and Michael Grill authored Jun 29, 2022
1 parent 44d66a0 commit e17d861
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@
"CONTROLLER_ID": "ctrlApiRest0",
"API_TIMEOUT": 60
},
"dependencies": [
{
"key": "READ_ONLY",
"instanceId": UUID
}
],
"appDescriptor": {
"websiteUrl": URL
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ public FeneconHome(@Reference ComponentManager componentManager, ComponentContex
@Override
public AppDescriptor getAppDescriptor() {
return AppDescriptor.create() //
.setWebsiteUrl("https://fenecon.de/home/") //
.build();
}

Expand Down Expand Up @@ -491,8 +490,8 @@ public AppAssistant getAppAssistant(Language language) {
.setMax(100) //
.onlyShowIfChecked(Property.HAS_EMERGENCY_RESERVE) //
.onlyIf(hasEmergencyReserve, f -> {
f.setDefaultValue(this.componentManager.getEdgeConfig()
.getComponent("ctrlEmergencyCapacityReserve0").get()
f.setDefaultValue(this.componentUtil.getComponent("ctrlEmergencyCapacityReserve0", //
"Controller.Ess.EmergencyCapacityReserve").get()
.getProperty("reserveSoc").get().getAsNumber());
}).build())
.build()) //
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package io.openems.edge.app.pvinverter;

import java.util.EnumMap;

import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Reference;

import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;

import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.function.ThrowingTriFunction;
import io.openems.common.session.Language;
import io.openems.common.utils.EnumUtils;
import io.openems.common.utils.JsonUtils;
import io.openems.edge.app.pvinverter.FroniusPvInverter.Property;
import io.openems.edge.common.component.ComponentManager;
import io.openems.edge.core.appmanager.AbstractOpenemsApp;
import io.openems.edge.core.appmanager.AppAssistant;
import io.openems.edge.core.appmanager.AppConfiguration;
import io.openems.edge.core.appmanager.AppDescriptor;
import io.openems.edge.core.appmanager.ComponentUtil;
import io.openems.edge.core.appmanager.ConfigurationTarget;
import io.openems.edge.core.appmanager.JsonFormlyUtil;
import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Type;
import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Validation;
import io.openems.edge.core.appmanager.OpenemsApp;
import io.openems.edge.core.appmanager.OpenemsAppCardinality;
import io.openems.edge.core.appmanager.TranslationUtil;

/**
* Describes a App for Fronius PV-Inverter.
*
* <pre>
{
"appId":"App.PvInverter.Fronius",
"alias":"Fronius PV-Wechselrichter",
"instanceId": UUID,
"image": base64,
"properties":{
"PV_INVERTER_ID": "pvInverter0",
"MODBUS_ID": "modbus0",
"IP": "192.168.178.85",
"PORT": "502",
"MODBUS_UNIT_ID": 1
},
"appDescriptor": {
"websiteUrl": URL
}
}
* </pre>
*/
@org.osgi.service.component.annotations.Component(name = "App.PvInverter.Fronius")
public class FroniusPvInverter extends AbstractPvInverter<Property> implements OpenemsApp {

public static enum Property {
// Components
PV_INVERTER_ID, //
MODBUS_ID, //
// User-Values
ALIAS, //
IP, // the ip for the modbus
PORT, //
MODBUS_UNIT_ID;

}

@Activate
public FroniusPvInverter(@Reference ComponentManager componentManager, ComponentContext context,
@Reference ConfigurationAdmin cm, @Reference ComponentUtil componentUtil) {
super(componentManager, context, cm, componentUtil);
}

@Override
protected ThrowingTriFunction<ConfigurationTarget, EnumMap<Property, JsonElement>, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() {
return (t, p, l) -> {

var alias = this.getValueOrDefault(p, Property.ALIAS, this.getName(l));
var ip = this.getValueOrDefault(p, Property.IP, "192.168.178.85");
var port = EnumUtils.getAsInt(p, Property.PORT);
var modbusUnitId = EnumUtils.getAsInt(p, Property.MODBUS_UNIT_ID);

var modbusId = this.getId(t, p, Property.MODBUS_ID, "modbus0");
var pvInverterId = this.getId(t, p, Property.PV_INVERTER_ID, "pvInverter0");

var factoryIdInverter = "PV-Inverter.Fronius";
var components = this.getComponents(factoryIdInverter, pvInverterId, modbusId, alias, ip, port);
var inverter = AbstractOpenemsApp.getComponentWithFactoryId(components, factoryIdInverter);
inverter.getProperties().put("modbusUnitId", new JsonPrimitive(modbusUnitId));

return new AppConfiguration(components);
};
}

@Override
public AppAssistant getAppAssistant(Language language) {
var bundle = AbstractOpenemsApp.getTranslationBundle(language);
return AppAssistant.create(this.getName(language)) //
.fields(JsonUtils.buildJsonArray() //
.add(JsonFormlyUtil.buildInput(Property.IP) //
.setLabel(TranslationUtil.getTranslation(bundle, "ipAddress")) //
.setDescription(TranslationUtil.getTranslation(bundle, "App.PvInverter.ip.description")) //
.setDefaultValue("192.168.178.85") //
.isRequired(true) //
.setValidation(Validation.IP) //
.build()) //
.add(JsonFormlyUtil.buildInput(Property.PORT) //
.setLabel(TranslationUtil.getTranslation(bundle, "port")) //
.setDescription(
TranslationUtil.getTranslation(bundle, "App.PvInverter.port.description")) //
.setInputType(Type.NUMBER) //
.setDefaultValue(502) //
.setMin(0) //
.isRequired(true) //
.build()) //
.add(JsonFormlyUtil.buildInput(Property.MODBUS_UNIT_ID) //
.setLabel(TranslationUtil.getTranslation(bundle, "modbusUnitId")) //
.setDescription(TranslationUtil.getTranslation(bundle, "modbusUnitId.description")) //
.setInputType(Type.NUMBER) //
.setDefaultValue(1) //
.setMin(0) //
.isRequired(true) //
.build()) //
.build())
.build();
}

@Override
public AppDescriptor getAppDescriptor() {
return AppDescriptor.create() //
.build();
}

@Override
protected Class<Property> getPropertyClass() {
return Property.class;
}

@Override
public OpenemsAppCardinality getCardinality() {
return OpenemsAppCardinality.MULTIPLE;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.osgi.service.component.annotations.Reference;

import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;

import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.function.ThrowingTriFunction;
Expand Down Expand Up @@ -87,7 +88,7 @@ protected ThrowingTriFunction<ConfigurationTarget, EnumMap<Property, JsonElement
var factoryIdInverter = "PV-Inverter.Kostal";
var components = this.getComponents(factoryIdInverter, pvInverterId, modbusId, alias, ip, port);
var inverter = AbstractOpenemsApp.getComponentWithFactoryId(components, factoryIdInverter);
inverter.getProperties().put("modbusUnitId", JsonUtils.parse(Integer.toString(modbusUnitId)));
inverter.getProperties().put("modbusUnitId", new JsonPrimitive(modbusUnitId));

return new AppConfiguration(components);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.osgi.service.component.annotations.Reference;

import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;

import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.function.ThrowingTriFunction;
Expand Down Expand Up @@ -86,7 +87,7 @@ protected ThrowingTriFunction<ConfigurationTarget, EnumMap<Property, JsonElement
var factoryIdInverter = "PV-Inverter.SMA.SunnyTripower";
var components = this.getComponents(factoryIdInverter, pvInverterId, modbusId, alias, ip, port);
var inverter = AbstractOpenemsApp.getComponentWithFactoryId(components, factoryIdInverter);
inverter.getProperties().put("modbusUnitId", JsonUtils.parse(Integer.toString(modbusUnitId)));
inverter.getProperties().put("modbusUnitId", new JsonPrimitive(modbusUnitId));

return new AppConfiguration(components);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public final String getWebsiteUrl() {
*/
public JsonObject toJsonObject() {
return JsonUtils.buildJsonObject() //
.addPropertyIfNotNull("websiteUrl", this.websiteUrl).build();
.addPropertyIfNotNull("websiteUrl", this.websiteUrl) //
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,14 @@ private DependencyConfig foreachDependency(OpenemsApp app, AppDependencyConfig a
if (appConfig.alias != null) {
appConfig.properties.addProperty("ALIAS", appConfig.alias);
}
var config = app.getAppConfiguration(target, appConfig.properties, l);
AppConfiguration config;
try {
config = app.getAppConfiguration(target, appConfig.properties, l);
} catch (OpenemsNamedException e) {
// can not get config of app
e.printStackTrace();
return null;
}
if (appConfig.alias != null) {
appConfig.properties.remove("ALIAS");
}
Expand All @@ -965,6 +972,13 @@ private DependencyConfig foreachDependency(OpenemsApp app, AppDependencyConfig a
} else {
var specificApp = this.getAppManagerImpl().findInstanceById(nextAppConfig.specificInstanceId);
dependencyApp = this.getAppManagerImpl().findAppById(specificApp.appId);
// fill up properties of existing app to make sure the appConfig can be get
specificApp.properties.entrySet().forEach(entry -> {
if (nextAppConfig.properties.has(entry.getKey())) {
return;
}
nextAppConfig.properties.add(entry.getKey(), entry.getValue());
});
}
if (alreadyIteratedApps.contains(dependencyApp) || !includeDependency.apply(app, dependency)) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ App.Meter.Socomec.Name = SOCOMEC Zähler
App.PvInverter.ip.description = Die IP-Adresse des PV-Wechselrichters.
App.PvInverter.port.description = Der Port des PV-Wechselrichters.

App.PvInverter.Fronius.Name = Fronius PV-Wechselrichter
App.PvInverter.Kaco.Name = KACO PV-Wechselrichter
App.PvInverter.Kostal.Name = KOSTAL PV-Wechselrichter
App.PvInverter.Sma.Name = SMA PV-Wechselrichter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ App.Meter.Socomec.Name = SOCOMEC Meter
App.PvInverter.ip.description = The IP address of the PV-Inverter.
App.PvInverter.port.description = The port of the PV-Inverter.

App.PvInverter.Fronius.Name = Fronius PV-Inverter
App.PvInverter.Kaco.Name = KACO PV-Inverter
App.PvInverter.Kostal.Name = KOSTAL PV-Inverter
App.PvInverter.Sma.Name = SMA PV Inverter
Expand Down

0 comments on commit e17d861

Please sign in to comment.