Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App Manager #1860

Merged
merged 30 commits into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
becfbcd
- Added Translation for Edge(de,en) and UI(cz,de,en,es,fr,nl)
Jun 21, 2022
2819cc2
added JsonArrayCollector
Jun 21, 2022
0dc4e05
added create and delete of components and subapps
Jun 21, 2022
e6d1ea7
added update for app and subapps
Jun 21, 2022
64d43d3
fix missing translation
Jun 21, 2022
534959d
added validation for dependencies
Jun 21, 2022
3b72a73
removed endless loop; adding and removing dependencies from other apps
Jun 21, 2022
6ca25ac
added HOME setting for ripple control reveiver; minor bug fixes
Jun 21, 2022
9693050
added dependency for HeatPump; added policy for properties
Jun 21, 2022
2d06725
code format; type safety
Jun 21, 2022
512bd28
seperated checkable config and validation; added language parameter t…
Jun 21, 2022
79881c9
added pvSelfConsumtion as dependency
Jun 21, 2022
9fb49a4
improvements creating an instance
Jun 21, 2022
e6c2c54
removed FENECON website url from javadoc
Jun 21, 2022
7b0f17e
improved validation
Jun 21, 2022
b699192
added warnings for UI
Jun 21, 2022
376b239
format & checkstyle
Jun 21, 2022
1c82957
added Unit-Test
Jun 21, 2022
0ad236f
minor test changes
Jun 21, 2022
7dc6882
renamed Apps to App Center
Jun 21, 2022
6700372
added translation for checkables
Jun 21, 2022
aa4a190
renamed counter to meter
Jun 21, 2022
4f9c2e6
added util class for translation to avoid exceptions
Jun 21, 2022
260110f
translation; clean up
Jun 21, 2022
caddacf
small translation changes; doc
Jun 21, 2022
804827b
fix apis; clean up
Jun 21, 2022
6be4ab7
javadoc; translation
Jun 21, 2022
4b8dd8b
using TranslationUtil
Jun 21, 2022
c4767c1
added fix for app routing
Jun 21, 2022
e09e112
Fix typo
sfeilmeier Jun 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions io.openems.common/src/io/openems/common/utils/EnumUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ public static <ENUM extends Enum<ENUM>> Optional<String> getAsOptionalString(Enu
}
}

/**
* Gets the member of the {@link EnumMap} as {@link Optional} {@link Integer}.
*
* @param <ENUM> the type of the EnumMap key
* @param map the {@link EnumMap}
* @param member the member
* @return the {@link Optional} {@link Integer} value
* @throws OpenemsNamedException on error
*/
public static <ENUM extends Enum<ENUM>> Optional<Integer> getAsOptionalInt(EnumMap<ENUM, JsonElement> map,
ENUM member) {
try {
return Optional.of(getAsInt(map, member));
} catch (OpenemsNamedException e) {
return Optional.empty();
}
}

/**
* Gets the member of the {@link EnumMap} as {@link JsonPrimitive}.
*
Expand Down
48 changes: 48 additions & 0 deletions io.openems.common/src/io/openems/common/utils/JsonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.stream.Collector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.Sets;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
Expand Down Expand Up @@ -291,8 +298,49 @@ public JsonObject build() {

}

public static class JsonArrayCollector implements Collector<JsonElement, JsonUtils.JsonArrayBuilder, JsonArray> {

@Override
public Set<Characteristics> characteristics() {
return Sets.<Characteristics>newHashSet().stream().collect(Sets.toImmutableEnumSet());
}

@Override
public Supplier<JsonArrayBuilder> supplier() {
return JsonUtils::buildJsonArray;
}

@Override
public BiConsumer<JsonArrayBuilder, JsonElement> accumulator() {
return JsonUtils.JsonArrayBuilder::add;
}

@Override
public BinaryOperator<JsonArrayBuilder> combiner() {
return (t, u) -> {
u.build().forEach(j -> t.add(j));
return t;
};
}

@Override
public Function<JsonArrayBuilder, JsonArray> finisher() {
return JsonArrayBuilder::build;
}

}

private static final Logger LOG = LoggerFactory.getLogger(JsonUtils.class);

/**
* Returns a Collector that accumulates the input elements into a new JsonArray.
*
* @return a Collector which collects all the input elements into a JsonArray
*/
public static Collector<JsonElement, JsonUtils.JsonArrayBuilder, JsonArray> toJsonArray() {
return new JsonUtils.JsonArrayCollector();
}

/**
* Creates a JsonArray using a Builder.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
package io.openems.edge.common.test;

import java.io.IOException;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentContext;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import io.openems.common.exceptions.OpenemsError;
import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.exceptions.OpenemsException;
import io.openems.common.jsonrpc.base.GenericJsonrpcResponseSuccess;
import io.openems.common.jsonrpc.base.JsonrpcRequest;
import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess;
import io.openems.common.jsonrpc.request.GetEdgeConfigRequest;
import io.openems.common.jsonrpc.request.UpdateComponentConfigRequest;
import io.openems.common.jsonrpc.response.GetEdgeConfigResponse;
import io.openems.common.session.Role;
import io.openems.common.types.EdgeConfig;
Expand All @@ -33,6 +41,8 @@ public class DummyComponentManager implements ComponentManager {
private final Clock clock;
private JsonObject edgeConfigJson;

private ConfigurationAdmin configurationAdmin = null;

public DummyComponentManager() {
this(Clock.systemDefaultZone());
}
Expand All @@ -56,7 +66,7 @@ public List<OpenemsComponent> getAllComponents() {
public <T extends OpenemsComponent> List<T> getEnabledComponentsOfType(Class<T> clazz) {
List<T> result = new ArrayList<>();
for (OpenemsComponent component : this.components) {
if (component.getClass().isInstance(clazz)) {
if (clazz.isInstance(component)) {
result.add((T) component);
}
}
Expand Down Expand Up @@ -167,6 +177,8 @@ public CompletableFuture<JsonrpcResponseSuccess> handleJsonrpcRequest(User user,

case GetEdgeConfigRequest.METHOD:
return this.handleGetEdgeConfigRequest(user, GetEdgeConfigRequest.from(request));
case UpdateComponentConfigRequest.METHOD:
return this.handleUpdateComponentConfigRequest(user, UpdateComponentConfigRequest.from(request));

default:
throw OpenemsError.JSONRPC_UNHANDLED_METHOD.exception(request.getMethod());
Expand All @@ -188,9 +200,33 @@ private CompletableFuture<JsonrpcResponseSuccess> handleGetEdgeConfigRequest(Use
return CompletableFuture.completedFuture(response);
}

private CompletableFuture<JsonrpcResponseSuccess> handleUpdateComponentConfigRequest(User user,
UpdateComponentConfigRequest request) throws OpenemsNamedException {
if (this.configurationAdmin == null) {
throw new OpenemsException("Can not update Component Config. ConfigurationAdmin is null!");
}
try {
for (var configuration : this.configurationAdmin.listConfigurations(request.getComponentId())) {
var properties = new Hashtable<String, JsonElement>();
for (var property : request.getProperties()) {
properties.put(property.getName(), property.getValue());
}
configuration.update(properties);
break;
}
return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(request.getId()));
} catch (IOException | InvalidSyntaxException e) {
throw new OpenemsException("Can not update Component Config.");
}
}

@Override
public Clock getClock() {
return this.clock;
}

public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
this.configurationAdmin = configurationAdmin;
}

}
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
eclipse.preferences.version=1
encoding//src/io/openems/edge/core/appmanager/dependency/translation_de.properties=UTF-8
encoding//src/io/openems/edge/core/appmanager/translation_de.properties=UTF-8
encoding/<project>=UTF-8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.osgi.service.cm.ConfigurationAdmin;
Expand All @@ -14,7 +13,8 @@
import com.google.gson.JsonElement;

import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.function.ThrowingBiFunction;
import io.openems.common.function.ThrowingTriFunction;
import io.openems.common.session.Language;
import io.openems.common.types.EdgeConfig;
import io.openems.common.utils.JsonUtils;
import io.openems.edge.app.api.ModbusTcpApiReadOnly.Property;
Expand All @@ -29,8 +29,7 @@
import io.openems.edge.core.appmanager.OpenemsAppCardinality;
import io.openems.edge.core.appmanager.OpenemsAppCategory;
import io.openems.edge.core.appmanager.validator.CheckAppsNotInstalled;
import io.openems.edge.core.appmanager.validator.Validator;
import io.openems.edge.core.appmanager.validator.Validator.Builder;
import io.openems.edge.core.appmanager.validator.ValidatorConfig;

/**
* Describes a App for ReadOnly Modbus/TCP Api.
Expand All @@ -45,8 +44,7 @@
"CONTROLLER_ID": "ctrlApiModbusTcp0"
},
"appDescriptor": {
"websiteUrl": <a href=
"https://docs.fenecon.de/de/_/latest/fems/apis.html#_fems_app_modbustcp_api_lesend">https://docs.fenecon.de/de/_/latest/fems/apis.html#_fems_app_modbustcp_api_lesend</a>
"websiteUrl": URL
}
}
* </pre>
Expand All @@ -66,8 +64,8 @@ public ModbusTcpApiReadOnly(@Reference ComponentManager componentManager, Compon
}

@Override
public AppAssistant getAppAssistant() {
return AppAssistant.create(this.getName()) //
public AppAssistant getAppAssistant(Language language) {
return AppAssistant.create(this.getName(language)) //
.build();
}

Expand All @@ -82,29 +80,19 @@ public OpenemsAppCategory[] getCategorys() {
return new OpenemsAppCategory[] { OpenemsAppCategory.API };
}

@Override
public String getImage() {
return OpenemsApp.FALLBACK_IMAGE;
}

@Override
public String getName() {
return "Modbus/TCP-Api Read-Only";
}

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

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

var controllerId = this.getId(t, p, Property.CONTROLLER_ID, "ctrlApiModbusTcp0");

List<EdgeConfig.Component> components = Lists.newArrayList(//
new EdgeConfig.Component(controllerId, this.getName(), "Controller.Api.ModbusTcp.ReadOnly",
new EdgeConfig.Component(controllerId, this.getName(l), "Controller.Api.ModbusTcp.ReadOnly",
JsonUtils.buildJsonObject() //
.build()));

Expand All @@ -113,14 +101,13 @@ protected ThrowingBiFunction<ConfigurationTarget, EnumMap<Property, JsonElement>
}

@Override
public Builder getValidateBuilder() {
return Validator.create() //
.setInstallableCheckableNames(new Validator.MapBuilder<>(new TreeMap<String, Map<String, ?>>()) //
.put(CheckAppsNotInstalled.COMPONENT_NAME, //
new Validator.MapBuilder<>(new TreeMap<String, Object>()) //
protected io.openems.edge.core.appmanager.validator.ValidatorConfig.Builder getValidateBuilder() {
return ValidatorConfig.create() //
.setInstallableCheckableConfigs(
Lists.newArrayList(new ValidatorConfig.CheckableConfig(CheckAppsNotInstalled.COMPONENT_NAME,
new ValidatorConfig.MapBuilder<>(new TreeMap<String, Object>()) //
.put("appIds", new String[] { "App.Api.ModbusTcp.ReadWrite" }) //
.build())
.build());
.build())));
}

@Override
Expand Down
Loading