From 1f6bacbc94d1f067f4315edc6c41dde595cd7aff Mon Sep 17 00:00:00 2001 From: Stefan Feilmeier Date: Fri, 3 Mar 2023 14:39:42 +0100 Subject: [PATCH 01/23] Start development of version 2023.4.0-SNAPSHOT --- io.openems.common/src/io/openems/common/OpenemsConstants.java | 4 ++-- ui/package-lock.json | 4 ++-- ui/package.json | 2 +- ui/src/app/user/user.component.html | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/io.openems.common/src/io/openems/common/OpenemsConstants.java b/io.openems.common/src/io/openems/common/OpenemsConstants.java index 2fe8e4c845d..a2e63c529e8 100644 --- a/io.openems.common/src/io/openems/common/OpenemsConstants.java +++ b/io.openems.common/src/io/openems/common/OpenemsConstants.java @@ -29,7 +29,7 @@ public class OpenemsConstants { *

* This is the month of the release. */ - public static final short VERSION_MINOR = 3; + public static final short VERSION_MINOR = 4; /** * The patch version of OpenEMS. @@ -43,7 +43,7 @@ public class OpenemsConstants { /** * The additional version string. */ - public static final String VERSION_STRING = ""; + public static final String VERSION_STRING = "SNAPSHOT"; /** * The complete version as a SemanticVersion. diff --git a/ui/package-lock.json b/ui/package-lock.json index 7ef2237d05d..50b7450d8a9 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "openems-ui", - "version": "2023.3.0", + "version": "2023.4.0-SNAPSHOT", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "openems-ui", - "version": "2023.3.0", + "version": "2023.4.0-SNAPSHOT", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "~15.1.2", diff --git a/ui/package.json b/ui/package.json index 537afcb15b8..933576338c8 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "openems-ui", - "version": "2023.3.0", + "version": "2023.4.0-SNAPSHOT", "license": "AGPL-3.0", "private": true, "dependencies": { diff --git a/ui/src/app/user/user.component.html b/ui/src/app/user/user.component.html index 4b9a4af58a6..0611f2439c9 100644 --- a/ui/src/app/user/user.component.html +++ b/ui/src/app/user/user.component.html @@ -105,8 +105,8 @@

About.build

From cf9bc0510187c683d45c9ec61baa668c4ebc5a19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Mar 2023 20:48:35 +0100 Subject: [PATCH 02/23] Bump fastexcel from 0.14.18 to 0.15.0 in /cnf (#2089) * Bump fastexcel from 0.14.18 to 0.15.0 in /cnf Bumps [fastexcel](https://github.com/dhatim/fastexcel) from 0.14.18 to 0.15.0. - [Release notes](https://github.com/dhatim/fastexcel/releases) - [Commits](https://github.com/dhatim/fastexcel/compare/0.14.18...0.15.0) --- updated-dependencies: - dependency-name: org.dhatim:fastexcel dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update bndrun --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Feilmeier --- cnf/pom.xml | 2 +- io.openems.edge.application/EdgeApp.bndrun | 2 +- io.openems.wrapper/bnd.bnd | 2 +- io.openems.wrapper/fastexcel.bnd | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index cfa780d8ae2..172bc773969 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -259,7 +259,7 @@ org.dhatim fastexcel - 0.14.18 + 0.15.0 diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index 498ddc75e96..b6b84813cb6 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -380,4 +380,4 @@ org.osgi.util.function;version='[1.2.0,1.2.1)',\ org.osgi.util.promise;version='[1.3.0,1.3.1)',\ reactive-streams;version='[1.0.4,1.0.5)',\ - rrd4j;version='[3.8.2,3.8.3)' \ No newline at end of file + rrd4j;version='[3.8.2,3.8.3)' diff --git a/io.openems.wrapper/bnd.bnd b/io.openems.wrapper/bnd.bnd index ff460d5d8a4..d9b5c084d6d 100644 --- a/io.openems.wrapper/bnd.bnd +++ b/io.openems.wrapper/bnd.bnd @@ -23,6 +23,6 @@ Bundle-Description: This wraps external java libraries that do not have OSGi hea com.google.gson;version='2.10.1',\ de.bytefish:pgbulkinsert;version='8.1',\ fr.turri:aXMLRPC;version='1.12',\ - org.dhatim:fastexcel;version='0.14.3',\ + org.dhatim:fastexcel;version='0.15.0',\ org.eclipse.paho.mqttv5.client;version='1.2.5',\ org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm;version='1.6.4',\ diff --git a/io.openems.wrapper/fastexcel.bnd b/io.openems.wrapper/fastexcel.bnd index b311f87dbb8..1f91429a216 100644 --- a/io.openems.wrapper/fastexcel.bnd +++ b/io.openems.wrapper/fastexcel.bnd @@ -1,9 +1,9 @@ Bundle-Name: fastexcel Bundle-DocURL: https://github.com/dhatim/fastexcel Bundle-License: https://opensource.org/licenses/Apache-2.0 -Bundle-Version: 0.14.18 +Bundle-Version: 0.15.0 -Include-Resource: @fastexcel-0.14.18.jar +Include-Resource: @fastexcel-0.15.0.jar -dsannotations: * From 52664f14022ecfe57316a1cda894d880ad1c5618 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 Mar 2023 22:22:22 +0100 Subject: [PATCH 03/23] Bump org.apache.felix.http.jetty from 4.2.2 to 5.0.4 in /cnf (#2088) * Bump org.apache.felix.http.jetty from 4.2.2 to 5.0.4 in /cnf Bumps org.apache.felix.http.jetty from 4.2.2 to 5.0.4. --- updated-dependencies: - dependency-name: org.apache.felix:org.apache.felix.http.jetty dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Fix imports, dependencies and logs * Update bndrun --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Feilmeier --- cnf/pom.xml | 20 +++++++++---------- .../BackendApp.bndrun | 2 +- io.openems.backend.b2brest/bnd.bnd | 4 ++-- .../openems/backend/b2brest/RestHandler.java | 8 +++----- io.openems.edge.application/EdgeApp.bndrun | 8 ++++++-- io.openems.edge.controller.api.rest/bnd.bnd | 4 ++-- .../edge/controller/api/rest/RestHandler.java | 19 +++++++----------- 7 files changed, 30 insertions(+), 35 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index 172bc773969..bae1c18cf3b 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -1,12 +1,9 @@ 4.0.0 - local central 0.0.0 - pom - @@ -197,25 +194,26 @@ org.apache.felix.framework 7.0.5 - - - - org.apache.felix - org.apache.felix.inventory - 1.1.0 - org.apache.felix org.apache.felix.http.jetty - 4.2.2 + 5.0.4 + org.apache.felix org.apache.felix.http.servlet-api 2.1.0 + + + + org.apache.felix + org.apache.felix.inventory + 1.1.0 + diff --git a/io.openems.backend.application/BackendApp.bndrun b/io.openems.backend.application/BackendApp.bndrun index 3f6b0a7c0f4..fd9ac7ffb24 100644 --- a/io.openems.backend.application/BackendApp.bndrun +++ b/io.openems.backend.application/BackendApp.bndrun @@ -100,7 +100,7 @@ org.apache.commons.commons-io;version='[2.11.0,2.11.1)',\ org.apache.felix.configadmin;version='[1.9.26,1.9.27)',\ org.apache.felix.eventadmin;version='[1.6.4,1.6.5)',\ - org.apache.felix.http.jetty;version='[4.2.2,4.2.3)',\ + org.apache.felix.http.jetty;version='[5.0.4,5.0.5)',\ org.apache.felix.http.servlet-api;version='[2.1.0,2.1.1)',\ org.apache.felix.inventory;version='[1.1.0,1.1.1)',\ org.apache.felix.metatype;version='[1.2.4,1.2.5)',\ diff --git a/io.openems.backend.b2brest/bnd.bnd b/io.openems.backend.b2brest/bnd.bnd index 188f6a5c90b..dd46ac7175b 100644 --- a/io.openems.backend.b2brest/bnd.bnd +++ b/io.openems.backend.b2brest/bnd.bnd @@ -8,8 +8,8 @@ Bundle-Version: 1.0.0.${tstamp} Java-WebSocket,\ io.openems.backend.common,\ io.openems.common,\ - javax.servlet-api,\ - org.apache.felix.http.jetty + org.apache.felix.http.jetty,\ + org.apache.felix.http.servlet-api,\ -testpath: \ ${testpath} diff --git a/io.openems.backend.b2brest/src/io/openems/backend/b2brest/RestHandler.java b/io.openems.backend.b2brest/src/io/openems/backend/b2brest/RestHandler.java index dce3bd937ba..a8abe998854 100644 --- a/io.openems.backend.b2brest/src/io/openems/backend/b2brest/RestHandler.java +++ b/io.openems.backend.b2brest/src/io/openems/backend/b2brest/RestHandler.java @@ -13,10 +13,6 @@ import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.slf4j.Logger; @@ -34,6 +30,8 @@ import io.openems.common.jsonrpc.base.JsonrpcResponseError; import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; import io.openems.common.utils.JsonUtils; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; public class RestHandler extends AbstractHandler { @@ -47,7 +45,7 @@ public RestHandler(B2bRest parent) { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException { + throws IOException { try { var user = this.authenticate(request); diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index b6b84813cb6..fddc20d64c6 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -361,13 +361,17 @@ org.apache.commons.math3;version='[3.6.1,3.6.2)',\ org.apache.felix.configadmin;version='[1.9.26,1.9.27)',\ org.apache.felix.eventadmin;version='[1.6.4,1.6.5)',\ - org.apache.felix.http.jetty;version='[4.2.2,4.2.3)',\ + org.apache.felix.http.jetty;version='[5.0.4,5.0.5)',\ org.apache.felix.http.servlet-api;version='[2.1.0,2.1.1)',\ org.apache.felix.inventory;version='[1.1.0,1.1.1)',\ org.apache.felix.metatype;version='[1.2.4,1.2.5)',\ org.apache.felix.scr;version='[2.2.6,2.2.7)',\ org.apache.felix.webconsole;version='[4.7.2,4.7.3)',\ org.apache.felix.webconsole.plugins.ds;version='[2.2.0,2.2.1)',\ + org.eclipse.jetty.client;version='[9.4.28,9.4.29)',\ + org.eclipse.jetty.http;version='[9.4.28,9.4.29)',\ + org.eclipse.jetty.io;version='[9.4.28,9.4.29)',\ + org.eclipse.jetty.util;version='[9.4.28,9.4.29)',\ org.eclipse.paho.mqttv5.client;version='[1.2.5,1.2.6)',\ org.jetbrains.kotlin.osgi-bundle;version='[1.8.10,1.8.11)',\ org.jsoup;version='[1.15.4,1.15.5)',\ @@ -380,4 +384,4 @@ org.osgi.util.function;version='[1.2.0,1.2.1)',\ org.osgi.util.promise;version='[1.3.0,1.3.1)',\ reactive-streams;version='[1.0.4,1.0.5)',\ - rrd4j;version='[3.8.2,3.8.3)' + rrd4j;version='[3.8.2,3.8.3)' \ No newline at end of file diff --git a/io.openems.edge.controller.api.rest/bnd.bnd b/io.openems.edge.controller.api.rest/bnd.bnd index 03028b82c4e..49dd31822a9 100644 --- a/io.openems.edge.controller.api.rest/bnd.bnd +++ b/io.openems.edge.controller.api.rest/bnd.bnd @@ -10,8 +10,8 @@ Bundle-Version: 1.0.0.${tstamp} io.openems.edge.controller.api,\ io.openems.edge.controller.api.common,\ io.openems.edge.timedata.api,\ - javax.servlet-api,\ - org.apache.felix.http.jetty + org.apache.felix.http.jetty,\ + org.apache.felix.http.servlet-api,\ -testpath: \ ${testpath} diff --git a/io.openems.edge.controller.api.rest/src/io/openems/edge/controller/api/rest/RestHandler.java b/io.openems.edge.controller.api.rest/src/io/openems/edge/controller/api/rest/RestHandler.java index 41c670974ee..77001e0c390 100644 --- a/io.openems.edge.controller.api.rest/src/io/openems/edge/controller/api/rest/RestHandler.java +++ b/io.openems.edge.controller.api.rest/src/io/openems/edge/controller/api/rest/RestHandler.java @@ -16,10 +16,6 @@ import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.slf4j.Logger; @@ -59,6 +55,8 @@ import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.jsonapi.JsonApi; import io.openems.edge.common.user.User; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; public class RestHandler extends AbstractHandler { @@ -72,7 +70,7 @@ public RestHandler(AbstractRestApi parent) { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException { + throws IOException { try { var user = this.authenticate(request); @@ -218,18 +216,15 @@ private boolean handleGet(User user, ChannelAddress channelAddress, Request base HttpServletResponse response) throws OpenemsNamedException { user.assertRoleIsAtLeast("HTTP GET", Role.GUEST); - if (this.parent.isDebugModeEnabled()) { - this.parent.logInfo(this.log, - "REST call by User [" + user.getName() + "]: GET Channel [" + channelAddress.toString() + "]"); - } - var components = this.parent.getComponentManager().getEnabledComponents(); var channels = getChannels(components, channelAddress); // Return with error when no matching channel was found if (channels.size() == 0) { - this.parent.logWarn(this.log, "REST call by User [" + user.getName() + "]: GET Channel [" - + channelAddress.toString() + "] Result [No Match]"); + if (this.parent.isDebugModeEnabled()) { + this.parent.logWarn(this.log, "REST call by User [" + user.getName() + "]: GET Channel [" + + channelAddress.toString() + "] Result [No Match]"); + } response.setStatus(HttpServletResponse.SC_NOT_FOUND); return false; } From 99e9d0aa99f5362e1f625f4a4c6d1c7767f15bfe Mon Sep 17 00:00:00 2001 From: TimStoecker <79842855+TimStoecker@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:15:03 +0100 Subject: [PATCH 04/23] Docs: use Eclipse compatible code formatting in IntelliJ IDEA (#2086) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Expanded intellij Documentation to include the ability to use the eclipse code format * Changed Eclipse Path to generic string Co-authored-by: Tim Stöcker --- .../images/intellij-code-formatter-enable.png | Bin 0 -> 104867 bytes .../images/intellij-code-formatter-format.png | Bin 0 -> 93823 bytes .../images/intellij-code-formatter-path.png | Bin 0 -> 93785 bytes .../intellij-code-formatter-settings.png | Bin 0 -> 104099 bytes .../assets/images/intellij-code-formatter.png | Bin 0 -> 134083 bytes doc/modules/ROOT/pages/intellij.adoc | 28 ++++++++++++++++++ 6 files changed, 28 insertions(+) create mode 100644 doc/modules/ROOT/assets/images/intellij-code-formatter-enable.png create mode 100644 doc/modules/ROOT/assets/images/intellij-code-formatter-format.png create mode 100644 doc/modules/ROOT/assets/images/intellij-code-formatter-path.png create mode 100644 doc/modules/ROOT/assets/images/intellij-code-formatter-settings.png create mode 100644 doc/modules/ROOT/assets/images/intellij-code-formatter.png diff --git a/doc/modules/ROOT/assets/images/intellij-code-formatter-enable.png b/doc/modules/ROOT/assets/images/intellij-code-formatter-enable.png new file mode 100644 index 0000000000000000000000000000000000000000..fd24cf9c87afc2be18bce67bd86ef0e880033d20 GIT binary patch literal 104867 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 KLPY}FKK~1`qaOwU literal 0 HcmV?d00001 diff --git a/doc/modules/ROOT/assets/images/intellij-code-formatter-format.png b/doc/modules/ROOT/assets/images/intellij-code-formatter-format.png new file mode 100644 index 0000000000000000000000000000000000000000..fa1a73880a41a7387e5ea4d42a998e5f432995c0 GIT binary patch literal 93823 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 QwF4^yJrmt3ZO7>U0nuZ~`2YX_ literal 0 HcmV?d00001 diff --git a/doc/modules/ROOT/assets/images/intellij-code-formatter-settings.png b/doc/modules/ROOT/assets/images/intellij-code-formatter-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..960400d823fe0ac859d0b7c00716dcaeb463dcd7 GIT binary patch literal 104099 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

xPH2 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
    qbJ$?dbDpW(ZqXt>(C(5?$&9# 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 literal 0 HcmV?d00001 diff --git a/doc/modules/ROOT/assets/images/intellij-code-formatter.png b/doc/modules/ROOT/assets/images/intellij-code-formatter.png new file mode 100644 index 0000000000000000000000000000000000000000..a270958f16c5836753ce29e5769e7ceba03124e6 GIT binary patch literal 134083 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 z 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 literal 0 HcmV?d00001 diff --git a/doc/modules/ROOT/pages/intellij.adoc b/doc/modules/ROOT/pages/intellij.adoc index 6abfb8cf9a2..fce2a42c0eb 100644 --- a/doc/modules/ROOT/pages/intellij.adoc +++ b/doc/modules/ROOT/pages/intellij.adoc @@ -49,6 +49,34 @@ image::intellij-new-module.png[] Rightclick on an existing module: New -> Module + Amdatu-> Project Template Project (Stringtemplate) ++ +.. add Support for Eclipse Code Formatting ++ +Search for 'Adapter for Eclipse Code Formatter' in the Plugin store ++ +.download Adapter for Eclipse Code Formatter +image::intellij-code-formatter.png[] ++ +After restarting the IDE go to Settings -> Other Settings -> Adapter for Eclipse Code Formatter ++ +.Adapter Settings +image::intellij-code-formatter-settings.png[] ++ +Check the radiobutton for "Use Eclipse's Code Formatter" ++ +.Enable Adapter +image::intellij-code-formatter-enable.png[] ++ +Type in your Eclipse installation folder ++ +.Set Eclipse Path +image::intellij-code-formatter-path.png[] ++ +Choose 'Eclipse 2.1 [built-in]' as a formatter config ++ +.Choose Format +image::intellij-code-formatter-format.png[] +Now Reformat Code will use the Eclipse format (e.g. Use TAB instead of Whitespaces) == Hints - intellij problems .. If you have some problems - for example java version is not found: look in File -> Project Structure -> Project From 77053fb58a970dbd8f62824105438c63ec548ca1 Mon Sep 17 00:00:00 2001 From: TimStoecker <79842855+TimStoecker@users.noreply.github.com> Date: Tue, 14 Mar 2023 23:04:54 +0100 Subject: [PATCH 05/23] Implementation of the Webasto Unite electric vehicle charging station (#2076) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implementation has been carried out during OpenEMS Hackathon Q1/2023 and is not yet fully feature tested. Please consider it BETA quality == Compatibility ** https://charging.webasto.com/de-de/produkte/webasto-unite/[Webasto Unite] == Additional application notes The implementation includes: ** Reading actual values from the charging station ** Setting charge power/current set-points via OpenEMS Edge EVCS Controllers --------- Co-authored-by: Tim Stöcker Co-authored-by: Maximilian Lang Co-authored-by: Sebastian Asen Co-authored-by: Stefan Feilmeier --- io.openems.edge.application/EdgeApp.bndrun | 2 + .../bnd.bnd | 3 +- .../edge/evcs/hypercharger/MyConfig.java | 2 +- .../src/io/openems/edge/evcs/api/Evcs.java | 2 +- io.openems.edge.evcs.webasto.unite/.classpath | 12 + io.openems.edge.evcs.webasto.unite/.gitignore | 2 + io.openems.edge.evcs.webasto.unite/.project | 23 ++ .../org.eclipse.core.resources.prefs | 2 + io.openems.edge.evcs.webasto.unite/bnd.bnd | 15 + ...UNITE_Modbus_Register_1-00_external_V1.pdf | Bin 0 -> 216052 bytes .../readme.adoc | 20 ++ .../edge/evcs/webasto/unite/Config.java | 37 +++ .../edge/evcs/webasto/unite/WebastoImpl.java | 309 ++++++++++++++++++ .../webasto/unite/WebastoReadHandler.java | 67 ++++ .../edge/evcs/webasto/unite/api/Webasto.java | 261 +++++++++++++++ .../test/.gitignore | 0 .../edge/evcs/webasto/unite/MyConfig.java | 94 ++++++ .../edge/evcs/webasto/unite/WebastoTest.java | 28 ++ 18 files changed, 876 insertions(+), 3 deletions(-) create mode 100644 io.openems.edge.evcs.webasto.unite/.classpath create mode 100644 io.openems.edge.evcs.webasto.unite/.gitignore create mode 100644 io.openems.edge.evcs.webasto.unite/.project create mode 100644 io.openems.edge.evcs.webasto.unite/.settings/org.eclipse.core.resources.prefs create mode 100644 io.openems.edge.evcs.webasto.unite/bnd.bnd create mode 100644 io.openems.edge.evcs.webasto.unite/doc/Webasto_UNITE_Modbus_Register_1-00_external_V1.pdf create mode 100644 io.openems.edge.evcs.webasto.unite/readme.adoc create mode 100644 io.openems.edge.evcs.webasto.unite/src/io/openems/edge/evcs/webasto/unite/Config.java create mode 100644 io.openems.edge.evcs.webasto.unite/src/io/openems/edge/evcs/webasto/unite/WebastoImpl.java create mode 100644 io.openems.edge.evcs.webasto.unite/src/io/openems/edge/evcs/webasto/unite/WebastoReadHandler.java create mode 100644 io.openems.edge.evcs.webasto.unite/src/io/openems/edge/evcs/webasto/unite/api/Webasto.java create mode 100644 io.openems.edge.evcs.webasto.unite/test/.gitignore create mode 100644 io.openems.edge.evcs.webasto.unite/test/io/openems/edge/evcs/webasto/unite/MyConfig.java create mode 100644 io.openems.edge.evcs.webasto.unite/test/io/openems/edge/evcs/webasto/unite/WebastoTest.java diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index fddc20d64c6..5a94e519be6 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -119,6 +119,7 @@ bnd.identity;id='io.openems.edge.evcs.ocpp.common',\ bnd.identity;id='io.openems.edge.evcs.ocpp.ies.keywatt.singleccs',\ bnd.identity;id='io.openems.edge.evcs.ocpp.server',\ + bnd.identity;id='io.openems.edge.evcs.webasto.unite',\ bnd.identity;id='io.openems.edge.fenecon.dess',\ bnd.identity;id='io.openems.edge.fenecon.mini',\ bnd.identity;id='io.openems.edge.fenecon.pro',\ @@ -271,6 +272,7 @@ io.openems.edge.evcs.ocpp.abl;version=snapshot,\ io.openems.edge.evcs.ocpp.common;version=snapshot,\ io.openems.edge.evcs.ocpp.ies.keywatt.singleccs;version=snapshot,\ + io.openems.edge.evcs.webasto.unite;version=snapshot,\ io.openems.edge.evcs.ocpp.server;version=snapshot,\ io.openems.edge.fenecon.dess;version=snapshot,\ io.openems.edge.fenecon.mini;version=snapshot,\ diff --git a/io.openems.edge.evcs.alpitronic.hypercharger/bnd.bnd b/io.openems.edge.evcs.alpitronic.hypercharger/bnd.bnd index d1372ebb270..865db1aa41d 100644 --- a/io.openems.edge.evcs.alpitronic.hypercharger/bnd.bnd +++ b/io.openems.edge.evcs.alpitronic.hypercharger/bnd.bnd @@ -13,4 +13,5 @@ Bundle-Version: 1.0.0.${tstamp} io.openems.edge.timedata.api,\ -testpath: \ - ${testpath} \ No newline at end of file + ${testpath},\ + com.ghgande.j2mod,\ \ No newline at end of file diff --git a/io.openems.edge.evcs.alpitronic.hypercharger/test/io/openems/edge/evcs/hypercharger/MyConfig.java b/io.openems.edge.evcs.alpitronic.hypercharger/test/io/openems/edge/evcs/hypercharger/MyConfig.java index 3d8cede869d..83538278ff8 100644 --- a/io.openems.edge.evcs.alpitronic.hypercharger/test/io/openems/edge/evcs/hypercharger/MyConfig.java +++ b/io.openems.edge.evcs.alpitronic.hypercharger/test/io/openems/edge/evcs/hypercharger/MyConfig.java @@ -82,7 +82,7 @@ public String modbus_id() { @Override public String Modbus_target() { - return ConfigUtils.generateReferenceTargetFilter(this.modbus_id(), this.modbus_id()); + return ConfigUtils.generateReferenceTargetFilter(this.id(), this.modbus_id()); } @Override diff --git a/io.openems.edge.evcs.api/src/io/openems/edge/evcs/api/Evcs.java b/io.openems.edge.evcs.api/src/io/openems/edge/evcs/api/Evcs.java index 53a8b9c22e2..88b4c7314dc 100644 --- a/io.openems.edge.evcs.api/src/io/openems/edge/evcs/api/Evcs.java +++ b/io.openems.edge.evcs.api/src/io/openems/edge/evcs/api/Evcs.java @@ -411,7 +411,7 @@ public default void _setPhases(Phases value) { * @param value the next value */ public default void _setPhases(Integer value) { - if (value == null) { + if (value == null || value == 0) { this._setPhases(Phases.THREE_PHASE); return; } diff --git a/io.openems.edge.evcs.webasto.unite/.classpath b/io.openems.edge.evcs.webasto.unite/.classpath new file mode 100644 index 00000000000..43d68895d03 --- /dev/null +++ b/io.openems.edge.evcs.webasto.unite/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/io.openems.edge.evcs.webasto.unite/.gitignore b/io.openems.edge.evcs.webasto.unite/.gitignore new file mode 100644 index 00000000000..c2b941a96de --- /dev/null +++ b/io.openems.edge.evcs.webasto.unite/.gitignore @@ -0,0 +1,2 @@ +/bin_test/ +/generated/ diff --git a/io.openems.edge.evcs.webasto.unite/.project b/io.openems.edge.evcs.webasto.unite/.project new file mode 100644 index 00000000000..bf815f339b3 --- /dev/null +++ b/io.openems.edge.evcs.webasto.unite/.project @@ -0,0 +1,23 @@ + + + io.openems.edge.evcs.webasto.unite + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/io.openems.edge.evcs.webasto.unite/.settings/org.eclipse.core.resources.prefs b/io.openems.edge.evcs.webasto.unite/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/io.openems.edge.evcs.webasto.unite/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/io.openems.edge.evcs.webasto.unite/bnd.bnd b/io.openems.edge.evcs.webasto.unite/bnd.bnd new file mode 100644 index 00000000000..948eb642dda --- /dev/null +++ b/io.openems.edge.evcs.webasto.unite/bnd.bnd @@ -0,0 +1,15 @@ +Bundle-Name: OpenEMS Edge EVCS Webasto Unite +Bundle-Vendor: Consolinno Energy GmbH +Bundle-License: https://opensource.org/licenses/EPL-2.0 +Bundle-Version: 1.0.0.${tstamp} + +-buildpath: \ + ${buildpath},\ + io.openems.common,\ + io.openems.edge.bridge.modbus,\ + io.openems.edge.common,\ + io.openems.edge.evcs.api,\ + +-testpath: \ + ${testpath},\ + com.ghgande.j2mod,\ diff --git a/io.openems.edge.evcs.webasto.unite/doc/Webasto_UNITE_Modbus_Register_1-00_external_V1.pdf b/io.openems.edge.evcs.webasto.unite/doc/Webasto_UNITE_Modbus_Register_1-00_external_V1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3c3d60e019832d24e45658e77f19ce95ba46c12b GIT binary patch literal 216052 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

    sMeE8>1& zh#kgjRo4bx>|>SBF?p+9%f{#&&EwKDQ?8QfRLnUiuFfL7RI?a%)Hs@$NL8t0F=`~y z8eR{Jz>0<_)UtiDS8ilwqoieIahAdfycd|>dQSOX*GBt6^P)bN`N^YJd_HNGeAYEd zKfw<#_`NlC-x1%e8*nCm@HCV7Nq4^2#Wdxns8 zyq{1(OTDzMx&`i}l78K+BSBM-$#JtD4-a1|Ae+T6Gpbm6NfTxBSoIvOk_9u3IOY-d z253%~Q~~HLml{Ke7$w>@U4N%jAT!>oGoM+yz;-7ROYs2mb&5&imMBfmh zkpNQ7x>+y7t5*%MThcO$X2itAD%ADjltgx_X3S0s;(+`};RB>abV`=D42yf_xkK~9 zu^Ex1ya+OWWZ6GtnV&NMj~7{!a-K~>NqILwn2`ktk@?Yn%wFIug7laEd^9z)ah*dF zPeSm1q45g=D(r{G6O^+NnxR~W4LzOLBYM@#fvbV@9k*-IiDVj)D#T7&2JBMRg0{5f z#=MtD$uQK44|l?hcE8%&e$yJ?v^s^L?G7@>M`qv2 zs8NNDOeZgQtXBfsg;nf~@XOnAYV|#<*TVEP$4zIu%x4&R;td!JYd*N1FRPWtt4Zo5sgcPN%uC(eb89dFT@ttDGN$$Z^% z6R(xcMC5}%{hetuipLVxbA2Zw-KPhNb75M-Qk{*c7mBZQitP&Wy2<{XlF+@OjWzG3EAS&vJOIG)U_yqo!&NJ#pqcYO^!eTRt^KjbSAHS_}LLI~El!L~>SN^q>50SY%vKErzaXZD)c|U;U zDsLahk{8IjKd@4VBE)`hR+Pg@##VWql)ijE=#S3cnV!i^8-L^KW(I40e=yfe2YqH* zS)!~WL+z67_Z**o$wi(T7G9m5vFb#mGYPV8dT~m0LrHn4+#Dv}-~MGh?$J^7Zch46 zc)4}ad)=p`Qww;}#}%;QiQ3pc6R`*XO^Pehk~Am(7oa&iUQ@yx@8YWv{d~u9v*%1s zFY?i#T61DNOWB;}oyoJn-@UGQcA7C)oPBW#GJ3>k;KVDXBEvV}-KyV_(iGI(Oz{-& zr1$T3p)_bFzS{cGO+?-EJ@Sc~m*S7t&WI&$p78Yu7v$-%#WCNNx*gei9*f=eE60Ml z0Qsfebs1TA9^a^WM@ojvFBmfWu}jCXd?X+nawc?_q{z(p_T9fkvp@9i56&cy1nR+_bHH$?U;o(dJ8jcXWWF|>ut0BGiO_$wnag8eA-J0_vvBl3PkH_ z`KOy)SC^BDZa0ILjCZ97Eyqcla`+Ey@ycaq8kkFjWnX^YJAg|n^K99{vw{jDh?HrC z%?NfBfvXS*5-3746mGDR{t}s#DAckbqC-#`eb-tEu8yiU;Y5v*u--SI-gP^ZvOs;N zzF*zW&z(Phv2BUo=EoUjX&ExXYW8^W?~88pUNK%rMDr>MY&YMEAq!qd{OX(*oNCsG z6fVn@R^C-z0{I0c)2m1^TaxLMPO?vPwbYB&r6w^sEq|(?sWZ%Ii%SWHmJfAg49#|X37pezHG3we`mBVWmQPb_MJU-1g0?p+_Os@%~`p*V>L0g;MX>IxOYX@Ip1n-R1997xEE~By9rbt)|Bgu6* z2XV95YUdviGTGRZ^?%Zemi1S*$qjlST2Q4_E~U1&iP#F`#|)urB!_Ex&JMeJ>%V)} zoU3`XB)6xOcFF&i_(l&K@v0LYwQD%^sIV> znv^ERaC1fZ@>T!zdjhcaEjqARwSb`mYDN-hF)`+anGN%&83!Z2%SVOt8W4=b_TRM_ z-eQm@HE<1w+ug6nDjV(tyOEj2i#=+EzzJ+Iw1)6E2hwq%gJp*)5(Hl5z#zdMz=icH z>dh$)2x9IRkjJqYIFX=%t~~48(JtQ>W?*4eoU)`j71tuQnL!0EDnFvZYF-84*JYLh zZN{Q2K7GZ%>muz!0@FaYs%CnBNGO}P@fPQ z;P6i#!_r)GP~gAIM6@6t)kkSvFD^9V$~WF@KBI^Ekc}N+{7f)lL90SwG%({JqXb{T zlPzMVutiz6N|LgzV35HoS1k{6xW$3}L!|9GGQ7RiS?^lkvZ4#bwhdO28dvEFKfr<> z)Uvn?F`(6uUb9OfX)Mh~Hu9o^%phNEsGuTaBv%zCVz6Cxtap)Pg~iB~U4ACGaeiO; zWOWG6SU6mW8@HhGe&ZFORc6E$;Nz%8`GahRkcEw?pNteN0`2KkA(UAx(qHV9p)#!s zRf5DMgc^bHmw{8X;MZSAIi)i4ist;%}au$&a0g*0`q!K3*l?)1` zrw(Fa0fa%ZKSg1D5Fil(In=8U zAU-^ zZeTFQpiaIzo;q0W9!i5$G0HfARD={wJg`KFKm?%z0aF`_2Cx%!eU!+&3kfI%I%1@$ zPA(Fn6awiY>n@B8Ad?gTttC<-h0HKQ6(l7nrWAu_Iu!vi7ULF5csli%hzFH{66=nF zFH*hJ)M(?YaImH2vw0OiR&s8KBs>UdDb-zDLsfMe78EOJn*cnDA^ zr{u_!X;lvZYoY|F3YCmPm2s3lK0Y5xc|kO5^Ta+7eA7~yOq!E%B_`k2h~6Cn3V)Oe z4;|4&6(AJ&{Pl236{ZXc2povmgoHgM)L9*}LZI5>U^(cH0wIsyK`B7UJ!n*>-BGK7 z@k1eoabN-U)qB8rW7f7I;B<6nXc{zv%-AGDammYOFd`_S>;Nk~dQc|8 zCI57!0FbbX4&V0RN}Du>sVU7_4k(&r|4jig-wpp0GV3IMx`yfIfASTRF7*`k< zP#UOG;(3wyM-l}}9U4RHugjAXe;7wpC`$R!kZ-_!m}0t!#H#5kA;j5e?!i?#t>B`u zRdXJO*jEiTm5l;n4w{{QJ6v~S%S~9PI$Si!fV@geVI3#eAt01`fXa(|0gIg+tvSDfeU_Jqd5P(vv3Yqfh>Yvd{u3bP$*I5ge7{-KLBGexN zF$^%OHV_8lUWD5cf;6MfX!P4;EpY1xs;p234u~jReAbAJgC31edf35B3Y!2wWf%Y5c!Fpi>7vAM-!e+5HD6)_e_$TBfyV$0QP4F8ar z0LxbC{DpctfjFq|kRc|cbcN`83^N*R7D)jqH=Bz^5U?;Yp>i8Aa4M2OT;N$@*Fa20 z3?zm)NoC`JO0jiK5dU5`oUr9#X^t2yPzT3d6J3MGx4MG>{Sn|F=&f%qyw{glaGCl% zeQ}Tw!N3n zo-ROsw$@L$pHB?IhZb+S+TMFfI67&kvGjwTm$9QCz!3WK`5(Dg z!*2|90cbD<9>Z39f^sT=H*kBO!RosK0waU`GHQ4)HE~z*0G5G!!2lqzPR;*@4RK%e zK7-Vg0BoQOz<_;a-x#QJ)jtFL<@d*hArK4rCOM@S8}=YZwnJl&f~^&86>SxAz&tyM zfr*X|JOv#ZVge@G_NRb`92*~JB0`7`CnUVZOe+y5!8mKuI1(fCAYO0;ZzU8KUL|~J zLNi14pI8O3w~-)0`UpEgO)fpnXCOm}W~Er>T^$UKmxC167_G8VJ}!0$~BOUK-sioWyU zF*LBSkdxC(KvKpMfndx$L!5+Z#$Zf-2VoZG>S|q`1hO}S{Hd1t;Vb+mdbL7fjf^^% zid)BNVPqf9%Gzz(EeXR0kz$2ckJ1%)An#QIU8s~`gX@ID;V`I;V`r~#Xb|j!e%yt_ znPn$Q$0j9ZWkcI_F#Fr%*&ddFo#<7>6m}!^+*3|^z$u)|^ z!antOohM#BKTxO*h)4s>4WEG|*^M~DaiNf!KWorFiZ=xZg41JMZI_6=QrYG5BIr~g z$2A$OO(B*Wt*Y((pq?DPEF9rd_e$EaUb)A~;$R8Wh&n#CrCK50g#@AI@7#5XErZk=iBdqKNtvQRGbdNSFgqSk zyBk%4#5V-k62wcUwv3DSq?D~7&QWV_y1<4@Qo zasPr3m?_95%hGYKzc-1)8gfvoHh7AGmbD-Hti+B>Vkm^k^A343i+~k|iGw8q{qQVY z@x2{zi$3@wq`Qc;=1PGm?&}|Vyqn|78oe@dcC<_DkiQcg58U{;KK3UKY`d-b>squc zQ?i&H8*^!k*IAn`QAEF}mSt+~@q3~xZZaCuZ!z=+XFm}|1N~cj7G{_@?oU+DuqvuV z>gV#qsDit-qgIs8~MsJ6BD!c5wH-4GE8M)%hSDI=c}bs1$Xgf63d6k zS78>QG76%USGCo~{*HZ}OXI74YbhKo4qrtK4>O{k&4aai zFiz5TQNdJT5uZX*(LHLfm-E)J=GQ#{2^Y$H-PLvbR<9^u)pm-tT`;kXdgy;})-BBJ z1l)*UoR;VF4ZcR-R<8feCp7g{el*A0mta?=8%|T0wfj~a;QA6=My<{uQmdzT(*KvQ zrPa^jyt#4sPeNIxrCywFxkW4>UU5Shm*wT{K>rJJlO}wRq2*}$1XpNpSZPhgJZfC zt${Y_My4A67rYluJ%RUEFIUOF{qXapkrA|akdFl1V^g2(&N)W#9_M|>jV>=(#JG#` zZC|4Go@~4ODNUt2CQpH!tSMdh5%$3lmF=XBj+!W~>QoRN=)@tZ58gE)W-(0gmnqSS z$=EVn?=p==+ONfGUg$V1S#d2KHjvJAhtp6bc9Y{X>IXb_bDx|q$BEWJKvq94J6W1F z{WNvW&KA$Cm5fz+z_jm7hM(Mlf8@wYaq`Sk%G>ogQv4r4>hf_~wipiXt#4^#6X!QE zt-N2d4@l4>oEO)JuKcT;_49askI=qdOFlhFf!nIWn+|Q0!PNaCmO?jY_je1v} zMyBr?Suu_NVq{edvh?Y8TGYMcwrk_D4q-VTCCA^m+*Ac^Cw{ULP;Ak1x+JPtf;p_ZJ5jQ}9sv zB#yqmz@JGTS4srB{XG-&{7DbmFTDaMIs34%RQ-j1asjwz6csW7rh>b4y>S8Pz~G_Z z+-TjNMFHCu2&q7AT$BuOpjD_jC=wrWAkCV$;3UcAm?k(jI^Bqn6xSUN%M*mVj$m6j z^yD~3OC5vNSecI9M_*|@R@1m1cLnA?&}DiU6@J&ZcjW*0(qeR2{yN8h0QzPw#gJxz zdMB~zZa<_WoG9`3k_J(2zkh?;4fZ!?xWx=dWu~r%6k)Hpakq0j9b(h}Xi}fRL06lu z+dA9Te_ja19u51SXy;skcqtBjLp^_K9{>Y+)RoTqcdCll4yanJP*AGo!2@%= z-*q~RWotj%bsZ8j#-*v%d2L}OKnC?TBu0l4#=_EpkLG4=;#k1RW{jJ?P*v6FxR}aB zPqtdJZ3!wGOJ|d24-H&XSM1Q}dYM~c>SMH%toz-uV_qjr71+XBO@bsB-$?mgPA+J$ zYp~$K&(l+DnG?C~0bY?q1zpbp5$bC=f0qNI;P{)7H1ZC-qW;Uk&G+#d!-3&NdDjh( zQr>3|$;TbcB%$n!ID;MkC_SbkX^LCvy4w+!iLwmowwqLa4;G`TXRbTrNWKJz^VQA-INqrn!qF>x zhjKGK^zG)uhcA(LG7Knb_VJ`nuD@B22hhXt zL(VKGYo-n)wItWB-37Nn%Eoomesg4zTc zEjBAYqU!af?m@&P+++fkS6WdZ=oK%iHZkW$26NHe7ZN!WBo7&YMO$I+GwQ0dWXi+|L$RZs#LS@X*k^U#l|& zf0?7ZNt`(ZnM7;|GmG)bYanuBXY_)7R_~U)kA1y>*iTvcoWwkyXrf5*Oz!v|TxALw!Yv&=rFS{y`lnMdk8O`7Hd?0^nJgjp zRt8b&%joC~F6astt~lCc&&`JPE{%c+SHF*{yy+?|LhCr5(evK1;Z?|}1gJ)~S|=9g zEyi9R*550i=l`}WBXwMZ-?WN9hi06OyP|C#^QU$8dP@HL&>){=jz@Smau=tOd#1s@ zzL2-1O-lPUduv5iI(BUzpgHo{?r$#em-cCo1Q+?vT{C-mrOCBlXCn7f0yb~g8P?s^ z>LFWksq4Dx8k4dsG_}*O6e8xE>r2{60;6Z{Ja6q958$(D>bodI?X~p)*Q;xt_Uo~e zeg<2`9WGsJ#hrId<(wM99UuP6vY%_*?bqeK?d`z_jT6mTD=F7bhc8}JX%+6jI!d&& z$JkNu`gxm~bpI5sUMXUVJ*L_<&=FWLFq5<#@|^Cjj`*imB%rCO&Rla7ux)#;A%+Ig zhqbUaby7^7ekqQVZT{AF=IY@ktiDnu$F?tJ(9ytAuU z-obb-@PQJyC8l|dKQO9TG*YA5;Afc5YVHZ_N?FOzR_$gFE8&Lx>+A4c->lii1t_z< zF4T8&h>K%uoylwmK~<=U;SQL-4pjFp>*-sE8!HiYr#{jYiioQ4tMm2wc7B&3%H z#yjX|FtZ!bfbg49LgoU}#IZ{WnB?g1Lc=~W9S2lv%9_`rQO8^O2Qtjx4VO~sQUWsa zzbF2vz`#teb>LR?iEO~s8yx@gpmnS*eWe#AH=$x)17K8pss@J5J5^&ydM35iUW@*M z&^-*p8dhE@O!cH$UG63X(5KsSP8Hv0{-jM}KKCejj%B|)Y860}!hbx8T&{nNJ7=_N zvuj_Bp73qnq^crOv%wwSmF2bI>ONI|8&^MuoaiW6p)r%W(YCN(bGZU>A>uhlMR7IX9^sD8 z(@&x8;M7GZk_hvEd)nEZGIJH&U@bmYH+@U@ovF!Q2zjWvZRQ0&%z;{5-zqhF0Cg!| zC3L2)oXKJ>Jd@T7VLosNaCyko$`M+3HVs@EIvkTR^=F(nCKPvhb1=NJ;8m5dAMPLL zG%@6vo|OlFY<;sIs-*2BPZiVJnXK_MIY9j=CR6sK#&%P9FY;O>B869^(V#{B!qdy_ z=1;Unq%vNuEFo;X;UeDP~Y0gO#}y&!ar+r)j6ZGkKaL@%8*B zmsxmYwKSOmzu8iUhICPwju8*Lp=$;TN&}I2#6Ci78BX|#o)Z}MNgJfpcG|U})mv7FZx^}3%Q(KyZ>;$ zhOM-6#&T&djc9Yy9&?%L#PZh|-}z6?IAU-|OT};Kqr@i%F*TioS#w0AM%xn?$H2V+ z)Q+G|M-+v$RK`aPnR8Z8@ZLCwyd@~c8bo6YfBMs9bJ2(t8jRY3Z|~5nX*cR+LArV& zkrE*rA!=c-HCcVqjgA&v7qPEMTaFg-BnRbAb>tyRG@~iRDwcjfBcoUT4Nq09GEQAV|8RMGj znxZc_MqW@^M9w112Cf{fO2js>h(6F$6N7n<@2C8QN{*sbl!MFuUXz-Ec? zdP)jUk+Xz?)rzldY`jExMhV^URJj@2f)0=5vbOcFLN>AX$nBT8Q$i9z2-?iQ(jS8Y z%r@dj>swrVod$o6zy@WdpfmX|9pTl^;_jL9l(q$E=3cXa=^!PVSfl{G2?h#py=c=Ge*T!Zl!`E{m=AJ4)= z>eAA_?rLOs`%rX&qfypTU z?3zZ_)pRY0So|p!=Qtt1SUq0_;14m9e) zdOtC zLW&?^Lq}76Lj^HGkRnLQR@c(bTG!UlQs3p@3H;YWUS5#2p@FIH{|lJhKR4JDv$Hb) z%dLW;ot1;FzMReL@+w6&lQd=0D>F33J?|CTKyZD~ zm9jV1`p|W-a%KD)+42J7o^LsS%-b6yY<)hMSz>#8JixQ#R955B*6>g&7X zn^5q4eSO&?$;Gxjm0AmpiPhpuzh<{@;YHZ+EZywLXz_lXIL%dVuMlpxCHQghSnBka z0!E7w7mb+4-G_(VnwB3uAi$&kQ;PNU)bfpJT5pGA?vzQx z(yif|bj;rC3(@+Bj%}>K=v3F-D4~wW|z*A2?6?iH#{nxBhYKvlN!2M7K zsT+-?^MX3|b@}~|{o;+5Uph0wI&^=0YO$L`mkzCPBTP40#QSmvK(5FBi{)%N`f7uc zV~P8C&Q>>JRMsQn4G@0BMeTD&%d#O^bpocTAT$?0JMt&3B=5Hz&Xt%^T`Eu-lgM7X zTL;Iv-Yf^xPAU|YiQ59`P&nx*_v_-b+N*PG#+i27Sx}Rgc4JY%%Xm=)^3sq%OH_g* z`6%k)ZD?=!fd!-ZPH!@Wf?Bdn^ytg0JKE}t_4g%#2E$Iw19lTJiSKS6>1Uo?K~~qF zxFnPO+|n{U5@h_g!{pEno!MBw9@yh|1OEjPip4h{Dr6|~O2>Go3YZ6rlI&y&uP*tRl zJWke`C`3-<0&BonmcyIK@F6BYT6H5jod>zq*=n0AYSjerQ^E4n{V%H=^Z)=uWjmQ! znX6`{3{E>x(tU1J(lPmvLi^0&?0Z!3@Of0fA~eh*b@l_~lMBtAGw#7N$4qW#xb&<7&|cjzhGF~SeXoouwgO@gEk zRg9z0iXY%_P-+>Rb(NLL~YI&W8>6U_Awq4rK&Z`=%fY%R`9ZdIzJ ziz*WcG41G;0qbWri#Bw{ zO9b)$&?kwaD$Oej)|o4la43rcq%bCZ@E9wnO@F=g-dF~a@)X9hhvN4lgan}oH^j+D zcq3;G#Iq_$Lh6(Sp>}`%7}$YZ6ftcRq|YLta9}9iF^QV60Q1*--b%K@`o|qo+)lbm9;NjXjC&}rn)BcP6p>9HF zv0{1z1^?0Jx%m^qhp3Jwn?S6C9!7y8L6G)%p(X{n>MGFJ0E1@PgxNrO0ENE@2e;$c z6uW(#cW|6UMghULhI0VRB}D3;761&@-U!UzDEi^};b+Y~!fw8RZ@m%4bL?M{X9EBh z&Aq8eg{>z^69p(jrHuXAIWyuB2YO{ z$0_8{ouzS{rQ|Uun&H*i;n}cIo|P&pkpfsV%I70LuT1;)dUo2OKK=cn=E(o@Zm4Sz zS7h*a{^ZjnxZrB7_R-_hM8ZJ4Bl~jO#SGX`m+jEylO$lig$_rbM7s)pjl%Gb;DqaU?upjU@lU7eMkIb!oC@LA}>847X&vx6U0ia(98G3p8Ih^N%w@?c^yNd1KiRM@zxU2}N`T4K=P;N$>Ll1-MFU*Aj`bT>;&sgabRmsCCG#LIIeV;nl?a(J8 zJrQj=qpTI^wi=ucBw&dYZD31>6!*B5)Fvv>NHG;eQJAC~+N&{id zbI zMV9%TZpZ#@rn3_IB*TtXwAMc z2^WqjND3p<5C73JDB^RZp`{*9GZ@o*iWSECv#lg%YUh+xGR23OO6H%HapZ)n%abrg z6Ds#EWZG#6ZJ(s47qM$&k}LNDX44t zEaNrrP57bh5lqiqu0SL8{A9^?{vjz70z2K33J z)YQ{Nk%V$?V*LIa(dl3z^fw|-0cN^lj z5O@e@g|eh7Q8>h~vD;6~|4D}pr|-0b(<0MQb9|d2SB4eBWuueZC;2nJPqHMsETWu3 zw~k~VW%13jm2&=X&bUZvR6S-UYZJle#`;=;tk4RKFIwCF!Io%W8N7oUnG&>t2w77q zP-wF!rtMU;BRMX~E&S6?fLyS=@eG<^n|VbD7)9d_uMR8#2 zha_EVwoxp>E`3O}PLvEXEBE|IVn39aq^z0dk6(J7bv~i`!C=(&_|b@k!l){oqWTsw z2iXo!Hw}pk-gQw*Ygy+eI>DFf(RR+XoNWpUM8?{oHt_;xn9q)`- z6dnE{5H%l}4j^y(dW0_zd?-^Se`6s9SJ-0IDEx6YaE!zrqxt=N`45K_@ni`n4 z+c)>(-}YLqJNQ=dY(OY$j2C39%o}&+&ibTr@4u}EiqtC?%2<4=(|{>sJ~c39MO!Tkz3mED)VFyx zB)2Ns*;)5PO*nHFYr?FJ*29hWA6+RLN^43Grn(dtuHnAzf@H{fJRL;mJg#=#Qw^%L ziaL@mAcd5p_pY4V4NZ*FPZ^U?3J$NXBW+dkTetSPHJy2E!j6s#km!zH-duDQlp$Xm zxCVmfV7T5qZv2vw4&Q2q6p0268pUd`{C?)JYn!T4e%RWH+EaJke(2lkJJNOkLC4`} zj(v6FPyI{=7q?pLwB=&U=X7Zc*!ZM62hDc*O5>^e>YUET4;0RQ@@w61y|X=N-!|hP zQ)Jtn4E|Ab%w?BkQ0Y!J0d;j-CzqPpG=uIf=}?97N#Ci_>Epf%I_rnF=U3<1?6*Mf zBuEvXSV)xyXzY6QW$R+9=0PIvYv(6S zQ9RLB=y6A z(ieL3mL1$&%SeG$lXi?WrC0+twFqzmu28v#74lmLQNIp}IkZp*y!(A7sbcpUvN`IM3~gem)X36{_iI_?LKV{45o`HCwzDf=;qm>+BD zrEYL|bab=Cf#eGWLC$3|x1~6w25xM}%>oK$So{hTJri1i@%vMZnCO~7w%>P2oS0$A z2DqBt`C&!d3b~)vL=Fu~mCfYySaT-r-Gd9G70;m4?eHFykR%KLdW{-xm(l&fd+_le=-*omHYJuMFcIaQ6I>3wBhwV+of3bR zb48>l^)mGv?GF-t2M~p~=DHSsqr~IuC_#p;w-DNx&k^nb;bln}Q?{3KV|=y*UIt2r z_}bjZmosljub`E@aJ#g`yO9rlP|WGi6C-oEU-Z{lAFON&=-=6>ir%hls$tL?Gjuvi zZ!K)`XNeyph;EXfRV8=&^l{cL2_wi*oFQnyqxU;|@in!bz{vS;vH?S6OckWe$2fK5 zaHx^lvmAbdok%lFNJ_tqqT)lg0=koOwB=zlg9h`t&S|OWBfV^h!wQ-F=SItonpKhn z%He^ip+X?7${%HoJ{GbW)(3=1bk)~Ddo0=CE`!HRENto2{nJ>!-Sm?0uFL=`*-R`n z4FSR<8tZbq ziCGdGrVi2d&5Y`YZP4|2k>p#;wG!@Iaq8}Im-85+e=fh2wnV3W6PxfrC3?Cs$LjK= zUuyOI@E!K{=w(*C{W4a(d5~uje&fgQ;Q{3N{=q2dUHDKfv|(lNhD`%bok$q;y=12` zGT!d@hCYw1K16FGiIK`G!1hm~PO!n(Kx&y*RH0Bl_Gz)m%Bd~ih5H>_sOJv@h|kBt zIDfn?jX8w&B~#j5!cB)PoRH02(q6w}Q<`rI;OSgmXP{v;M3k32b@Q+3j9K`vVZ zCCHTp+w?Q#w{s)K58c0CN1&{`<4NA@)xRnAO~Bd!VR(OR%G;=M^R6DbCb@`FigyJO zRjB%KH%aJMJyY_Lca3Vhca3T!>1G~xN$9|hMFF8Os>MvvDLN6^leWC;*G8SnoO$m= zC8%+*gGN53okaSdq#qxeDH|@~ekA$Qrb#;Mkmp+6{9OLHIhlnbX!LuH)r=*Km71m+ zTT}pF10OTtc#5^>B%g2#(mp& zw<5N&O@WgB@TZ1k{vmigK;H2K+leI!alOm+D2TPL=!As}-?lLVTjDk*$d@1xFVPn6 zV`o^*XG3T3uRjuq1pWe$>q1w7wNfo&@lq9`n|Co&&VX-_@>hRiD-B-Zyupv6K#@va zZ>pJ)=E!#jU?j9gt-?G1OTod9Dxs@sH3cHG0mKzcee&B}7m_Sx&9>JLe<@VzF`aSePyj_C$7KqzJ1) zVzQtY8}8VJnLMJRAUZFn6HHUul3q%X*Z4x%M&^~ zIvaqzp5N!~7Hdq@+kGpIu)EV+l;T8qHv^{OzRr%3Y!8a(1x=+=4dE^+1{%r$l_5v; zQ><6agMJ1s_jAJ7rsRzRW~Q{v=Dj~AM1w~_y1u@u{Tvr+L)~-!#1-dl$39RxSYm6B zIX^n3gj;|Rt8BOE<#6~j#>2z^;lE2#!+ zU?a3z?qa9F9(&NRJZstUhP?l{$E-I-s5b*V@;wST!>odpx4ZS!g+~y5K{uVsDLTY1 zezR@*dN{VSUKu%5EsV1!fuYTE@_n3EEs?5oiFI1K7x)C>^auyFL7Hw*xjv(4@u0Ag z3xH*!TOqI*3E!4ozt;AYd(`Yc?A4Yrd##ax#36;^H@h>f_ejTD*s9=fpj1A= z+`*EcF<<)NpZI#Hqi~}Vin>$#+P^&&jpkF2`I;Kr&8i_c=mX5TmKj3$dx&ECtE9Ac!8{prsi>+az)-#y@?ELx$;iO>xZ_02C|CFfy=aLX3 z0~6E#maAZ3VPXFMU-c?HJ~=Cj&E6)t0q;mu!vdnh%BdI=jlKib>U|hSdPyoxS?QS- z!+pj#v50L12O&`s>(nC!&V)x^=GV2Q{JY5PY&cC89;_@*tJA)F`F{a+L2m~W0Aau&RRh!V-{ z9Cqy}vdF7qWTQewgNLxnp~hN2c;ZZ6cZ7E}3KKw8XPVD4I1?o?a-Q{;7ss$iypuub zbOYqS?MF-bvgx_>2e*Ws#Qp>`j1-gW(}w|3aA2RGM+4rfH#-fLtK#DB>uUXfCrcdVD|JBVKLIbX1?IF}Bi{Nj}1k9n(^) z$-M3L`(zY7ANlBs5{k=0YhE=8w>pCMX_|UP4d{&?E&8^FIg93665fQY8TtA_?u1S>q)pXUgVRJ?Kly$ zBCG|=j^Yf$(e32yt>H^i#7<0-=h<1GDMWF|q4Rl4cA0hGV$tl>W0UiWz3`QE?z;n5 za^E(G(U;TQ35w%6T&$Ii0i3P)tTm0blcKkCJUd|(K0c) z#e!0KgmxKExDJs{B}^Y7UJs>QDzeY~ z=S0IeA{6{W8QRufUYzm#JhfllYzD6h@>3da?v3-yGPNJ2r%%|uK-7Hd^cFNb=3aTO z7QP+&)hhUOgn6fn%F`N8$%i5=ZKU$0xJ>!0%&-+YpDDjD{tdrJSdO&qG2Z@TQGH`D z)s~HH@%3h!^^Y`xU_+j()murRi?rTY#!9F+EbY&a`ctKtx)dcvIUXlN_YpHo=T3P+ z%uHH08OK4ZA^x`v3lT>`(5v6t3w9@P#$A8L)rJv5N2GpY#!W*ip6rdrP4uX&S3ESw z(K;8~eA7ujuuU##;YalVjX;5=EDs@VD1=f+_C$t0MLwqYyxeg0XljVVaL4>~--+_! zz$n|gzgXpsUucsdY;p~)ag#S3O1Wp50j?N^hiGyYuixV~kr@!?VWy#~ymi}uWg;ei zjO|a{dYrq8eVRKHe(7rX6?Ttj3=hIKzni2y@c>Vqwtsm@gqS5vemGIQ=j-LzArc!i z-PA3F;eJc0T||kcLzVL?i4`>wnf_!)sZArC0yxYwRAf7`-^Pzz&cmOZRC&%wM|vz% zy3ZKJEBAiUVVTgg&TOx1M$A1QT=_su+ zE%l`yyFoD4`rkYhJ=d69%^%y0;ac_K-XGBa<3{fn7jl`$yk+SB0{4F)^YvBtU?CxY zobH#NB)^b{Or~>XstqR1EhuA*XwfQsCe$N`f0n>{~;>lz?2+bhzupcjw z{Wiu<&2p(U;Z7QPCZ6uu9}~_^8o8}*q+`D3&+X5hb@JhnT?AtO)L9?S+|ndpIGa9+ zbQ2YOGtzs@_vGr%dQ>&Ww{*S$mo+x)Mf)Z~`kGL+-R2P`TXoJ68IPYHXTM4nw$#wO zS93Y}sP;lVW!k8rQ|NZ>>QUAz`=;_HvsUI+_Lljk_$JSnnIS{|`>z_f^PSsMT(iRa zH$xycv!9s>D$6+I-w+dBjDf78eJb)0LgvZ6X(oVRO;Lh4s< zLwfixwKkGlGE35F4v$H~ZEkxfB`=iXL(II95ua*^Fy54ty{n#A*e%1>pVH(x1B@Sx zlV6u+AnC)Grs=K<^0;a(ZKiKLMG2bN1hXJ>wMK)BtN^6Ly|EN7V@EBEk>VsKh-}Ia z`BR$&X?nUOW}D7?n;!kp-Z1)it=*xoJA-&Gi@_URfktR}sc{Q+vZ7{( ziNfr$3JZdz`c#ft1ap~v&Y+mG+`*d`FU7zT^Ux{O4Je1e6jE^^~jm%aVeTC5`k`qFf=hEL)2>MtIQ zc`ibWJC*G=IkN6)F^=KchC!|iNM=_{4&_1$Rc(H+zbM|>i26FcbgSW`BJIKoC#TA7 zH>UpdS`XwU8r)5iHTB6KQ9AuZZ6J5qZW*XxO}Dx*5VMg8=yP6tRacn(+kLa3d8t5M zs4Otl^@Y~{$BaJ9V0QRr)Mlc7VW?7#&}~se0|eIU8%JCTT_^f(GtyuSX4($w8Eqb^ z@@T3O`!NwgE$%W@*&@0rQd?V7*;C>Bxa0e(t%x+s&$Br?%xI}@*9=)GXg-dmYV$mOg|lp zLd-R(7h!bZpOV=d^Y}PnSa8&tSA}%ADM`=#!X1)2=JBlOO-j0 z5!h-YAhuQwirUjmb<1jHIG}JF8_5qiU;cy zbUh97^rhlxYLBL|feBtd*4OqBL=fiI5rDm*!%z!<8|a)jVQ9tujT~YImM9&ng_I~d zF7{)EnOPb9kjGxNT;}~kC{}Csg@moc+AD%$fq?dm8)_?p?r+VBOdnps39?&|`_sUK z*le0wzS63DaTnLj0tM-|npMt*r6p?BP9o4Pwf$b&zEjV_D=`$LUNdqM-q56qJo}a_TB$YP5eO1Rvd`)z) zonTg8;;H(+5LI4Y*-)-dC|^|c+_l>l?ew=w2waThGvFtD>DVkCa~!vG3;rT45<~$mRn$^0A;q>rFI)C;zBVM1el--D z-8B-cnp3L_fERtVr)?sUxYs(iSDG0lwNK*~n8UX~n$Xg>H()jQfi`czvDBw!u%3T3 z8i+hJa^cU=KIj(jX6|EM3S!kqN{^@uqH1vk1GSYe!wuL79pbQo$bwO{aikcZ0wDwZ z+EA5jNU3yFep3;yVQV5XsHhB;S;o19XJpuV#S~QW>@7d?ekl#6;O1fz*2o@IHo|uu zbrx3+&N`N<>|XE@W_v{aGE+tiOX<*W7J5E9>R%FV34*9IKqzjub}}QAi+PH8q!$dP z(l4%pVoO@YEKjt~m)4!0pKVEN!Yv7X`Yb!}rL+%n)k8hU#Q&wQx+ zX!XG;Ia12Eb3$9L`4(menx&m_-L^e!UQFJJfDy6Me9sb18lZo{KPJEV3plEfB@x0D zrKbHvq1;B#0X`=FkO99!j)>Kj1-QqwQMLmB&SKMbv zw;ZrC?sHc6Phe&2=bUbSAROg{PKYPifO`;b$G_Ac;xFg>ELcrtqZT3relF|=fxjqiu7RJ6yW3*#B|@OV z&-vYaarXitXL0jo-A-WlqHbQ`E%ik>;7xAR9N4O`DG6+q+dKoimv$S2pQS@&f)RwL)hY+g+k`yoTWolFn3Wm6PUZCTM^7%(5(~aEEv)kH(%1N59TiHCIxdBcME}!74-4|CE#PZO#vXG zoL&=PDfXOdBFkSjtf#s@G0 zPA%(p0sm6c^8*~k$@LNbjo=ad>gLaR3-54@aX3#pT_KjQANfB_=oJ7CpGl`5#PY8q z<@SjFj`9hndHHj`!8^QS{Qo)ezr)G<`d5ZaFwN1Q^90^u5#z9$blOxbe=0&Q?`u?@ z^lz0DO`W+Y*3={qElhr6y8~LCIo(Wh`m}-S(K!~V>Uc@>L=~nIJH{ zI;v9(qK@Ki3VckdxDxIaYz0D-a2V*e|G-M!NL_hoA@W}(?lO+(CXXoX9Yv!R?kJ!r zvP{uJs3BlTk`z<@iaouwe)6DFhtlY_E@zr4VoXXwm?@(ol_J6v86-psGqIN`T%Xzq z|ELPb=XYZ7eX+hkb`qk;te%|D7$<7%SZrVHkVAHTS}0Y}Qn&$UxG9Vnsxf}=ND!kT z6N)bWaBR;290STWEp*}|)6JGal9We-77+xQoI=qGqAkUfwntp4(#YX zdUM+tJO-~3<~)Y4F}U~)9=#7dAb0HBTJ$Yl*R^F+2bp#5X%O#K16RMaGNzW^Yw9VQ zFPDr{gpRG<*CbO&Qe$@gc2Z-NS9p-Tq;x&k=!3E^4=@RY#)~7@pXYc6ui?3fj9i0F zai?S;DiO;axu22YlYgbX#DGLBy2 zLL?hb0g%undcDPN`)^{}?YTyftE5r=#s2D!1Uc9rXOfAqoCybCbOgWd|AJJxBUsAC zfIg;Fuumm?|6CnmO2?+tb@IL;FM-qEqwBjgNh;szjNhqQd#BqA5^S%4QlTCQGnpc( zzrKml|13049%GI)rLRlrVoq^W=^HUmGGnhyHpNlIRs>E-LGawCrW%Z=5+Rq;s@8|L zt$%_J>`zazTK}X}#WF}6Q5#ZU^fd9uxL;f%VtQQIy2_sSWI*Geg`Pp<_kHV;()YMv z#|uE89S#t7?2YVVWub>|Yn6 zRzbL!n3x-*!=3?G#+#pDWAIf^zx?6o_Im0HyD>FIl^qU&qN-&==XAipVC?Ypf^iZm z_)^`-oAZH|NgzZDLFz)vMyg_&IFLYX9&ZGz2WtSUBWmLdUhk+J1Re4dLL9+tmlKl4 z8PiLa*gu2AGemB~-ni&U+1Ptaa}8=2SYJDTL0)U~&hUnAk34_Fy#MI1mfcKrk9v<;4|eEDhp&gahC$;XLg zZ)r8+*vbv**~p;fB)s2#>8Ra&yiAnSqU-|*+D+~a;0_X{FK_wq!hLNwJ|;R^#e>N) zcWb}>Wl1rr%0f2lL?`MDVcn*Erj{Th@?#`aq%ds-&zFknTRCAr3)ODMC7Dd@`HydY z?a=v45sen-58gQKNXtZ?fhVo!%C&A?bMv)t?(>Iv$R>M`q~>v@_ZPgu`O z+UZQ}n4InI-It`t*#y@KM9}=GiK+?r40}Q^(kj_WK2MLD zV$wwUtJXqs{-hSE>$JLLZtBD)S2wT-fOML)+6b?ib4K{ZQEx1vZcx`ycT2M zrrIWYwMM_w?E2kCul|RT%~s`BWowml?!NxMe!E$yPijlxMblFa%FVG3?smz@>xfzG zTYRjsY~h##`X_FvL~M$LPa$FbRQJ+$omqKiih}k=(^BUW`&Q>;QZX(AhEcU$XDdUq zI|F#<3Vm!7I-?VlGt*APSa+R$pbsH0Hhubr~hnjn_kNLCf zOAN!}_F@Cw*3VYew#i0;n?)2Miq5I)9hH-uEWHE9ZIy$ZG=Y8rz}Nly@QssB)V4|E zXj^nkj8ps!qbt_lNqKZ}ba%9UB0<_5gaAq9*tLb5mQejoYsT0`^G(Y|{rq@~X|;x{ zMIu*yqvq1zsTnMfmBJ)_g#}&dZdTYrzV5B_Lxo*8*5P*Erwbja$P_W3f*j&o1}9&w z{C=LlQ=g6hP_7ib3vh*KVy;09Kj>Z=f7lZ1t%VXB0nSMx))`T4L*K|mz5<2WV4Prn z^F-^2mNl*6v07DVWSz=q(hKQPVC>{QbRE^CU09(U6gVHwl6xK=6Vb9vTyohJBySlz zOqj+i?soA|w05m+k~dG9opF}KkQ~q8AjBdl#9y*U{UtXKh{?H2J2s2PBw#2g+$`YG zVCN+wFpFL|lGI7QiMkLfV&+}IEFX_=krJ54fQj$wB}7S@fGr%f+t1*m@-=Qdft?+v za}9kt*YMo(vrl>%*KlXd42;J?n9Lesk~uC=#>`%z3&2asrw_o5W#tK2&LE3G-TNS2Ayj~j zKny8JUNC84Dq<8Vkb^*OV$28ty)Zj6gcvA_FgG$}2q=j#GctG@V6lwT_W}qB4J?!B zqe27=2O0z#0E7E_19Jld073vLAW>ids1V35*n8kD&>_&T?_XQmBkEi2)96d>!|K}& zoDG}>_5yN2b3ur}hyX;OL?E|dw}4yFTM!2@2Y>^p14u1cEua?kzfB033d9P;0-gq* z0xbe9fTe+@K&rrAP(_eKd?4`K_|0uaoDxC4CwdjY(F z>I5?M3G{9E>Gfsz5%gX6+4cQvEq&8{=6jTT5_^z)-g~@z+IzTr)_b&jGJCLl&U>tT zOnt?D6n(>e;(e5RB72~DINU_sNNdoxAS*wo%P0e%nCiYDR(kv1ur$9xFAWSo;i>}u z-TQR6Gv$CcZRj*$kfGh#&`YUSF;7-c{Df6J;=teG4$Vg2^)$?_BeF9;MYe^N!#f zN+tn?+4;@VI}cNZb;MjFePNV0MA!oEf|g*rcf?&lQ%2#27o+Gu#*NU0Rb!K%Pt5J+ zU~01#Vk_jZO4>Z9iVwn0K$NH*)cu5byImc<4PJg>EaooMuIKC5pa&rvB!%japH{f? zr7{%*pOd|XY*=J$xffOd26h=ZWiGs2H|l9I^cJjt0nXZD(SgNHF}PMd{+Oa%ud)sH zk;?W(7_VB=7IU=P@-~*$-!7s1TEQ7=5?&N_aWg|nJkc|p$;QuFqNfYq{LQhhgxTMj z#Sigi<{d!BA(x&AM#1u(rF>Tyf5zfoLqS~yjk({h94EtWuAeMBmGIxqu4LOGJY<(O zz*9=m@s03vD{tUU;rsay6Z%RPYkpE|-HR9&-53_lU_Sm*y?Cz=b$py^w>A$ihv_dq zJ(%zHYi;_M_`(=|sKl($+~BE(=d{E&@Rz=~GXke`*u$@Q@6GrL2d`yM-CcXr8a5df zf=hw)o?rHTuw6L0&Z@;75E;wzVfMGZ_fl8pg}!v#60L_?TUOM=SM6YL3LS7Z?}Qs7 zI`=NBtr}A=^W7s!4=QkfE%EF|lYA50l`8kYt2@yCw*LL>A|cH}#ymW+2b+ITd9<2LXUV}dwO^mMVAu&=nv^Ld?}M~sC|dF9ML1l+ z#Y@2Ag{FT=+&6V!Q~BYxo#wwxxghQ?JQJkX+i;%M8l^7Mq=hYbW(aF|t?~&V{UleQ ziDZ}KzY`Ym_m|4ulXL=|AB$s?gN8{wjpDRQG-(E;4--yq5(fF7r|Ku$f zXL}1Pa3M~GjPDH`O1IDW0JYcO}+y_c38GL*cQkg%3K6q1~_CwiM%i1=j~ z_eL?R`aOB76jMGjt}$)kke(%yq`#g8Mc|>7U?X8p z{N(IcLSH*#?5HE}24coa`e8X<@gkJ-mWRqqOKpp!<`B1Jr9n|^%k?fHB1(-Ib_ktT z1$*>I47(s%jG~5OB4s7p!0_u$++!0F*#OzEj$-ZsQt<+sAX0jijnBAId?r3u$q+J9 z&SLfzJNKXepmSGq`RVD4rK7I6xL`PJa}5r{Q+;2bAub)?*SD_PdU}bhq}QWw&pex_ z(khX0MNXt}g!RSTiye^BfD*aKB!3v}=m{jD>6R%v z<_nUL@QXrPjP1eWWRV23nL3Uz`bL(tY$FN(d=us`wTl41-Nn2RXdVfK>vHxiO`t_rlw2PuG#`*aeo6fv!EbFVBC|5 zISHKJ{^L2pg92XX1^Z3w#biEIYu;%yH%61xIvhO?>t|PMbyW+Y8DsdV%g1-Fqj!V!Jc#CRw@A4=oHERwr-R3%2xHpgS1&cyad)?0H{ks#&u5Xg_f6F+L zJ8gfB6{*T#;q!!5k3`H~-Q8q_S**%pzomZ2Z z`1oxd(f_PG>#i20Ys&o~%D$LK1$!y_DWb6YT9)U|C#e(^K$ZAU1LdnBAD5EVQ35@U zk9wQY-eI{7hZUdedt7N@K3hrM6qe@pQ_53n2^c9$sj#lfMqc^$tNaj822va<9O9gh zUbEj*YZ&8lG}eg_&7y9-+en78R#@?21J%f8wW8KEFUATKU(xB#^OY28c$1;$w=&emn8)SJ&xhF3j1{8_ zh}KL^EX8)eZ-Ve%juN#EJ%eqfKYe-PFSc#HX43+);nu4=PeN6GaGrR}>nB_6Sb7%h z9Wgf^;|;cxDfoPU)Oz?@@JHQ^sYn#0Y)?VKq>0(di;(TlA++-kI!B z`B>&azZ(HEIvrQ`ZyuW}IVIbmvUIT5NEGDC&sl6_TJE6oo3S~PxbY`h=?{LlUcE2x zCo#@9nT4=G%AT*0L;@ENge)dueh^a-H&cRB9k7sd8OP!kP`zgn3Pn&jZ18%tPuceb(%I)xw9P znte9tP%Rp$+%|J6e&(s^YB56@dYFx}hH$HnT{`T1UL{JSu#DV|U)KjvN7jb5*zQyf zSY#E?sA@iu72RUX`UTcZC~Gz|d;ML6kTGX%)Vyb2T?d|yLxA95-0`H+5V>?UG0(Fs z_&9`tU<)%>c4$Cxgx`2tG@#uQ!6^q+r8n3q;fj~(d;ZMnU z0hklu^Fbq3^=m>3kvITFkrERafPW1xO4p%|6Cwht?#o~U!@bAhvI5*jsjE{^M`BW* zRq3U-FSjHF*Emf%^ypVlviEmr&VJ_J^S|E~%SAwE~^ z!d)dQG8ULpw+w`1Fo^0_=+9?v8yJ~8mHSj9Xo99TF~q*h`-9`0cU-DAjL8KUU>W9> z5c0#FM(edT8GLi|v#E*>ne@zGx*{BIlJ0%pZhbf}+5gmGg*sf^g2>K-2ota^!%a9f z1W&^C*LFhkg|(%@aD;=ra#>SmV2czO7{t`!qE(qLW#C+wEzyDqRrD6l zKt3}76#|I?ly-sI6So4xREoD>+ZWMC*fdfkV@XQ@vvRe74AzeuSR?u;TJE<^XD=tc z)2lv$ztriYIKgVVZh=1lV{?YUya`@9&=W-LC~@Iyly=bDBJ}bD{BK(8LjIvxyxKiL zDH3!gN+9gOY|6Bu%v>^;@@Ww$xEp5PT4vr#-00KH!9ipBoNOB8u-AuP8?LjLfX*K> z+BGTJ%u#}U3~aZ;esvdDvWb6Z{HXK4xEMdW^9YM94YUSts<7B&+rWBQ!pi`m1a0|f zC_rMElfZyW+l^_N2Q)^S;7(xDt2w9UYlYdn#}= zK7B;Q@y2=tD|}^q0bkG>l!Zc&E^~yPg#9GU(5szq?}y+lY)9doO4oyxiF|_9;{%szv?Miy&xHxQZlgc_)A72yDrGeC z!XP*!J3U6bLw6icBXAaUZzbrRO1y@tkX3l^0FkKFS`=I@<`xO=6$$ng3GQc!h!hE6 zN|IBW?9e8JC377`86>(Y7;FUqVi^dk%Y0e0A2`QdPZw>`_^i%+)7}@MS1eGZXz1)H zZJz*uN-OU!yz5yGJf$kEv7tUv_(}nK}UT+K{LjwSL z)tN?B+NY}*s6n0B2u40inQ-G?c5qs^1BCyfTbF>J{&P zq)H+F6ud1(1g`bpsH}el^jJAu7LBMeu)KQ4Z?C2c5d^(JJNLOs-LM&b8<$_(M2U7eNr@o!@t5`O1q$e~%l>9X8Wvs}i$_PY`li>ed|MKMB zXfe{I*Qi$>OZgDQ6U_H(;hYU(r2B=G zMK~~IN0GaTgM&)N0c=IWY`R;;?}gmyQTV(3cB)=W7{Eqap z@noG%K1Q6hrfrVpr1evai?m{A_#ODE6C3oQPUOp{TeF*(-ZFpB6?G$63M$pZ8A3$O zVqJ{qfC(R!5BQQW9h}Z(#LF=+Bw>IYBtnWRayjd?f}bWtVpo#eN^P2La{TtnrpH}d zRu;CUyE8G1sq6gnxb1B$ncDb$H=Q<>HXS^BB}wld3^$m4{q0Yt9jA9iLB76DuoGc1;wzZ#n5KD*2W zKDqjR6gj@q<+CKJQOc(VW~#q@3^?T$4KWwY@;>-zog|{>=dtv|O^Byr;_~};<@T+8 z@d|@qF#4WRK6Hd%l(zdeVps{oJkqBT(R5y62KmJM``JPrSi8VtuMVJwHVsWlY%y@t zC4gjXoo>8XC+=1=utC|pr@1W-2Dk+N;B?JGM zh}Gf2bBm$xS}0+t@jTRB4RU?o(>;R@k+hj=Bq?Ed)>$CpnO+ zH~-wVm~qnGK->f~n(_AxBo7a!Wfw4d+&;WJyq|v#s^=;`miIuQGDlI=KaI7L2>608 z5U%tSZS-CJW;2pP-l8A@$M~rd6&|lKb2bPYuZzoxxmr9ypj&bLn{zz3QGHLZHuv7Wnc=-QwPL6+uCB)yrxH>~lIaxU~gtTg7$}+SqHj(iKndPVeDmO})L#!af zzdtVYCjQXH@29df(3&VA4>}=_2o6S(g!9>QS;DsJ8((HOji01u{YV5mN6~o2>`67Z zQZeqMCl8FF2!RVQW@7nag!4sKmm1<@m90F7VNdT^HJ_)pp7;t;7ZkEgr;hw@A3O-3 z#y?WH)M8A4?LEjW+TT5DYP~4}lhz{#k@gDVK>JF+A9@*vBcq5t<@bkbc#=1OkE{({ z$kH4nnqjmiP=i^=tU6Bm;dPiEi=DiAdAZ-4;X}4BXtJczj&}hq``PwXO)~i+oW`XD zV@DM*hNaX@YNPG#Sx?#7L|S=K5??X4QI&xs@wiFg&nAj~lP`jy-kMGZCkZ`r<-zT1 zPDwl7Qvn>>cY;+sCkSlwsU+(Hj&`5kE?i1y6pn+P3aM?pi_9U()?-~n5_!{Q^9IyK zOtuC}X4K{cs{WW1FDWFW~zt zskOf*(k1agf73H_1XxZkjs~V?gSL1X>liv;9 zG~EUM(Cz3=8?BaS-WCOWp<-RqOi$k3u7=*GU4k{GHUwovMN=0i+-mTaOZftN(XQ(yhK_3 zKLrzGFJ28YX&+e?3Zv5oTaz-?RVFUt2omD8PwbHAoWr$&#c=DcnJ#n|zB{}QMn)M`C=dYm$&hg6~O z2kyy%z&_D55UV}Ft20U!;{D2oFmF!YDt8ldr|r@x@IaX50!xSClF3Gswr%-IAn8)4lSA%Z2Z%DJmRt->1HZF6Znc!(NiW)>@%Ilxu zciB7T_(FF%5u{gP@?&0`FU{|)(T?sXVj{p)%voYPm##BuX21~!LkQ8cpnH?o5Oe4f zw0S-1`_dJ;HcT5eZs0JE{6lRU18bLb2Fw@U*n`IXoP5e<{>`#`9xUKDC>v-6t7*I3 zrj}wVWj)4RtK$IEN>m86=Qfa%S;hxwHAf3;T0{<8Ajwu%{bPoFV`ieP9eR@}RUE-q zH*2RfS>>p_K}*5F3gZ{|Zr4+z$+>*H8Gj)Obe@dca(AXqg-dLY*zMc+li%+rJj6$h zIQM0o`4{}bVI9fEdfVTs%dP&0Z#}g9oOKp$6Iad;ygL&*{FpOnf7TAB=RIv$Rnl+P zw-UEmkWcLplN1s>QA`yS;umqHeNgQ<>Z4R&B*q@>fwi1KCZUxOZm>d-thh}%bR^>| zr`0C+PHj2F{V72BqJ(y z4+4tX-3eIYSw|T7!mZVeZ(T!PdiHg2_cTq-}{STA2vA zc-x$F#2|b>hWbYGS4Vmf`ghp2XJXEX2B#^+yob{EyzSa%ogcpvmoKhza55#9Gt7~N zm6ye7+Vi|8#}{5?C!A7gMDm@to|0DxpCITc1k_$p<L8xF_Q-a^}-5~&25l>pDTABNTJ?nyxl z%=P###u(r!%O&{d$!J~7WFPI=((y75pd~Mog>M(>W%`fP5y#FuiE>ogs30H%!j$D@ z()x+d#|RVR%LBg#u^a17>ZWv`M}GZw{Ns*h75DC|oT>iclYR4&JcH`|Mmtr6QcL@x zP|Knb!vCXE{Q)lNi@g{lP&+QeQg7eGPGLNcBv5HU$i5Zp#?(lBhFJQw_MWJamjHP+ zR5Dw^m#k`eUZS)(0nifoG=`@v(4c5!#V1vZ;7#>`ky#hgzczgC$A)T`lOMfE{8!<` z!tuiqGP#F#8rbl0j4GTby|*`%w+*0lFjAjQEBN6sG@*PN`3;Une1s?wgG=zGlt0At zT0K;!VgX(*$MD5kSx7T+1Z>R1`x5#mi#U{deg_{x%T#=2*b5ck|2Gu)j36gi+@L-n zNh>Kr*2+1Aww+cux_}zIcIAW^PlUGC>TG9;qY^BXen0Bi@VX zA=6eOU_F@f{Us}+*%5u%bhvnQqvVq&u&7CByy(Rr z3jQ(iU_LE;N%uwqD~qX7(*Ne-?EEq^esB=@Gcq;_$L+T^?A^$Sw8lza*`0~7iZ;4OG zVynH{=#08_ZK+kazn_mok%x_>{i<+LtN$`9R>TVZEi(`QOoC*Uw#((k&*zJ0&s$9k zuDf}Zy~128caz_mbnc+b_kc`mFoX-eTF56x&0uS{SFQ%{LH;lQ6*Kuh2m%-(T@Bdo zG~mk?D!;b9jAbLf`7$RxoDwdv3p-T-SdG45Dj-vmLzFrhRC0~2_=y=VCD%1ubwk`} zke-T8o}-Qd_>_QZ8`ylE-VlM;sE_N7@yuv05@Xm%g7dfWap^ND5~I7DW#y_td&?a6 zsFT=>s}Upk^AkhoCcVsaOIs-CsnyKKcpIu?V}+CVZq>p2qDG%&1HCs#?E+Y3?!{8x zdH4SM2f6pp%s7ead)xe{gBixQ!_u;g z!_)wUcB)p)-<1RLG^|}!ObgVGDiW)q*tk_ct?K+;tenwEEhpfIC_z{2B+i@Be74{O z!jGr)vBK5`*0Y}%1qoFEW)XRjPivVV+I%bcV!DWP!xeI3fSLE9ILzz~R1J2$YhAF&@$D6F#E zEJ?K4W13&#j5ECP`nbB+v`spu`Jf*G9j=+=<)Zk*_r8%CmKm|3%PGlzoZ;+u?NC(m z{@#b&xbY;KmI;3n!vocX#{&d`1vBUosIFp4%Tj%C)C867_I`WB`O&U(yqi8Y$@eZN z-$MyHdCw!FSg=#Nxts9g`*I%U(fJ&{2n+`!3v3@d=U@J+x;ie%bDC;{*FWh!7Gr{6 zdMLqs8SS6)$;{o3F=fqh6Q*?n`Iknqi~C{ebtraX9Ey(89ARHntn#&I)a`&PK%^2H%1Ejx{!>FTPVMSmHFsY-W%Y!mK|U+y9a{?h0} z%Su>g%RBO9f!+9>(SJ-^@f~uB6;&r(v@bk9#gYP?#P}8Cx?e-_g+z(<5wLh25dMA7 z5wnhxj4!;0BOgk2pY6?{-5|yaiTLf(UxyAhxk~);T8*Y{zVe@c+E^VyUPmyFyvzhYB^Qdlf=NbW27YXt(j^c@(vYUUV*H%9}{`cET~oZ7Edv2P_jRY_>v`G=Joqv94| zT7-EB<}5Z|Ej(B*7}|`kg9A_9d{=qV{p-2S_zF3eQ+8U-BPQ0*m;D}hi4gQ#+oV?D zs-*!pg%YQbFU9#u-mKe4-aLwp*@s{``#x$0H@r1v5!t+(q@hcUP`rQ%2@ZsRa0Q&_ z@rH}24ZB>Sq7GJUWgk(G*p4_l3kSsv zha99#20T0oc8V&gn+n35G>0&inp=h{m@Dc8VZzko1uF}dSyf1oI4(#-3a>rB2>&n1 zf>OWnM&hW8aqDOViZy5T6v&vm>#7*sK~`u~foSWu;|bKM$52wyNU{VAym3kFe!IZg zsV9PV>x-SpsHGGrPK4cbGkU=?-?q^X!JTbHSHw91g1{A9hbiS`9-r`$@EiUPv)P{> zPfxBW9S7EXa00^nwmb>f|D5F1IW@e7+tP;HWWx7Ub>3I6CJ*Wf;J6#)XlTz62T-&17F!uYA=;GF2y!p_ikL=ja!U_KZl)kVp z$TEB(&J+qCOJZ=m$c#v1?Qi7QtEow-|0HhY(r*iW&EbH5#c>cDFdrqR9S*QK+}0#s zJw_Gf%+Hep+A58FJ={-Q?Jcd>KhKspko5FEvD+OSF2h=ge<0WQ?M)wYsF(g`;hln< zFIwdxuebaD_!3au+FA5FOkIicz^@sfW*@M`Zhr+hL5mGyUL}>GnjYr&i480iUwCRL z_jalV-l_y%1_^Cy>)@pKzB;c=!Fe(kOmjW*6#m`t4~V;!1TaH9DITc45r~VH?1RQt z&E-u`?u~6&>Z`|#=hH9yk8htkN6~I4Xzx)R@31*VfHn4^{6W^fsUCGX1#yjz>AYJ$C8rTPlF<}^qSX4QM}bWlFE(A1Td7&u>I_0!FW~j zq>+H-#4-^}%Okt80zBJ- z_?%DyXq1A^$4Q@I|EQpcz1Ln>UNl()ge(!NmJRmtE&COjen6sZ@q4|r1(DsL;@i=X zB>j}}#DD4vnldAc{h3Poppsk@*qzA@n-F*Q0ur{-VIy*Eb)f|unV#6#T<_`G)5QMc z5W54pf2u>k4mGVwsW*7C`V#wubh_yy+F~lWNHp8-;w?5pTSQEjE0Y_PAXAumKpVGp zx!wi8*@ARxw#J(@HCg<;04lf)i>$n?^+JV9d%EQ;Wb9o&^?s(O4A#vwqTvluI zkF})6YqKp_SI(6}bZK)nf%MdRQt?h;ZQs`Smzlwrrg{rDl#zujU@C~QrBE=7^~#h! zCG`gv@$ZC5-d`J&R{qL29_d%#L?u4Wb;65LSoAT~$?s&PABFV09=m%TI?jMmNz;#S z>SnrO@MQ;E%&F|~Puzx=n)>>dd>HKhQo@W1N&1}B ztB?9&A7%z3)JZ;Ekl~Raj$}AG$FJ91@n&v0x?V9(i!=6b!`7s>_xt`wg+N_C?r?X_ z%GC5HWo(I!qJM>h==a7))Q)uk;W& zQ9rD^S~D}%C_pd0OZUP_nH(G;n@O);QE)(D$;|kmSa7jxaDCFxTvAZ9vBL3sH$$}N z06mINsq6}Zu^JJOY7Jc-$ii1plViT8a*EOUI9L+B|BKigC!S1yB@1xxTKY%q$=1W8 zq59kEgT4i~5mh;6WB{0+v`U%oB_c>d-f!b(nS(vuLGT^l%mi>btazx>DE_4yuByf> z^WrDVP`>tdHqUC z!j|rUzz5Gw#7u$=oqjh>4|B9Af*BSPIQG6%Nh`g5kS-sz(>9b(`V14^%b)V5miz;0z z(vfXUkynW(a`^}&YRC)t&MYIGVc}lDiPwtdaH9GTgH8<-IxBX^ z>g?)2e6=mvFmBDoSab72-;SYcRE@?7PuonL7c!TjF0UvD;uLg#Oj__(k;Nj|ee+Qj~K4=>wx>=0P3w)6z1Dqe@_JyBP5;G@>%It{< z$5JcVj+@c4(drvix$-Z5c513lmyJZhX?43!t3@TCUCgzDS75NeJ|n5pS-z$_H#Z!C zMp>!lo)6Q7tn5BGcl>E`(4I(z$(*-o3fo3->SH5{0?XAH+OJq$>{~ci)f(hOYY?`w z;a&?GxK~2Iu3Co|zXzGE#*Yh7B%DFT06HDb|Np}7OG*bW&nM9dj8u1Sr?ClRXw+f6KOevD7dS|Rgt>3c)RRd z(({NlrE5#o`6c3_x!m#%dwOCATOk~|-qp@Q1nrn+Z{dFY0QO#oXtjqa zHHIhYo>E(>0N*MBSuuEA6G<7xNokN>6$J(sNmov1eV4M2M-n(sjkc;rXPLDhXkBbY ze!8IbY!CglbBggnX2MSM)U>EnyGS zT}|7ySv+bPhoV?c^lv*P*gX`o2_@0d!_+d0Ez+(HwGX_Nyj_Mu-`OY~@bm1gO_M)Ol=CWp~Ki?sHmzSOuU1x0<4E=&7=yr4%V!WxHw%JwiQ!O?<1zn0Q#~msjuHL{oBuZ zW`qESba1$|wCA%B^@?pn;dUkz3)>uq^gX6^_ux?z%h?O1l+vZZ1^&%>iWVsG*ZP0q zIg!D&EcwgAPcfg#yB`_bJ(b~a%fdVay6?ubYi>-CrOS|mq&1j?2; zYK0GXfj|I+SYz8EjDTyrX?Rp>!C(Dt>fY_;YO{7TDA!D3$u52B@QmEU$dGiEU1cQA zP(HGqmi2f=x87Y7CwRB+9(#YvRi}qktY-ml(P(U1aJauMn#3FRhcl5&QXmn(R4cF3 z?Fh#Co^>^-PYE(T?BCRwk4B!g;Y_#9EI_1)JK3sdSvbq~c7+=Q3>Gp-x*d zjf-vgM1lpb8CS(7GxYA)t~SQwZO2(hl&)h5h@hWiC~Lb}=Jfo1YHFo$_10Av1pj%- zc_UorlmrD8KiTRbwFO`H<@7QG$QCF=*5%*}V@hbw$;`baHX*s*+!9HenAF^D@q4l& z<+u$>F$(8MWheYC)JwRDGVP9X-~o4hjN0A@B)E{&x?0HA(qG$%(q1VD#Qd5~7&}&}+)-AqA{>P$ zN6X&O5crFs3cNp+XM&2}-AmkxS2XEZkrGRQw4m^erLoP$y-dM9mrMCKEYwZRz?B}? z3M_v*XE1^$2Tr%MpjL&(3j}L|j*Hl;t$d&L;>;T8(BB1lYu2dVe93c&2hv@fcf*Vc zv_O$@P)fK{CO@L2io6s-bfs~scmt<%(S0k{A0aUM#niR1%(cI=G^A(9^4%ua=>sFG zp=NF!^R!5YO%uQ8X*j$>)Hx3B>qZVCd5`aWOk5B3 ze|Hx2B0YUb?2Y<9YlhkKAeWZ_Fj-MX6j+Cs;h*U%FvpiwouJjqlza%@{_@Uf}}7WUSb zNmb6TGzhMCMl@=TQ6=lF9D5_Ja8O!r|Mn{|I#?_eSgmouXv`duEZDRsKwx*ZDDp_Z z>H3f|5!`KY+sG!8!CWb=Rw`GpyhJ+k#&aTc(Nk)R^DmQ~cb=&UB8rB+`oyo0_^D2A zx=90vuAjNLJ6j%&s&BS-rMZDYu)G#p)$vwQL;|S5|C6PPNm;Y-h(jUv7Wbhk^R=8> z!kZtj*fY4$6q1$@(K$B}Vtrx|rYc6Tu-otYi20M)3P1z1uQKd~%oWrIC}Js^hkZ?~ zt%@LujG+t2fv`nmHglw5KK@A_eRnYfGjzmnS_*d!MjInO1Ex}a_rvXxR_np7ZCvX* z_g@;ef<_3-Qi1#moo7vnc&2x|!~JC|{;R`#r#Dt_3$#J!_Y7N`2X2N6iK5f3tJm!t z@$2q;?|tNbvqx4BL{D7*>ZasvM}Dixsa}$ahu-cciw9Q0PGNK5QatgKlE$cXbtT!- za7Dw&zq0mDP&*$qW*e(vcime-jJYg*bgx>QXQ5T7-I#Ye4nuq$_pmr z*zRA3Zud(lbK8Wah?0`aO!<0#cYV`Ibkx!KQ*s4CfAbo$x8o_(BR*n3PRdScaihb) zs^mC)F_`9kNI(&P!}0V6K-a`zle^jFXZUix<}Va=?IE`95@jBKgy4w7F3(0^%Q0x^ zmi6PQ(5gTWWr$Ml-Jmk<8F!^S%xX48)5kVhCkf_k2)`iSrwVF0J}PPK&Y<02m5yjx z@N{OMm*gdFEqGG$-Xb+Qo^wOBc4x$5P7Y}e{>izf<%MWH9e;=UmqaJ?nmX&bO)1Aj zP;~iDMBZ{DWAnkcC=I#Vgv*6G|6hzPzLKS}DUYDGyr}9tRN1*94W(mk;R72h&?ix6 zxwd@OQ5iXNdd9Wj!eB&)ScDz;a#mIdy`@*0&%S{#jqa82f?BMm756Lwx- z<<83HMy3W`ypgasZ@&_yrO``j;cen~iZG*?mMyWDO)AFKa1W1aMd;*2GaR-7#C6wl z89^v3R#>rN`>A-W(b7>N&aWZvZSc*%P#866a2v?h91V=Y4@1m3d&Mfk{Wn8p*;2M@ zX9}u_QS61MGhUBBS>E#t;( zX<+jaXUaufW=MsHC@p6wZFuWWjrIUkD%}P`~|FPC>XIQlT<$q$h87ioT zzw6iWjGu0t-eg#Bx8$ptyFvS~{p>2C>h76NqPE-WC{LD}#?OgNc~@}c?g3|Mh&0DM9|zW=tq0hB-N|;lw?Jof!Al7^ZK-ebEuE*B94Y0 zmT@0nk*egHPlpd%1k-^I&3qJm1Gz`O=Ys$gL3N2;k+=(IAfY_${a&0;e!A`F@G*F{uCLU_4aiV|!pzwWs82tp4P??>5=g$II!` zDC?L&%F`q(tkRyYh9!l4eLOJye!!xaDH<(ECW~SsD?|Jr082o$zoikl<8b*=to?+wW;K~R(Hf_q!92yxO1$T$yXMU z?8ci1T^Wn)Xx(x5mYLhPq<@K!O0@vB8i15!iQ@z<1lioVP#8{?#=JrQ3ewScW!dVx zenVWZcb4O84{Tb}F3|`=B2<9iko$CBC;Es7u>MRDQY5SDgsiG7vZ}7gs*6xo)vH;Y zd~leu)kxWAsyfPrM##E)5h>1gwQJ$x1>8mmhptxOxsH;%`Mz2 zMflB0mXNe6lMsFx4SYDTK&sA?iUCX*t+o4wmbY})8>peOO|JszOG~^u8NXq)&lv30<>Ba-!&sHn- zp>LY2R&FY9AHl5LJ~@EKKU+~Rp!BF_l$2so1)02>E}xaB&Q(vSCid5}kA_`3n$a8V zI1d;Q>U~0%kdj$!Y2v0q3ME#M4x<=)N7(?+ql{#1C~SJ?PNP*O?N!d@X5qnV6{j6l zji}#@HR5SSBhsX%5%oiG=I>SF$fp8>(^wJiZQE?5yL>S18@oCl_ii@mOzN?2^>sFh&YG~ z{&-gLZv(0&7f>xZ`1%(1h|w=k;%)d;7dfE%eF0nkj{U>!8Qn3Y?RD{z@ZIp?;&#Ox20~h0f_|S5=e+3NrP|_9#|6w(J%<1 zUyC6S4S^s&8U)cGNC@E85D1}GN=CAmLqX^-hY(Ia1C8tu>VZY?5Whlbd>(!=1Bt_OPVq7bK(q-1wp3~82M<9nUVr6tS9rY)YwT3(nzht1ksAE{(@aO-I zaIADjGfQpbEer+ao`gS`x7|EX{t{s`kwy;jrSsB%()U2VYybs?FC&+pEv=s~3r zsUFacUSl~B4}o|P!~-Di2XP-rctKJJQWWUx2mO7ZKMMw0fEcucNl{HgqSq1&#a|4< z5kx^fj9yDT3J0OX!q6x_50SknPKyV`kBK_5WRc5a`)F*m?=vl+1^ulBMK(mMT>e1I zZ7t*mc+@e0?Z+P>n$KP+7B51YE1YR;XrOFqp!~xuDfxy*1u-C^OX+y!IwgFejV*w} z7qP&L#9O*rND_*wPPq)^*pEU=-Qi< z$&vI2(k`BQh9sY$OzxCFkbv)Me}uXX+Na(yG(2A<$^S(%7C7eu79;s%61+e%){xuj zL!36)ga)6<2N~w=#Rk^}n}OjV(+wubbcTUUN5wf%^}X%X-jPNYNbEbiGQY(U-H9?%MGg=b?f5gt| ze)3}-XAgUQF$plhS$oq6tcjp6Vq>}F?Wc!Eog*JCkBK5a3B31hbqZsx3!#0KnfO<A^$f|xr1OA$(p44`I4v_?2Sl5_2sI{T?x~myopPoE&!H1a8fN@mqM`Xo^2d6k z+4%Mgb`O$x@L=s@q807-N9s6 z%8|Jo>p7NO=zf?zNG+=Ie}rOCl`yVubLmek7&}&hAI{m2REV6I`)!WmDfs!M=U64V zz;-`e!DFa-02QgMfq)-g6{V~ZTx$j?BTF8C$Q_&QYZ>nfB*!c3wwMC#@z_AtZ!}rV z{kzw!pY3&jVkX%ix3smi6r<$7@jPd0jiuz4Vmh}WD@QzOugPMUB3`S_@AP#|=0DEM zK{=6#CLpaUkXB#NTZuT)P3*w5Vgs#DgKa1!2tHYo2y1{fx10zsxb~SB+fUL5wFFde zuL?JeiGt1wx16Xb=h5vaEAUJ$-PF6Rm43PHqR6{J&4SvMWE1%Xgk|Dw%VnLOuqc~p zz38^t+#=m}ZF}i`J?_6Y1=^yq;e2u=6=@5I)SJT#8#AmNaSre%R2oHjX@s;2f7HH{ zjpaA)T_0QD8BBFOlgkD=)*(DV_~cI7MYIw#>i!zB^YDoU)_&X<{;aS-J=&7|yy0N; z&b)XtjgsuMAFud?@MkN+LJRe1rNxl^e8q5Z$u=5zN0B;5n*!r{g{}CBNhhf@gx}Zy ziBD$6ZyK~^l5q#8r;vIwu*qU*WMX_QGZg0x2IygTm@FpN8G7Ww>BaG=o|7cjY%y~- z3#$t`c3r>gI$wm5P)}GHKGjF`64Yaz3eMpv#?|>W*bZHpEO?+KN`ZYYhDx507up`< zn`FILL0r|iiB6J}Co1v+-}YFAZx(1Zv8BIySQIG4A8~~wS(L7Qj4lVKxejxZEubf0d+`bbCAO6mx=E3qam za{_O5dtGLpp&vRnyfBqc4$pN-!{d%*hac(mDEVFRl-^5p5!c{2w8cW0BNlM4V z#z$KBhmXt0(+9kZ<^wo>QB?}p-)Os_6g=BnjgM4X_ou_hD`^>iD`(f`8Y)G~voNS&V2XB^1eJH(q!+--WZ$7YAjp5mZ>nsOAz+8hNtLzDEsm@O=6;yr0! zkJIaO){2nzI>dkQk4~T0+0{MM={7P(lZ~K=GPdUNC!Ac@;gjQ?!Q_zNly^t^9dd6bUvBs4Y3CPPyCq-3*4iQZqP4w#KdJL1D-eU3$XQ7a7XZHB&wXJpJLEA?}< zYS7*#33)`FD^-J%cR*vpW`zq*cTc38qLtN0udPD4_qFzIYLm%-uS;uBc_g2$9n;=7 zuRrNzbZ~Po)Ku5Qc}miM!j+&UMS5lMQ}}QMd_>d;?LO@i=kasB+}Mo(6==H8R$L|g zC-^w-=a5`jFT3~drV`Enpar*GyJNdspiSY{TqvAt4K?nWbn1lOW-ZaLbBFYxDP*-R+G98xiclJ#cY^zU>O3G<0c(-}>bcUPcBCL#fm;{(cxw8V^7Q;@I5BZ(YHa^#>_H*6CYN55w4v9jt<;kjqe*xj&%CH9V0F2;SS#%y4wnPi~It-TjUqqpv1jfSwwz2_6ux; z9XSPTYd)Z(J@ewBx@&+cpQ_ESfvorijZ>Sw19W!t6D==BtMlS=@1Quh#@&)mIy3>K z&9WGFw_iWd@D9q^ZY`; zo##xSs5lqQ9gkJ;xr#MiTw02!wQnvf6O-+R<>s`aXy6pw-dVb~#~m8lHR#H=?^jXRrA#+vOG)qp=nm0FPOwV?v_Ir#&EibQBUW=r zHbDFRhmzB5p!GE8O!{hHT{_=J0!fEaXVjY!lK)!rTc8S`qNpJCeS_!)Th0Vqf-Su3 zJlITh*R{6t8RYP5K5XRtpP;Pn)3(6PQ` zS1dc29vm&Eg1wvC{Ot)hN5j9+dO4a8v_WHiteB>5%dE{hIYHnZc9WH-MT-zlctZ|H zvecOv$jA(DV&PvTo;Hc5l-nP1$}zm-WCYUd3HouOP4Ob0BqD(X;<{)RxWIwLaTj;o zdLZ+tLD5kcaTD`}H@@{F>=oMs2ds(X6_>SS<&IaZ2Mn1<)wMSBmQDL{S?`a?D%q3%jz2|-iw{?pcwF$67(_mwz9FcdPm=S_>m zys|_BSKjSJer|nNlKS731yTj=fX0^=2Zz4=(l9s~uz3U{rF)8EZDFrBVrQwRX_^te zHrZ>@QxB2U{iIR!&^Bmi@q(#lHlluGBWDEvmzQ`W|h+=n=!PYgOUt^;@$$8JB_GHSYZS@UG z@TMf%4kg-tx5DzzHSgZG{Gk)8KY!D&)E!VH4V3Onl+hY;dqQ@G+z-e-6k|j0Y%KM+ zI?5oqZ4R$wAU{l!w*rIcvfEu|J@s*tyagB~g-o1aZX(kjp07RDAevd^>O|vt@VFuX zMtyCTQ{SQ4n}pWVR!GAdEXGdU;xA{-ol9{km5nagwRd2kMTQ^5$A znvZa_Z(gb!QJ9S1Y7&yVmy0d>=JT7v`9M||@PxWka7VW_5m(9PP)&M+f!s&~G3a*s ztw!=gAEg***}H?H{_Fo$4}_rG<&%um!9~g_c;tDJqk8_ynMve8~XJezz0) zExM!RCrG{Ib2|M3ph>~R>5L}!Bq<9vUPl^uu6Bq74;olFr8uid;FaqK;P(B!rBwMi)t5P?Iapo7X;(6 z(6R1Js=Eh{eSshWd+870C3+5;x+x-tYZmF4XHrB!Nk2!RV`u4D3BO0K_|KnfHsGju zy<2jri4LBDUaZ~jwHPE|v`4(2h}~#rT**Knhe#$ zp^S&)Jeg1^>*6?97E!i(sS2LZ?ZkK3qs(@h+)V@tJK1}d6Vvd1KS;ov6)$L>#94H( zS>hs1O4C9DE);Nhs6l+RI>(c!lr~KD<_O4lf}-kGkBS z)ufR@-72@+TECS=Xwyj#&?c+PDmhr7yO(oD-L9yE`*ffqmvuddrVmPs0_(>;LF9=C zA)TJS^d@+aI)?k3+LRs9Z0E_t=U9KlH9-qd3NIEf;^G@bB6O@IU{QpJSMal><@9+F zaWI%f983lg2baI6g25KVy_R4&i(a#DCqv2s$WAxUyR(oo$KhS>hm_%nlyZ;y^Ov4I z%Y#WM%@YK=!OTA*GBG7;0^gjnCNItg#ej^V#Bsn)%7XXcLd($i=mpAU(baM(w6C|c@3zpi zfbF;UK1a6fI3e8I_g=DAj|4;4#^miQmPeoojqiX*E$8f?pW<6_XRAc+=M;aA50xM^t90EMfw z%)CXbBqLqrHb+HQ2@YV%V6?FWHTskJ4R8H?zW)^^$4~$SsIk}I{>ARy@BZu0#w9dO z(h4LGt_3yx4XB|Ds}z z{_xM=!XN&LoK=9@(vsKa+d+Mwoqvw7QdeURVQoHZ{;|gL670OfkC0^5n17toNGvZ2 zJ($slX?S)mS~sGDGOI?tfGG_;!|(kIX7<>$kI~Is)cnpvY^3Vl+1w96%sVQEdC%yV;1l) zkdOp94F(qmO-TRat@lt=&(q+uFoDuzOSkIS`fshxtxXb@-Nc)<44I!SFqneLJg~jC z=mCL9Bwsr*|NT>^=O6o?f>ThCmU$W| znAU5s^8}Ca7zI9PEDBUTP&rnpA4o72e!)PpllVDfelnk6crf(sDqPasw5C-;YO;)g zm}Nv>GHAlz8$5IBaZnjBlt3LH!uw92!q=aWs}&R}0o8r%$r(_?Cl{Rf2a=OOZiI!% ziyYv&SD%s@&NJp`gfRu$PS}Jh7{mD#BQZadF|a5hNbzDwVzkGG*<_^Sy(r@ZpKky)(B z3&K&5!l*o-GD?`$Dgx`V6dN9HeDV9;x(^tYin;k_c%MZA{`o-XKH{h4%Q^)|ANfNowxVvw>X&}T?DuN5z&o3y@hMT$XB+ze(O&zm%~QK54g zO)i}rpa06Tw2+s)W$~Kg|49EdU$i`pWg*{eTKGs3mXs`y+}wa7H#eZj&4y{sAlTs= zPE(sMj@)dRNofY*wP3?^3cSDK$j#x(>&_p%>FKM=;Pde8Rb|tj)@!=k_O|;ytyg!q z?Q8cF+8r-_qrdC!m-eUN^RAa}T=(@|iOTJFty_2BZt%PtYEc$GC1{BstksoBE*hCx z!g2=Vl*}xiJYyRGU>T3ky@ujzL#eJz*x;L)6nX{K3X2#dC=;YKEgbBX<%s%tK;?R; z(csiGpF&${80-+wlPEc`5;%CNSq^uOQbs{;xQBu3183%x^s@v-;E>YbSRMr{&uyT6 ztFe8;ST+z7PnG0=zgWdAab$*ZIxDQRctt{9&KXELILKDa;?dLe5HbORC!t(L;j$ga z3@8yqMVM5&3=IoSr$8xW5(G~*L9r#fAkqC0_^noi>Z8;1R4PS5XK$kv8u?s>%Al4> zW?Op%xM3GFRpw{qKUM}VACcV?F zmH)1CxTD_XO9U-WpOXd>7))>#>v5ZWty2x9qZ3y(JS!LcmUqt2lLtWi^ka7l?NdTD zB~%@~{*I)-qr;yhVN~LYr!lp*N?T&gx5Zm+URQ=v{w9xw+1r-+iF)jFWzqP->Sv?Sq@9Zu-*m=jcN`u3}sPuM&)~umjUZ=aduOzZQ?v}C^ zz1Gaq+3^jL+@^>lJ2#tRtp<&OQ|ofFjlrJ%4OJ6eR5(!o?OHfZ60<3EwX!XtF#6n$Qy_aj z%s-RL@23ozgD7pGlC$~^&qWKgrNH1Y2DG5xASdf@_`!I^SZ7$Lpx_nFoaEN#`1bY! zcgr<>jzXVDYcn~r2)kU(P&(~=rE866>bnyqXSbi2D%a>uI-iR*vvQNo=&YM)iVs!W zNlIeLAy}tVrnPB3{`q?)WMt%4xb7cZ_=tRma$?0;12&FU&)lk6qHacMu_#MsiTbB8 zWpJUqobrHQcUrq4Ig9Jl5@4xO(iS}OaxkGlW*Bo3n@MRmP%!_JNLV!5S!@!?N{4&W z6^;duJBf@E!lWWUx2hE*RBsu-ZkKR z(p27`%xP_mTU?1viJIYRJN{trx36jPH>YlYXk+)I|8&QArCiN(Spd0NnVMC%9s2&D z#%|J7Y`tT+YEv>>Wpwa|o|r5s>ewpSdMn6-VC*=sx^yJlZD(lO$juVXXD}nh&El13 zEd9)|80>pdr8P}i;JcX=dbt$uJ8im-Y;c8{APfWYAW6yT`660v%C@?^EKcLUox4}A zkyARJ_@i3S(BxZumc^p}>@~P-NTGRcvqEd*eK|C5gI@YJgC6}E&=#97Ft-Uw*7vy$c(_S^! z*Wz~6cML{qukJ4??A%cu+0?Vfk=@+8i5Te_8SVAeR#n(b4$XZh*pjGrIjfRQ`6H8) zD4H)u&H~93!jjllGy}4V;0%CH>tbLAJmpKwyWP?VoB;Vy)aXx3Ggk%CQWcGVcVZq0 z6e(O1!1&J}l$y}^myWC)|B{tULfLY66)Vn{$yr@d_jQl%%I&Bt(kdjhQYQCTcZWxg z^%oG9n%2J1j(hrjrKyv94?H;PKjp3+Nz`ntw3(v=$=0vpuXaEFz_GDP1*_F&S)mmH zt7Tgbo*dL<8C21+W1W59y1JqNyYKHibShOCYTsHK8>!7fI) z@giixA0J%*^{IGt^6vHG6U^8rz*KlZk_+Tor!Zr42}?r5**OOM#Y|d0dmtCgOkJ9= zegW_>eZ?6C&erk?kcEbMmVnCgi`Q1dREcX9Tts_l@&Q_*lFkiEl?+V-frP7fn8NAiTA_g_9Hijv&&=nK*`iE)9{NUoYn@a4p&cezR|ZUWp1;0+1xP zKUJ6w{$k--;=l}JD5OF2SDeWkWWyN@DNgAOfCL%yV9v8Ckd+QEL&wZGEz7yldr^ev zC2af_1y-uLuv)K?k_wFyH#PScu_K$SHn$Y3C`L{x4DtTG@eM~eZ>CcJCc zdK07?$n;4-i!m<786t=lo4WHCoKC7~&~U}Hh)Op_1X}EN<}aks7c3X_m!ieUe-ak& zs^0hL_L|-6qZ%1as#WrE_f%bSOPxE=eW2|+&|XrSQOkEDR4nZbM@L$V74W_VNlDew zp1rmGw+;YQ?2pw>brc*~e|)@5Z?|jIx-7lN>hL<;)x9N=4NIWtPHZU4T@!J*0Vry$ z2F}PU)gF&^2^6KJo!jAB-~Cn~uLrrgfnxk8`gwV9N!)UEm){bj|{YE9B7J#Tw=x#OEvV ze_p|fcB9U2F{#K_sS@4#k$ryKA}4MI^58ziiPtXYM7RT4a~AACw5G^;Jci|CQGkG8 z|B&CmVgteoo3#vHoB@RpC{Cx`Q6LjR0YpZQK-1H@(@xF#br&E=wo-hj! z>1B*mk=Hn}rgm3n(ARl=U)6dqg2pPiOVjc5S=mjYsgqL`)7!o?73Iw)m5Q@)yp@xg z?Pf=ETXXfMxI?)d8Yv4datxyd{iB!+0Q!gVn0`sa+WE1dR@_xM>7OhEId9!9q%0 zIlJ&_LIFM~qYI%BMZ<3?*j*xL#c*mR2r=sVJW9>J@kl(rMC@7Hzhp~OAkLWQ4s3f z3L0%Qn3Jc#NX=SKrFuZ6<7Y5E#X~AJtxBaP9#N_3vQ)aL-X~8XC=F5?qsQX*as-Y4 zZtiZa79i=LE`g+ej~4+ciFJX|at`rm8P%{o6iU+|-A$KuaU@YX*|m=YGq z#-O>O%RKlGq~vmxrySlz)o0;t<*1;T2n&{rVl{BN+l;noL(ZnXYtFtaK7i9!>%8zA3_0Q~^Nr`eleN-e!J7xIUZVfeJm? z41aZSK41ay4*+@ab>;#D^7UU9K92@|9atdG7l0y7;Cl$I&B)ZpK@CZtf4}bzRdYvV7-Yr0(kVfaQ0_ zOE&g2IT6cm%Bu^RAK z(0#H{Cj)#aQ{=@vi$?BPpHGDE8BX23!B;%_(4Nj41`|H+lsh>buNjQl%wUV_ZLY1t zU+sBJ;Cr3Ur2_ydV|h*Ujo%w|gks~zy86C(RRh>o-Ts{h!1tlT_ARBAqqRAV!49SR zIGCI7t|a_2MEGTh@YU0rF@W&u)6~Spgs%pKKL!b34c60%D<}MSEA~7(wc|u89NqQk zF8F-H-#8kr+gj`PHIByMlQ13r>G9T@Bd;7g{L?#I6GvXXXWzGn{n5$$2Ej8oHhCX( zV7c%q{;tG_xv=P>)>nJRg|xmkXKY)kZBXm`B3$-hFHS3=(zj+Nh2Fq5@5M{#eACwO z_`3?7(`0n$WxrN(NW{Uc=?n~F3*>?;{2FF8~d-B4+F)=f0*fg3xCLM2O;u8X_1dC9_( z_4NhNeHv^~whT1r+N(Qr?cvsf%HgC3&s%d{ z%`Cn!Y)p%jI5?~UI6Ur zyHb~@bvuD@{V1>bwp8aZKrbcp`CxlU!F?@$8?AE$?Czjl^=&Yn==leT`ETHpc+BN~ zFKy=X9>r#vc$>+nCOR3lLb!~7wUjjz9do~e%s#U4N74jHC@I7_gm%X#7nwaOFnjqd z&L))k)gORCk-x>1F`h1g>!<*ma#nwkLPaRkvT?Mu-mgOH-iy_{a88N=iAhua-uwGP zeYFKDT7uRKg|DKcBsrXL9J|Hh&vvjzoyCIx9y;EW$d&T>-72Fciyu6`IgIzMJ33g% za5@FUS+uNCE#(ZHv%I}vxSym*lLP;u%_>8R1g(7j_c)2;f%aWsOzd3v1Gx>XM#Vrb zrUX4N5Qn<7o>!O9V#>&e!Jw9MI1-)<+Ofo6#3f%0l(a(CYYav{Oo`dGo(n1M7?t?T zq7)FzT(Pp(y9}(i6>q+CuxWR9G@IoD4HI{6ve!fdtc;))GKH%snYVVTF`Lkr)i(Rq z-`M4QbYwiMDpsnumvxqwt}Qmsx{p>wL`M$R zDGi*Wuxnq(;JBPKs5c+&bh~3~;W#Q>_>@#HC+ZrJsH-4Rb6~|iW7@)OTZO3MJ3!R% z(UZFc!M3jf~R1&-rc;y5%*A>ZL`W~1`+A27%~hh@kKug3$= za-fE{1@z?v=u1e{E!ciR!y6(9q~RqpG`!{K2|WBsSFm95fdU z-m$6w$hv^3v^$mnli-!%Eyc|tqb}4Q8(rr#m-Q!;y+r`q`l@O-g!MR6GuiCVsUNNk zcC1M_%oT~2{PNAsft=)Ed7wENv)L*e+VMZc+w?i54tsHazPVsvp7oX&g)CWRrKL7! zx!-8ZNB5Y!KuflQmMp~@1n+yN9bi|goxxZZi^EyL=j!#A=qJJChaQhKIA*yZUAbyx zsDBM0Z!r2v%9H#sg|bU67gEyIRt(9?6=S*jH-iubH_)wWU+u)*Tk_Uc`_wc|NTdo% z?yYDGwd`olAq?forko9jx_zPH}|H;q;}D%b74H8T2@uI%jC+Q875LSq1J)B)P4 z9kda&UZ_r6K1RT>auWK4Txq?)jph7x1s*1pob^JA8>4dmx(XReE=h*%d4u;%*6-}8 z@^ZNY_iW$x5B<46utYi|@s2{?8tyEMcLq6vzwYJZ?O+Ri;O@Tbe{#IN`Hq)w-}~U^ zV0G%=b>LZ0mAV(qk`L%Gh_$Enzx>m7j>Alh7VLc!Pi1e-=qWVt>CvR1${x2 z|5FYvQ$_(#1p!adN?m-Oi>I}84ccAi{46p5Fg}3ixm>SHg}C(6*C~z7q{}iH zl*A~*38HXr!b!Buy@{-Y{zw*N%KR9R`FW*zrBLRV3o<{7WPY&veYcwmZZUoGMKV7a z6=c4<`u!9tLYY3fVwu0%nJyCgqJFL*w&VVh%1sS<40JCc0YcwhIZzWFN_y<`F+C0xn8jG&f(@=UF9wf>#N;%d?cs7%&Vj+ z91ISr)EREfU%Ru>N#@GI@Mwm~Vs5zLaB<)^s`@iezu zJk1TCv8*cPErOJ{Tvp0woaWYmUxu3BOR0dEcl%fxe`xMMK+j4zHSu*7r&tv9k1G-%61yBt5;VprH^v<=^=}*+&<9&0eSJ=Ad0#BtT4b7>+CGWvkAK~j+)^9rY^<`H zDr#EuW1H9HdFuwleMdvK%DT1qZ{uxk342Llz~~*F*JoE0hb+dz;+VUovqO|s)#7;X z6SO~InDf(WtO|~HwJ-UB+bu2sFn`SSp)_-_zxPIkIMUt856}^A`G=|eF{$apv;e>I z!&}M9!`o^$w|@IQqq$8nFDoZ#25h^_T8cXNtjWf8rSayxO*gi=3WmNm(!8su%&q>u z6|`6R+9JKSu%*0Vil|85anruOV!4`CnX`0e4HzY==*XdZ2(iJQy$wx=(L9(sQnVRJ z?wrcC{(`0wTXx!}k8(jQ#F~Y%qbCZ%FmVut)0o0Ciz}uz-5&5bP4$WL`-S%e`xXs+ zJCo9ML(31vbP8m+lzvBlu~}dI;4?Q|fA*^Ks)Ike@dogm&THS-y#AVIS8m7NmUY*( zxQN5|e*E~RzDF*6=NlJJZR&gU!h_1=FCUJz-S*6G@tL;kql}mfD-q_Yi{KJ+BgZHi zTNl*}FNeH_qJhG*Iwg}piRgyN-^H9yDVH?d!;nh5kw@lyV1I=}hv{i+KG3q&*mY^$ z&cKpx=g`v(S6(5gcY;X0(+$--{?l|%rg~@PdF<0dA*kdDib|etq~!5Wr$EU}CC_Sy zv)U^#>Vv1Vp zY2{MZZqV6{Mis6Yyz83LK%gz^cKcj1E=#XAa%wimV+jvlTVH+s@h5h_CFjMs4&(vQ zN*SlLr59;?`ZG>x8FWhfXQ;L5Hh_=fu)NY!T1Ggf{WDVgbi-3xW^v&Dy){1vDt14% zyJpwA3Qk6mDm7Euv9lp<(03qxN;|b^&^OXtq7pSf+VHxmnt|Jv4EpfN&fCXhI=fS? z(%B8!R>w+vK8@6!SYHP1`P{iKcqvz9o zE%Bc!&3~VrF`yG#(9j~+bt!r;iGXK>Q(7j$q%v}^Mu8c=YcFZlC(-dQ%XH|pRyOzH zqE+9^l+G2jXBRotFKe~Xs&4>)7(eWH%>NR~NeR4POSxm0U3F`&Sq7 z)?AA?$|fl_;J~ZWx}O&oIk0$9_miKH2dn=Kp{~=kd}v()1yLC#K*2vF6zqg&wadrT zm!?5_Ndtr|{Nj`Cg=%;)0IVtsf9=-B%h>pF4rh)DTKVB8wx5`)V2wsbskP}?Gb=ON zOzzsr=IV`A4hb^!)3}^+9-Z0VM-Vt39=#Rp6+}xvf+nBCME|AaLC|g)6x1tHP#97W z*aH=uv2-%Mt56Vp2Pg=>{JYq+NnYTytY-CRKUK2uViG(+lxuBTuNNL6g1U<~ZJ_S| z9m9~#*6+z#u(Cj#tzLA42%XA*oS*m;l-=E+tK_Gp%X=6~cOD(Xf1GkB{)B{lH$29X zPp71-b?W~^8!h5o_u~&98?R(oJ)dRKTUi>}Xgxg0+Mtcr9bL#q>%{weZ+ud)(W)G& z^(@(FftJu>0h~cCVO|kTEGHdItN=P`&4K5o1$ai7Fc@=B2mLYY;BltT1b;eD6u=F> z5I(~x9=AHh*iKH-DKmKf7T%fjK>uAtK|-!@f(}VwBn-cmkb@G1igpEoA%DRd6vhu7 zkv@k`^)UseD9E=843d+pv}?vV=*-g5yx zA0N5@s@^hl$FU!!{^6BFQBUp0Jx8&$y%}JYAg)Bc;PKdTPZsX6;n`N)W5GRU96B>K z;<>1IcOdO(MZ1QilHQPG~A8TFN0x zdl~hKDmQ`$?09Y#^u(N)O`EJFa08qT26U!xa3cS_M8P7?2|ZGAj<^wHgeGL5-(?0y zExcmPgGcis>7|e2k%#5~`_Q+-B=56z6BWEI+)-LJ(p02`nihhRnPMBZ#{}rRW$HDe zKF_h8%rR^yD=P13vqe~78zdxMv>cPA2dyC7~ zCo*VtLzy4mKJg=?LJim+Xu(Jc_UspFRT}Pqwi+QoApauJDvs{OC8E$>dI9ds$2~sW zuL1Y!ajy;s7y$-}hr&G)JYdDqTFMJ+X@S86elR#$F|M-^ z&-qtR!+6iOV33_%_&kvXav@t(D_FoY?LbdJn;0HNncKX$rtXim8T?1u#I z3*hWq;_Q53=nY|_3f%zvVbL-(Kf$Hk(T`J@8_ZMmZ5IJQ3d;9I%>TvqnGwyGvCqUG z-1gn6C}%dQm7Im=pn+zV#aTDLXrQ?S`=Ws+;APQ56Y%oOi1jyvnRW`X{-1<3nFDLA zf^*@m94j!wZ^cCr;RYv$aRAT1q7lCjg^6Hi)1_Ee2vdMcv0^Font_oh_Ooz$(qa$_ zS9(;q@C<{vw~-;7UZj$Yi0bG&!Sh#VK^b)9x@;RFUg<39{HZJW zh(Xy0ipC(%@v!**7#@i=#KvNzCx*vni9kYKn1kme{^WE@BOm9%O_5C86p30-WHbw= z1!zLiZnijcZop{i8YkE)L5nxAYsy30CE4P3>9Q)(%bC1I(iU%l&YFCk99q0F{;IB$ zE3kNLIYyl8dHjJpw#68h=N%SM`U$st}L&QiYwDRMET9^~nv z-T^5JF=YUx+>c5zVoEV60INV$zcq~VC>Q^)7l?15JSs7z4x}7GDQYpLlT?H6X#^=6 zF=d!&#y8WuKngFWtOqHBC`AiX(5^6-c!y|3c72PUFV7&)m($Sm<@1^Y+0RqgU*!4n z`IP1WmHm7Qyh?ARaxUITEmQUq@A$fI=kmC7G4V zDZo2&DY36ZN+{rkS(SpC!X*R_JtKe`wk$-5anPm_L6`nR(4rroEpQdMu##CKnNY}$ zZ~G4@OP?pN6|UQ)b-So-Res~!De#&seLe*;2s^e;Nh+20ed*RNb*sD8Evfh2 zZMT=U+Z(pqfGuon95*&#V=xdxFd+*`NMqB&I!qzexN>Ib$>h8QS z`bu8Y-RJ4fc)Ghi8C+{Rjs9C+M6~^(yg}>@9ec_4t_`!4 z&NKJhLdS}Tjj>?{9K2SDJyR^~Aq>yX2wcU=HpMP*lBQuk=xwOkXElR(R_OY3N25`+glTdghq3j6pIqiFeN)$8FmWuShvNzbd$N978+ z8RNi!c^Kx&p^Ie-XPSI^5FsP4T(U(VBr*7YPjRsBYIQg~)oMCLj8)HS=F zgr}*)4Q~{~lZ5b0tw_|x{mTlLu8-22tTT7LiXt^?%2Ja{$lUaZFw_gOD(#3 zz!(iVC=%*C(&UL*GmDY}>R8p%y)G->rFEoy;USyO)9Cf5U38>zT~DBKeePBJ1413x0I`pacQF%8V z`tJbQ=yC21aZ-KV{Q2d)5*N8QiqfM??WC(>Hr%>_|P5MfR7ir4M}wVGsxU zP+ldfts(=63_p$@2PU);J)XCabqO4CGj8m6Zq$85zlUzNH)H3T(dHvKY|}M6;Qtpr zLk(WmyN?w0d+_EXMSP}RtB2nz5eDWiwi^t!i|upP+OcnZ=TQ6BfxyZ!Z=;WQbza`t zxiM!O>|3_xfwo+}jdmuyyG%NNYrva!F?~aWedyM!U^s}LjX^dT%{c1^(l#;P70O-a z30{VFMCxNfgWF+aGNmU>ez!}fb9ns5R6GhLy%TWjAmA3nx0|ZxD}bcK9dj+-PvxDdq}#&7L`(D}S_nWcul1{T_wzR8euBoXh4-e$1bTkKnbg zxDQhH)X4S$TVuot;5(+K|~$!bVoq!2KZmR5a6UMx#x)`17 z25Wswb2cMG)qyMjjy<~jPiLFvXo=~hdnOI5vK?UTGj!H!=T5tDC2i0e1U25$)YO7ul%Qh`S~==Udvwos-h5zR8z>nDr#$xl@!(A# z?}ouF0Sv%$`wtuha-KQ&AvS^CGmD_}9FN#kj0rUzqxaiEuRliI1cVxNbRf{ry!uQ9 zK_4s9`w924B6#>&&%4x3!D{j>gY@jNXiW86fCP6+s`%t0V~hiDf@= zU=DuHs~~{>q$oYOqz9xK^n5ePn)T4*8${1C6aa(AWlD{n(VJ+3h3>#H=&|%ahZVSz zXF!YHrUs=4z+4EX^RQqXdSKRXysmaDpGIqCm0=sf-KK7JV%)mok3@=V<-emN1x1VdWSr{&7R&~Pcsg^p}&@QAXGXXWMXLSfew2R4IZ}BG;g;P9sBJ( z%0E~UFA3*GnfG^q|ElZM^Ul10ztRzVplA;sE>`~n!9Q3P!SWxNcd%G?iMiy4xy+lL zNd~x@3G{AmbLCQATCP-*mQXh2j@xO@-&WtQP?g=n7kc_rP1aPflqt>WwbdCuTB+aqY?feLQkr#dhTv3Fc> zx9bDNn!KM8W9w=#HV!d%E2SQ&1hP?-{sC@cKxGQ~Z*i^BEm-^})qqO#TkI##pB61U z;EoXJR(gjFXeY+NF)DP6Oi>OTP}*fgyGpMh5{~*1(_yzEnera>A0Tmb|0z$sr=BvO z29hNp6zntK0|P1s$j8y(4R!-+cwk07L94rC9@@60zE=eKgVCeK;0=V~ff;>uNv}n| zIbho`2W#ts16Srlg@^?x0YWZU8hy=Sd&+0%?Ta)SSz5=VOVt{RD*aIxWwL7uu9s7z z&32_mqcRH6(J4h!8gs~+NRc#;iaJ)XTFrN$s43QqNGk;&VqwsuAVMqe)AuIfU`k~$ zs6b;s2za1^9qIl+fM6V`<9k3wXVA>|FT{fxMl&V2tOJeZlox*)># z)dK9Wt9@OzbA7AT*0*<@uk%?cxZwwmNP}X$Bcwy^!{OE?N#h;Sti52NZDEVG&a8bc zJeu>?jqK_hx@AKXp-`(?hT$ohLLs-Mx_lgOPxr^uO*%T!A2o80x=Ku7j0O@hdrk%Y zc?DU&o~IB!!Eh*dRJcJ6MIH$I9CS?x+|i=+Y!14{tG;7v{kqZ^MiPI()jH^jgTZ7d zQThpVn~0v0!k~_7c$QO@D5(BrN{U3!iB_9{tMvd^dqJBeK%2q6s~uGj=^^wW!XqB^ zAUvhwET2+IJdQpH_pYKx@|-H%NHBiX|6S95djT!nU(B=dW!$!yi!-;Z?I?_A#NKSz=(i);=6E{Gd(8~X zxRNeoz|JZyi9mb$NT4fWG1TQlmRQKg&~|^s>dM8eLS3^vHEgvnL1pex&}|Q!RC<%S z^fR4J6t$FKwsWk_sI3E1?gkul0FH%#l$S@5rn=MUk%tkALefymjZQllV%%@B5K!0; z`y@kgc)pO=qH9a@{Y8-77du?^0i$quzKo;in}fMCx93H=aoBsW9kZlD77C04m4Z9! z2p2*+%rR8oI+`@P3hQ$n>sl>eWbAboF=VCHrhv`Xfv)X8IMJ+7QyNz5FsalkAlZJ7 zx2AhTk+SeNHTFk&)=?*#gH{a-XKORqwb%q<#S}8=+Wa<<62}gpHxnk1qOYW6vD+|F z%44Xcguz>klwz!;@Yn&YmEb{&P)SLEJURl1yv$TdiGh@`^p;pjae=pJDUZ35;stpU zQXWes#SKy%Qi>I(An3V)bHBj15ottU#bCN~PfG{;b(NFD0PC8bCod&oIDMAIGFlyk;;SgngK}JRsH!3jLA8%>TMYQh+L&5OQ%WJ zqUWtFxKe6Va=A)FqJ1Q5<)PEoQF0 zK6`!O>Rt7_9P2lEHj%x9)F6`Ylyx$(6rUxM|n*MTKQ-wP5MrxqEnb z``&%s`x0BWHEa`Ct+lP?mMk|c$C}&ZZK_a28`-^Y+uG%Akx1L}wcGaXR`@n=aQTqv z+2~nTLSFD6n`F)=F8zVRH@H9L4cKKf|9j=j`#?L2e`*n>CU?8isbs=m`PNmwjg{}} zbH%*-`QP)OD-3h*z4QKl_4n{sW2sc^tMKCw$#^pEfmfx*1o-z*G9FK2OW^0U2otcI zXYx)TjinL^4;oLU;^!ZqToTi{vJpzDeC^u3+eB*dBwdSVb!mbdb)T))DT3niqjx;;3p0GAXy%eKYswsS_!%8WP zMmD+WE9*9VtJvgnYhAp<#wZwvw|7g|9k(hqj6y{j%Di|P`%vP=qe%6BOu9cU@#YZV zU4i%~#9WC2L}*}48H!gTJTaxwu(B!PGRz)1P+TS%et*+9WTAfad{m9N+r81vI z1*v_1I8%oL@f&deROS9f{2l1=nS5HhzZ2ByJ?Z`#>3$XVQ`}7aE4cqrCI1<0pTvXb zr27@%evfqjV~Ho-Kwg@O50I{MRKgzs@H2MG6Zgb5;%W4@yav(GNjhn4I-V7YAQT#7 zCD>bePg!{%{QD9XlH977vj>}w7b`EEB8)R3-^$y^YB#?7qzN4;Gd8@kuHv7?N0J~_ z<)}R02u6O*p}vWh>>7)fQ{qOoNU81qn6;(X=u4VCy)7PZ`>F0^Y_{pY~t#&hXv}s^FScQV2RV^veZxbojmmX+HjWk$DTBlMO_)aaMwx)fe z&u#+G8u|h6WPo=|B;Ng`!prBdqf%S_RN|!wp8u5iHLw@W<*0c|5lG4j9@j#F!OKC@ za%dC^)DJ-J+DF2?7&HEw5Hqt8W}Z_xgGL*t#{WRdDVKv6XeIvqk8lMo8qHQUp}>Bl zqu`Pp_7pErIJ}yE7#jcv62~b)k4R|Zj4Vq08kG5YX_r7npCB&8TSoAYdZye~isG!G zU?;hm$Up$;mfhx4o~h!z3_>-B)Dvc+A^4qh5d^4;0*p#uAW*eU5G;&b)?WHm76X=B z5bSD{KvkHMHR}yFR)sCy`~vnLT1JVXghGDuIE*-eldJ~&?+T?1!(=M?y`>icvae`A z#D>&?F{uZFMHl24*55H(^)ZwL6N9;iPpq85EqFD1}Kg7i+&u;j@pa_8(KAzUMT z|JCN>L*R;iwmO#%KkjKu_(Y9P zz@8Lz=Hx)slB{#9;YuRfq<0C_-*NU(=?P1nmHwsH8icJ{(S!&GWU;+G-qE3701Ymp zD^Ds-QyRztaZ0|kvhEJ54i6h>OhCuMddkJAqI~DvdBfWJNl+a6(Fe8pFtzzB6Nj~C zv-aW5cdd^fGB=NPj*k~swAf^qZ~o>)0u=iRL6_ci=jz6dy@Bapy1K5Abg`tH!8p1+ zz7YLT7c)wS4pE9zFZocPPhKgfzgkYIrN97kMk%vCP)@`L8VTf{ExdoW@RdfI0hH$* ziPg`B1<*_5%rR-oW0D5-L2n_H1axOel-~MSia-TEK1S;aI5DE84O&IHZVKAS&<0xZ zW0DfIjG&eOO2HV*_6F*5AcLWD8zAT^M1?S*$5+D3zAtHlN_4hk6`lfHfr#aq?Bfdbadag>vj)IKbV?&J5&Y&^=|@50 zDGdr(R^}A^Wp;823|#+cCjE6$5B>x@{Sl_&L|RTztOlO_FI#7% zwLI5+T%A0PE17KrSK(xb9X(R*D?k%f@CX=3 zxvQFpsc51*PLg`q!*4xlpPGq%Th&B*sWSugV4pfa`fWAT`FUO&%;8nHtvc~N_<8if zyZG2hOLioo*ToiPvx^gY*~WF>*wTFV*){io&*!q62SVYYiN@B;;rC`qYf4xNu^_=p zdwJxr2eF71*bo)MdZy%Z$~~orHk+zNiSJiYq8wO9kVo&HDpqsNL5Z-v=C_foR-5kg z_H5`{N@`*JZdxI-513;%MYvlbZqcvp70MUez%@t<)L0gcH_QnO)n{o4Yi=gRN z529b#ur7HPu$ICcgpA_Vpdl9OT#ed^-w8b{BL#UtCg?Dp;*OGdVL z*{{>r7wVG*A8n{_2j5;Tc6Qyjwzp=A-`=?XTidglt>50ddjE(!zI=E0`2G=3eEB47 ztwyu~%gBnrd>J3s7|po4To7C;NFthqC7B7y2A$Hti^lTcUs{{OG8%QMTSaTtM;|pX zD(Va=nw*Av)Eac7iRVqC9$S9}#oLW~#Xf>isivFt;8(q96E+~5M52iOB!jzj5*J)} zxc0}Rbk6fmQ1Wp%iovo4zm3N?$)?lsaI%~f##k-VSUcd zCs%dfiQZsFi-K8ix4F6RrkD4$n41RlCOyElltQnkT}^{^{^3yQ?Os!T&KqCUV8w*Yc;2JY@d}c+gmr>$q|h_069t{Y-{=y^751qoFgB0{X2J8#RsCtX8q~w3;TBsD|`~!od;K+gJ%jFhlr0xCC?`=d^oR^letd zXs16xpDyL4n7F6|>yfQNl1T7))C|gTsu+zD-a4sKyoA1%`O%7np2PTt8qU|QHtPA= zwZ@+C(#ifvZ_+L&6$+Ko66uJp-8Qkyo3(R{oCj7b!UtI?U_i@n2$?t91q7p$YW&<)FXU0n`{g?vG0)_xlOfE|r`mn&$TW zxg{^}F_@WxyW}ps1KG zrLJkU+W@phI2YisrlySpbTyPvAU&c4tl$`HDQ0MP9CuratC+d^TW9m8#Mig~MYM)tC(J zD{Y`Dtp@#A$I7Cji=V!NrKBSg4_XAl%tN1aJnF($1OAzj0FpvNd8J9|_t)3sRsP|L zs?L~c`J}W;HxnVY(dWC=em9?A+L8p9pjO}W)!V>{*54_NtzR*`Z1vbuOtF3U<(Cg^3Hv8H>jyG+Yoa^Qu{ji(K*v+Lwgw^O_2}}Y zS*3P7`DaQoSv3CqXX8f4LJr3 z@fOLRIeF&7#<{rn7xbvv@h@Y4C;`>>AF~ z=&ft8t1-=@1FI9!l?O%_-2}gHS~<9--4^KG*gSY8{N4clFd>g&3VZ_CH1l!Fcp7`- zM2%g04Ql5cuxs8=v1d#af&VBWV*;*WbJwZ8iKl#E7DWzCGNNjT@q^tey?Byi(4w zlsT67IP-mDO*^HMK8P9ctw;xwJdqc{c=XI8MNuT8&7miyQZ`Es$it3J6Q^MdChMdk z*9hb#Oj^T*Et*`RHyAL3w`)V2t0ig!IGI*h>YBa7i^neORMHw%p?geYsdv~L>%c=2 zRL>pDIyY?|$}L%gPDTbAtZJGCLsz4h(J}1}Ed|=ZGaXF^pM~M{9Btrqq+G|US1f8D z(_-Wpkk1Hm3TwnSN;b>~Z5Y%Wk5*0CW7r#r0=7r)(pF4YYsHdSqhYC0H0w)mtF;R9 zKS_r_;9P1rgZ}FW=x*Qbq)J8JPFqYiE&2tm8i1ow^!n04DN-2n0LJ61kr)y^9uXx4 z5Qz|;V433{P?qyKegR8%Nkf)^qRV@`H@5m)LL#A%YZZbo;~yR$z095zXe~#h9eRD~ zcYI9PvlqRqaaoH^siAN}XLL|ns$(!$P|$i5hQy8Jn}!#c6FBZ|fd!&(aXGCGH0fXkNYQ5|VvUE-^+WcA)WlM*F2%+~e zT0CX2u+wj8Rjd}v)bR!u+O0h3Up~M!6XJpGomVQ2Zg(JnGgYoJfNMAssc5AcuAOJR zW^LD;%_Va!mv7(Ro!5^pz1s}hvuSZ!xO>^?WNSXxmhJl--?yl@&@<52jb6EW!}4Wq zD}05bHy06wP_yf*f^Qk>s86NpgDs9!>0hEbx4jTeW*W=w{?JUjM~|BuXARbq6?^q& z*pS)>+*)|;<(=0vZ}3nb%TB* z<;c|g(oSvjKx_c>7jC_(TSF>v1VJkuRb!`2IOHf6I+(|ngS^^Xn)x5 z$hk?`N1#P0ggs7Sk7GXuwV<%45ont9Y1o6LrBB&E(n_Uo#rlcV?f=chia6~svj}?b zFmb1hAwB}5aP4uq8gS!yQI1HJt?XEX%g*?}Yr((&ddXrTKGIvP#&`<6`IzD^ET;H9 zXl@b)yoZA-+^KhVW4ounp!oe}Fiw1`Ola|9gf(NY%o4t+LcczrWE;<;M=nJKQ$w%F zZ&=aW{Yy|+rVTB7_s z8knIM=oc8ehQ7{nHFWhw=uP%bZk&6sOu9R2=6S7XS6qw) zrSR}9nH~|JHNR+n(Xy{h*47KqE4H6GSjW$u$6Rl@Z#thm*IkUfn|xpMC(0BM1OF3J z2(4ph=;S^C`^M&|{Dy#4JUT=-<>*toZs6bWlH~5 z`pA50$TVs)!AyESHJO@zcp+;3e9P@s$_BE3QKeSx9J;T~+4jYpJa=2}zw+-F#tRP> z9%}cskGFr+v9jZDJ7b;4y11?fx=r0TcmKNQ_Fh%*_TE?iPg5V#7g?YM`ZLh}IrLVU z`gMRd_uu^)>6!iyt2AI8@LiB52VNZ14K9=DzQNxQH4WV`bj#44Lth*Ei;K_)e-0WR z8vf3r=%U|@tRMN8#rqb&x}><|kE1I_rKD+j3YhPK{yYBDTPpp6JvL%D^85 zO|(sPPn_9&*X1j(;I9mB!MD7=<$r9wW9wInmld}ZuPI(%yrp=k`1Rsn6~A9RQGC2O zCDGa9>sLjuy78(Hw|#v(wf)f5rmKrP@EwPCya{Qif9K@Rm#(p2^R-<)yPo)5+vk3~ zTiAVkGBa72?4KN+Ts=84xovWC^2W*AC%-)T^Uq4x#uw=SM%uIQQ|Z<{hxSr?`Ms9C z+a%g8(Z0R6?me{kp1pqw=>F@n*L7Yuc->!KcmDz{&;l*c0xi)0uXH^D=x#v&aKq9H zeNm#9_AT4@`o7oq*8}?Ujg2?ncH?^ou3Vr6TA&45paoi>1^R!QCKqUd7HEMMXn_`J zffne`L{A;~_@<$o&i*g<&IB&1a{vG5%$a=##N4n@Pil#YFyI2I83@B-2*l!6w-{yy zm>g!NnL(h;MnuJ>8%Ki}{7Ij0d@Ib@}K<=ahzntV+k{Bl_}aaHB2XI3Yzu3dd_ z&4p{0tU1s;jh0ect{x}@WuOd{fih4A%0L+?17)BLlz}o(2Fhq+raIvv#q`ERGxkBLuH}XePm=07E++Om+H~nd6*+`Jo*3jDb7-Pq&nlw>Wnk1GtR88jF`hXv${H> zpK)e&#+lU_XI5vNS)Flab;g<1qoQNQ3#B^ayn_?D6wbsYb7`o};~boo^Kx#^hp$S` zkG@RQyqt%Ax1h&?nu|-sNCxLb5xHXYRdLlA^U;q#Q(U4%!tMA-xt#p|_1pj$5)+ zq^s0o)JpA@>DJ+1FYT$tEE}aJqQ9E<&ExW*6QSdv_qiz7ne=`;onhx{uqL5wqu)hI zBYCb!`+amz9neMIy|5i*+z%}rxYGv;nbaBwwZsv!!-B6G+`%+t_E_i|qO{izNF-7% zm`7wapjC&OpYDSX_En(nq&j&i3u3PW->W22Osb#S#MX3Ci>y>r7hT0i_bHF=N+o)T zKh{!$J}TEP?S+Hd#8~*KSNI^+BKa%XF^|+QuTld!PRhq4Y3V{w4PBMV^ifh_4akZf zY72`EnJv@ZNxg=6Lbc?%M5`LiwP1ZeZMo=P%YMz6u~pbUx+J^Ylx+o_8P+(`B0{a6 z-p8z7f_5T}-N@aXK&91C2@RA(trVq^yk+lmNuEsXXZzx%-XQy^o$fX9Tu;avrel>f z$A{K6l5{_;U^}!lv`ZH1BP0T9df6ps9xF7l(Dkj-`iV5VRMEX6Bd6!98K+r2U-BH; z^QS{f3Npu;J>5^&v{6qat1JoaK{zr`&y!V>UwcBciRZE%cVWJr`p*BEe5)VGxc_4^ zZay@za`80ECQ9QXmqWe6O*QkQkbE_ROG2?xw&c#5)4V59^0_3`8>kOeQ7OeH8q}sAP$7J>Aqdw~A9%?(IAm2xJbrD^IWts*`nvwB`c3Yk;=LM^j zyGfKMPzGe4NAiluJnf-eT~dBvQtVROBIRT|%_t6PA=9pc>LKrP-yQQycQF6)p4L+t zvLWGDWde38*eFxKbo#LPWa}n`*6C{j%c6CZla3wv-UbC`&tk_75nNnGr|XmCCnD~v>@k7Z|KRx zM$cXs%_EjGTFQLS(#xw@K5$FlnN_S_OXG#*CmTJ-98zv!a>z_4&HiWhQI^GB($0jX z%Ms#;c&ezT`OYD6CRsg-=1aR|gZzXcQ||5633O*Hv~J_%=c~SXu5Tp7_sI)(ny2gN z6NQ8BKG{_Z`Us&a%#g>DB$-$C$(<9W=nZF!@Y8^-&2KrKe&uN(#`TerFUt@|g}nJH z^s#-Cy@oxVIHgl0?A^a~!pUBF=2MRBTu~@;d=bwgY`>Wo*rl~t#&${jodS5RH-(n(bt z+RMmX!uBvp+HoI^5@$#UIj(#A(yyl)dBQU*BTt&%J{=}eM>*E~hx;g>2DS93x@v<_fk~6_VZkpShMZ?5H>1ZLBjn)F3mc_Iu z4}BuCXfa0Sqm_l;Ec8skj1p;l0^O+v^c>2?yfS*mF&V}9UV!!@n&YxLk+w6tBQnn4*6$wX!*G|Hzf(p!d~MVMDY z*Uz9fGi?i~4cQoHwwS2~WaUK3RyL3DnJpbT=UHer65_*n$aiToUl zmeLcV5O-!#OG_v{v&4*8n@?L|tJqFuQfmlR!XOLvdHBi+u`8zEnJ&c<(t5L7K*z(g zn0*=2_e@Hzkha)vWYShC-77MhAnj!_wWIH<3#ccW>8uQDaY@KSvZ?nn?Pc#|YZOLk z!qy{u8>x%z)#5M22$Ld@mq|N)Iu}AcgEAp{m4sG4lVrr^4l%`)oF>k5SiNqayV5Ua zy1gE^*W!1$U5R3b(>;EdaA`-i_7Y^El@=&!bm^YTi?e23NU^4VvK zKD%AC*HqYTHoHx9vR=_<_gTFT4>6CfVYB-!4yP|M)8cegcpYR7i&*1^K&)eN`5?vX zs1z$LH4bNkSm*Fpi@w?lztb*y-B{P*s)ACO>bKY6PL~Y;ye_-fmni1>#Y(%yU+cB| zM6VrIIQ&?{>PrxPH5PEST0E$eTWV^ZeuoDlU9~lKFJ}7eek#Bxdc1Dz2GJJMolbY1 zSPi(MqsC*g`bCFJ^b^+547b2W7uIrDiWQD3Dwr+gx7Yh|vtx-pQIyP_;1g>st_IOs zi!Eh(6MQZ}_F7JCF$x;D7 zBU3TcS!=cUD%~ys$E@&TzFLpR>44*qu|#o^yB5S6#9FwJpExV&CLpZXTE9I(v^jhp zI568#kJo`wE2h}-(}HcZdutqiKg3luP^)Bj1SPl(VEag=*6%?Uu-S>3WKOl+ z>FG@rc?rJDrjreE&^W1fR5<)3KSh;79c9 z5*x+cJ53Uly%J?qR1w)69}OPZ4Fq=F1;+*%TY^~WMbaZ7f0o|3I7}Wx4zomQNi{kclS}ds!=%NSXT0iBuyS&4z3r z`khDfEa{GLw*<-Ei1zZZ(*ZwaYZF;sc2Z#l8brjx1d_`gmE@osyTp!Xy~(vy&9<_BdEZJ)^2D;ISkN8i_PjqORIq^9weTFsSvqpp2agu(^># zsV-O9t$x|T!hQ_rw>fCw&0sE$G`7?pap1b#eiAY)nLDH~W}YGq`KrlzP+{*Cxt0h+ zy<~ZxAI{{!7KKipUjjhlE!QlT6lRw$$S5|8c_m^|apC;DEOVAPA)^HC2?^qYywcpl zvQiNi+S^k^7G8-%PYvtFU!g+$Pwq@ zzJfxW>v@Po2rVrX$%2xoJaY*VHqTs~nTuw|oV@(J(nSekc3x=#k(mvl8DddJacN#= zS$;;bSX5SAR9Irh@>vjDkXMjhj8)9@%mt-5atqKWn&+b-mgHvS=hLM!%AkEQ)i1NK zXi;%qPHw4~TbQ3^M&}$eG|QNiZ)QuusLcF~ym<*?R>r)H95cPE5K@ZiG)cP!xn|mh z^)m1$vox=;fS8e4SWsGwW&*4%E)CtfAg{!nAZ8Tjl@K7=#f1=0aN>?aDg^fxn3)uU zTI{tWm_piRCFZa$S>}v<$SNT>M@~+R8u(aX;A4T`z;@tcf#2_A0X_X1_-NpN=0^i; z_Xa*582ET#;NyXTj|ci@^MQ{DdVfS9(;4`fVBlkdfsYCPpZk~qvB`edfa6ZZa;v%i zE`{_r@;N@9ef9ePrJjB%l@}R}Jmx5he(n6IC^BED|F!c64I=ZEt-p4DObnT?+V^Yc z4<1bBtGj;f{2@ayA3r(r8wyG~Ux}|Q`h74kpT(Wc#Uhc#aZ|bTfj zwMbTt*p?f)#oV8{E4Up<;g4ga4e9qF66$-rg8POa#Qn_2@Ou7iei%QRAIrz{lldZk z2EUlk;s3yw@=o5uyLlI1%U{bcc}fD#i+BiX>ryB2`$Zm?Jn9xq?@*P*|?GLbzU0BLo!7gcXYQ z!Y0KQ;fP|Ja8&WA@Rj0O;cLaqLYLx@a7^)$@QtEN_*U_=@SUI+z86La$A$4iw=h}w zQJAj0NVph#oY$L^Fz+{Tx(=Myfzu{%x*ME!fz$IC*$+;K!RZrlI>8U(Rp2xPoJON0 zfKw_snZcLJsGvA?z2B(qW zbUrvGgVV*}lmkx1;It5&s=>(xPRqgRkKlACI6VSRkAqViI2{D1_rU23a5^r0BPfM$ zg~8x78k{D9QyMtU0jGR$nh!1&y*a5Ljo>r_oX!KMDd3a=PKDs~2XI<~84cjn0#0{= z(?j6&G&t=8r$gZMF*tq0`FS0$;6-ps0H>MYlmkxl!KnhAt_G(7INbG5i)q9RHZ&0zRmi&hJso0jDx>vVfBZoR)#pdT`nZPOac{ zA2>Y)PA`Dd>)`YeIDIE<5>&zwAzC;p#0g&s7YJX2MVF8*91}{xsREol;Itf^Hh|L> zaJn0u9s#E(!KuABC%rF%(@1cN2d7kU$_A%0`nPdsgF+VK&CLA?oE`wDHgI|aoIb>8 z7dV~be0(%GO#r8KaLNa#%fYD{oa(`;37j^9({^y$4NiN&>2+}W5S+f_uTyaRT7{8c zuQ&&sE&!+L;4}xEiooe|aHka5@4`J)Dg36< z9-KCV(++TY9Gv!o(?7uJb8tG&yA@i#7ICyxkqAyR!6_G<7J^eXIMsqvBRJgzPIrRS zgWwbdr@w*Id*Jj1IQ=9nK^Oy3!Hd{gE+h-r3ubUy1Wq;Jv;v&gfzuXndH|fB z2B%lR>1}ZO0-R0=-zkxwlxGXal@|!z%IU(7$~nr5lm+0lxHqS>UX9>13Y-$b=@M|N z1}E}2wAX>tpD^PgaC#XdpK=R$fm_TE<*wk9!D$XSm4K56oNfT82f*n`aC!xt4ujJd z;MC0*AqOvpzx+WlnRhBK2B%BG$qG)_fKxL#-3Ctgfzy-V)B#R^2d9t03HeFT@g0K5 z?-dgH1HvWnjzvP5umqfH!D%Hptplf4aJmRHgg>RK>z-co$?Et5z!KnkB-TGDy_Z!?z=Z`+^~T*>YM0QPZy=j69GgW+GuHRrt6fq1k%NrmU69%)2h2g zc2NOMvH)UFV`ElUe0)rd*1%~EO=6QcH+^pUr6^)R45(GSTGOSiZ*HcmX`oy)SwpSl z)hZ8B)tNsG-&{||1)w%QX2nqoRN zN=~C>+L@>rGJA8iTE(eV&CNwcqNvt!YF%@nIZ%d7Iu?bEVWg;88=jV)P8Lvgq7vwg z(3uMe$czGd)jY2j0_52#z~d4E1{J4MX|*viBDp;fKm;k3oq7fCB~5arr_&~>kSh?N z&7h1U$eQWW6%+)xPit!{-D?VjB0;0PmF|1DG=f#d^iad2)k@P$rlO*jZg>H87V3l2 zNLo7GbJpmlN|XI$>v%#V9tu0AQ>oyzLOL{43fO;8>1363F{lDGHB^BYo;i@=RZr>eKs= zEA=nLl{y?(>VD!XQtRIwSOx`dmIDg`McZ;@p_{ftp%n@q|X?;8H0#Jq@mOmB8thLCo%yYA6~Nr%{VE zz(k#n)9JL_P!xhVgS(!3gHFxsv}DC@xNEmggVwA$)ap62NK4n3N+oi0iKOyV7r_Wdn*%%j@)e?z-!ywQEE=&$qN>iudbefYf(nS?+WLH)iwU`LVfVISCV!M{p8F*b3iNbYK93}@y z9BNd&hHO$jd{eLH^;+EcWII-Ef07Kbv%J|uhm=aCe*=a#_%&)?Lyq5`Kwz0($>~+0 zU`)qMjb<6yu>dC2_mT-SC^0D@19}y&C&AiGLb9b<&-3~)&VWY8YmB?O12kE&Lf4f< z$vQN#Riys*Cy89rlvIV%8YQohA~ZniB)yc!#B`E0qLLLiQF&Ax>?2f2_#yr@dQM}= zO3zBaAVA7sJP@*B3>FnN>m#PZXQ}+I7!q||dS0QIQ!q@%iJ(xDK-2KN26mEg4JdeC zfqImhGpNb`o<1UEd8Mi|O5pV>F(PI~+CwVr!jO^lbcVTgvJNqHbt;v-UfqIA@**j8 zX-f)Sv0ECWDx`;7%-`UPn%MaG+}!3KtyT^Kgs)bTg7{?tOlS5`Ltsg0Jx^$ig)oa@ zgObItk~63}v1*r8E5~CAI~ik$lk0Vy9x)t_;_Knr)PFR*UPnWOL~D;;i{|VMMj>N1 zY3h3#X>hH;DDlJ|Idprd?}Z{c(8u@4WKF2mqc`ySs9<@p9NDk+Ch;Z&(K?X?6J3LZ zGmB@vj@KJzOWMg-23{5D;zUyx+abjf+)Yi5R2LFy3Nq3DjGYpjs2IkPB@ z)8kvq5hbIWMERtRh;bGv%4P6ugPJ#xc#I5kjTGc`Oxb^w8_3Qe%0pqU!Ps&VdjUMU zEbA?{Z=4%cyn)h`0^Pv#h6vcdQ=}8i>S@C4`n@CFz$*-Lr2nU(9xd>Oh)^dXPP@Xf zP6laLM6e^=S(hmG4tN6%cU$5}HJ_vxW^>zhKO_0leByEFo4R7zUl{lkcmCpUG;b&{M(0?C zaZNHFP6U`A#Ty0%V}r4+@vZSKxh=UQldjUP(l%-hI^JLi23k>CP?`fxD2*s90(2;j zv-Zji8ED6Gk^%HtgDxnyS!!sc3f4El7?YN8H)uFRL~@9sq64R0BR4Qpr;GL{d%c&?Q3b9U*<>_(2E8{e zi)0Lps<4}B;gmu4N*m4@jm!E7Z){{qIE2Wk=8f8jw9#bbd1K_}1hfWT8~s$ULu`sD z^i@U{+3UT=5FVk~gSKVeVFrD>kaH6WewswlT47+qP}%jWusC@2akKvsZUNkJ1_#Q--@` zFC(ubW`4o(Am2h5i6hUZp6|XG2zW$a%74Q&&LOtV4V`xz->KJ8W>4Op#83 zk_#fLJJ~peBa4u1kxvsPRpLF!#aXf}*!i~JNzfr$VaPt(X*PVR3?PpcqxtuYdqT@u zW}lLzl2luCR)IpFm!vyxC?Y{_@{%*GM^H>-Q9<6`x6V&W<5O~6I1O7%FwzI^OoT&W zEqV$SV}{N0CZB>k4*w^TUTk6x{-Zd(9pK5?*}3V-xv9C? z_CU9AgRzC-W+fzz9(6OV7JyEW+k6TZ=X&OefSBC}c+7C1eY$j^kh8y)ym_Eff^rp>9rsX|!B$MkUx z2yQ$zmaV6JO=zqVsn*+`zd2p_Nl#QvCA{;|6s?onGr0|{O}$M-$YT*pFXEjC-7?i>FAFggz0jbY~!LKcU|S2u?LE?_KE%nbD@B4?_aS zUvwx^qree$Xg*Z}xd7I#ln8Lxv)p4}B|T)z92Xxk^(B*jpJYV zoRKNQuWs3!_jW`Hy?C6N=!@+r14$ySa4Y=JYA5FS?LS@Xw|>D&C^Yo5buSMOn3x~4UePA z9MvCMsFw_i_-4~q4$);u!2?V?Y$d9&df6WonzY5K_uNDv+u8JT8RZu|r;}Rk zc<$THe&3FczIc}(M1Lf!Ig+qXTq(2FavMe{$8*-stvz>M>RMXkdCGp`-1eAu`C{*4 z8Pktb;Q|ir%6G&@zp`k(45Hp0=dVE6w01jPmn*N;>OBP5MG61Hx3SxIAueEv23t^^ zp8!te`}qMwld`AB0|f}$Z&uH-66AGCu!{->*etVHmf852oHqfNUoYsx)2Dw0E*jvh9u=MH>9lT6r}!HN6n$+xl_moCqYZIi+kF_YJ>=HmHap zb}2F$_qIPgy)Iv4BN?jJxde`TZeH$@7`iwOx7UN-u%_ka^V=`T;e3a8`jx6^F-C~pJVk4Ke_yZ32{ZRy_6iGJo{Jk`jZ9$&Y2 z3iB=QW(OZ7Zx73<`ijP{?PIT_z@%J(w1$tu`#(nlnVyZ$~=nq=b=;kjgnBgs9lwM1A{=E@i5(R`qqP|3=y&6l zbHO)FVDdSme#ghN{Dk68)j}@rS;tvsMWkK^@|)y)+EwzmxL!iQ({nYXP^3l1OK@8G zG{mpwiWM*(dVV@Y8mKKTkB`Gr*}bfbA0?(O3?W_EGOtT-od%ueKINX zKxM~uWAAY%Hp|a`7#|_a*ac{+Jct*GmGf-8Fa2Zpb#a<0NZ@liwj}+iU#ok171hr6 zbT!)M)Bdu-z9^uH{&3eIc=hIdBT?BS*kn4FCb<3Puo%W4s<*}yvGeA1=_6vB({Qr6 znRJOYYPa`!>pf0OtBb~{edCfrdwszw5rW;5)Tjs|no{rVL@3FbpUAC08A_@e_FMf8 zNtLZz%@>GOTA|nV9_=&B_bj>*H(g@H!lx0gPiFhjzSmyaX^_!j=I>k3wBH6;zrWhHmlM z3OA;Cjg@kp86|o{!sjPd&g9@TplP9Uo#pwQ=7!m&(PXCsY>__ua%g%x>g9h@yIzew zniAA%n2j&=tn~Sc_j}y*U8`0{l#4{Fm=fV>Wn&Z6e)-2c>s|g6?`cSE@08V&@I+vQ ze%t-6qwPnBHj-`lB+Esc`SW(E6T_SD0^mX0PA6?$4f*MKRo&>*wT;5h* ze_~>-by_b@ozwPWT$kBv#ixM4^+Y-mlS<$9`zF$spW9u+#_rbWI?>B6_g&Zz3$A42TKqljo`*5r{sDJ_i#eHg zA1|}5@R^(k^)Cm(UukbD>qPPtJ*{UGovf){I$!HG<|&(P3+*FseOOQLO%L6TNV==W zUhQTrkBO$VZv5}(kEOLf7cDPt`i=Hqn%o$6S#K`0RgWfvH$`hLUP@aBVpxLlOG>Mj z8ei|X!Gh=2TE-qnGt(Du9OrIF-qPH4~j*`mOX^PgyM=`%_m$H^miS zEMLv>etw5<(Y00KZwsvsm zS3)QC65A3R1-I!s`eN|!OX~3^?qSi4ucw^+FJ0dq&s3)ssH^>L@BRjga56#f%Uq&v z=eOd$2twb7?$v;sz#h+!o|QYI$IPLAeamf{ZWoR15vRk=_p!rC*`wZR`j_|hqnN5C zcpk#)&CTY=zO)bJk=pjX%&UrBRL`1^Dh~iwE{1il)ofdWx-FNXudLg3gap!MR^jI3 zUiXZ4#V5*_t?T&A5|m*0tX$Uh-048Wx3EHZKwiDMDNVsJ2{X_rmD+tan!CteQN8`c+n@&DdZHlm4kr3QgGZ3N3}?I zcsQ*gR^aBd?c98wD%IA<+1W?jam!!Ohso)H-c1udHacQ`$?09*52#PzC3#X#q-w($ z0mUqafIZBHv8)ndbVK80I`cr>6+k+3F zO*A^aYB`c3bSdg;HuOA=9v?>`{pdr`V1~8!4T5P1-p?nQm(i^GIoUMULoQ8Igo?Fh zbdHsr;0gIOq0B$K__5b>dDVNzTkGVz@$}}CJIh^r^>|Pj3Bym+`i!uU50XFFIJjkKV(SkOF4?W1;BzJEFx8wlwBsC zL({K$3)_1kC)BXn-Xg!ZRz#38$zL}tDx6f6e-^(|Y1LNv^zQ{-b8r6LD8en}?_!tG zC{xbvh}CMY+9Fw6jO;%Pm$r=LS(VY8IzlotYbCm^3{QeKS!c(hQ%M!Gh-2#1J}gI< zM|ADFkPbOm*_zY(cdsqo=bq|E$YLvt{>Q0u{4n;w8I)EsRYSiF8x6NtdHvFx7Z6o1 zfnlnWrIvxEB}$?T8_+8i9Si|8Y2dpBlx~nkuOyq6Xoc%e+qPPD^^iMy@QSO{=VR+y zDtw5(QUSez!F>s?UR$nF_d{xbDwK(VoyZ!kL~!*%AZ7{$1s5+BRP0Mx==KMDwKM%? zvblpA!3 z27w|vHLJZs01N%}pBU~`6INe({Oze|6J@KyG(L#qOhcBT@ra0j?>V*xryFNCWkO@4 z>W;W8T*)74KHNT(Bg@Nhs+&;g6ntvC!=GfTg&1#1Dg7RM(B9a4#fwDIM#bg18p%k-|=^KiP@?)-e`xn3%OzoJ;VsGI31I zdgjEdlY{6O(3}DeS1zlZp--@7K1h;h=ii2jd7W`L$4~IKy{7pPsaPwQnj5orC)G}e z!i!^vji66HsS#WJQ)*}3ZpmBzh4m08Sg*XQi(K{7+Kof+wAz1Ij6}1Z5<))}dU1mG zoYM~_+_yq$qg8lsYQ8?C#oM{4i=_nlAH}w0 z2t#9wjf`e4RL*e_OrpL*&oJ+q;H3(oj_Jp#DeC8^!pLDe<~|w7SVau@+!m`$-g0E0 z{c_!hIeaeZefLj2wD|#QN=)ZB_mdMLZ-sACd#*@_*mU|d)yw1_=FYvoD5-73Gn%-( z<$`@X>h7NksqYO-f8nP38nA@TJK~4R-jgu#hY+vuhDCv?e0Jeu4>f*$jaNMoj9ADY0{5{0Ith5d z9uOY?z+XEBfyZBsMAJOaoxO9QvKQj#Fmp^}nrrIdfA$^(wHk|lq48fB{iA1Gpd zk9Z8%_(+%8c_`kyO5!~jrBBms+Zc8h44dyLvx}|t3MZz1nk?fL^Ly~SJ&P=$iya{VaMul~C4>{39XC=7VYvzV}zgu>Hsr0?%+ACDM#rA`77hP)@n#co?2*pM@p1Hf}_Xc?R%SvFU-wGu_n+Cwj z>>y~#&-?LulLXAh^1fRLT|c8puAIqgpp~Xk`kHeaO)2awOpqeIGz?wu@fjWAFKfC0 zQeLF0Sd^iav6MCAK-8-X_p*a`2rmuG2$XCLMWzrsCZ>>g;x8B;7P^V8mNghr?p#kT zolJHicuwM`O*K7eBt#x31kQV0FDy0Et|cy<{R>p-QQkMQlD|z^9YgUac?!={fPNYL z+RIcdbd;w&P6{Hy?A(yuQa*HP0nkQx&v6kEA%PjJTEIw{4y!Tyi)p3N;)2HMbi8&(Kz&G{pvqm9%1=uzxb$IKah3b4r75&gu- z$myT*foG$O{`y!FzvGdX180fEyAlbf8+;CeU9t3~71;3Vx>N9wU)JM5W#MeB{@_B4 zNA~uH?c)nCKNpGaWQQPuF>GYi<ho_{TZR7Ww_Bb1 z1u~y*NpU2xHGR_#2D%>=6eu_wFAUJk21&{?~mCx>zKADV| z62^jPmun|6qbG<&$)Yu!qGVPad@wDEwe~Xm8;5sje}sbYf_CY2&MvS0-;}i+WtG`N%}xY1MZM^S<zuqtOE`xo9W{RvhekbJYVCY* z7SO0X1bNY3-*53H=#(sPv(+G5;ukZ?=U#G)4M#YHdut~7{aFM_nCne7t~lG<$WT4L z7G|KHpmk5lbY{4^zOT6(WTUv`B8sJ>p2|2T`*v$60s4npB zL^0O=3=h!^GuhNqlc?!KS^u)ka8A5(Oo$JueSMBuwgr?sv}d-HE3cO<#x)6Zsh760 z{eS4cAG#$hIbz1XNc_%N-G`p?r(WRsgDcGMM3grbvv}Cn$ZKyNPGyKluC5JU_*Yxn zqf*;-Hft}>vTnJ%xxeRzec;H!{H!#&@IX{87HaGBq_-Dgx$Wx}wC3zCaTE4fm96lk zO;2pe2h@qqgE}LFCrw2cHaaWBly=g?Q}?8=!d1~J_esB0=JBC1Xt2t2smRm2QjZj) zuyje|tS~J)6p0=~^DLPPJn&E&H$GCx1I8kFCxPww6JeTjsT={;)Yinw+0oR{2H`uh zGqOZrW+7%G{-1!4k5T-OwX>-sqqw!9v#F@5v7L!2ql~Goxw8c^GbaZV`+qyk#GD+Q z+$;hD|9ugxd)9e2jDgD1!}Y9}-QzeN%o^3CG$rfW6LP{|rXX_g0XaxCmEXU?!hfMQ z)=>vYFO4+Us8%XjHAhUCh#~|;M6A=4Rky8Vcc>`OcVNgI@;>Eol89bgeYCD0WKVkZ zdd=!?cOPxK?MUZCf`ioUiTyxGKEP;}=4{>u4R|5`do5%7QuSx0SuGnZz=88`8mF6~ zZNF?Tn@@xbmO*Vu$x?K7YOli!-QQ$&qYwWQcK+KWs8a#Rwj#7&ZvD427?pl6N4LD7 z>notxqtzPC-#AdQ$#4*LUj&1-#r1{N_lNPb*^wJz`>tIzHVxMi{@4Rpy3(eaOUcq=X?A3UdqRd&OVx2GvNBWE+)4Uph)Ggvb= zb~;YesBa5G%zueI^}~B?_2rmgOX3nIAB@y=XI-Thlx-k7a#otMS&+?zb`17|6Onh zvJdVmGI7FH6(7y-l}{H4|8HH|X>R9dhbb~xmE3xDb3?Ll+lZ$L$3Ww?AY+GN+w*A7 zpkJhgZ^$gbFYdVFi~Vk??X&Uyx)xa$0r0-+q;T-Xusdmg7|S2}1&-4Dx8Z6D$>2uN zi=m>dAcCgC+YhBS^eIMr1@cs0ZWQ^%TI0)jRtQ5?MNusIiZMgN;04Kd_RL@l$w&Tw z#{M($-{#Xx?1NkR{~r180|z_WK~{d}IRE*;|8FCV>i%yu$DgL+eTU_aq7DR#}2b&0%bvR>kbWJztXJ+mkgWn_rcu(Ka8Eu<<7y_G*^QXaS zCe_cqP#-VI1(_4vIT)h5g;Ha`LX0m0wfnbP(Pvu}@#v@8xCp67JIGw1&pK9g~qN9H$;O zbMxLf4$Xf!%+(E5`rv`VTgz1KG~ClKV`E#`XfU%UKOySqw0FZY>jcuEvhZe*S5lLP4jqAip;8R{ zTRnUUl1()ZuLG$#8@H)A>N2+aGoTqO*YK-wPPYHa80A-3D|}Y{iGH-vqck_qe|jOp z`t0{yqiV-XVQ*&PXu0R6r5Uqpb`g+=Fyo7!(4u|2bFB9<{=rZX-EQcc&A7650_T>Z z{DWdqp*BB&a%{wLrgj4~*uV8P(qxoBSONUO zny_c=4>r1+slM)=qrOpKA0$(`NP-ti(=bXDI7p>I@Q#_eWk5NeJ4#?9o4VbVP%_$x8 z&fmoL!q(ub3{*{k%hhQL=Yr>~|0zBxkVdt_t)2BCw<(h2;bLtwwZhlK4wub-hqZEJ zLEBmMScbZksxS^EsX;&&wrG!}X37&_cyMsi#ivw7sLW5MLH~r4#SZtj`cKaESKJNE zfY{k4D=s4)4DEnKBdk29xoV+u%cQDL^bh~($=6r@oSvD9kYyH*5GQe`TqnaVa;V(1 zfR5-GgmX1R1u_62#oQdYro4TH&XBfqg~FiG)@B<@@T(`UWrh)Uw<+ZI^%K3Sa)acD zdz-3>nwbeiI>zd6xH^M>7X-X~AekQ3A$acXe|~}3vVz-yu_1(+G(y>suCtlk+2f(X zD>>74V8?DqwWkLkMZGTfgm^yM3z3JQenAWLbK`gyI63wbp9*_ZnoGCOp3|8>Qcnp4 zpYxcl?2RCkLO3JxCcffkxyu1VDt?6i(pEGQnfT%V%SLxWVAQ||)wVfN5o_foD&76j zN|&{M%ee%>BIj~r6EJoNy3Mn!ew8t=61%~{Ma+>7WZi`pHwCv=9Db|22+Pi3;=um3 z?Z=Agoq6W-kbYj`V)Nk5yWyj7K{r^pn5M)2k$_!kS`xeLy%w4t8M!-I?G#p_#t{a?sqDVP-3*ESBOPcoxK0fkS zT^DyKe}YzOPfrfztn?8r!u7UmE{^#=;ek}~4^OB{v%2|#S`eHZ;hqsN$Z z`_EGag-wZpt?)7LQex@%ni6EvuY#mvCgq9iRPqwOs9|k|)v1P5uRbrq>1s8zj3>SMQ$3wj@XuD`oL$x0;>0!0+Fq&bEF#5;>r5(LWC#(adL4iT?(0=(TfkCn3&nUpz zAS4(f4g3fq2m&4W2zrBlLTy32BzcDU_-q3UimjU_QV(m(w8sL<4X6ze ze71QHT?FkY^lm`6qWa3V1z*z+OanergXn`Yp*c})iQfZ4dUEUuTzXTkod(#0Dq++W zdud_Rkr}AoqwH~jN&^&Z_rrh>(t+S0fdP3KEQQcJm?IQlVXjnrM4)wVA+!UgA*&%8 zP-Z}U04Hb>1`qlS<_y{j#tOPSh)|d_KhhpIKXDEiOAu>8RYh4vT1B2EWkJ@2s)n3` zrUgA6L^;4BOqTComsA&I4+}IIkPI3Q^7NYm7bO6S4v+?h!G!$y^Qo#tDV-r6W9MbS8 z7Lxe5Utv^3DEL7d!tf*+$YNpSqH_cTCy0Av*y7L>t1uh^$p$1r$W!2G{lATIp*>kn zp|t`+h*3lXet{s8{KBS$N9iHKr^F|HkG^IH()wxxrF%$$a4f!Z&$Ph*O(PO`Q~^qF z(Pvhm$N*H((~0lZ3t4uUAPV9$nL{AV73%hlL<;dXW!FJ$R*3r|k*2?U;5830_H#^X z$m(;9W~eeq9hz}*juAz#s9!Iy{}C;R>fImmjsL;xKPffvpNs-rQRBY41??>C=aTaY zJ$Y>sX~wLI5D*sP@k=%O20?Dfx~E+u1BC|ulUQu`h`64ALwa&UdSdMv4SBbY2?KKH z& zRK-bYnAB&oLo$Yv6f6`5^81&;Gi1Ss&=oR<>(JaNt{oy@*j+xqXPF`ScOVtXOmT-( z*})oMpKg|8Ur5_@mumTRs8#roTp;2V`qUN>Ivt7nQT9YuhIbeGS2*M3rpE9#0M=vZlPYFC;O>tnR>zZ=}PX?Sp`Pc z7D~McPngr;GOT<#_K2OZPy-b5h|u`zxS!UyvBt4`>7Pt3&7RO(p9(F_9nhsHJTL@7 zt^<|>Gy_rtALhqv;Phd&QyLwhMuz*sPpqG2ilu;!)?(GF1#Q4f*L(9BRQ zp;=*Ap_hVAf@p*(@&n>zeiw{S28jxTk>nst*drUkFb7#^nW2*`IPp6|Ki~ld%R&{t zLO{QlnHIpP*!$}P|DhIpX;wi{%!lZKA0U`d_{#_DfdJ6T-0`OHR3H%jihg>f;1~Hy zeu`EWTX-qt1MdRz;2ZVqQ}$F~E71-0;ECzu5a!(#Zx5M2O%#zUEKF+%(Qe9}A3P^x zK}tu)hKdU<4I>R*iY!N&C8{A)Mg>5TBc~&EhiMMd5k_q1$&3>lBR4@_fcX=o5|H_? zV6_N23!Gj^Bo3NXD31!2kCW_2*0O!MuMhrHr?S}sfxwt;|5vo} zWcQk+ME97uM0eK*vnx$)PA^VXyZfAWm%^1Uhux8k=md|#9}cf0)p+_FWxR!+flv3< zcwHF?Ks?dK*VE>07wr|#X{+Ek_NDIa_3a0r(5=EGY?m$;f z2m^}t)?#vk+OSsaRYX*EgWG|NM@P|O1#efjHgA^`FAoog%O>E)KGaotw3uL*V=6oc zv9P$J+q3y;`Wrcq`olnCiyrblq1?EX3m(jy6wwQ8K+3tV{5Y&73uAk^nzn1wDWjWS zJF{Dsd$Q}B^RQjaUFx1{%|GnrIAe4rsg31z=5*RcW%MS--K=-DtaUYz^|B42edKj? zICV24^md+wdsX#)yEC18X&Xnoviq(g_=H<^TdJH3WrsNKuOAN@2Nk}|TpHdk@80mt zbL%eBh;+6C)ZUORVn1dl_2YuZcnDTJ19LcY>c}Q~BfYrQ9u9R8tF=?wDozKt$`sr~ zkO0=JS{bBpYfwasv<>H4%UV%;OL2?5HE5<;rtGSj&+2QHYKE1rp(WAv;TPQ3&71a+?Esog5_F~ zbb1~#KAtdK`@7vpx_kuKOZxN@%T+!EH-6bna{c|2Dd1VBE+@WEdV(GlGi0Z)yzyghJ2G!w_-~|g=1GAr+BjpPp z@|du>$mI+VelgQV9yRh^IVkw;UAF);V>0BZoP`*x0w3x?$KFEIU)P`9Tcs3u)*%xh}s5CmkY1EOi(vXn} zRBI!+6#ay?_17P?xyGa0@!#%6yA;RMEc3?FYUyK~_oUU*q&3?J8Hf7#7wToeI}$a~ zzW{O`^7hYnA2I4sZWRJ)Km>bq3wuqXJz6v1V6V04%(xDUFqG<_-G6lg@^ahfYfaN6%eUy<#7=1nzReNw$JJsvJ1wppSSHy;8X2ma&=eL`mST))W-UO z>KR!Z(MZ}-!sc_#O7I`q`Dl+_KWIOQJ~SzQ2*{zvea#_CN6KitSghC)=A}7itc`{l zN{0ZE?D=$@_hMl2!x>(#2Bmv}hhix*alVUGd(8@fJUxoAN2-Q4e; zQjhH1r*Hc_fQ+yhqlamN*AM?-P_W-?lXaiJf`6BPc^9O`P|wU5|6;?fj?p9c!Sr$7 zM`No};}cmvGGVPFqf7=f<1!02NgmLiwaLPPEhZ-1g#|$YMvp)1WQRGS_iGxACgP^ z%KUxMDPzuVDG0xCW{lo&fQtlwcJe2QRu~4pyX^=ZjBr65IeF|iIkP;zeuTORnxU8> z;VBB|Br}Y@K)hKN>o%y_eHz^{NN4H@PHe#4FhC(9#hMPwpdJ3~mTS_GkS{J2W;nvt0$niL=4^k);QhYR z^%MVC_E0b)xEKG~esY`mls%{G7BkE&e|>+ZP5SN-supn1pTTQPP?m1~Vr`(Y4=liw z3k-}9>kknPbRoRi z^@+S4<^=9VE&g2o`|R)XCSjvavT9QWoVoCrJH~JcEa~cKXfSEw>+ic#YKz&@(&R8{ z($M`zF22q)Z5W#fxL@aVDxSzkcko#l3VzWdS;R=@nlXq&MWd?`UQ=V;(9FWDT*7uv zSk9BDXK?denUV1wLC?m;%Eh%29vLMGC0x=%@+oO16i`%la8G>}`m?oV*e7p);@8Koo`#TJV^+`nP<~0XWmk1r05t8MEN-TVLv z9MRJxC92EmZW}KuD+`oy6_SK*%CLTUS_G zevFLK0qv)OM{mI)9Pm_X6rKG-AS zy#rL_YMbEVVVJk?%Vwj0<92FwL6sp(;bA9SO{9NIx!zHb1G}2VxC<6>CR__ktUpy5 zbvWL|g*`n36kNx9q|Ffh(p9z=>l{sWSFBspyqBEJtrcrN!&J?C!1&fA`5SA%fg#~4tV>>x9jCvg3ph!MMoN z=q>7TQIHvBZ5Ji8QF@Ja{wcn!1Im(F`OIY}=xiw}ce%g1cT#_sPXX$?yThe>w^_hJ zKNvTR`s5XGfuzS>^+vqeN!sJ~r%ZxkUa?2hTv}HTnZ1OHsp4|PXm(@b>wecp*|cP4 z;;C!wLUT;9MkSP#7O$$t=EhZJEZ#J3Q>H{$5Zf8BsE$G7_Z*QZU$ar#Q98k2-=f>( zKsI5=yFCt4J|PpmEaD4xu~MqBKg@>{R&sj24nA7IhRM`r>$D+46D)zT(1^^4yHa!U zpkj6O;X^FU$#Jtx$wKC}DOpymDgLXRl4hiAb)NxI&|H;9IrEmxknh6&9ad8mBe#p8 zKfQ-A?%T?h`R*(zZ*i)9Z&Tvz>sAYBeLoslJ%@4u^$NKrIaEgTQ6 zeq9oNB~AgNz;jTXX1pN#tsSD-U6|d6@%H&};OqH_Bt~h{2&D&Z$^Mih4%t?WyIaxC ze9*3_gjUlUb~5hKPlt#rtqa^hP5rFwR6)O`qSH%=bV*6!pzWeW@@z>#KGtD^OvUrx zX>q{cGbRo?bOH=r`Lchl?ROIK;aWiZk6^;t`4c>~8t6&$Sp(?*P7}(n=kpsDPbhl9 ze_=H)Ms(GpY$G>Qc5j=&G;0(XqX{F#*F1B%6^*B7rsAicN+C9mgr41a-2hj~$$Rz& zQOQDy0GSB59B#}55iBUY*zBGnX;FlJjMwGR?yI7|c*rjUemj7egdsDw&sMo`n{8Cu zC)5g}d1L)#4GBOuhGu@7@{GAxM+ zx7c3kUMg26cVz%`*Gc)XBCeLSD(oM6dC&%nihC>q$ zIuM83NW&~_+u=bh#blXzm5s0b)uLs}#~6tnX>WE`Y<8o1v7Wa=DoT(>A_>?^t#N59 z-6$-sfTJzm)*XB{oP&`w%A$>krAN@!#c|fuqztXCzpZeduY3PC!u&SlYZF z%LA0|^NRwtE~*z52`=U`JY?04RFx987IJ?$RAyn*A#z}4gZXQJc3CXp@J~0=L`2Y- zu|H+iOA)ENIXZ7n)v!A)C)sf|o=ycQZ$xewV=+oZgcvSQlK6FS`l?0?l9>>v`d^Sf36ldC!$J+8Um4_rprsS63Y|{0H;$vwj6yh4%*|wTYlbaHkj{K+VQrtL*jG}~! zUh{nw6W0<=Bt!rXu6|8)V@}`WCC8+cn}x#D-QQk4ign^#W`rG_aBhb}4d?cTicLgN zps4*hpOHe0Ts0gE;Q{-0b~t(S`6@nW78WX+W*Fh8UH){{|-z1I`3mL z0QbF_&wgg)+A@#_Pgdcsw(-wjl`|94bc_K)cckEc%Gxm_rTgs2)!(*DE9S3|gcZY2 zX^PrVcCE?;&R-#qjudv_ntsg*oZ;Hym!=_NuWw1-&?eZzNnOJgtmw2Jv{OSI6Lx>l z;NugMx<74IBF- zwGI7vY)D~;dKkSq37^iaMnMFI!dxu1U65*Y_|t>7&1lunPizj`!O?KtDVgsj{dV7c zA~Ba*-nZoc-RT;}rJq&5-9Oq83IQ7n^!^F#MW{x|$b;j_!*k)j&$Gcj?8r;h$D3aW zX?Gp#&nT~hO@xP=YXQ@$ugOf+ilblkM9|BuFNUaKZiT0(ufx=y`qsAFM`>xyIc=J6*;vfRF7y*$tua)K^D6*$lnaF=rSQ zFSt^sXw6SpdO7%Rk)4%`dEw~~R_x7~b3X;bA843;(G#25?CWuPMzhIqh!?wiRP(vpdy}Ti6}6tTFvK8tPgcd24p+mD~T&c8|o=h<-BBvprPTOjoR{ zp1RoLE3x59HMozd3S4^nN4H*Q&gp50tN#s;mE0KP!Btc@M#>S$wJ_1w7b5WYc=ULRZ$eX>5HwcKU3IdVHWbjav0 zY`~|t7JPI>a=mlVPSR+)VUK6*c&RxaQN&CBm>^v)Uk!BAjNYr-{X9`ITZ>6qdaq$K z<9q_d)>Ge&Xyg1Nx||sV>20 z>!kZ687pBo>0z@=7g4n*MT*mNBQH-zxp&i&chJKoQul;1&-zaP)=JH}NsDiUG}aD6 zKmYoG@wBV$(U_%03~ds}md1Ks)OKKH9&|NMxDwe8**T1c51=D}N*-;dD1N6`vfXcn zS+1gd$&A_w1e_Q1%Oe@BG&nZc-DGj>@#i}!_#izd1~V%C4!fIF8y+lOtr{?USS z=P29zVn5hG5Oc}X7m3Gb*-1Xp+*7=Oz?y)MHY4dSi~mJ)6RJwLw1HMUcPo3d_F^Jk zsIckhf%rj|EwEGuPoHGk7AIGNX~LLnx$r*kWATB0@;08`OR0Q5@q6c&Ds}HfO(!da%8hGL)W@xU z@3K;UpOSNd6J*p*Vh8W#3D6VpR5!mFW4rZc1@CPi$#F8y4QgUO5{45jUAe7|;vn?F zToP|$Myl?^?C;Pqohmk-nQ=Zi;dj)+e-VbBIVAGn{m8ca!EHN*-56jzc0<l4o&U6)ubY$eI-$-sVzhQTyw#)tJ z2H`_nt+0!~IoedqlYB+oAp-Sgz7q6Ex zVBjlTJ73w2M}AlM=H#qT+gHBbQ_}=NVJDjPB(#k=9QuPIMaLO3VXxofnP621g2>we zb@hrOJ#EWF)MNx*0A^~TBI)@-K2^=z+d`|AYU4m<5ul3g!>2?_svyc|;U zI6}D?rw0;>?;b6Gtu%EFB%o4}7yTuoC1Ax<2NEoB^SFk8O}* zi6ErDB8pLJJ%{ulwVF%IBUK;Ts4!;)_TGQ0NYf`PaYOP>cK>7EOPn#+-%_r;ECzWB zTF$Re5qe$NldO*&zpq~5RYk=NqZM8y} zjA}vQCk+jA<%$TH;+3ky&R#YRt|4w#*)d7W(th!1Wxih+3PwuK4RmwyR|S^nnTiS( zw0@P|gkLDmkQukA|9H;-A?+=ID~XjXQ8P1Bo3YKz%*@zkcAJ@*nVFfH8Lp|#ZZlJx znb}_Vdo!~e^WUG@mB7~DD$IE93``d8Py|BlrqK(79b`URLMs& zgxN(!a|rvDdTa8_3;!2o8UgiQsepk}Pg*wlzA#Z1i(~=_iqtN+b{KVh$*(wUqyTJ} z;Ip_$NMu8Ypx4bod}#?6_^|r<(X81wxk;m#eUENi5)skWr)3ik5Qo^ z3e-3r`cIhHGahmhspu$B)ODUXodo1I3^WoYHgY&9Fld-c6Vl-hxt*~eV^7rlse&#q z3lV>K9453%V3`kG_-@68tJuqHxgOEp)e~_H4RSmjGbbUB-u4n3=7d@Fe#L!RNb=}%TsCKGy zE5bncL-^Wz3h*3IKtwHgSVB@78VT!IgC zkVu`c0?7geNg~G&f=1w5W)N5{-m!`&bleO$6x|_-g%&Y-S;NUzLj{bRfD$^(PuW75 zB2o#FPeKwD2uUVJ{g7DVZAk%qQTO!8!|xt=RnxKlx3^&C+wSGsct!QbJz}%y(r6N+ zWhfm2--f@-DvdImJB?i zq0GX@kVMP_7kE&?FkeH>r{v=1pb3Bnh9Xbyj|mw7A^J{&lObXThD5ZQWJex76fls6 z#LL1HBnRs46yhr(0+fvm_U!K-#h|cuOo#%kbCW-&E?#i5;mog0=JTw?=Mxc}c-cIZuHosf~IR8z!>`s9gO#r_5 z%fYIq0T3)IxUwTAx{Poq5byV=!|9SxMkK~J0G1WGIf{RhjLYRbC0C?aP?-!DtfB-V zGhCkdJhW+0zC<4nglsUlBJ2D#F%X!Ac%8X-7uZZ05fCP9dKI(`(@PKQmAB<~@67pQ zwZE^er2xVE^Viba=i!6jn8#KtRF5sP*B0?pkLZ;N+h>pLjBjS1IQLd7Oph(P*VgwZ zUz|;$a#rL$ zIKnQ0-Yv{Jf4#m{APp2htXTa|5SMg_GX@|_NPQ}x0GJmFA7D>S&<9AMQz-onU@-VQ z<`;mW_|HBB$T|@qZVUk#u=gr@{X`ahTHq>Jzk3KIgFJqmYfK&9s2U&H175qHsjdWf z?pr(#XJ{-PYv#sz47;MAmIh7N)(fNgk${ukS#BBU<`fLIR0VDAs>;v>)+dy}95yle zk(n8WLS#JbRktX%eBA7^P{2vKLLLVc7O%B{$TU!;**rvynRV}E2lUi!Bb}eJ9&Tmr zT3|7wFl6k4Vqy8>h`~MdLU-5|SXB?gKur&kny)}+6E5D;Bk`f=6R{UW76g|DD6h30 zsV|q~!9=O?HxM=P&VBfZKA=$6Bf*kkQ$Isyh5;Nnt6QtvGr4oI=4;E3+Got$>5Obv z=J|e{haFHTXJ`!_KZRl{VZ14Y&JKPl;V}C>(`<8U(X57!4jPHlGpJ>h{|tN0(DHR7X721V-us9quajgHy0KPGzt33N-dERmPY*6FF zCv_HfKg4L8KO-LtO_pR!sCan>$>0YFRl_}MUx6SC24I}TPsq{b{;G)Mwcj8Ak78Z4 z6mev&)S!}eUcc0tge<%fG!`wH3n9ea>0T0{G^P#b9GXk{$-rjy(+vODp6-&Z@06Bw z9D|n?I#}I{*CXn`I?c$fV+eCghFtM-osXQ0qtC@4na9W?rkaLWgJ&y;RikZt%ia|~ z`vM9RaSDIP9xC7(_>dA&`ik7Yq*~@!5%Cdn7lZK-xKuB^?ZqUN;m&5CUZk<5e%n## zJj9qLum=?Gnu}`H$(3m~RW8M?WQN+}bo6_+-mS+}PnYSUQ%qx`+fWg9;qkWiS2U3h zKU~jq2oKd>bEF23BcxZ$+L@~LdSCL+J}Fw9FN~I86qYlKB+ik%e|>Aq?faekNrHLW zR{fOkSDaDJkknG;6&8tJA{-7|;i=!6KUne2ZDb%UcSvt`=p2ZBlWO<^C=O9yia>D+ z=#}s_xutvwy$$SY)5Fq;u&Mi6EsKVjDWxJoLsNfdzc90`)%vEk8HCh5H$|7cPp|LY zrq<&-r~w;@elTJ%MgQGyo}pGtug7#WHL6d&BDE|UVK?0gt$e$5EjBWBff$&sBnaUZ znzas68dv}VMkJy?#Xvu=HC8IGt}G!L*}f&%Q-g0`m0vWnkN6I}!8?AER)-!~5ymbV z+d7I;j`c6j55>;)#RCnQ3xuJhg+@@DA@r7DJUc3hwt5u04fcuS1&0-HiytTH(C413 znUHkhj&+t^lr4>%1n;C&cs3G+cqID0S7M({a(=(CmH7yj#9}f6t`vWNu*N z8nzu_iOD>i@xCtKJ*$rIS$@|QX&ZH%aw9ki!y!X+WPJE|A^rU}tmy{}NSFKbN7!3}j*T(VIYnr_ZfA^TQ(M_6bQEDb~gf z1VC)t88>Tn0PLCY3k@sFrow7*DG2=&#`na&x)=L1cE$X-0npOSRmpBrlI~NNc`w+K z^mMVm*j0=RifC<}mcF;UFNIUjcCRDWo{Zwj(B1!*w)osf;S658wMUyvzxc_cq{j2?b3LoV2stXMlGsm(C5-; zZ;A61Kjvwjk)qzf-=?9!dgjme_%y?PKhY28bpjDw?}?}SkDYnXNIjhmmYJUm53i9S z3);MT#^JoLjBOKc*_JuZ4EvK*YqV+J6dH$^5#Nj&I(UZC=_|OR;B)Sb3uW@+;Z!@Y zgNrgZ$M6aw&!bgnqn#G)SY2j^G>r&+WB9*7u;=GtzSf>sS~wiyaG-V*EmVoOrp3BG z%x_Yx*pjvZhIFQkQ|Qj2j$6(t8zZBQtPRSVoT;1|Bg!crc~=L#P$7HQ$h`+?|9->G zK)V65{b>LXj~G7MIY(~L+SMb~RVB6*adM$1QXA}*(e_ZEKk{dGxEBWif2xim1B4TY ziU9;do*IWL?tuXM&bZ%~Fy9XzdANUIpBW$0s0Yf7mJA_s7XPO+^NEUEx9oDtukt0X zEw8uxr{ohe+fZ?rh7)kXAnH8|Qf7A6AD(mC=wruvwoNZz&1oyQf zB~i~!9)Qdwt%m7rS!=#Uq9~BIF4x`JY+jmr;YJE(b;H#fGQY zVr|PtPIK47=B`hcNetq#W0IPAw3`9r{xAP`x}EsBW@=gW`5z95zu+%*zPNafn&Q>O zG>;l*DI#(V6K~5MW>!oPon$GNqI0BTu(>_=VyvZ6*|{WgvNvy^IIJ~{Xh=>8*LciT zeag$Utb7lmyH&j@RBRNU&jR{O);k+v!C|F`wNV9gG4!6bJvnTnHYscqGrSUSPR@qu zOeUwGe)u*9_D3o=W^S@!zI@nikd}IzC2_7J8$R$Yaq3^KvaXy3Gnx^fm{diYuU;8lnq9JnkL6=YB=PbiATEU zQ)xm%ua?TRS~_<)wLAZRo2r4Q-&~!zOSCN3rP`6g~HP zhJ46BcbAE1tavcHWh;vjABS>}Ty9oUr&*!)ybf41hn)A7_9nk$H2eS-4$M8$Hn3$V zK16u@(MsWqW915(_%yP<_l=VaR1dN5(Djf-i?wZ)j>_wUX*1x-z~)uy3xT7m$ynK{ zZmG9s=}uTD%gk3#L$_{RI_6YBfP4Q@g@K zV7DfFGg?0pPrIINGotm5@D0P$Ak8f!0vJ&PcOllehtEeleI>aqcT-v;#~>inkEkLs zoW+WK25cJOzP$EfgF(9Bzig1#ois6bmKlnCPtN+?*6zGMa8HJ}E+}0%hFHsf3DCvj z41a&7&3`~Mo=Mzt1&L1T2lZq|0A2*ajQ09iD3vDl{(&&K=l^K}2yD8aXYEIeywl&V z@=~>#(gHQBo?yYQljgJ(D)Qb8R2(MAx;ScN6WQ8Q8`v0rUfNLRq_lpVNeCY*?iBu` ztb2l$_+-~sK{;cf5E}6wS-#S<^`X7a9o6+5R^-q`SjP$@#DE6{X^sXq{dtg%6%Wu0 zzQ@fC^{;{4r>)E`L1#F4C-0pF5~X4SoUb>g|i@hd<7x;!l*cK2dCHLvL~rFL=|{hD2y@mcKklyf2^PfYd! zH;XUlA5Zm>tecj29>(-DUM*9FPmPmz_xc|DQ!4MNiVMroP+kKXJ%vL)kKx5c`It%O zt4z;yvPK`6+*+x9`N)2RId<$BF97N1!q?7y{c zw-p-R#d^zeQ*rilwA*FJO%f5cF`K}~!HUR_SAwqdG}o)mmTxeRfT#{mHsP}b_+e)C ziFBMJTL-JpkM8{Idr_ZU=D8|nU#8%_k1JdzK-WiU{G#kftQdcV2ll!|*SgRzxOzvJ zmTb;@d*h{tEm)XoPstdw73wBPe%Thjc1=yA>5pQE7FRh*rbEBBLATdmxq%&_5`1)p zP>{)T0eyO#7~`#0Vau3Vi%T z3%t@wOc>a(Bk8{}QV}tX)g&1bfAHxwR51A7?6MuV>JQosI=DV{;o2aGQM5t3o0}Xc zv=PJiX%gWazhzfCD6S0f<*Pckh$$t|QLyCLZ4uv1C!&Se$SH+sdR&a{4qzpE)fr=y z+M`X++5r<~Z_`%-zaExk6U6UHSnOLK4Z*6qDQXBdM1g9PrgZE6&-cu}{^b|EI zS1WcdMXM|a;-${h_wHF`NX=j|E-T5@X83C^k=)teE62SqJNNCc2d0R<7s~C1F9e(h zkrTP8Z6aHG%v0{Mr%4^ce7TgV50>ug7nK@^oW1P~iBA#8?Tf44D(4!Ew!o)Hv7ldj zR&_7$tol55Re*cs((Ms*yjR<#&^mZSsdqaP4*3U5Z_@EjQn9X9Y`GaGK&5Mmb2 zxDoCK(xoqBGJJk{Bp}}2^;7EosJ__xZKPeZyq+jWz`@C2@`*cS><}? zVY981)m_t(yVgbSXDN3IHn$ahCT8xlou<{vgg0Gejp#eaxp71wpixe-8t`-X1RCFf z)fEHsPu3!Ad8hWtWx?{5)*Cr`h7d~*pCy1imtjei{ekY=!>fE$D()jbEDgp1d#jF4 zM?tHLOTg;$5%qp;t(%Xt&W-RT7%JYTT@YVLu+7tpQQ7Xr?C;?go zPZLM|I|Uh~$W@Ro7{{_T74Eo_$S~Iru_cXU@@z6hQ&-ss6zsDhI zl^sSly$885x3e>BZU@{pA6O%TsrA^FcR;e`XmM4VtF!dm+L?EBKrDpo6Kj=s(YThR z!dapkQQWq-qz+yh$0c|CF7dpF&p7<)uu524VjClopMD+Yley#nE8(EcV&1j9C z8_rXhhCW;Z1eLyGpY!P(p7>{-K66gT#;a)ZV|bpo;K}soTW@lA0btLs1&%0#2@S## ztI%NQ=Nc4{1jV)X=2?RGA2aH%YV>t+X;X#CWc+E{gIikM+1QynmcPCwrfzub4P_n* zOS7$PJvXz|9v?f=-Rnk8#Y%fMDL47f)yOn3arW=vo%J}Ia(swT-=6`6miFH2aNT^+ zq_@&j(z40whqZB|r*9_IO99(nvc|;B7qJYui=ftZcOzB3=&cl_H z=~EM%X)Qdy+Z{+jE2N^+3%OcFnALd}aW zk8pkB65bScY?rw)h1!#SS*Bshu6j_ptmX4bBkJxtoHm4CyV$)$v#i>FF5>AmmRyMJ zY^!$rAW_SHf~W_R`lQFjFlGPr9&iz&Svw9+Af3bkdF5ufW=3M&fMN#I0Z~}fe&XAL z^!Xx}86qziI?1B*JI{6m2{!C825A&@mOf@AZiCABPudG+>|KoC0h2@Y4dmM7c~+fc z58-wS#ZDv{>MnK3WEb-*f@=HzXA?;==LZi@H!XvS&s?y(>Ijp|JV7Xx#%ut?Y+^Eh zDVCzkAiG|27oq$%+h{BL55Ev~U%nQLVRtfb?U90v>;Ch22VSRIgFlCZRo@Jb=qv8(CgTM3V{0#JX6rbenCQ+FYyAYV zt2GH&)!o2>Y&x@`&5Rofcc!IQy`jX;fD?JA%hPaY5905lToCOo+s)s>h~_^jvs@y7 zn7GN?@UI&F2Gf)oF}Ca-g(&&cR#qhX8UffFzr^*H8$8C~cHVFv%MhYp^_n(7-8i2& zERJ{cf#k7w=DfJC@(fP<1a-jtH2hc8D9ryQHHw&pgQF86E8D+wq_BQPeV4;O`;nWnVN^dBAe=;^f$ugJE z9;477f;zLRDDph`o-t-qg5Y=xfiuQ%-Pn2HiO_v;RV1;XrDT){LK^T=ag!YD8}&ZA zuZo&1Rs3xPh@rU<&*T%8eIY{y+98HRruj$c&Ky(X`4yS{T(v-Ck=&Qw-DLwURFzQv z0M`fBEpaHSmDabR#(0z1PWRiEdn>K;HIIyleWcqqY z-0VM(a+}N14y}I2`OZ?S;UZ@7{;8!UH$ZO~8SZ@}bt}cqmKyLmzeb6&d6XP;6CX0V z00agx`TTL!j4DhgqAqubU}M8VJVL}Y7d-AX4YwQzhh4E!G5{nQ@n;GYK3c*?0g{&wsh^5x9_(j6_+21-mb#;=(d%g;(owDW?E4^|7s|* z{9g=34pxSLAB#*ZUvxckgp3Rf|9`{rEMv>&8#_X%p2_BR7)m+60CHZZMSWzRAQJ8} zEC5r^fsOIx39SZ{#kTj)tgTB-TFK1%*#d|lU$j_}2txTRcH$lihMaUY?5$8ZW(t`} z_n0(ngPmqr0>W%g0p>b}g%T#TG=iX{RA-Ddd8eFI=K+~`Cx!_^!d$?=mFh@FQ;OPxcbB(nVCrNbC~`ZE5qFGMyfmyT zI-4(wsxGL{Bj^ZGb%a&CRIDnhHk}ly-m^9XQs$i!R#lQ$XPqPzilbGESM#N-ilj35 zBFbD?(8Isaik4*S4t_}&@mUSd6 zr+T%P9n+-h0K>)owHKcW9S}?dQWmAAu zs!R@s9Q7Jg?ypy%7e|a~&tG>!0hPGQ=qatOq3o{mBO`~WrF*jtGM#iDx&)tJHtbu+ z)z10x&eQmYZAt*!pO;hH5x~OjTFk?RY9$6;w0$>e{qGN z+z;I<`z0<)mD$J`OGC@in8Clk5hm;v{ZSgizIWS)j_|^4eHzTrr~k_jABekT9ZA3` zYhV~;5GWB&*bZa}0jVFD&{hS(E%E_{Ki}U_l~`vJ@GU8yURW=LZ&|u7cNKyUe1w8vr5)l(Q9h8j(cauAe+M_>T77$*21_cV2adVzdkVAa3_ zf3U=e71$$4KxhQ{)J7bBt>Jnn-p714aAAy`QO2C5i9xu?#LULy0s5k3)-=8`A|Mj( z`5W`(MM0)q12N;9iy2#?iT|65gouwAxv{aBSc$Q*oEW)@v6@(j4Nc67BHjuk=Wsmq z9?C^&Gr_5xhU;JlvYST&Zn)c5k &XyW+T40PK*8n5*>gX&`1CWDEDMC=JhSmAA} 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 100) { + phases += 1; + } + if (this.parent.getActivePowerL2() >= 100) { + phases += 1; + } + if (this.parent.getActivePowerL3() >= 100) { + phases += 1; + } + this.parent._setPhases(phases); + } +} diff --git a/io.openems.edge.evcs.webasto.unite/src/io/openems/edge/evcs/webasto/unite/api/Webasto.java b/io.openems.edge.evcs.webasto.unite/src/io/openems/edge/evcs/webasto/unite/api/Webasto.java new file mode 100644 index 00000000000..861b0b6ff5c --- /dev/null +++ b/io.openems.edge.evcs.webasto.unite/src/io/openems/edge/evcs/webasto/unite/api/Webasto.java @@ -0,0 +1,261 @@ +package io.openems.edge.evcs.webasto.unite.api; + +import io.openems.common.channel.AccessMode; +import io.openems.common.channel.Unit; +import io.openems.common.exceptions.OpenemsError; +import io.openems.common.types.OpenemsType; +import io.openems.edge.common.channel.Channel; +import io.openems.edge.common.channel.Doc; +import io.openems.edge.common.channel.WriteChannel; +import io.openems.edge.common.component.OpenemsComponent; + +public interface Webasto extends OpenemsComponent { + + public enum ChannelId implements io.openems.edge.common.channel.ChannelId { + SERIAL_NUMBER(Doc.of(OpenemsType.STRING) // + .accessMode(AccessMode.READ_ONLY)), // + CHARGE_POINT_ID(Doc.of(OpenemsType.STRING) // + .accessMode(AccessMode.READ_ONLY)), // + BRAND(Doc.of(OpenemsType.STRING) // + .accessMode(AccessMode.READ_ONLY)), // + MODEL(Doc.of(OpenemsType.STRING) // + .accessMode(AccessMode.READ_ONLY)), // + FIRMWARE_VERSION(Doc.of(OpenemsType.STRING) // + .accessMode(AccessMode.READ_ONLY)), // + DATE(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + TIME(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + CHARGE_POINT_POWER(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT) // + .accessMode(AccessMode.READ_ONLY)), // + NUMBER_OF_PHASES(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + CHARGE_POINT_STATE(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + CHARGING_STATE(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + EQUIPMENT_STATE(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + CABLE_STATE(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + EVSE_FAULT_CODE(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + CURRENT_L1(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.MILLIAMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + CURRENT_L2(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.MILLIAMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + CURRENT_L3(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.MILLIAMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + VOLTAGE_L1(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.VOLT) // + .accessMode(AccessMode.READ_ONLY)), // + VOLTAGE_L2(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.VOLT) // + .accessMode(AccessMode.READ_ONLY)), // + VOLTAGE_L3(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.VOLT) // + .accessMode(AccessMode.READ_ONLY)), // + ACTIVE_POWER_TOTAL(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT) // + .accessMode(AccessMode.READ_ONLY)), // + ACTIVE_POWER_L1(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT) // + .accessMode(AccessMode.READ_ONLY)), // + ACTIVE_POWER_L2(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT) // + .accessMode(AccessMode.READ_ONLY)), // + ACTIVE_POWER_L3(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT) // + .accessMode(AccessMode.READ_ONLY)), // + METER_READING(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + SESSION_MAX_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + EVSE_MIN_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + EVSE_MAX_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + CABLE_MAX_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + SESSION_START_TIME(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + SESSION_DURATION(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + SESSION_END_TIME(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_ONLY)), // + FAILSAFE_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE) // + .accessMode(AccessMode.READ_WRITE)), // + FAILSAFE_TIMEOUT(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_WRITE)), // + CHARGING_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE) // + .accessMode(AccessMode.READ_WRITE)), // + ALIVE_REGISTER(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_WRITE)); // + + private final Doc doc; + + ChannelId(Doc doc) { + this.doc = doc; + } + + public Doc doc() { + return this.doc; + } + + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#ALIVE_REGISTER}. + * + * @return the Channel + */ + default WriteChannel getAliveChannel() { + return this.channel(ChannelId.ALIVE_REGISTER); + } + + /** + * Gets the Value of {@link Webasto.ChannelId#ALIVE_REGISTER}. + * + * @param value the value + */ + default void _setAliveValue(int value) throws OpenemsError.OpenemsNamedException { + WriteChannel channel = this.getAliveChannel(); + channel.setNextWriteValue(value); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#ACTIVE_POWER_TOTAL}. + * + * @return the Channel + */ + default Channel getActivePowerChannel() { + return this.channel(ChannelId.ACTIVE_POWER_TOTAL); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#ACTIVE_POWER_TOTAL}. + * + * @return the Channel + */ + default int getActivePower() { + Channel channel = this.getActivePowerChannel(); + return channel.value().orElse(channel.getNextValue().orElse(0)); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CHARGE_POINT_STATE}. + * + * @return the Channel + */ + default Channel getChargePointStateChannel() { + return this.channel(ChannelId.CHARGE_POINT_STATE); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CHARGE_POINT_STATE}. + * + * @return the Channel + */ + default int getChargePointState() { + Channel channel = this.getChargePointStateChannel(); + return channel.value().orElse(channel.getNextValue().orElse(-1)); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CURRENT_L1}. + * + * @return the Channel + */ + default Channel getActivePowerL1Channel() { + return this.channel(ChannelId.ACTIVE_POWER_L1); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CURRENT_L1}. + * + * @return the Channel + */ + default int getActivePowerL1() { + Channel channel = this.getActivePowerL1Channel(); + return channel.value().orElse(channel.getNextValue().orElse(-1)); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CURRENT_L2}. + * + * @return the Channel + */ + default Channel getActivePowerL2Channel() { + return this.channel(ChannelId.ACTIVE_POWER_L2); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CURRENT_L2}. + * + * @return the Channel + */ + default int getActivePowerL2() { + Channel channel = this.getActivePowerL2Channel(); + return channel.value().orElse(channel.getNextValue().orElse(-1)); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CURRENT_L3}. + * + * @return the Channel + */ + default Channel getActivePowerL3Channel() { + return this.channel(ChannelId.ACTIVE_POWER_L3); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CURRENT_L3}. + * + * @return the Channel + */ + default int getActivePowerL3() { + Channel channel = this.getActivePowerL3Channel(); + return channel.value().orElse(channel.getNextValue().orElse(-1)); + } + + /** + * Gets the Channel for {@link Webasto.ChannelId#CHARGING_CURRENT}. + * + * @return the Channel + */ + default WriteChannel getCurrentLimitChannel() { + return this.channel(ChannelId.CHARGING_CURRENT); + } + + /** + * Gets the Value of {@link Webasto.ChannelId#CHARGING_CURRENT}. + * + * @return the value + */ + default int getCurrentLimit() { + WriteChannel channel = this.getCurrentLimitChannel(); + return channel.value().orElse(channel.getNextValue().orElse(0)); + } + + /** + * Sets a value into the CurrentLimit register. See + * {@link Webasto.ChannelId#CHARGING_CURRENT}. + * + * @param value the next write value + * @throws OpenemsError.OpenemsNamedException on error + */ + default void setCurrentLimit(int value) throws OpenemsError.OpenemsNamedException { + WriteChannel channel = this.getCurrentLimitChannel(); + channel.setNextWriteValue(value); + } +} diff --git a/io.openems.edge.evcs.webasto.unite/test/.gitignore b/io.openems.edge.evcs.webasto.unite/test/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/io.openems.edge.evcs.webasto.unite/test/io/openems/edge/evcs/webasto/unite/MyConfig.java b/io.openems.edge.evcs.webasto.unite/test/io/openems/edge/evcs/webasto/unite/MyConfig.java new file mode 100644 index 00000000000..bae652b61cc --- /dev/null +++ b/io.openems.edge.evcs.webasto.unite/test/io/openems/edge/evcs/webasto/unite/MyConfig.java @@ -0,0 +1,94 @@ +package io.openems.edge.evcs.webasto.unite; + +import io.openems.common.test.AbstractComponentConfig; +import io.openems.common.utils.ConfigUtils; + +@SuppressWarnings("all") +public class MyConfig extends AbstractComponentConfig implements Config { + + protected static class Builder { + private String id; + private String modbusId; + private int modbusUnitId; + private int minHwCurrent; + private int maxHwCurrent; + + private Builder() { + } + + public Builder setId(String id) { + this.id = id; + return this; + } + + public Builder setModbusId(String modbusId) { + this.modbusId = modbusId; + return this; + } + + public Builder setModbusUnitId(int modbusUnitId) { + this.modbusUnitId = modbusUnitId; + return this; + } + + public Builder setMinHwCurrent(int minHwCurrent) { + this.minHwCurrent = minHwCurrent; + return this; + } + + public Builder setMaxHwCurrent(int maxHwCurrent) { + this.maxHwCurrent = maxHwCurrent; + return this; + } + + public MyConfig build() { + return new MyConfig(this); + } + } + + /** + * Create a Config builder. + * + * @return a {@link Builder} + */ + public static Builder create() { + return new Builder(); + } + + private final Builder builder; + + private MyConfig(Builder builder) { + super(Config.class, builder.id); + this.builder = builder; + } + + @Override + public boolean debugMode() { + return false; + } + + @Override + public int minHwCurrent() { + return this.builder.minHwCurrent; + } + + @Override + public int maxHwCurrent() { + return this.builder.maxHwCurrent; + } + + @Override + public String modbus_id() { + return this.builder.modbusId; + } + + @Override + public String Modbus_target() { + return ConfigUtils.generateReferenceTargetFilter(this.id(), this.modbus_id()); + } + + @Override + public int modbusUnitId() { + return this.builder.modbusUnitId; + } +} \ No newline at end of file diff --git a/io.openems.edge.evcs.webasto.unite/test/io/openems/edge/evcs/webasto/unite/WebastoTest.java b/io.openems.edge.evcs.webasto.unite/test/io/openems/edge/evcs/webasto/unite/WebastoTest.java new file mode 100644 index 00000000000..7e6ec194245 --- /dev/null +++ b/io.openems.edge.evcs.webasto.unite/test/io/openems/edge/evcs/webasto/unite/WebastoTest.java @@ -0,0 +1,28 @@ +package io.openems.edge.evcs.webasto.unite; + +import org.junit.Test; + +import io.openems.edge.bridge.modbus.test.DummyModbusBridge; +import io.openems.edge.common.test.ComponentTest; +import io.openems.edge.common.test.DummyConfigurationAdmin; + +public class WebastoTest { + + private static final String EVCS_ID = "evcs0"; + private static final String MODBUS_ID = "modbus0"; + + @Test + public void test() throws Exception { + new ComponentTest(new WebastoImpl()) // + .addReference("cm", new DummyConfigurationAdmin()) // + .addReference("setModbus", new DummyModbusBridge(MODBUS_ID)) // + .activate(MyConfig.create() // + .setModbusId(MODBUS_ID) // + .setId(EVCS_ID) // + .setModbusUnitId(255) // + .setMaxHwCurrent(32_000) // + .setMinHwCurrent(6_000) // + .build()) // + ; + } +} From 7815639a81a35ddd8f840629acc4b097b722c268 Mon Sep 17 00:00:00 2001 From: TimStoecker <79842855+TimStoecker@users.noreply.github.com> Date: Tue, 14 Mar 2023 23:06:56 +0100 Subject: [PATCH 06/23] Docs: update for Eclipse compatible code formatting in IntelliJ IDEA (#2102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed Screenshots and descriptive text to use correct Eclipse Format. Co-authored-by: Tim Stöcker --- .../images/intellij-code-formatter-enable.png | Bin 104867 -> 104872 bytes .../images/intellij-code-formatter-format.png | Bin 93823 -> 93887 bytes .../images/intellij-code-formatter-path.png | Bin 93785 -> 105284 bytes .../intellij-code-formatter-settings.png | Bin 104099 -> 104103 bytes doc/modules/ROOT/pages/intellij.adoc | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/modules/ROOT/assets/images/intellij-code-formatter-enable.png b/doc/modules/ROOT/assets/images/intellij-code-formatter-enable.png index fd24cf9c87afc2be18bce67bd86ef0e880033d20..3194f18fed72b5aca87c5b9312ff70ff34ba38f5 100644 GIT binary patch literal 104872 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

    jlP1jr7?7tePch9Q}|A2rCSF5X1!W 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

    iN^8njw9eE%**X6 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 P_mPuQmMnf_?Ek+23_f6$ literal 104867 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 KLPY}FKK~1`qaOwU diff --git a/doc/modules/ROOT/assets/images/intellij-code-formatter-format.png b/doc/modules/ROOT/assets/images/intellij-code-formatter-format.png index fa1a73880a41a7387e5ea4d42a998e5f432995c0..07dd2944e72cc13c487a9bf538c5993e41859587 100644 GIT binary patch delta 41086 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 delta 41271 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 diff --git a/doc/modules/ROOT/assets/images/intellij-code-formatter-path.png b/doc/modules/ROOT/assets/images/intellij-code-formatter-path.png index 832ca65ad3399d1fef1719268de9b5350b29942b..2e5bb84128ef121c7ea58f783067197626a98f1b 100644 GIT binary patch literal 105284 zcmcG$byQu=(msd=cZUGM-TmMmT!UM1clY2Cb_B_3K9WMFm>P}7O#?Q32GFCiHIvT|-Afc$0;weMX>nOw2$G-@Y5+BaD;B9zK zdV_R>5XXKI6ui8I3%yYKX0uQtYoofPpi;4sZ$=4C)ZfuNrw~0rz`gh#nkWES=wH7= z>;x!aZ2$fB&$Yb->vHhFZ~xu!0$sun?!OyhH<7~7|0Cm1BmMPQ(&qnuD8x=GcKfe) z{4HdV?*E05F~)gNvAoRqeC*sjY05Br4t-Ri2;tO16lmv}ob)E(>$x=|Izwf{zGoPi?bw{7POrvaSZf%Muv!Z z${+y!Kf?tgFdL$3DWLbpf?x?n_}P*YuTjJN`*uj1Bz*+c|AQ_phT#kl$=LZ~=6_3< zvvY&!M5hI{;-=$UHQ}ct3q^2cAc}sQ83Z8OJv+KPnnO61?>)52!za^;wYGZ?E)<$F zBmMn?T|Duu1nx&4oHO5kS3KFKwykI8TKlhKBx(0Sk&Z_`ke}Xv-TZ4$OPAL?GZa}2C_Z4mQB)fuhA?(x=4_sxx>|tn9*5TU= zjC>VUOo&8*rh?9FDF_g@p%hfEM9} zIraA9VM!k%@7W4#GtQaJuN&v~_2E`tmhG>>bb(Kr6vt;05mfGQc6KTe=PvZ@9+Ucu73l-{^PIW$Un&pG zCkbC7!1ptWR5OvV?**DPV{QABt8rqhPqQBh)IZ^2V2Cnew+F@o6ji*k2x(oi9Y60k zY+dF#ckhoX^!KYXZA!9u!LxQY>Dr-&6R!08DMwD8pi+YYGyp-FQ2w)rz+r|={l=E5 z0n-J5^ZP~gXKTV{XHh17RxKJ1=bNH?CZ4nr9Es&TR=i1n{hh zF_L_bK8?1u?+sus>tC~={?=PxcADgPkgk5Dl#t21@Ul$5x={8m?|M>r$ok0r(jr@b zm1oe=^iciThU^1okNZSC3}7KRkNki(nCoZNtn-C^->X)&SB0Gu6JA z&YD8h7P`2GIdLNZe{?z_O2-j+<9ar-V2Ib(oO)u4m=fZWudnLYC*_HVeh<=Ah5+TZ zm!Np|gB;h!dzFAC+UxZDru$(>OjozqVU6n~#BW$+{`_%$RoJHQB}slP z7Wnm5aMSe_`y5w~@q2{USTTYIKX^ay^!bTa=0ndX@b*I#zOo$S*UdP39ZK0ih2-;Rg(5AS9S%wF_d!zN#!199oIy*sn#BibM zxxq(#pYJ9s!-*@Y6UG;s9bp~MNDecLi()Pg|huqclXX# zT!Mm5TNhnCqn*v0*a*=(KzXzK>3$7#X+o#Q8TdTWwE^nXYrNSUZpif%HdwXzCM$U< zN^X&~55JkCQ8ac9QQ7d5m}Ly_Hk7IT%#w_tiZ~s`YQLR?(Rd=jntOl2aZUe}N!XXN z1cF_s-thesOzW3#P+L10!VM3s0wzR@xPuix=*eBSfjH&_jO|0qwuAQ5oKM_xYy82G zG#@>s7}N*zfh)kGK9Wom64ZbP=#nILF834_rNJOD>w5HkzPRZ=pH%v5kLXmGXI{^G zhqVE5aTt570{f>XTMcAW$a9}yKW-a8yTs797w9hd4cjF*UyrE-Y^!;Z&Th+}vDOll$g2l3}R<4MZrC%8>Ss@H=Sl z{$YUNc*wx!xu9!*HA~ycOB40t3FR^6LRjT?+M>29l(Z`AkmP*6qHsH>vf;;0ls0~R z>N@{z$mX6S8&^^N_V-@7ZGag)P2qg3aL-GyEBWp(7Z3AL5wbXbws4pjMDx+oW9COQ z2OW=@uzL0x)D$7}RmIE~6;_JL%%USn?w(EIpwcYRU3SEoEP^nm9}(r~sKi#vi3{Jq zP7paPiV@thU$wnP7AI0!zD){CH+?dt=aREqf+&=cGtoCDR`BI8fI+IF`ZB3Kv7$t$ z7hc%Ma!poa)Ah{fb2}T(%EsZ4W4g_tVgt_?qwY}47*NLb`iOfsjuq~ ztKeqoYEM#kPPAG&YDyG(wtPBjA?Wu5gf1beWL|${bV~1T5bC(tJ40A|V-J-3{qVD`K>(%K>poV9z`4X2;z02RS_!$L^Bn{F9Q}?QgVlTi>>vFmqv8E|#Sm z%ZNc5&CXnhWT#vQMxPr4>5~-Jm{kK$+j_)rS>s_vS;kJK1U?oR1?RZN(RlZa*BKo* zCfRoOMM#YNLD)s7Th_<3*D0U#vbm;eE^XyLeAMlZ9zn~xKKvrf+kEeD~kavd5ZzMtF znxOISW0981ux7MFqh*qMPcp-I-ndGYcI%Uz!NIFvoU~nb8@)7qD>lb>F%Q4^1rsWg zA`NnM3z&_ifLAYUt=vgmO-;@OoEaFLvFGMWvo=IrTo5;KuxQi<(I~I%sk@eLaG2x5_oSbylT0wjnGw`jIY1L>C$}}O1 z&#_jXM}TECp$W+sJ`Iy_o=+Eo8qA9~bB9>SSus)CX5DFQNp6U|J2cO(_kD1#GHzGb zebO1sf%RSu^S|fIxWbo#n}WE{q?iqf2JKA?{ooddOlGUh1gVYj2rM1GBa1xL_*lZrsxOijnHqpHiZcE5-Y;ZwLH}p zEagGXXNR}$?xk0q{8FL+zH{ro()JF5wB8jXHINi460`{=lEoLNJ_2YRophL434QZq zyEigqaaa^VWLM5L#9&@P%n9Rde>=e8d7|QZ%px#2S-|x~_j;lTlb^1efpdmIHCleq$QR z1upW(;PEiXjX|+pX=f!8pswMN>Fn$V`vT`Cb7)v#&w2Ag_(4PcX3Bpzm`$A=Ua{npwodEq%A0zOKT{Hh5^ALcT(&U=utp{svTJ`|^YRW0g#ZO_p0B{2 zJ!oqHwmLFbI3eLpdBS~{H%K0Y3=4aMc|SG`d!a=JRznrh;al(?j<>9v7b|;$jMQ-Y zq4CL}mK8rd7EWABog>-Uby4lkhtu@-0Xei<;%6>h3)BSHlzSHv0}lh!Pz`yToi)Ez zaL$xAx>-NA^tJ|Aq%l-`tRc!aMVu8Wsgxx&Sg6z)9Gdh=`ufL| z*Uou|6*u66SEhJKO|>%`&!^M-T2kU$StXjJu zUGwd+PQOs%^l+Mi`rI3El2=X{G_T3;p|SPzG#5B5PN``ePIgV)E=pF{Vv{-H6drx)se7l$xTO~mG?5W1qNFV0C*4mW z)S=0X7BBK$eBsMTx(Q8dPkcbQM_H>uI>dTs_(3$fAu~~N?$s!4M)sLt0!~?*Wggbv zUr^3o5!Jl|F=@@g#wvLC%rvi};72bPTyaTx_xTw}HvyiUu`@k+TH0J>#O3nVd(|WqI{JMPof{VRZv1$Bto?#dim#45h04X_Xtp~xQOvJ0 zY!Q!I{%d+$WQ$tlN#zS`t*yd=c@0X$J$K}pvFKF6?fL;g?hSGn+e}>y6&o0w_>64aMh&CO2zbF3AO?O6e z(O(&Tgr+%LC)#_&7EmfywSvfea7?Z2O|@MIVPR>eW4P&6c(n^Kx)7~oPLTsG0Qa`% zBfKpHdT`87TB%28=P)^~1`y$5oA1!)8TD4Bx8FLp&zteG8~>G`&z%ZQID89ZTeRkX zgGk!F!+sA@Rnh9VwolB)8<*ZbQd}Cgw6`N^#>7+u%r};X$S!S|TX@dgg%0GW=xoi8wdv zA!YOOzV5R7u#b-qQ1#OjE?|^@e`}LR_+Bbc=*-XL@i-{-m&_D}`6__xm)z3QY$_3o{I~=oBI-p~C2q+VX?EUB-=Wl=e33xgJ+iPhR@M!WKT%E& z|4!*#x;d4h+X1eQCsj1NFswQZY|jZxx`kp7-+0*5nE?W|3Vy#n&063!ljocmTrx1SE6SW3Q%*W$U&a?0B z6By~-4$0sY7Okp+K~=Wfae4jL$ucU=pf#Q3tK)#6^=*LiL?+!OnpRtcI@htZWPop3 zAhWe>@!b&eadvL4e>*Ew3LMOg)*1DwW2CVU+A@c>uWaZ1?y>)JITo@oA_ox{QP?hQ5r)eH*G^MMrppD3dZChFQ8AA9OeO`BpT26rE zJS)7Q$+|c3wX20^p+L7h6#Q#%!N#g*_bh7Cm+}Brnyg!<_YN%EHNIT{Eklq*LY<3LQ~BhsW3)_MW9Zz* zBR=`j^PU1PdD%NeRR<>n4m?VnS@til2~E@~YwbbyAb(Oyec_1qaZxO7GGrBloSZIt zo-&Z$1#Li=K!2$QnD&8Y{teCcKR6DlejvR4w}xc@h2l1+ISLaJ|BXid)z*_2Aq8TI z6~SM}heIDlD8k`W$6KY2p5WhtKH7#5#clu4!-BE1J0e4&4`@bk@5l^j<^=1htU(n0 zPcu({c(?E4gDO}bz-&GRw>vtE&VL$**!=vEnj;^O8Wh!r z68_&fGc;4_uioT;2J)}I4ptET8O(q8`yQ7K6=%^d7UJJS{&N@D5TB61cJ%t~+qYW$ zu>Y1C^0DRoe}G>9|0JYO4eCoLxg!Amn<(BX=Lh)C6E-3ukqiNNRTKYby7q!`1uYoB zRVO|!4JMaEVENZcAM7OQ9`O6vpp4{kYQ`^9@!a(hUWc0)@BLJ#40s4qLcJyh{Rh?0 zlPS7U4TEl{Lm~G{6H~mZf0jmk2nYLd>;H(htEZRBj}}f zuOr;oiw3N5G^Jp`;sEmOKIFL6|1xQ@*TV}`=(~hoWWbDGw|VH`PO^ZK(v4cMgNKA|7Jv7%CjTyQh@dl2q*-V@K1I5r zcwU!sfU&}N|O4iU)G`$QEJS<$zJ{%Zwa# zeBwzy1LKCZX){^LEr*$>r= zWs!E+sbgUbIOV(Kle>lOg%WXyyeu* zTvWs5Ko@Qn1AbcT+hky@ajRv?xJFlEpaiVsJj68|b22i1c4vF+$s*=zhX3a+JSpXS zV5A@%4vWf71zFSu=%Sq7BU*H|wL7drrn}@Qo*j2b^TPLjH}Hg@@B!8m#6+GKy395o z)Tct0&-D1a;ZWMdbE>ok8>>z{E#yhXA#re`P6610&*ncDQ>jm0jb{rhe#H!oY zeg=7AXyjdeK%8lJzix=H^3-f;l!CD z4Cb+%ys{V6q;%QeSSM<6nIjP?$DT84!k5kqsde!igakP=@qNM!y!~hEIOv1AyI)sdbfJ$=Ijg>C4$fT zd(kUpitk9L0KWU@kjv0)Y)xvGrw1m?amjLmaXXp`Gyj0^s%-%O+dc%{()oZ@GN*F- zQnUtoR0L@*sDmW=%#PTdk9|bYvL|Mtpp^v9ZKpSCU#lxQL%PqcT*a7_V*~~XUp>)k z)j8dq`uJppxT%EhKy+4yjHf%Sa{){d`!pxD>*#243q#yl`sZ1Ax_%i+;pn*7v58_% zYv>x6&%_N-ZU$pGfZLLC4Zx^WvoTM!|!a}61G+|WQsMr zA;~_62(0mK5VU=wqM7x}x}-rGER2f2CG5lVY4U#z>?4uBXpGy&bYP9yccPmFaZ@ezD228e(_APlKfchbaHa=|MVV(J=r5?e67hrf0_)GPf}6 zy+M7@v)A4!iyxX|whV0t>=hlAB7Wh@zCI&iNyb9T88tvhYTyl74XmpPon*|%nNZ7( zN2%Y^-3r3RA{;oZs;1}2IzGijF;X;ZmtVi6zQ`UE761=70IQLt!+(OwCqEXr*}Wca zq|k?_{4|b9qOHUK%7;GK*7-^py~mW!cl>+ylI@>bfZs>+(ARr$-jvR@CUQir2j~M8 zc|0^1h8zFHG@W+VG%(&$Ft%R+Ca{mj(Aq0wHk+Nkcp!nxZqdL!r{iBTV*{&k5URUH z*WFFKS88*^a`Mm|iS{irZLP7c+0T6$qUooUdf%_53Do$1v_>Jj*I{h6oLiO!ntl_W zLm!7JF_fuC#xVHIYU~s+q|2c7t^YA~{I*sRr3|*M1-?c&V-K5fEA_aa4F_l-Ea+`J z)ghm&gEd3eOtJ>*_&tB}EG4yHj|!%q&AGiiMoOP?4rgug2;OK9hfvqJbWM~!{qCAs zJ-pNm*_XW^`l&Yj1f{~rOA=Kak`}w+v$MgH0snxZvBh^6DW26gm_%r7?MQX`vQ`u? zMQ}$hxy!0TH@3ZwN71F?^iS;gaL`gg+T3H>eePUiasT5xMR$+%TRm-VsJwz_0R<>x z_6{{&p0f-_0Rwc{meNu_FY>7+(s+q7Ms^ijA$o3Y@*tqCt z5{RHGo)I=^WK>;N-C9kUsGA$DPN_Hoq%Hf>+^-7;Bj(w?=c7`iDekOUr!664;{p~c zD!--z{5TY7M9jlT&jBb`4)WgAl@(g`xL{0MMOF7?q%?|ZcPl=;%PiSj?!)6V1c}q$ zjbpN->R7%4Uq?Ej?hV<;V<}I!qcg@qGs-^fBzZatSvDpUC+5xYq87$!*Fe0-mkv4k zC3+)SSwKo^^iw#+a@{?x)#`+V15r@^)Lx7(&w!;v)=J)D&9jToFWcwtXl>Ddk=sRT z|7Oygxh1X?%#}jv3~vm^M&LXLPHi&U?_L$LX=*=9XVkTY zLY^np{i=z3h&oI@T2^|c2DTPul#0tyV1K%bV>?!Mz1v-p(QV(&}R|3a++6izr)te zwAmgcbiG~l3PY{(PuTJZ8i3)@`AVkv&gJ9!JiqXW!SB( zb3VLqzNjqWLIMt$z)cHqU1+=NXOavI&&~?Jsb?B&%iaE=OWWKnjj8J)-K>t=J#Jax zi4WHTMWX$k4V{S(e*skFjeBZzsX-R-sV40b;9@^C!BKkq*>w-;Gj{H(;F=4=b|T8AsGx6qddkD?{YI6Q@TO$-MJwo0v-As_jn>9jXBW z(_A3EHoE)#D(gT@Vroc*tcy#hG;VeWHy|hxzBUeFn`g3-&ZC$h`jQ+STw%r?7wJ9l ze#(7XeC6wC%Ft>7 z_#HjIxx-8Ce>w38?l6Knwy?&%%i7mmLVvEHc|XzeRa^d6q|N;+?bntjUxil2!jCe7 zx_NS0OP^?^&9qC!ay0dJXAHP&rBJ3oJMBlmrcEwEsjWTzgX?}IcE*}l`TIp2g_d$J zN4B}ocFPlD(2nv-p6MUK@ia0-_0NXi-t6?l1K$;(-B&rg_887+;c~-A3ZB=A^y_hm=fSlVGw}6JY8ROu;Wkf9rElCGvn&B`x^$spaQU9k zv$#$o3@-BIs;M~$(qQ~1KZQk~=^vJmKLyNAbq^q^H`;g%&GWq~2x7&Jh255=q;Y_T zpA_y~+c}?eNmLLrA}ws4_RioAbWBW^-}f6>Zg)v3P7hJ)zduB9k3EcW}#G=E%cdz>?EmOfj&=5s=>G;C`!VDV4(aO-O-0MNll;ykR08N1stWA#Dszt->Z*~Rb= z8t@As6sl#m#%}^6+wU)6G?b@JDt8BN-S1xaAx2-m(b9Y+8$=#lQ|UJ${9L31Igr}p zw-1++nCUC(prGU!;6-6xsZC*<-f9xJEnM-EkkBI(@_mLYx$BXM{Fc@+a-Lw%KhLT7 z$xwyom9TXjHB*{e^@k@Zl?7LV?xM=apaM9=?bA%5Se34$X5( zS68WEyXy<-ybEBBrT`uy#{Alo<017O=s7JF=@PPFzegmXbpOcZ-8}O$*zqPi+W*4- z|6~$K<7Kts#gfuIQd~2;m=%CSg@-ULX_qd*lv45jRL8;hRs8n!Gp>2Ti=GjbdDUfE zBvHaQIsP74sAjyEDpR=gQo4Z`!s;yBO9M02{=}}mS&W$gS^EoX4h9QIPv|O zosr1##$eMj>byYGT7&07?yHvY|5?a@@Y9TtuGJK^)`VpuXGUdng_j^KqlCpFG~RQ3 zAC|BNpCyHhB?IjlDoc~Z8ApBfET&EfV;m1?NW>0&$)zkD8T zxUc9ryaDdqon!xj+5QC9{SSrMp<@#ib4U60Er&O``U5dBAva|emUIZ&EL0B-oW@qo zSzJ3TXYQ9QfZtT(Z8mI370}lQoszibcr%IlyVFUEXiPt2Qv--(Nw{z|JOQY4u}rL) z1zc_fQ|QI%FGo{ajz0#B`>ViOIS(wC1-@@{a&MJ%W9bgJ-rm>L?%_MfZ|+Rh7@TFw z`~ee-dP{@SToo4{N?G2;}cL==kh0ek5t1nAVl!58C@HE1=9+Wp;PE z++(@i98w5;GD+Nd-31U@i)r{KA4_FhL4-H84!C{?RGsZ@ATeyS?e~l!u{e#Q&)zL4 z@-+N9B?;61E3+(--$cUQ9R5@gF53Au1Jyb^oxbIA@Z*f@LrucWxJDAU)K#w6RG}=~DD_9(Tc7Xd2+zfI?zX+?r}%AV zi^J6`xH&_4Ogig=C`%-djyv)vMK7W%ext`|s&;*ownti0WIpSd@K|epV~6bE>t3kJ zkU>jHERwG&OWir6%@@(EHsxF2^!_AzvwP>aqAvy|@>HQIzIuK5_!zqxNAPQwqN=Wp z*-xL{U@*L>tJP-Yi^1pPUvnI<oE>bZnQDsM#e(_g^}uO&BQeRqSDcU2IRry=?tj1N5fSt`FPJjyKA|Eqd@!8m;4kG zhbr3SlW9-_ALVi+%~*dfit)&g4R2s$O)>r%lbu(%A!uBiq+&vxVn$9MFCG_TUDT3~ z=))OWy(#ILj#E&PF?n}^)YIDUStxt7eYPgb>dJbRzFRhGW;rZ5D6hda3RiqV_Xo9& zu=$5*MjZHWqWM^Wmu-UD;f!7X9QJ?Z#3l95MW|qd))8KQ+i+;nRpMBxi6uWPZqTpe zE=!X~FzTh5d@B9&Uj%rO9hsjjM}&ZNk!5tT8n*)M|DE+dip#%P+nTB5A2l8*_O0sJ zD_j^|I>F0ua5+`Rm9yU4gQM@&_HKWhcB0w6&Bv5A@N0|bMc6=V&C5@IB9lr(hj)c=UQehjT7NTz%$QMyGM6dGPX{ z2R&6W1GGe*W3BTtnK?cZ^Ey2P4SLKMdy2I*jH{V~LfV3qo-H_?riD)G6L^~6V0PpA z>ndEYIG>fYwI|}__<9yAG((F~oG&*hLjSJ$9>ho}RLZKpsl{?6rv>7St2YKws01zB zXQ#d`Qd6nmsZ2!9Iauwh_V4%Sks34|Wp|{~Oh_dIm=gC|L-RePI9wf7Ay-Lg#I(BAwcpY zAo2$xoi3eT8Fq(<8SC7&OzGZtl}UPAL)uT3{Rn(uoz_D4x%*@kJeS<)2#z$KH3@D} zDet^0l~gFW2h(^?*U`F_SmVE0xzrFaCo+TKnfge^aAoSU$z4;$*RRM$BDqs$b^ zCc}Dw-2yGmL=Ecb{niIbfqhojg98q*0pT&ouTqjLeEEe<0xA_Msi;ecWG&tD=*i~H zp!+;W3S3G97p9e3<9YFrVB%wriM_EhWS1uLz7OjS#&bFzr0~2g1@dy7FrGwG&cTJy z07MTNgBf>SW@g;9@n$+tH=#x2ILN{)XQPYp586m3)Fnip^^GTn_s3Fa@j49|57A?7 z>=Ydf@U4Efl7Mo2h<;s6Ur=_Uii6K31@>RM|i1CIhCKs}mr`us$DjB8<_!O^ZU zndW>(gAFV$E!_>o($O1BqLnP!16GYwlJL<%X$;OHv3J=0+DvR3-jdL@Wq_%4{ zPkrLjxp4zh9rv%IyZeAu)D7v+wKscFo9a-Hrl~9b6wYMwx1G>ADMfE*sT~<>V9Gg% z_1M5g&aL{Ua`*prJXp(9s0@ zi^-Oeh0MDZ{E~oGY32Vxzz5iWgOnix5M`9p!YR}&Evj00J-r`fp1xcEnrjpsy<6KH z@?0?4im+WUlWjn+<#9k@=!_RnBMK~s2-Lg9nPe-`>*@evmwHbu7e%*C**1FNhR>;7 z_uf+|p0mc;Z3Hs)xm>MB1{J59Nk>`#8gt>>d2!Mu7TI4PsQhkj{B zF1fe;*B3T~b5~(Nd6XGCxkY`}iO9JdH=ADiE4-JgDprns$n315j{7m0j>kEh^0)mX zAR0FOr+>$!h)0n#BI0F75emz3_Q@P{KlJ)k9ZP?EAdogR1mq?jk83l9Ckhuh;wmP$ z8KNqm9flDK^m!FTJPm}a8Qt4jdqBm=M#8@Lm8)eJ?LP>v<5DJyDCUCKxA{W=R&AYR z1`KEORFV|d`7+#SjCXl-1j}^$3|aD=8+VxvYYi9Bdk^^zMa1pj->V3Bph`SKNP7a2 z_tNxPL`jA{-O}QVsHA+4A#SpcmWVU8wLC9tkeZV z3!)5Zp+P`pjG($8ap&zGVT?ih3DWXdT7n}l`oXk}v**Wa5=;Q`*~&FvPs3PpLfmA& z2z0XsCEnsELjQ2w;)&|fA97KsZQt3|S0MYJQcYQC9Md-^=!e`f53#BZTQa{6N7t1E zi8aA$dp!}-wqDqfRCs)%!t0!s^8i?{@&L4^el%^0Z&atYw4jYlx6f;Hj$dq0n9T)s zF+BSQ6~7nqIWJV-PgDdfR_Hm)vMb@^3d(WcHpsZLeo^)sn%p?A`^irSMSW-A+T+z{ zZhAj3r=@j8IagRZYhVd+)qh*=ubXPpu1WhKYb zX_F80ipxDLq~-#s%5_)*Me0Bs#$+5Glg_H3{cwMkWwgmB(ixr`gjeITf=!x7dAFt! z>r2SW5IGKnOs>7ZW3-AraG!ew*V>;SR9Tz}h1iY$b2tkA>qi};i%;#3(DPu|{RD0& z6cM0I?ypMlZp&~{nrFv|JRD!tv380q6ZhM+7oh3dQ75n^&S}e_cZc!W*()fQ5<61t z%$b`#4WVsgGFLSG;kL?WV(WdXYu8=^#{HiqW;YfufwX(i2|7)Ex2}lq*0NIX(kjMM zZj&C+j6F(2eW~_pPAa6LvY0)j{O#Lq)0NI2K73b9Qj1S1ZjG{Yo$o~Agj@Z-gBBfD zdjpdU9oFt(9LM{%Oc#jsKJ+f@{YLt6oGJBA1{dXTD!iG+ko)6U6E@L=Q!K~Z@h`Pt zqJHfHr}SS_@6IL%uNmdfI!kFFmoh#6r~{?|VKtFf+E%~A{VnbX@p2Xg+B zW$pjLDF4}Iut}CEx;@@`ozJk}pBUbIyI!7_4D$K_;I@yfxkDk_+1>{j|8JKoFNeV0jJ5W>r^L;fK{<{V0ZBOtK&$dnfIR4thLucU}0 zYU#AkykYwmk`#qcNX#F!j10GGiDNMbx7c2c=s8qYeMV82B!%Bc@So5{oooKoR(#BewYjA^F&P(5*@B-e z#pRIr#{k=P2qR@=jvSwA5KSUtx1THto{sy**}vTYZ5r)Xi}bSE6EFFgBOfYpoo!Yo zYcL<3KPn?Wut3~T8K7N5T#GRw+_axz!5H1H4eu^ChA!V8=vfLeuKEbyLVRAAe0CaC zb@y9>Rj#9}&PhjMB`@*Lx3NFb{WadD6n77s zHCak_6T;$;8*?xGS75P@$u|4yc8YoI_;f*9sg-5&3msCls*6J9M;~uBe%K6C@DO39 zTt;;#N~gin_$It&#_jlN$+r4!4%^bmS5!UpYEpRaJXyk0m)P zr1SKK8mk#~b!o%K^qNB^oq;SKF#!F>K1#1LlaMMWSc)*PBm_+ISg~tN_=!4{9?Vfk zO@Ubk<5y`+PsrPCVxn;rHo4m=p2+MZMC)7!3MOkVC0lbZfPzp ztR0r=4r9!4)x)jND_h(B*?@7=oT6i(aPYy^^%%oV+SW@@UvO8xt>0)2iHCfISj(3W zc<#@18+*I|b#%Qv(RP{SmR09s%+voCr#Hd7sSZy;Osr3iR3Y00Q4Jj(CjHpFK zQ+HUpnGa)yf1qsB630eciJN80MNZ>I3C^8W)DTQ#iW)CBM9uY_Pgt7Hk<%aTbweM7 zEUqvoF_bbscv={bR1)}KY34AhsEAO+T^YWU(Nfc++8ACFx+y-^NVP|vKXxC2qKF>Y z_5A!E>IKC&WE|b2$C$fx`Z%Zi)*J2pn`G1dlo02d6fyWlWHyS- zfQm?|0V`Fs<3E(|8sD#ThEoO5`vU*=*9(=q_`nZzi!~VWN~!*ax6$(oXN~{uXY`bZ zV3IEhaCO>rQqkF`IfG+!c|@H<&E7;Fn;}d3&st|<24qArAbN!^nD^;1W>dn3SvCnPXi{~;wRXD?z&@ofygXo)RbkG+tCYiTclD+y5<<>7B>}=m7!eSx*sjG^}t&#Dw&>6iudwO4Ko4VwzeCdAPDn&dJb0InW3{CEv zpPWY;iz-1zEkC==lKJIwnR{r+o6D>pHAYz8D@Mj4i?2$K*H;nHeKvUl{2+k5I0y>K;eDEL3(qitI z%KBQylpE!KPN{THP%Fl@%v&I*GQq0_HOuQ{qtv)WHP>(_1U7StP7{ZWU z3S>-{p?uSr)V*QcoUSiCK5F%2ql$ZJ|6IE(jdYerO27N4nsqpl)!yGq8u(S5ZAlyT ze^hvdq*y=sZ-Zzs?CTQlN)oEwEZy{miOk!=LGeF@5mvgO)SAd^rArlRiyu~gX}Bop z+zc(WaMW%2>ZJFe1TQn>bqxJXvj!Z(sbKb%AVQ!_YJaB|9c}$729K zVqqQ47v}!YYB2)x{Sp(M)Ii}>8FZ`F$uMQOYCG3)D<%g(}H?gkTu-9%uWt`&LH zGkllFGwC_%1LkhbRkLQOQ@_+M^J zXxz#GABK0y>IqAU}i zPPEq>pPlg3qy9OC2`ICI-Pq>4 z)4_)$%MA#9JzF;;4G|?JXiU^`GhdC}aaGD7MHLFUxrIV-1eTm$-axGIGXh9rBnk>B zVa?1+`Zef^OCti^;#p<-4w0r;Rst*KE(qJ|_r{qL&H*U1ScOZDOw{OEc@D1rL?lP4E9TJMb2xNY;_I!$I z%i*WX`#x?*7z!`4@J#SEJlH?A00ZI0_&>yxkz!&pgDOww=Q&VQ46CJ}nOsN*hd!=} zDM_8?&$eLD-aLWDAr^-NnQ$VP_382p3T9_!xJv5t@lB#iESExmb~1Jpw!MD1(1>V= zkEqEZHnuTQn;UC~>xrzZ${v+*Sz@Yj=Z+^#0hc-`g(-Su8C!AqtCH!us$kpUA`&Ii zH*p{Abv`RDkFyVj%u9lNoQ)@Ru^}`op^B3g_cNNK_#FBXPgM_SkY^7EazBk3sB$~x_ z*2PEHBsgudGLn%1u#*Yg?^n4!f5|4TeXDryaThoR4BB`*#3Qa<9b=@hJQZ z;W{epGZDoxM{Z0VOkL8|*Oo;^ECZc5%v#d`#7)A5+IAX>p0)g~5&pnIu$%dcySAE#dqE@?VYGd?zjXrDP zx&r{oD}NPrEel+Ab9*`#_|#53EGwXkdJn@A1+ii%k(QKFFD09yM~M^~j>4J^r5Kg2 zIuYkHNOv7u`g|;hJr-`i?I51U_auDU=#u@tcZZ*VXCa+upz*c4EbvVn>o~r+8F`m) zCJ}G_s%xCZhA-Ux7cE9)M}Uo$a-4dT1s08$_`|OzRUm2AuY@I?9k;`($A?ufn8p(_ zJ@GI#vnF51N)0nc|I7FM@o4oDkUe|5XOs_Y#;xCA+yZ$ zt}!d&RJHCRQnzM9SMIT5rC0vW`U!Hn_&Oe!i4M|-I-tp6#F>hEJJ`Ql3Yxo0P2?^c_k z&SMH|4=w=wh;Q|D^%y^*CA;MqG1|4i+xoo7_3|9>`3LD8KSzZsCO&zMwauu6qyJdpR`F@27eSTaDneb>yIu<8}O+36J@ z-8=P_L+*O>J)4|xWz?nnDR7pDvy3=fX3A1mM1c`RGuF8Kf`HQ|T#p|*qW=cUNSKfy z9kCX^X=lFyhInq$+>}EDiiJBHe&O%z^$ng8mi1{JNY=Vi}jK*Mo0%*g26@Y_{pKy+-aTl`!hJ z(Aetnz%k8$L8k|(%vAl|Ko}zhhY;Dy1e!8>`*8G%-0a`ESM2?!rW$ewQEIFfjgvU~ zTCh&+;)T6mk4AtS&Q%L7(B?djkWLImH*?tZwUl3j*;TOzCA7M%a3bV zYa!Ls=d)p9^|>6Yz%Ws05otq15@e-SiJDIPN3T`t*15*;JFbOUrxJhX?C^=A+4XrT z7abZnvD^UpGPK@jO?1v7C!TYPa$nBIn@7p%1- zw-0#Byx=*a!WI+++*YX;Y;?q4-eEO|a29N6gDgB+&vBnqJdSotkR85hWb24NjxWCc z!N_n055H1STz-tmt|wiMgcTOjc5hE>_1%wx(ER|*rK{5E2weg65;_zGb-X`l z9DQu@Jz4(_8532MWUDur)xVC{2MBw%tXAK=p>Hb8zaYJ%Zz|z&jWzKNdrk>#yd_)Q zQiRgBHp4A&(xnskz@kr!e zka%pA7wQ0VpeFXTI>UE7xfkjgipNbR$`}ufNcGr+ayBKT=FJcin*kml4pQyW5oyEq zHat`MN=#56m#B%}pAv7K_;w~x?Hse$C!kEUW*;(Dn3gYxoRdh^0cD&&*+ZL~BZjb( z**#iQ-NaUwWi3h1bWox|^qG%KI8pgUx1V%myLyjDJw{pu^1&;T?0@rUsp1 zk5)GhyzfrzsXrvq6`r)?eN#twnqtK4+#JEnVf)@!+F<&-N&#jlEB^la1O1G_@4e-2 z&wx8ODfJ|k-Z;Pctv{f`6c@7z4P$&tga?rr7ToGmV`?v!pIPe#Te>5jujwCm9MRh# zhj}*w>dwrZyBfcQNc3M+ZT|_$w$E)3iYPvD^P08bUVp^yvN*=k+mwy=>A-ecHFkdA zkvI)z@B$5OH{_7R;gY*`>TJ&@sT`th^yzjToVZ|jZ|*!sA#1%aI=hmT7qYKQo3qRv z`YR@!a?M`F_8lpg9R)9ESb}VCrzY875ojahQiEZxzXWUR=&>l3l%w7K<2F_w)K>dJBF8w8$6|90VVT!dCt0n z#b^8}k}>K5&Eoi$BTVhn%`ub1c8q@bV5WpLe)BrP6GXP7>-DsRX|cOyhk(^$T9cSS z4uh}l&PlloS-VH7Q7xZg7Xlp_;r*6Zi!PU%Pu2{G7OZ;<9_?72cK}NgGE;??LafUR z^sXOG-TIn^AuhR!k~4;V1aLQyNe}Q zn%=;`axKNynd3|`_&4%1y07t;;0}k+~v>T#^bA2@YGeOo8|L1&%Gx8&OP7H;f;^CZanEt zrKwsT8>T%}_Y#Bi7t2#8`>coehbKUypmc`5M4=(j9u2#E$s_OS9#Mc6rw9Ks7s}Ih z68~VlPsDOkN~lxcXqkGdK9?XWPz_w~5Od?>?15S1X1T_T+Cp+BH0pjv)6L%oQLBg; z0t0sW$>rbX9G-|B%Jts;1P#4-Z_%B+%l0Ran1$_Wf!h6A?^TtBUj+tApB;7H)0z=K zOA?)IKI2zFHB=dZg4$v>e6}jcO5#NUv*_lS7@q55)fP1b=2#ZmK4DHA66_U_%-Ipo z;mD_aia`zxl1%5Xr!h5WDsI+P7|O^-Hm~4DzIYvdP#?;@{@tDB9YO_HlXl2*))Iv` z`W&cHUW^}|7|lP*Rq9>sfHkY-WmFt4=cmNu)2^lsTAg5HS^JcWCO8%N&!RtT_iNl| zvCvG&zm-2sE4#%DnXHPhUZbCea`dilDkBT`YTtk7qqaIsh?$xx^do#Qd$&*b6S~07 zyH{aWkuhGrpWu#5_2n7zMYEmt%+J_0v7W&N`$aOEuBU8U=b1Z2Y~UTwcD6CC&c=4zkMF%eUMdJY{N*WUu|q|fT2Ei zLR0elSe9mZ<-5nbW6i<+Ma70T+gY=77;f&ls3jtCkj95U?g4Vgo7G)U=yl3>?bqd> z9hau-h zOM@;(Rr+Nubj4N5;qvRETvPbdeAaMT6t()V%*e0wR`ZAK_I2(#>mhj@t&W%2RBuR1 zEs5DYY}t=}pA{z`CESdmEF5;jSb%}tT65a$lW|n!dOg3Gv+uC8a!8oK%CQKy&WhXL zabBVqx97=Y5kaQBLtjC_R;>zL^@Tg8u6~380^!!x_nF?LRDt-FNQVY+B85C({V+mN zKaKu%e=oexoC8IL->aE-SqtJ*^Zd^XFZ80A|3;7TV8NRrpJ;R%{S)DoU|3Xa&&L@O z>dMjLBUEddm5NV-v1Mck+8IDuRW7c@Gckmap6-kmE}gw?za@Cz*2!C>TP;0-U%am~ zvOga4o;MB$%o$Id&-4o~ptE1^sj~JGJFZu#xi4N>@Kx2->;IbVa`g|HJPje^OHsW3 zD83v0zz6R!KeVq}i=i8LLq8h!A=zH(Z^qN7^6)sML<}x66+*+KZZk+ShBvm?EeOX) zZrqN8(4R_42Yfu;5_$r!6TEdugG!d(sy(%FMHX3@uhnf|UPpvL_1RXj($HCo{Ps2K5U|N{;-j8XFs#*gx?S%>0=2LxZ!iTpo?**|aTu z=)#?YNV3_KHQR#U^j40bul;4xY_(7MAm+Kb7Tv|0z%0Zfqd<(AN{NB&I79nqUrAz8 za(Kx*tjQyocsM>I&i7>v?|v>AK#Edhd}FK~26OZN@D&0T+l*u6Hfys#>-bZddT%v( zjpd62O^oJVyWIUYt6`1(iLo;;=AK;0F;sB~tb@VkhmnsL%Ae_5OV|+VTWF)_B6sJg z5`~=`3Q1T6moo1oKhaTBCpLSJhPmb(t4Z=j&4~#l3=nD_*<@dG^B!_PQ^f?T%65&* zmCE<{v5aFQ*6Ptt7{x+=s_PW)-&~)_Dn!Kr$97$(br{f@c$>O2GA>IjaFSbCi)>+x zFeq1mbmu&?hC@QjmKh{xomajON9V4ne$(fyLM~>gDN01a+qxrGZnAGC+}Jo_ ze51RkqK47G;Fn;QtHqt|?N!Suu2zEo@N}Wb{$f+1yWML(dhwiGRg_rEJv#!_$u2Hc z4cS1(>8|x(JTNl&Z|Ba_@a+@XCtO-ALdLn#l>dvn$iYrtDVsATW8;JJJXP!BL+10a zVvmN?F_QQQvu6_e0<9H+6bApk)@jk6rp@Yz^;p9Bj{1WfAzo2)s4Q{ndTfG<)}(v4 zKHn+9-9v_(S2lw^cu=2^n)>A4q_VOygB=jvOj#Ty>vM;QBkq%kp5^6#KSh19Tt=2$ zLoq*5h)8XAbF|gk^YlDuIVDGKpBIL3^W8pPIjwE>x6H%NsSFw0n6yY#P=+N`CfmbI*=N2#=Kne@Ypis; zrXMc5pv1zilw2heCJNR4K`fmJP)v=SzpFovLK@T`^hcaxh|n(|AvGvz|F)7}n)cHQ zj?@jX)`3aJLJrrs&rB;cSxLARS+ZxnQ;nKr!N>E{;4h&!Q!}{aNEhIB&P39 zarHr`i-3)Dj`qApU17pj(@v48I?r!Brh!7x?kjY-P_hPXBmH2-an|p<6M^e=8CBM6 z8@b+D77dxNvFpk1VGwVwp1E9n1|iU&sPEZN|8b@TG5_OC+q;lR)(-2j8P?vZe)J@* z;!}a#^MR#ZTT`AE@|qgQhUzS)mtzix9?|=m%8ut9Iq|(_PvyIX%Qb+_5eFvaQlWZvOY;#k=^6v!|Bo$&dA6}izXcc{yUybI&EAs zflP7N;k5<*_30=b)%i-^z)CIl%+lqd&*1alG031vzl$DoF4j}fXEB-MEpK4sRE`}k zcfd~*6U3lxgH)r>TsEL)IY6QNdwpQa zrxiG<5Uf_w|Hhz7LtoGW&*%6$KW-zW(^Zfbq5D zNSHW|P|OMOms!TsU*w5gnhJVj@o>AIz6F{`XiL}rcSwQw-ywx{Hc9yhw@VQ$_S=gKhx0B>wYdrsPjk93 zJJ@E`BFH~1j_ba5G%i>Q^tAgS?5(x{uJC&Kay%SX)6j_FDvv8yC&yWcYbJ!YDJDlO zNbJ;`~WSY^?8OMEYsEw!iwDuML(ArSpJ{<0rY?<_|ou%4*VWN6Vi9T_1ldf*z zb85Ld?ux#x28y=L5c-wTLB8|-@Q3#R6mtts_3oTleI?zJ4$t7&D0E!v2srEntab*yFPyy>{E@=JFA0+x>#s_rVNiH zJwu7E%N3lTTg6aVp(eI$XiA$&P>Upy$+AS!a?+l0GJWCE_6OlUq+dd2B&!Ki=Y+pB z_-iqy zbC~_%8hMcN#Zo(gi{a!qgeflSujaxU>le=Oc-(PlZp|_dC}})a7i-D6lsXd>17V`4MQG>oyS;Ul{z<>?Rf|HCCRW!kAZZNS)b1UK zH6yirIlx_~gd7?pM`Y1!o@5McXRq zVIIGVaC7$}doQbgy5svu$BfTbukle-lP-`)q_F(=99j~ zWV+^wtigVQ)QD6avPENDY?|QO)~)!P6PuZg=IAV()A8||u*Y%f9s2d&F??H@1tuq? zH34O_?>Gck^e@4MYFbgN3gZ+fj_C}xl2b{;r-ZTJGBw-cl*Y5qZt@<9Z2*}&96}sG zTx@)(I%cJGedNO6Ao619_-Y?@`WS_{6bT`(-&_Sz(zuiWuF`tc8lL-w)8yh%-F2zr z_#K-mj=u7P+Kd~)$xPKO(Tbvokqe5@!OsoXT~g=HC+;z1WkD;|)?=*A{t)poma02* z48^gf*FCBvdX1qn7HqY6B&-X5Z)PnavEKMt0cU44vuG~4HKzyEE-qz(h+*-Sjwh5t zHAw&KHs1Yz_IbOsyPh;iYzuNrV!cnEWIR4|l9MGwp6|?^uVXaXY$xjQic~C!IqZXN z@VOe;T3ew0n1~zEq-fbg_TkT`yT>t-nE+(`O3= zmh+9`^Knn51{{ufS(E$JYm)x?FdS`_;F#o#9 zWC=#s4xUERf%Moq16BW9H)Z|427I+Zw2o& zKim&dl{BXN#4p%EPTl8eSy`V(M5|e>QTzJeb6$>XEj_insJD?W?$fr^!`*9Qwr`SX z`vnQvImp+JN_^+BfwDI9FwvwoTVbz)N!7~JL}1UER_vYNHYB&o_y%%!J)CgC6;ZFJ ziKI(?xqhk6MKt(-cQE!}05<;P8U*wW?pl*BeB)bRM%szfP*WUlJWey44Dz4G5wbj2 zdOe-srt<#aigx7P(fA@n$n{~3UR3=N$FsPq~A&CkyJP1!yfI7mMWY9UjKC z$O#DraG(DLO$M}np)9=J(q_pX7rzfQXL!wl{pDBH$D|D)(|7l!4M0z}!Ff6urhIBa zLQK~eh7+qT+>bL?33b()%i@|sOvaN1fp~-ir-Z~HJdi0m5&}J@JoPUi3_#{dBJMrR zQRn%t2`?q;&$nUtw~)7Vb!{|6auDDj$`xpP`~%L8tN#mL2jw6y0x*q=7zqag9KEjT zZOqfiK**ONBi1yt)eKOaYm!E3z6zPpOYd36*V@fNJ$00IeEm{SSaf{6PyEPbg+y zXMV!?Eps^BwLFSZTRm}L3YeqT@CD+Zg=r38!wMJYZ*jR{;|P%-Ml|F31!h><)iL+c z2+H#e|96NK)GHBA*q@~tPS7$D9M`j|w2w-a4c9aOY%~+iG^X5mA}p?x;yt_k4tf+r zvi||RxgnM3eIbw1Ae9(~TQHzR1Qg~eF=?sJ*aM{X+GPW8gUnbb&glP=BL0J-4;Tpk z_(}klt}eHtutwzdw{Q+ddMY-AD!iJ3Okf9C-fSj1;Q>MYva~nI1jfW1Sh2!@2Tu+# zW%i%iEzIxC3|{#unEQwMQ2C!J`R7k)SbC~}tp}yg`{I=RnoH7O?8Mp1euVN0&h2bC zedL5=@C9G1z#$$816VaOG^#axvX2z1AhBVW0h8(s3iraq=zG(Coq8AmpiJh8^ zlwZsX`z@G#rv6&3iz8%hY5n#7buLTRf^X2nW^o(ZaT+gmr6DLqW*h*ZQSW-4gzA;8 z%C0VGq~}*|jBC>6FnU6mdx_Sl^W<2kL(kQ{j5|>MuSYbJwgHrHkexhVmuf|%A?12Z z*MgIvq9i*L{NQP)EVXzn@79zvKS2aB3bb?Byud&14$CFXpR;_Pwiw?yQhG=Z|XWKX($)<_>Y<7Hy#4ClzMthUru2nTOxfn?dqJsaZa;;{|7 zNAgX4b<$XBD)VKg4(zb5I$iDW!h-n}zD(O)bGbn&KMu1;w>sdN9%kyI7`;dIA1(lD z@uc$ZxR$_*mx68nw79n(;rwD%RLZ+Japy3j;(v&kphp>6%4%=`p{g9@2P1!bg^$A( zgZ^R3RoFz3Ij`D^CTl#sBYkZjADRm}^>)Ze9-ELXsy`$k zB=8U4>0gsMYvdlV^*0LY7R8tlaC-|;Aq;F&5DLlStuoYyMXT$9%suY!Xg=ih8$dOr z8y(;rwR5*&dEw)eP@Ob>zaJhGADtY?b)2zb(EW5P&qvEfCqKO;X4)5oqJI$DxQzG8 zFe5wofNqMA@>{butmWlU5EH2OUn|MDMXygQCRCr4g+94M8BV~27`^Kw;~}OAxzndx zBcMM-oqAT6Ifp7Ih!_!%3-YHAA094B0w!_}OXgua94^Fn^y{6N&7F&nG3PAtR6xK% zP|D9C_|Ybw;iRZ12C1^5&w6zC{_ zhJZtLyOA8(U6^_=&Z`cWeL#+~6*)p;l;ZpJ$2#+JA^S~p^@EU2&bY?)ZI-)PpKyw2 z{rBDa;$=*8q~JIKZ#BA@=PQzivVJ`5@9^^6SzOZ1`>n#>!@Fo84wKz6vWSAXloaWL zxxkO&hvn=PkN@VY5XR?GkdO`R+AaYw;FW&$w~}H-&1_!uuFq26(c;0)93BRjT8p(- zr(zaet{1@0mCVgqL#I2pxgxD(NTu- z&#*9gY&-c=3hUyH$Z!O34_P63+{U~YjkY;mptD^mP z^dpD-s=E%%igpBX-w3}Bo)TE~+K2Dpdqxp`5Bnpp%BH`(vp4keu`m2(OSHE0e9rkDkv(F=8Pq|qc!FP-Z=CtH|MV{j^ik~Au{|o z?E8UCd>1zm%dgkIj( zDP_*TUeZ9smvb;O!RNl)^vQb=OB}$<)eC!AP_N69KZ%GG zm>7Szh#1txXu%QA|K^EDk9&5;Jh$*2HmHcB`STV!+&YbBbJ~(HbsE|i{vTga+TIMa zImbTQQWz&V{-Lg5WL07PNw_BDK;+@Y9sJI9>6U}9Nn1jTO5yizHd**r5+0Pbegkpp zA~h&b@}5^%%Br=}&nrR!4CM+lQe&p=&iD2pN1Bw^x>o!jueP+odP{Fb(?f4HT@|U!h3alxO|8+vRfl6BSOZTVv~Jd znccGBJRhgk+ZuqAu^?5|D*V@S0>Hhleqo}&&op>XReJFB?zh@2Pd|vOJ}@W4-dvlU z5vCUXAqE$6dBR;9YpZZk1n_-BLINC0h1|;|MNR%P;Z`BwI9` z<+pbGh!8_~y*aux&8+Pk2*zyZ@wRcb%Xc7qhO#X)%7muQy?*{K6s4?rL{?IQ1VBoY z=D>pz($0Pco|_jJj&aq#GsT+$vGr*jO?WmEbaI?ne4R}qZ3?=fR>Msg22%jVhK#+# z`ud!uZrm>mH#Dp)4wr~J3P31%37rSx4b5+256kPGwhJuBZ=rb@0IXjM_uoN_h)ncf zkLeKw%BSQKIc)7^_KzvEUgJ+pHyL+imGmzOJHyLMVZ*wllq?ZX<#m*FlUpZK-Z>i| z3=W7XyW&zZ1WiIB-YeYjRFL`p#ijn`xP&MHm>P;`BBXE(TID%Sa(!D$a>d=H;TD-L z3o?K1j^?0lhlB+b#GZ|#n!K11@2i&v;KO0j^$Y#WwUE`g1QE9^ty6`w$TW(=GG_c~ z(VkDVT>G(*zVx|_f`TY|YsY+v;BUjGLulE8vKvH-J0~S2cHc5))b5yXzXDj>q8Aii zdWOHv3zK{oU@1A;4)GHDThlLeIPot*Q6J6Kt1Cw2iubm?NKiqZKg_mK>~I!q_$bU& zmJatdSdxzd0IYD^7FjT)I{>22GvnHj!!?T_oLI?2f$MmmAR=Y>pU0eFu(dJVI z^FxU=qq0N6$xX)&I2`IS&F~dCY&=+`IAQ!Gf+d|n(Z3XDzUwPIbL&Qv7ZZduuu~iJ zh|7r)vrKdb{!*(uK#wmSIo>Cg0)pAN~xw@Z6K@R=(pPi-oUGGw7;k_SxHFj zaaK^sf}1@Y0ws~XhzqL+m}~~Q=i1=bjuynuvB{v8pIQychV+Rfd(@{AgY`xo%g0A4 z?zokCqLWNeln41i^)dhJ{AE9zSp4#|aLM4`p{kYJEuU4eJPYKm!M z-Y)cPko1qcrPXl{UNtt4(lcmG3had#2Iq=-(|$mUJT`i1m!tt9)~c5-jfboegi`Q4$cQ6MlOr)qF9yyo|I#@Q`{%;muBY1(! z_M={eNu3gd5jZ&8y@R-lrrFYh+Jhk63R#6q=cXBBaZ;0QQSGJ^&zk0VUL|f!b;u5mrK} zibDy34B@58<2{P1;Gf5p94NHQeG${%8+_Ara6~dGl99xzBoTshs9=MFDkI!8{S%tq zGcrr@q7o8-p!YG&3)XKI&07{#dy>t;gsee3@q*zUZ^}+VV7NA_xQV!gL<6y!@`8GL zSUibVkC@y|rT!omy@MwLTm%y|^JYOE-KSbiniL&=Ya4ntkBR=nUY6!8*T9Ugb7a31 zHB&@wtWr8&*`KkgfUscUFzNmN-G$-d=M<1qM6Du0zp(N&E6xb>)P7S@5-M5bx8-4V zo0GSf#EN`Tpj&7O(;fO|L;6QiB#6mh-?s)23c{?iET=agF|x^1*YM1174wXnSUyq> zc}AkqZxfe)_*yq>DB(TyZB|@m#Ix>})mmj^0GmZurC&G{zi>Q%?neHOy@*@PPDQ6+ zr4pPo4Nq*Q=8jpg^*}8<8+u|@q?kORg9OUF8QW^W+jg^;`0OM&_t~SVVK6eU9P-tz zT;T={8QFlS%p$NlOTeasdtDtlA-AZ`b6EBOk#~+|c=f_d!uZ!q*UP4c(s}EHrI5rV zS@9{QcI}Dh!i&Y@c6+^}iRI2=^{;Q)snIgPJRL-NuSbV61^KUJ z_N;HAs*=bOvdXz8ml>Tb8SI{^8@)sr*N{`op5fJqD!Xj^xgVy~H{s#peDkv9<2wKZ z*ys+$g#+I_EQS(T1skqKPH?1jp|lCP)qUCL08WTiQ|DqPzG=S|9{G`J+gN$EkPYV* zcScI*fjq~%Jn*=lO1ErcN5}hkwyAItun%1>QDVYAz08`iFfMu+hn@&NlptGlSsyG3 z6=X?vqet$RwR+nP`!8bJm?!p7A9KWx>mAZEF$jTnEX=XWD&jzW+`{fGsVWb#NHIY$ ze?nYA+%?OZT6=9Qi6|b&!Gc)phgtX5s4QOuN2N^+vFlgmcd0a&CD~4+i)Vp6Yh{xLiimk>b+1cjb1oh;jMB#mT6}_A`SBHof z&MLn>J>0pNMWhZUH=`Mx6Y0|cD7G1L9dv|L-yBV(q?7asDXCw&LIPa6^qMbNLRv2@ zu*sG|qDHI8GwZGXP%Wc5^yzAmgFXW3Zzv1uZzyX39vK?qabKrvQ1CuZe^GpjRzLy$ z`zC~H%zd{i{MB`8yd4~$^QnpkxDs#Vj~ zkzhtfH3lJ!6^AwGMfGL21FwT~DUwY3697o#V~#uq7hjt?*Q?tZ%-OeA0e%P}bWY~| zJ|@%5xA?VI%}8?5Zsw|CW6RwHT1k;GqP}mfV?|sJLb)BY-kjJ6D0yvtRz>m0V&JmJ z@Dpd8ILbUTgHL-^ip1y$IoqJ$d_j&#Z>UGglFl!26q;tV#+iKK{G1Z1GP4412Dkuu z&W#0Z%?sFE#P`aei)R4dd0{=dquW(IhV@}*h?TV z7`4Y&8m~NV{oYXx4vzP<_C;CrpRKPQE{(bXU+uroAo>HISVo+ ztq09FYR*&(^X+_pwW;@dt(4~4?@)aanRrZqnScNynK4Nj)z9~ z*(HYy_G)bh!=w(mk?D9a$nZhXO^XWnI+6m`++I$d!o+%gKl#3*S5JHUFerrK17w8s z=}66BqZa9A&!cjN&}%vjTME^jTp66*xor9m^pa+X2tW63#je6fZ#3+vgQo@j;kB-bkW50(Cj-NrvNlL>T_kk1Ng%sqUjP|J7MXugmK2GHa2|b2T zUVxk6h&>bEeI2wWtXK*IfIVcmH!$)Yox5jQW)17p-9MEUtSCyJ35OW96qVt6? z(F&1Q6kQKAp;G{s#ARiO7D|xpw0B;vC;bHCXn!a>C)ZFp(Aspwg{-DXI{QnO>{F>~ zVJ(SHHWyhOQK)@q{5{#E@4WVep6{W>{>F(3V`S+A$T~OuRg|#lP`Hn^=zdsB(-=7+ zSM+BCeF({b*!B$j{_BHm1x5gp*4N5{L{#~$sy*ZC2s$4ujxU%HY3*0Ry{4?WFP#Aq zI??=?&}5VpCC9eC7t_FvZ`TY`A$nAh#KyDhsf%I4M5bi{9eIZSGC!D|j~@-BC~3rV zAA%ih*E$6)HHi?qLt^!bnbtKF^NOjrVOH4PdJ1mU*S#yXh|%EVb4LsIJDkoTg_C4|zZTy%%NhmD}gQ36*$zdkJW$t9xdL#(OGsx^>jcaA*7H zaxc^L1^J|Ok)reb-JvhhxYapg__Xi&vl>qR1|!(6MBTCb)IUIhYHt&4*=mG1V_Ezz z@wFilLnHJZ=oVWI6x(L|*D)`M#cD$ZS#lrb+{5NY%op7; zA^IX_O<8{7eI@uH?*qi*p>!({S!r2A6^7zG(Gb^)7xLCeoDaC!#m2>?5pUEZi(Fjq zYjj`a_tixFa9wwioM=1SDNQxW^qbVl@q#e2K&v2oQ(<_7#7{( zwRVUZ1NbG>+Bnb~>eVkcc4z*}A17R@9zd<&??tPub%D`39;rBmJbv@r=>E_0!tm>< z+uog4Zk12f-BZ|1sIcQ{YhlIY{4|l?XI{kfp>jG7!Zze2UVE^C6X6K!Y^KLo8A4Xt80H9BpD|QfyskhgJYCSK zs2Jq`WIo=wcuT(izml6gH9z!Lq@HfNy@PkU>R->#5*qlb?g)&zW7-qdhJPzDM~c}g zfUWa*DJ5<6qZu$O-Vc~tXTA8(v1cZ>3ZNB+ghfU4o--I=NBjrVXHLd|bY&`$W)^_+x zyM%;$POtelPl)p zN?=X(@ckb!PxAtzh?FpE=wBhVN+}4fc+#>;29|^C&wFpEjH& ztbv`$*?`eGF$4)hwZ@yT9|!j_zXHN6mx1t2{D>G8jLgw9tPEC;1+$t zAyByi_&f_?!kpdB2|x3B+ro1rt6YxvBTLls7jz~L4Pi_Uzz-R>EV0h*;A+>^$6qOH zyy%203X28~6zo~}H2Lk@Doz{5*hxTbcqdDhgpTgIn%XjVqj5jV0^s_3Y(VaoHZh>U~yGF0yT; z{yDfqYEpu1_^@b2Wn6$w$6!##U`2*He=r=U{{+tFJ15t1#PZ|mcl&e%Z4JnQ_}D4` z{hJg38LBGH?|p}mrN%>wA6C9h*+z&{2Kqlg<0XSjk@W1>XV+RSUZrnR*i0EshldrY zakjL4&}zSxq{YIhX_B-NKTd3yj-}Pd;(zQ4hN{%>Hm5%p(6)!XcaL`^t!wX{r7L>jgermhCo&y_U7p<+tCyY%E-V^n9l`x6b7bk?r)*USO? zwMoTZSWtcqSTJ$sl?X=x*J>%R&g5XQyXQG(g$8%@xEk#+VzO;pTi5|VVl`u(QQc9k z6AhJQuVqEvj19TTsD75GE7k}khMmOTo>A=S5mh_cDVfRfcf8beyIEiLx?u+1-X2TJ z?ar8Lh^HM@h_V*X3XpK#E^=9P?3W8Zy#8j;TvW)mIH&8s!`xCi z(r&pq-@8Nq7T1eu4~?KD@VH>rE-oXXza0MsoSj&3@T#6U9a2IB`FA5G2|9X$!IzIz zB~9o6S{o`R#tPw4#LJac4>yk+Z`o$-0%;7fd#6fPjmes~sOG1eY!|zR^>9=Mu2)S? zk5Jt7W`~;l1E1KcB;3m9*u$*Nakwd~?OiftlMUt~6SXSp7aXq5wZ5B+i~>|R%KUnX zBQ!D%O>0g5@l8o7#E<*0s#>)N4yT|4cx`N6BI{0!opd%o5=N9Dm6Lxj$}nIMZJf>d zeBW!TS+yK!&x8obB}_(zhLDhx8r-)xAJRpH@9){SkIzbyBtXKkcf+!2T?PJK5-*&` z4ioDJ?0n#BuU2Agj4wi{r$vZNg2BaCm8lLN8 zYLFi7F=ur+HAT(j?^q0&WvD@;+YaH=vOnXVMU(TS&t5i2%&y;+Cqvv&8ebugP}lZJ z%d|P$Hf<)A#?eNU1^0LQ+K|Ry;FmUpQ82K3hw;Y>7@M*w*Aocgfpc%|ly+v-0G<^n z{GImCjFtVc?ZSL^?*i$ylY)|ll!`Ig)s;038V^$ZHfqEmG^Ehn+=70sT8OfWLp`E& zLgX!T#X@c(i=s%r0x0c#qAQ6ox$r8f`t$k?alfs$m{(P+2mGOluSTxN_GH`aqK>dI zq{(l>meqYj(2n>N;L1T}OM01=oj6=zR1Qs!DNL8Sca)gAy3HSoFgu{_5y-aL&VRYW zNKAO_{z5A_I|a<7S8^wakZ?e+cNYbeqwDOQPGTd%fsRgP>&=Xl%~KGmXURNehD#Cn z3C>d)=W3*Zxb4x<6drM=l$xP7zVkA5c}&jIkp7948;|--sFM0SDJ+I86vA%AIuEc} zM>V2p`48W;efw=A-D9R>YumFdn}8_00mf(2S!Ofy`{}t;>|itrALfl~r+g3Zy+4O( z?PIo{kS#yj(9b)#+}=cl4Yz_({5S1CA^1w1l;;1U`MsO9N3t{SEbHYRUPLWmRj@-c zoEDLi$PvXtJ=;3B7B-J6ceI4Ys(PoH*QiUlsT~_w4G=f+2Zuw77_uIXB1V_9ZRrYq z;<$0UPyLK#iMdCP9Y`%_+d&5j6L2K@^5x#gF|2mXo5cJB;PW?RVlzey)%nZodxwUjPI1P_ z^WeK~56}#Uff>_4x?`rmv-S7Xs4;_!3k!FlJZn0jxAtd)InuA`J;PHFT_-XYAgviU zZ$C8G860j1KyIl9Qa|3B63-qK>OIQZU9LHuI5}$TKTuyFY1{M7!q%NQkNN$F3xJXS zd3!-r@>L1vnQe8ChuYG2INXVYyZ)qdA64(r~^J!I+HZB2tcO_NF3X{7jc z#p{=7{V>d?SE%9xP~&ylhY#)oUrr!68NOMfy*u@KR7E$`NrbNMVtq<|y1-|htY_ya8h^%m@hu&}V`C$Flwaz}cQ z^oEbDHGSd~$tAK^g<)3Rl@;%pok05buNK#?MuSDl$Jae&Kt)CMXO#(b>A#!dfFd*< z(f>5!BthGMUj%x=tVQvU0QLQ^_B*r?N%KF~f$mMSnrZDD`ui+4E8ejId0xNlN~E&tDz zk!r-$5Ns7KJDF-PoJ0D!dYO2BkoLGD|1&hmE$VbA?65)0$Mo*);?0f_c(|?9aWly2TScki0)#YE72c zcou!&c2e&BKN8yi@+=Iq8x8YxetDH*|lZU@#j(3@vKRmt$Ji9ZOMs z6LxWNM+3wMrJ6?H5busG56$(_@cEjP=4#uV<la zd|e-UzHsi;#BcRr$3cL-wg*gLOjLRwV_^d$g+Yp`B|~;bF#)8L3Sad}w{3mo#;nP~ z(^sP^dBi;)LVgAZ6jTW3H99>)-Sw2mF#czvMOz4iwsM=CwLRWwS*_Lh9tm&=e)jje zG}+Z5Tkhg-nP7*DkBJY7g2&yezs|cH#B0BSb-!+gn2ux&KXiNXQ6^qob!&5q66jH3 zXKM*s&kA@ygn-Z8%Xbi4U?EmyNZ2J|&*GD?rWncV-+A8Oqakb}o&Frjc){3I|0QvG zl>X|xDq@+iaM>9$^o{3=wcF$Hv(?6DG@A5@hF50p$5JYe-%XvxW-Z@yu&?q{I}P!e zhK*t|&M`l_pUlP8jLCf7fotUBRNHEzKeJ;1*fNiQarY(8H+M3#Z+rUp&z5E|N_qnm9Dt4=)~6B0oa0)7hu{`keQrM}OT$%%*@&}{MN z`y<8VcH4vKPc3Fh4}KO@a<8tiCO%I@*-!0f4swR;vmzOfi^&`_tf50o1*v>i$$b`);FfIl~5B*xt#-5*mqA~wDR6tPgLLu#|8A_eXfUNZ7V zr61GcAOOdVI+=lZ1jF_3gn3uTcmm=3a|qaqhd*_2=~z%l@#24J<-icdcX+P+QUO|z zmpUI~J_p_J**;U7AD5VTI)EsJMcRDB;4%)kg21wzbMSx9MjV%!nl=xHxrNC|6No-T zQfoQlFEE!i9;nWg>hWPXR5&0oJ^+jw=7qPaJ46Klz&OV?51;tDC#b7&w)#FTV090L zl6$PNlc71iQR3|bu_{c#p_=fv^i7B!Dm8{knq#J#&WamwE!~t-u7by(uc-ruxrQgZ(i{?x8@hwZr1J{;Ee@MDxPpWHr5AMS9$X*LXfMQ z2!GyzI9}bU=vk|M!!l%(9cI$q=M$;MV;s(1twD#I91_%MilQb7ws0q|!r5+y`cg~xC<}lpTw{LfK->P3#S2atJ>qr|b1{sc@oLVm5Hw#|u zNXkfb^&E3SwGYlMhJ}jT$;*?9F4*!u5_y339&f#$vD>|m6bL49KquDaIuS>MWW=>Z zE8a;(e2rDVU#KBSmOSyr%Z${hWm=!~;{XEgx2TUjVl?G1kHj(}TVlhhz50NWpDrMx z(FBW)yP4OQIJhcKJH>dadcQ*o!faj%>lSEmLUml;9*T=k`gjQi zb6%XHt}ZSi^|P?C5s;%N+;vhDtXC5(;bN`8*5{mIv@@LZc;nBjS7yq8U9X(LVLE28 zyXZ*IC;`O3ws)FCwBRMsU(AuMHfu?2_?0(4-{WEEQDsR- z8V_&nru7b4ISfm2az)^emo_X-J>xB7dwLc0bea34H`teC^eC0{9ZlmtEHSm58Nobkr zU&Hdkf;#JqltGv{RTiI#EPc^NukiV~ANa>ee^C>?nb1v{HwT>Wy5ly~z5Prttck_z zPsS@{V{8y@P?&viZ}{#0$eKa|i#ZL2s1Nt)1d?d|=gMnm5#CS{?2%cAswsLMI8)>+ zhshaV!bffuelUHq5DGO5!C0akDNIf#OGD_4q(t^BBSK%!%lxBxZ*N}i7qIvt^_naw zmPf?`eGrhI)fimnzVVk!cK%41S~C)l(6;>Z~$$&_v3F7n4PpS|x1 zGF19BiC3yJH6K%6* zdbU}AjIh`#6jVH?k}!(OyKAxCzhxt$Kx1KvrK)!Nj?8q%Gcb{lFg%*kUEd~Kr8tKh)!D@xAU1lQfnPPMiOulxn8yv@dM z0$^>h+Ojj;d`?TMn6|BAk6z7MP-$eyo0!5^*|dp3ywtTz%Sa51l5Wemgj8ZqIM`ZHgY)pFZHfcVWGrcw^}9Z1-zvi2na>cFkHkIiMyQKy9&_ zKXpr0xrvQQ^y&wTo#?JUH3WV5D5P)mBZfbQ13-ZuLfU(WQlRA)73>n!y2 zO0O0O&b8n@>f?Rq5HuzW&y258MvAY~>^`-04Q}~ldY5igs}dptUwJNw7TH&!2G=Sf z*!dAnLsJq)lhhB$%Nx?9&@WY^pt{mCBPKZRvIEkXk&~GnHnNB%CV;9A4A1+)exC)J zY9-2eW{*Q8PNQ!x({_zZGT|99C)LiSd|OJIsqM-%`&S5kF zS)=E{gETh~TC=um@OkV*vQl*KJl30fPI))S&WI>lr`D<;QHIq?2|_8hrgDDQ(me~l zHbPI48U}04nQ;vsZ(YIq;uggP6Q;gaWZeHZ`_dk&)5dyB&k5tIe&WC;CL>eUESK1O z>T6U6Pp9vgglWTK)TpE?xYuHs{g`{14-TsIdT1{rc#QNUD*k{r?U=nSs$GIICsQd zAFLdgSa}#q%3KcOZeCmI1|?vfYSxBa?3VCO@7WwYf7_cDuMLk{?w*$`@hCCiUs#f3ZQuKIO}H$&9B3F#%%d#LP?j;qp>ov!Tx zYfDA|XuWz?N7e8$=vrq$C3wya$R*y81p?2nB6zjjOi6b>aj|9I3vK~k{Dd-7ZMIw! z=o388Xyk?NV9S-Hwhu^gY&W&Fckg~VK3aSaN%U$BF0xt^on=A2h;wA&d|BdT6oz`B z$hceZ)OZ|0^f;c9<@^2g_<9o`z+kW^iGrM5r;hiUcR)qVe%%BP{oXhY?7H?{SY&w2 zN0HMHeSop99VY#=U4ge9J5+5rLIYZ7KS#xH+(5N=4?KgP)A&eaKVu}rDyV{b;7+-s zspNV3M$Dy(vN;h)760rnh9Dlb5Iu*L;-O5x>)mK;*_on0(qi- z1d>gP7i>_HcL%C|@4{cgN*E=T4B{e@m4{QML4nHtLCuYy+!MAF*DnzPjN9+z`Gx+Q zIpFiO<+F8u-L~RPW9vlj*6EsOxr2V?QCj*$lDT~yyA86rc?=}f%5Z}*e`W4<{`!_$ ztutbLcJkv+W4Fh7ryQfECgM(0@_K>&9B4R2JeN1C^x%E4Q_Dz3k?<~mO%Ql%(uNRy z5gNkR@2Ts)M;U?RP;IP@-ZPrN_8w6cT(0w%WeWCnq2fP(jT%|1H&yN=AIIZAgF2kY z&G$;(m~Q9HdUFiE`Lm1rB9>B_YJYqh1yQAw+L3J4(++XktpEGp(?JHui>U$O56g~0 zY_H*MxQQYd=zmV^9kIQUy>Jtkme}-A<=L=tnLqpuEMhje#?d^)nEJ5L!L)CJyVIEH z3f?g#3d{0CY~IDirN3?7*j5C*ps%lfqmBMIIS{_mh6BlAZY((#mliK9FaI8&X5eqb zo`4|L^akvv4gK2!7H*4$0Gj@}Ak!3f4z8)`Wsic?zafe?#?T*p=I>AcN%nu^oBt2s z^0xEuTMGY&7-|9wNdIfXZj+B70viW$!f+Lv3AQ{po#bbtT*sRDV& zpnR^oiV|_Y(w-@+?#4IMgke34w0tk4A-v@&e1r%EIS-pWLLeQ#IH9uQL%Iu_nB#zG zOYISo^aM#%D{mCzR^Q2lMBVd+qadmW4a2h?J`R1*#Eb2F0cIrs?Ocl3SPWa9&58vJ z;rHl^UBq`D4D1gcN%^h?sWiX4(QP6|=90_y`Lkal#C-h2^@Gg#CXoa$cey!WMj`f> z;1zl%4|U~!Mjm~$%4ojA#;Ppam+APKaXXF=fZ45Z4;o|~@E}AAu(o&fQdm;dpQbrD zC-Fmd>KANy(sT2u;vgs;+$+(wA=tKdY7~T=*!{D#^-`vOo0F|VMM|%dZw2Kq$pX{j zL9mRO`CjeZnjVD9bmImPiZ3^N5r-pUh64O;%!!Q!SBGxMuN}BARd3Gusq!h;ZFwq$ zp)~{_@Ryv33-WW0t{SfN66n(hw$mt<6W&<961vVKt#-Y2g@#!2#b?8mt@kiq;C9rB zSRTNc_k))_?b?=is{@jd=k$u~f)^(J|G*XduWe$4jA`hMaiTZ;qIB4R_3fiKmvh0E za3BN{dLzU=L7}d_gXH1#?OwAJ<6ZlbjIq^KyR8T};D_C^%%Pez2YG%@J<%@_@-;!hr%OXQ_AaA zNB(A7Quh_I=f}M##TrzDw4I~A4IAdV3LlY7RBiJkzl7~#hCLUJ$m$E4RnWnkdIjZ)kKyAWnCQav4embX+MBEL&Tp(;3^VioWyBy-cGwxnSZ zr4_8re7gVT?rma`Y4~87OuyKW0E;hoIGQMbIGSeyp%fu?7pVd>JtAWUE1R|yU?$sR z8}fYMC;Ol7^w?W=1EywYt(lESq`G>WCMC6*mlKU%eN(ZWPpG8@`-3I@Q5UiGdiuU zxQ`;Fo~=>~fogiN3kCp*KKTPG?|9_yA75pP0>d-tt4hX|YFoJIn3 zep+_Q)IYLu3`T5ajMU2=+k-@wN-YLD-(@lpQ@&QYP`V&(Jm8`ZBgwu!0Lc)UhR)-!qVZ#d`XNm0>*VV# ziD$BB=GjxpMQ>0t68y|MB!YK3-8AX$5FN5{6?a%L!I$!PCmO?xBozR*pENFCx~z(b zEPC>{>7oqmt!>vg7l&L|N&f|5gMiUrZ1&%F)mts~)@Qgy7)s)t-!wM|eN!W(uD9Hz zfWt{m_uE<9EOdwD0j}-XDI*_Fus`;=gu3RDyqk!d630)M_LCEJ|HSeYG;V9fB5RN}L+u{XK!C9Pq8 zaO9Gj*kC(%pM_^ z4nnsZkeFi!2#Lp3WvLi>xi#Go*sRI^@RAm$d)jITuLC4_JcD)e0NFf8qvJ_rbq%rYMfM#6gc)rwnyu7S!^QLC&$f`@fC3U%E_ zou+syh>7RjnT+6U33YxDTo0{~F)&Mtq@^IKRu-qa<(ZvtZLvEhhzaK`im=)Tn24>H zwloxOJf&Le#v0DW|50!2gAvyKyquDRqwGnP((;v`TsNQRx2Ge)Z?C-HOa*WU6Z^|N z`ZD9m96QmWIInqfK=M9VCVg>oLW%2xB(`rG?$v=?0B_+P$@J})tZRJ56ODl{c-7ei zrzZVw@}smqlKdvf4QZe5%${l;Hv1VT#ZNn8<0EAJwPGeVQnFN``bxUa71;}Kq_8ypQmcJ8{V6#3z*@8L-qnE?XJJ)tMwyC*?b(qfstaci2w zn;>QI%gurc`22GiTWkoxzb^l6)alZIdqHaG>SuL*NVTeB&R;jlo;TM7&McC+yIT>{ z=M$1lmCf%15au!YRh~4{s|#ceXAT3U20%J>inbPOPEP3-6n>w&8YuZ&4oNOBk^Mf! z9Z@@=0$py@oF7#Z$}}O0p#w%b+zIaO#bbifsd{_#=CHx$mfmagQM>Fx8C}~~rculs z)HmmSHy9}cde3nHRwion0`xv*N52*8v-}=sjw>#)lxv3Pa#b`M&*03ncGsmBkAn~C zt=Hwjbx-X~M8|s&Rq;O`up5Ehn^PyAg$7-L4(1XBt7x~e_X)C6IeFWjT7ruK#*1%f zWt?syfZ&=PYLW4~9Oi(rB1kVI+XqgR({ygHIi1)cNe4s`t&_D>K6R_<>}?nf10h40 z?kDK09%s;<#blCy;G&NI;hG*cFDN%?#gVrc-N=fI#iUFVBHRhQ!IKr>|M3u;RsD!5 zQ;%Xey1Cw0_i*WVlo+_*UM`(RV`dm%-}DFt@;U8!%|gBj&wh85gi9=s4 z6{e7va7NRIejQsti5MDJ+nj2wu3Yz8R|G6B4Twp%?(midUaE5Ok(#gIqbNJBbE+Zq zL5Y$TXShT^Y@@_|aT0IN2oW6~9wljw zwntfB;k`{8x82ph(MITa#rx!2W~fFKSaRQ|c6wPSr>+%9$(N~$DkL)e;_k$bU40Y7 z6H)n4NZTq!Q3`cd>xFE`A4he$&L!eF@*2Ql=W;|MWk&W!Q zRPfREV6N|CnGznXpU=$I92rz4VK()4Ah|MSX9suQp(!pZ8W3(=6hgJlLgr0%lpxS%MSnYDJ{=;1kY92qBBJuSqn%36J*Z$-``vq1{U0=-o3ZED(`%Ilet=KiIIN z_|bFZcdSx!+w?%kCvO|8Kk{{WFs(1;$AN~~Y0qI8wSxs>YH^2JMYJ`OSl1k0E?cKB zY{*yrxe=v^3Hdp(Bm*jXwcgks$(rWP5MiihUj_yM^cg}_?Xnx%s`3k5PJ7$uh$gl? z_TgmdpyD`tTt@kYq)$U>__=7i4&thF7fAn)Km$)ls{RGdGYm=3G)nNLs?Z+Bn5PP0 z;f#A|E^Z(StJxWAhg&{$`d|Iy;TKJJ84ZO`Jk=mp;*3bp1O%@OYSlg&Y zJ+hUm1NqOuV&O`|Eh_wu1>olKINk-a2eJ9v#<4cFh0Ms`ZfG$YtaaBI_$Q35t=BIN zmNDGw=iaWBL|p(}EG228!~qvMqT$KBj_eN-!Sl0P_in8XE?iD9(525LiPVQhLqEY& zbKsRI33`3fZPB%~(W?Vj4;4;d7L>RkR4x#(m7_=6-LG9;+r@nAK#bCR`A0Az3+|3B zTH=)Z%9*E!;qsuM!Bm2LwogokmnA({>q`HzaogD7v6-OT7PiC%>8>#$b!_sFh@ELe zLC>u*k1*Kc93KwvOXO2&N$LT+uqL__gdfB@Ls1fXK9mLf`Iff5fUCuJ@9EyQ0*NJ!Pa(^=dqOP@NuPnGTWF$Np*TclbP8QOejkZd&2RK zETwz%Vq$#~DZeW!0`UeN8_oZwa4A&JIS=#66Y48Z@hh&OE9EU;Tn3(`==$|6-Ug@> z(&W*ZIL#xS8z`_3hH@;5=!4N$*PJtsL>V01n9AL9=vxbX8YO{xb@es}%c3o+iKDSQ zTdq3SSd49UL~9I`O;jVEH`ZwP2Xr4xPLY7-Mpg8!DQt$8!e8>zu2+UEMDc;6+6Rug zL7u6rWOW`Sw>VK$b4YTU7c|XIq-PTp;`3jikU6PPcjsiKf|AjSnH zK{(`WXp`2i%U4fNm>f~Vwe#!i5+%e56;ku>sYY}D*x@^io@N?g_hI(X1kd5q*a?1S zQx@4L9ZrtmI?&+FR1yNoaZun@BP0RBo|ZY8RXwJET`I|}u=&~^*NfNF1u( zvDeH5N1$FL5lRMHB|Fuhc#ejW3A$_^3TUx%6DG zy)i}NOtb@jvAqgsN<{@dym;-0mowngd$}R&FA<&xTITNV#E1nPB7WD<)Xd4b;Z}ck zXxVG(uJu?{UxE3+ci7y~HiA1p*L{#Rc?@X&hQ5RRX{8F%ssic57SemGu9<+@>s zGBU5PJS_KK0p1KNJukgn_9kNUd5^ucUN#jy?3*jYq=5Iq-a9$wgpAdfb1z+^R>8e$ zLkqVeu7I7Z>EP758Sg&Q=L1M~IV*w=$krgCu1;uG5I5U_YwqQ3v)+Mh?)RUsy@qs| z#YH#mk3b~YH$75StQY6k}T(>Pjj;I_{BxdAB1i41}`Z=-v$nKqH^^Q+)!lZfgu?pt| zR2$zy_P;GH4uQ|&JwfASc8#%;6QNiU=_6f_7v|=E>KdS)K>r#rj6({JJlj--Jvupq zzd^Wo@S3doJF)4S=#2ExClj!=KFc)dxb+lDcN1Q|$I<&mkF0Pwc}SI+Gh-0IdFj;{ z=RR9%bWzI^j=|A+;^1LhYPC2k`*JV6{}<-jF4A>n+12dUBcDa5B;(7Z5B^lpp1}r> zQgu0%pT!hx%Qu7*v(z`YNzK3k4npHcL#lGzE7KZ-z(-S)Bi$xG6VJ9`nc!zYUW5wfpbK$<9s>{o9k>Pki zqjU{?32ernIq@M50uE#D3Txa4bLmY5dKHDY$!XR=Bo5o>4w4(~2w&HrQl?f(U>J|o zAbz(?b>!}$84}@DP2B*pxe82W5bvt>(hwh0^S%a4@Mc;ih3J!_Mo9OYG`+JnTbI3E z%(H#hz8_I0~{%co248=h!W z=RMn9C+l{W`P&vt`Xka!+5jh}S>k6Sf%E6hiXVG6+<59LA9Kd$jL|Y6csV7$2V7;> zwP8~Z^qj#vxCB4n;>5T-et#BclKV^7jzNF_pIT09do0-4*yI*e4IyHv5caw^G)U7w zL^**eYhRpMcjE-%M8}+jj0JH9*3dz^__qJ>+PQQi2z}KwZZP)KHpGJ)5ErMQq};UY z(XCzx5q@72$afA_Gr0jXOFxPIbx#No9+$E~kFk=P$}Mb6&fgW(a{C)il85ccaDDtc zicNUiN$$7M{2@C3U!i&b&2}S~(UvPV!<_Y6r%rzJd35v`zCNb{LK}4#s>_ix24jn( zg8z6^LRSvpLi-aL1Sk(6;iSL2Q>L)C-AsOsLi768O@Lm#%7>Wm7Q@V(bY0cT$YZOy zgyGmV%IT_$@frLhE+A-}5wdlR8X;x9Mh6!)D+nq6#>d;Ithqbi-lwBuV6<2)SCG^X z@pM#Y*UV~cd#J+h4H3Rc@xjl{FY&uH#Mbx)!X%c+`P~7?cNyNK)cH4czVg;*973)V zB}}lX*1HfTSE@ykGHy6HVvhKZX4NbF)ALiaFDRW^ zbZ^$0EO84VC4bbbbozG|F7jE)yCrH4zht<3u`%)22Le*1(p;yKGIS4|U!?y5HplZV z>Hf8D>iPemd@(NiKf;p#6^BihxOeVmLx5If{&VK_d*o^MzK#&!5zGC`nr6v`y%SMU zokSjT5wsb~%qsI+ zIf9W_$7dh5{8uO`MoC58J`)9vK*@4`%}G&v!eV$wb(H6LQCrOwzd@|ZW@6U|LbOZ|%2{rF8Ov|2vye%Znd=`h)MJkxsxb%^{MYYAQjaS5HcHI2~ zqiy`nCq3$BLhG>3f^3huI&kV*I2!Mn^V%6GqrXNYWc)2CY6oA zr_Kg1^#rGE$)*D5VjcA*1^%sjq4$U1x9n%0gltRrSr)m{T3s-RR56L0eFO*-8umfA ztBaq+hcp}B#pr!%wJFCSvz7E4K3MS)X94eAO) zh_g!^y0a-FNou}{osMDQGQ`8$7#`X8e~{w;SJ40r>>o;N})xFIuVd-d&}nTvOy zamv)XT47ClfFAM0i@gcALvNCFq#5-NV8R;<-X%BKu+@^`iU2U1kxOv+6i6Q6^P!CH zxS5_FUw;)^^zl3rx^y!|HKw@II*WwYTHA#={*~M}*`WD&SxjvTZzHoy=-rIq*x$-eI&S7yLTg(>_RFl#0EGo6S^3*efegU+^nS~gVKxH zhxxV^QYVcR`EXf9H00yEe(A<~%D4qUso~AO0fvUtn}=Wgl>mljnF%7;irDrme9mDh zpgsWOmjEzWeQjrbr#ReasbBMs!Rz816$!c6$b#&A+mk|(8yMFA)tYkaVW|MsSJamf z(PO?laDHr=`0e4zEF?ZW2A#(3fZlj%w)zo-t#acz7#hyt zfO2I(o-v$;MR4;HvnS(>mdNY-6}4=~)EK_qtvUY2>$ZT^y<2}clxRJ2%`$r;W9ZQl z^zKoVhvPiLs#4GMv&3AZad0O1x zD!i6I+u9H%HInYOcDYuBM&v9rHaim3dN`pWh{U2|@C>1MwoX4>?=gQFOx?>)GK#VbAviy7vJe`8x%6gD~=gKeZnk7KmLe z$+6<@GoR|(h&mGTr|%mdbj8btj-L!&F#i~wxS*XloCbVOdAakaR^i})0s0^^Lo$lx z_pV8Jf{iT}TnUzP-D&Ku+t*@w0`YSQxhtNaa0#AjrsFI0$HYHme6oGS-K($V#C!v5 zYKo$TurIAQ@djczny?2^>c71;;yNEV9V@gznDp2n7vx6_+!Db|&ZDmq0i#D(0j`wD zj)8_cWkG3SLeMN))+_-EY1>C`%E);0Op@&B#PqDHN^I>BQ>QZqGF~fMOg9%iwuXly z=hoVSr!M?K%RsE1c__r>Eg-r#2q`bi_v*`^?_Ckrkv~=i-J;rP=gAJyGWOWM>5z-T zi2}vtS&JP($NrN*tiZm7+0R~9^m3q2e%mb}2~$QAApc0K1OJ+1!VEu>YZV&C12=C2 zv{@OYx1jw3BUx_A&dk(c+aS=OUwQ|rCLdW_?zZJ4M!GjC*S8UO!p~FsW-M8)4`3_b z)?PBlxW;bPI&I$E01&d)><{}Yds)4Moc4Gp;N+>qp*L4+Wo^ATKY)=hn>^f&Dk#>n zB>hDnGn1Id4l%Fy7ti_I)F>@g%w_h2HzMvloDho~-YK#5NHRPTAzZ1_KmvsZ#F?E= zg|cN)zQ#K-iv!*F0pdP!aA#!6eK;&?Tby#rz%(pY;b2KT!9J0q4J)vCX)MD(@IMaz zbB~XphXgVhY=^@&I=G<1hf#w%=H*l*c=tniL!4E8=6%8{+%Q2&pP)N46y}a@Q)iW+ z6QJcWkWCJGS5uNA=B}m)j`IZBf=tyaHE$IbAUNPF?fj)R(}imNP8ox$_-p#WTq=B| zTQ?NXnI-L1GKrnNOoiJ-wgziE*xpmb7Uf0vL+|c}g@-aO2M;bLk{6$Ngz)*hei5bn z=SZ$GWS5xK^0b%CRz5(~VH2k3i$FnP4& z?rhimu;Q@hxaQ{F@&ME1zwdnK?i}TxOzV5%3E?$=;=>`^2?x~l=*-A+lkD$TRxr~kCd$hxTQScJ7=gWbPxFq#g)bZ7!_PAGo;!`X- z&f?GXB!nONb!jEWs`OSU`r?D}tV<2dzwYNRLJlkcCr#jH=X)+_L^2Ywd|k|BAxrkg zWD}xAU6C@i`MHDKVM9 zXXL)0e|d207LS@SWOnY=5Xo;A!{^K}l%(oP){kGS_-2RO8aeC47q}%FcWM_C6ZgsP z3qEy9@MV9|Ld2lMmQ91$&_JL5tJca0{n~?JZO!2ZT`M9KE|TD#UEZM(%t&>yF&SWy zkJg%V>r?OXw+<75PF!Q6VQ&Yx*$YfXEiQ8IPwkYylx>Yz-cJRN=%JaJ_7GO;RHt;X z#8S$Z80$WF;5IdCo22w*Ji+h3fdg+2eW|IfU2{-1izP0YvON(JWlivv@>iN3U6>3* zs9uN&^R?CVQt#ZoShwRAAIj`pG~5c!6zp4g$Hh~oSe4J;bv(h7TVNP1BqL-UD%_6D?@zzPlH zx@NMmzB`hnM88{^N#9jgub@zuKIfE{HwJt;xF%Y(4L~oR1zjG{ZshB?JWM)4j>N$m zy0RQ)XhjTVV_qm#UXD2PEG`arj--A|U@+Q2-Hp}@RH=vzQV`7cmp(m6q-`~d8p8kHIBtE@zm}2vqk=tKd3!4uM^bKp4$SiMZPGH%E7{W9CHcuR^fn@G zr8}WZl;-)FNyYSgsHopvY7{yvlpnj+4NK7-6Zl#J)2$-#FfQ}_u&#CzSnA_(;|x zK)GJpdn$q71SR#gIFjbjnvJ-A*ge4~I;sv}M){@l4$gJ5Lm+H1S^8Rk5VP-&_&_fQ5y{ z&E0bUv|0aPOw~Y>iS6AOdoXKnaX&_!)=Wx;zWRlQj%G{c#Q*`^=HGIoL=zbsgL_*+ zmWlAM0@bIkw*yi(KaK-sFXF)X>jHz4V`q8!W5Si#%3;Jqp0(TN*-6+MfvD96ox&o< z&6W6aiz#N@jn=r$V~*o%KM;BaqBsC!Mh4s5Ozn-5Q4)q^0Xdr0#Bg0jxeJZcm@ITsQd3Y%s4uON&^)hxCvAslgao7ek{{!0PSR32!Ym9kVRn zP*N~3MolZMo(|DsB%^C^hYdf`5_sHKr`}hj< z^pt;jijL=ritS}fPTK1%>qCHjWdBaG-AerZF4ExbE~626_;Xb(+2Y2|(b(!nb+S>47U$xNJ4ZKH{UmF4fN5?@e(sZA>_0Uz`>?J-ad~vnCIr#Zp=hu}AX@!=( zgdr>60RI|{&q#S>sR&jCf-!}vv=c>BX;$Xl4i~K9_M*(L5{&LgOj+9i!xlt6+?(@@ zRKwR&sFk2IWi}Eh|Br^0i3t%uD}IG+>{9XP1nXxw(A}WvG2T*4A8aAhX zm6Q+qwLSP)PDaau+RgsU9~t%k9+}f5G6}!bfy^tkLRtq3+zOW&n+huQFOY@BPwuRp zJ*x}M{wQir*r_GK{P;bsr6Ia2CNP4*;=N-4eon1loFl=!T~c#ZKw}Q8jarjZpAx&` z_r@%ul{0D`pP|?Q*oyoHaiyO*ZBYp%s0TGo>GN2y3UUbTcTALXdMtc4A9PNrcaKb6 z=x#1WdUfUPL|H9Q`F8WzOKCPr0U?=vgO z5&~1Gft57}NK1nA;-=N~-2d9+0veo=q%oFL#^Nhwu&~lxw~}J!PFlBPr0@;5G=BR3 zdKHysF*!|;V*P=lKe>FY+G6{Qlo}_zd92LS0NeD@+k+{bN(T=(%YvKpU64|mLPDic zb}K-qOzOw!qjoO2*ff;85)MgikkZp4HM#FQx$ch1Z-Wn+nK@g7wB&BlBFK7Aean%0 zy)i@uh=cn%YP|Cz}5P;4*t? zu&m`o8=0fvuf&}NWwI@;=3ac{#N5TMHtXY7!q(39xWxYqQ!4*oQ&>SJ?za@y2l~d^ zGkUguYn{=9>hpQ9oA9o;N<%~%FZB9}HL5;JS7ubh>%3cov39Bd2oybFGb28@NUE0) zj6^Tpofl_<`*{Qxlog$p@a0n*ad9)C_M;nmIpdc38J^M3=-xpAV#BggblP-B6c?&Z zVN(R=YUMBqXP{`JvE2e;cl_}?m(4G$#jkRjUXse0cSbjWvN9hnO?z=!EAotE3|Yqy z4^2ZH`(i2>z1bo^`7d7;mb^I8N~@(^HrLtq%st%X_-hpRn9%Gz$!e5nF(Ff@KEiDKW%5aK!0_r95kDuQ zIL`@DmNPoV?v0$L56g6mm)kJ%KxaDu zgORF_rcd3{aoa3@;IC~)y>&6KY?ikwj2LDgvkVjYN1T>Xq)XeD)H2FUv9Pcx9;F-| zufGZ4DJ)+qvbiaCLlmXD?_|5y*^eD$b;Jp;8ybX`Pno{|v!B>{$5J%xYqlh`TDJ_Y zW<`DZr{yh7lAq;4g7m@L*NrAAPJEFbq#;Tf2$d2o4%Cd ze-wN9=NeRcaYzozfBoX3lN`(o^~Wz7vT|7R0wnwySh1zzNh3y^Anq(Ntju!c^08oD zyf4K0znihuj{Z+iY*8!KO0jkU9n20bCtd{VY9YN_D#J#xmYl4U3IoGpdtJSf!tZ0U zQ0kq-V1v7bxzR+rBgn}y)hnVB)=Lu{`IhzgfA{Q^uZk!P^3<>LuR=?}6HMTOmzy!j zfzn68OV;=-WHA=~Q*h+kQk}c%1^4XB;hBqGw*D{jM*R{cx}31LAn=po-0TF&8?U z_ScAPrk*}$Ae0q-Xo^}!V+;@*?wdY)CYJQD1~rcrO`N%S%H)@+^d@znXx-nk)zCm{ z6p%gUS4HS=mE&%CZ{gR??t5A{&wWk(z{K#?@(rpZg>yjm2dt?6oZh|exz&vGYUNcX zq8Q*pk-aBVWVQk8nY;HV&>L!Ts&PHy8V-%^?aq~Bx?7C)mBT}Z8&~G`t}Yk>NoGqZR`8&+z9=r zILhq@l#506JoeSS6ZB2OvG`9;30=KoGV-Ji_NINl3M?zk2=(=rx7?+H3hp;3j#$o8 zML>Vw32W%bx7zM}G&1moB&elY)@P*h!}FR0?5D07a{#ysZux;!`L09cwZ5y#%i~|I z0*Dbv#OW!TOduuGhZ)4pARJ2WBy*X6^^zr5+y++klmcfobvUU-F>ROoIbUs161DnP zSbz)$>y~?#UobT$W~=3K*49Ilx;Bgl9{`NXyB_V`rS(XnM5JQnU5XqDnVePZ9`J0Q z_bkgt6|YiUl&LgIAUc-oPY< zt2_){&(}R=)XVlh%rhtg5#x9vuHKSaM(e|4!$uY2=Fb-tFD4R#;J z{F!+7e8-dM03|8(g!9Q3IeS@%xV!OAE@`AGK(6iF&8doIjy z+6g4c7;mngmrA%VlIuMXs!0igz93AwZDMN8&u)p%PFrex&t-GpQrq3l+mPVQf>&>_ zu@hQy%FO10`$f{nbYf^>7P>_7*YeaeS#iKv-f_z6)qDMgD*|$Y{IfyRwX<14I z^qNk2?$Uu3X9E)^RXYSKEzwMb2R(ihRW zspRSngxx;W^V3V~DLwp7a&zU&*6(D`=bvE7X2h-Ja8^B;F7#C2#9{l1;7r*~nJiz6 zW-!g!MA2?EAMLKMv?eDCnFi|GyXbAvhK*%zbr-p;RldR#Z1dOwShSbuxlC?IQQzRoOPq{eK8~s0U$$#r|F4#ZzyuOXU z@7SnAoAxWn6kbMLcbDtsox{UT@fm!#Zq?)zyjEze@Z!8UmTGHS5#hQ5 z*~5Y4v@ZSp9RpSUnbDaO|+bS)#AmZr13-wS1RA2QI8k$P!uoON1wgoOiRF zM1y|UU#Y+M!Ij^i9b0Ymhka*DQl+aA?bs2Ly9s+#ID8?}O|>>tu>_u5noG+iGKV_` zn_Vi;`SGjKT7nLmx>I_cV@x)@`W!!fT`2!=&50ks`M=W?*Y-CVmlge%lXLtUI~=%i zF*C6V`1~_oVPwknLwBJ3&Iw=LsL6OOH^^lU_m|riC#2aa`xNlS0=b46+fPd&?X>jH z`-#S+u^#J)@>Cl?FG7pPB07oTIlH5*g|sP7PxL#(!w~`H9MZttn_CA3O!9=s_?H~KVR0q;BAKI5 zRBqN^wLSNzlH~5tacqY?=Qp~e4@mDmf+>Y0`);&iQ)X^m#4dJ`i|D@%s9z{Q=HE#q z>B_V{zzdd5HuZ@i!e=bVew~Bfcpg37uP@zjVzTr?e$)nS)Dd~rdhzNzD_%I3+*T(4 zl8*n5)ROvJJ6lHQN`Jl9bYlO93=(pA9GSg;lz@I5eDIX37G+(`)2T_sx6gEZ%wD9noNqs z#j%A)u2o&kfY{QCZZH}zVx9-7ZI?ak3c_Qz$(V$~6-Oi;zZ35sdt6W@p1X*`jGbBu z*8_}3oRyg;(6cHx*^TuMA~K`Dcxe$R747$@4=ip@xI8BE*p|R{n?g7PS-^gF6MnS` zEM?q~e?3zFW`Eo7pS0-j= zRL(A=j^)j4$%^c)?FMx+C(m=P55iE2bY&6mcNw*Z0Hl!@!GPkXCJFqWYWngs$==hR zvihw{RErgW@YXPIf7Qo==MME2&lYoOo9=guS(>H5yod9;wM93I%2}huX;4GDM5aDl z>`&?6s&3G#G$XJ+5G1%e1c%`65CXwn zg1ZOz!Y#NZIKhHD1b26LcXuf&P&lu4viH8JQ6W4W%o>ei!~!BcEIv*V@W(~4`nCoFO(f!LN|U};uUionOn=@PbiF#B@!WCQmrq9(lhG!;&@z zVW)36L4X_dXL2k0HyI7d{`Ay14O@k6CO7orTHtQvDeUJJuYbAIKs3 zaAyJ5*1i`)4x7zfU0_mPhc#ihv}h%|S;ZkZZC?M5wb+0xHv^=WQ2A{O)hlV$(xSOs zaV~}!QylzF&C~hhjDegmm)H+1C(vt+)`7qu=3a2>xbFpLV-~=|DR}%ZTG$iHgyG?yR?fPBTL0w$Ja5==p@@6Fa%qt5C?+w0ZMy zj;Oz80(4PnXQXH*P*5AH*?wc>Gz$?Y+=Ms=1lXN%q{<4Jwnil#-k0|^@T$o{zGa~iWn&7=gmPBo9X2*V8%=bt9Je+TouYpx@yQw-sk)R2nuCToKZ zL*#j*_A5+9nh3b|qk z*+zv<^%-B2P{!j0+^ zZ>;L~zfL`guU|TwucWDw4w`qj8h;wYA1K+5Ot2Rg^8>vO1}H6_63A)urkT-89|lOg zbMF|aA0GFjps)b{%)eBQ=y*Z;q^-XF?d@}c$(M@9wAugIRC2yHR_%CzRL(g#fXw9> za6yZTxJC;r#q=xV)&k=gJxUkv_FIT;iQc38{37z)`7ta%oH=}4r#j@K$x2~6o4MXUuqWiJV^<}D zWBsm)@+vG{J}?s855jB}CQCiC0<7A3pFJ^(z(Ag0W48($Y>=^U!@?L<%ldYUFvICZ zPHtImPZ!4mTsM}+^Od5Y1{%EO=9l}tA1oq&Vo>hd=Qlg~Q>xnUZ|=*}jo{W?!8=P; zePCRa=%FW5hGAt^z2AGy&8(>i>^oTWr0)V)o)wl6740TIrufkvkxrP^KW&-aG;m+_ z6^s>)$ZCRfgL&oImRU}>ChU{+$rNoT*l}z;YL<9CNSLXm#QKESS5+jSe%^3#UpoYH zukAFv{bvO6_*YvVEtB&Ks5-vkp@heFSB3sl65n`z9l(C3${;Y-F5S?@em3sRCL zNp5448$u1F72a*bdgY+lX7`dgk_~~wKoBkMkNVneB!b21nn9=UkjCqMa8?2 zCU9fy?G^ky>A`I88HZe+qUPZ7Ym*^RN;n)viXQ6d^@GR$UJn2X_p0YLsW%fzudavO zyQ?3`_FFGr7pI*`B)G<5uUqRD_2|V&LeSka=02OLDU&k^8+3~|4xG`f?PMQ6zNYx* zMH&9`o)xF+T!ZMR_m$2%J=vhT^FNH1nDheYn>TMTeG8hK@8>N7H;997X0m`EBuOIo z<#)5UijkfB5jpjCdx1Tte4b6tZmy3MEh0i6hNq=>@uDcGXT>As^EX~sm?SR&=Lf`P z%-Ql;)0C~yt?aX_53uMS4ClSmEA3276=*2g)qnlWTISe0U2#p2FoD_wwXXxNN zN-0PF%lZez;GW)XM@DmwA#S2#JG_V-8R&oR8ei~#kbg&HwhRCM5vUr={%$pj#h6A& zB+JMxV_B~f)SX-ozOUK%a+o{{i?`ttk@NK!xCzYrY9rrm!;KX?fcP=z*4q}~BODdL zECq2D{sTq?f1CqTH@B0D%zqVyFckXRlztf95Wfo$vk_oKgb;@Sbcj-C>4I$Og1~I{ z--GW9I#@_La3glR?$l>T9YPur{{w7((^0Xif76NozI|Ka+y5uTrSr<*i*=C+#4q9` zCFXHVDfI0>mw`Y|iq4MpZ%h4kalJ6IaS*$}f5rvm8L8%eHtPGo{<5Ho9jq1$A4?l- zYK>`LlL`=2pu_Atu6u_L1;!uC$S=v*tcZ$C*c|cd2wq} zP1B;IeyOo@OgA|IF~3Qf7WK4&>2Zlsv9{jhpVebq_J8{p&ZH?Rds&YSh&@?ahcAAD zu^h1_6ZvyqVcC~s+NdAd9F~#g#7G8&#`oq2Yatw5LpZTBd9P3J=Q{S1BJ`{cMORyr zvjC_n0I|QOpn})i_mJ1Z9a+jBgEh;=Ud(J|vIf7CJ;nLm+rNzZy$oD%u-Fry_+7gT zvQ4qgX1{tZXpZ4qhdMhyot4KD}C9=;BRA3UGcIQ$Uw071|cq*#AQ>IVcdpkX*bNz#=?=}*Le3VwV)l+%Px8?4+o)qLI zYQJ;N9s7~IcTx#ExEsTx_SXA$8S4c~*Q3KhoYbOp{JMoR!gY}fm+5=omq$6>PeDH` z1CFQlyc=IAwsazvhh}j~@v#=WWM6zkxcj0o>e;JnvFo(DuCBXQO0uL3Sa0y}`nI@Z5d@K)ZRG@CrljcA@Wl88jb zJ>mZDqHR%!4cacDT>jfi4wv@jv)#4+7MC332;giptL=lX_oBDJn^_NlXBZ+m(aYVp z*ICg0<(Wk92un5KG`HJ*Yvyfs4B)<@b8piqWGH^PUTcGG9K$kM>P1jx=TaGclZ~2K z0^(j5HlcChfj-Q=*mfOyjBS&4S&hc`oLOmXIWqz7`*?j)?Z{e!NU1Q3Q}jO3&+T+| z9`d~M4X$j-H$fP*s9TqVDNHrtbY$qVP~FGgGPH>_627!x!!YagQI)P zKn}X`AV5VI0G|TY(Y>-BL)$m!j;T9jdK1Cd_)d5?6-~jQE$rZ$+xc!-lKAzgLDiQf zG&7@xsd1Fw$d4g8*1MYs{&vmiOd*=a^nA-gh;rV+b zAW_a-@P-bARCBo~-}@a6xJ)Ke*st8%jYBQRGTNE_!0YECKz7cj*a@Y2tchF6Xs&Ja zP8x#+rOPw{wxisWQwqYko&@XneVb_AlTCS=WF?kKna9ey?5-!RDU^pK*{ExHF-)hn zIWjqerX8r$CWDxCd7H9qTNI~=Vbsuel7)w-=_xNYw_P|%jX<(3O+^9Q$1U=03yI%u z7k{ba`Tr-|ocRE4{ogq8<^Ww9HsznZUF||A_cPSyPqvUOB-x#d=3Lhu&Bq3`;-A!X z9S!rpIDGE~6;^pay<}O4kiCETJJIGGqO*^fDJa-oM#Vwqn_um1m!L&2eQMcq(>{b@ zG8e^KQ|%IG{LU2vhRf~jNjVnYVQgK-=@P?k_%yKl9B*!#G;rra% zWxKsQTW)3-fmm*OxS9P1HWXH4Tz$aC_)#7&^-MP-e#O?LI874{n2TwCbvQyQ;Ef``6J6S+CIojU8_<+pl?)cF(#iiXC+P@r5Cps`#{XkW-f3 zo)EB2Ul5f)&$X}6nHSsnc7&nw`RuV$4EIqlO$S;!gZ9kdSay;YhIbz(A~&mD7GKPM zz^o-0!&!_`YC*b+@DKy5a6-pYF`SKBwa2JPm)CwL8VlE3BG7SZrE$fo88Xj5QT=he z_~0E+O-nm7xy)bW6S&2yb#&y@UYQqdZu2RnCM)agi5ZtVgO4cF(C!iHLimN7DG5Wc z+Kp>N2WK0NObuP-)O4?4s`fy!Rf%-qJ6G`Bi3Z5>iCSNP^za?kf6&o|{#6UmhVvoz zHU5==i$3=vBw9A}xmeB2J>o?QtdjWE9LClM{oTH5bQ%U&X^Zm^6hY$Eu@yf-`L|C- zq&hG7vD_jf1vAXJHjlXREABOSO*6H0R&tuHF*Xl|p4ZwNqwANj&UGwzmylz}(rj_U zhkuPXB!lm{nzmdAQ?O)&$0Z1dd@NnKOkf%&6E30p^b5hd;6LeTC@#^o;rqtN<%ue` zYb`v(+uN%|k?N=F7^6eWW`!$YtjAth)>}K8GC*Krskzeiwy5^~8D!&F{Nbi7GVtX7 zc7DLXU8p~2UGYxHT_cp5R3toRCY5NQB7md%H8g@J|(VHmjX$qaIlYO znwT3ymGn>Fkr%+1w>HmxsLA2*a0*+sqosB|i1#Q^$%o0Hp9vD=7LvJBV33axRcKZ) zNsWJLMgF9bzK0fiYZcesL3*wo*Q2!5GBPy4^alS&c8#U}S3V4)O1rvEcgfrH)wi*C zdac?fUq$2!_YxqV%`;>d+YHIe{c!XO&wkb|(c+LX1<&-G`QEjy+xJmIY7VhS(~#~C zl4^7{I2H5lXC2m#nn!toGu@bg6^N`rNU{3bjr1x@)hPlIlHmX|PpCkr70={3XP^)$dr?f8MFt%GE~QVn%>Xes7_o&S~rL z^7c39>LU;qXEUGxfA+jSq8=)5EMdn1pDEPY^a+NyZ$9I7l#emoj+>eTBeEenV(k{1 zbX)9tFw{H~c1KWXEAq|u?{Hn2itEvZAPh6d=6nGEB%D*LhKRf;9j=b*=vp0~5- z)abKs5kB9@6&!Ga_G%;>XU*TQ__p&31YPGkOJD7?@#SX1*puzIPC!8?7+lqu+8CIX z?lRpm_^Nv6m$1@qJi(A@Sn2u9bO%`6s7}?rZ|snKxR2mjJUQOz$oL96s zjge`O`52z6XPUR7OqgbA+dQx6Q#YjhNpvI9>z9vBl<;wLbyh`R_&{ZJq>{Cmh6?Y$ z?0VuWs;-BX21&iOfdN}WzlFN86-~7ocop9UKs7BDu?S-9Oe(L?e+Y-y>V5_{aKvO6mTW9{Vol|nNOeI2|%eSa4`se_bQJv?3{ItG2Wi!<6zi7 zG^KOc6J#S+0S5akVW!1cKY~{2uwv8hN=^h77H}%kL8ZmY=J_S34~*eRqHisCKqJbT zqv0kMN9h;1Z;ERre^j~(MUn1}NvkeBr6$${jNgjf^N;7%z&Y^~S>U>q~hBc61s+fzB_#PHIIgXcuFQ%nO zTvaN-0h4w)H_Dxe?pmf}r~09>Mdjvhy9bmU4UYVUfTP`)K-j7s zr=m$0lctE7XjSmkvfCN^kA3TWy|KPCr6yo;Dq*$~wrsW8dmw!Uwyr0`7-ANCG4koCc@#a~;@7kXeOhI3uCWhgXcR>;3tB&+f)#GIfDO4Jp$*zPqZ4G@c?N!5Xn1ePE9t<27X0O0JT zEiYQDw|{`AdKFCOy*TBb2DjJD>Q#C21mX`d>Rvr#d4IA2Iz;0xQIJh$d~^-L(%udNZ`xax>r`sMP$xfoK=O!C)|88hw>~QX#Z7 zSVE|TO??)KW3Sm&X=%#;qoIz=rpf5pIH7A^h#3`tBez8E%h7Pb!7x{`!;SrD)OjeV z&f}iORW6AQ-JB|v#mhU%G4cb|235n|Q{$1q?T2+i{qZCaU*>@E^i{-1b!~xJqH%)j zun(a*-_|8n{C-rN;9(z^*a{lhQd9DDgAZJO*7x)kI0UvIk*apeeSAAQ+KsP6$iy@H z>7-K8g&N4F2#E5W(%C3(IBHz|YLm@Dp6Q@_!+w6=uSv|PbuS*4wqp&7|CY&LLK>*w{vV|=TT?Ho7PJmoVj%98%NT2X#s;}viq2G{7Zfo`YRjI(? zd*-z?84fGfdpyFs&I$RJgQ;2&)wL*2XwQ#2dIe59asdI7lcs)syCSx4TAWF(`-G4C z#QT3Sw|4|MqDtvnyVRkUSHXyNoZHcIJ?3258q}6EP%NI{Sq;5I+uHgS0s&vnBPLfm z1%~e>Zu%7Ja**7q&d$bZa*5cR8$fiN;fDV48&{pAkM@l-JC#{ibELK>7LQcKUJV{r zY<~yXXRZb`UABD6G_Fy9y+T~m!1F8;)SeMYk^M~Fn*$2v#r%nwcXj!85loYL6zUY>3U-KNGNk7;K~__uS}?XNsCz+VW-vP_(*oH7Nyn@;RzYe|cTu|vk2)dUOF zdOaAyDHGiqw#pF};+DKdTTZaL+?IBsMQ}Z;Ts9~LL>J-;lPnSPxt%4GliBDt8dlMw z)vu%OVSQ$VXsuHgy#&LHL1K?;Jd2*=a;n&6LxgwSiItx*!QrIx-lMJ?P&NS{~(98S8C*5>#W;wE9i&HB2Ft+#qu;HU_g~EscN;ky-P(!lE{l*o>{qV z6h!vq6-~3V!}V0ja-DOw9Ket$(;k>8Ed7!e13b?H|Ag2DVEet`mDQH?Qi?vx4gBWfp$>901VGZet4Paa(G9pKf1ywwe7EF`bY;LdMn>^Mb6-DcgFx$qSHD zXf94K6{4hrS$R>bY!qJOqMgFGL}(ZP;b+fiq1Tx=K@{k$PBbp2@eZ`7|2^;Kx&3pb zD!b4qB_AQGUjBVtA~=>-ndrhRs}wtWjsb?z5xiKDc54|KulGvnECV=BQn00h;~mYN zxna@us1!yPwLtgK-4|NEc3dpG%2J=s+L3}|mNM5FR;*i6bv0f^bRRsuTEKmrhxLJ`3yK7En(5wy;yakbuN z1KZB4A$yNP?@jBLe-bzw`I-xqm6X0-a?H)mflV+UnGadI9_6W@D9$mZ10(I(OXp;a zo)M7623F2#u~D%i2dYxWs8($9n)T=+hJz!M&w;SKKl0e0fYAw2a(zbX;dexQ?%q6E zXF>x^!uD6|RR3m=HkQJDhwWfV7Q^_9N>ziDv(_Z4=XnYO1nEul^NqRF!UuM~P$+-b zX@zji$UDM=6h!(lZ4Z($D6Yirk#3o2FAE(IZu1YsK_K`1N(HcY;YbrcY>El{>WcvZ zc0H`f+HLyUZHT0v{}QlaubSotZvUl=9z*?=Lp&%4LUu*?=OVtK=cE;U+W0!l0BNRP7^|Xo zwSN*mAOv*V$E4ql^)E^NR|4;?(7+c;AN->spSC{~m6=xrDyvG z*Gg6YX8L}g@3|`20+SdjW5jFSc*apgLuE1qm%tmE7z!s|TKX1|+8Hjkl0a;r-L@4_ zkoa?`>*tnRYd}j16#Qgs`m+1w`TW0K_}5Xv#SgrQsM?(3KPU&Utt_!#_ibze366M~ z2uY$3?up*U+t1zS;p^hqX)g20aB%f)e-MR zBOE7WYrxK_V9KvNH7%N<# zkQiOp>X-wAjmANyGeDVe)m2KSidTI(8F5i9I3l|3aq+(f_y+`_VPkCk<~tASje`#6 z)9>&V4}4cQC#Q{NSXbPx)bU~oN%}u-b*%D=H>3N)QZw=jX>vL1CzoA(!kckvNf%yW z?X+JzbH_CNFhr++Nb!3p3IrRVa+ut3n%m#L8VO9MTkFUYG8^ly?q~A>Fu*?pQe-w> zCe}0HC0*C=p8c|B);>$O71hDSy=PAu1H4*ctXe`bCn18whdbdysi}=Lkx#NtwDH9{ z9R_QD=jFxCt{3v3?F1E0d));)fY6I@Hmvn*-R5ivh+i~ewVUVGjz2XtPuxAd zT7=F^>ZKv~(^r4YK6lOp`P9#BmlkF@^JgOX!*mu`S_!xT0R;)cx0}Uhv$c!< zK@Nh^J}BVkf2C`r{B(Pclp^~fO0jc_xfbcjU zzZwAbUB7cHA$Y5%`wKg_Mt2&-%*4;n@3_~fU@&qp zU=eJIsJG`c^1pOz;KHpTv$hzJprmt~F4VQQbG~bD$F}sieX-1~W_v=*2SreF4|md8=Tbgb+|*m9DN^S27)P50Tw#1aA*50nHeowj z^O(1r96yr3)R07@b1@8piO>ao$|zaYw(m&j9I-S`i!8@6#~1{>W!Q zeqPO)pt?XMXIL2$`fqg}xumb3Kgc~VT;eJ#pHi>91}2$*kfvR-!zyF#lH$(o*HAvZ zR^cpzn(#<77m(>^+u46N9C0-`GGfuYsMF|}A}{MqR2=_sS6iHNgk*0bSA|x&plB6N zws2SVYQA`)*pAU~IZ&tg-DRAHrx55MD(I<&4;|(dJ0pYnjV#EKXzg(oZN8XL*q*`c z{xOY!V6aa^Q{rQQ>_fo6Dm{Z5{akIBtpefS(E!e~-sbBs=tyfc#p3BwAiHgD)5P`8 zoIW09M6xZ=AYvYl1|2f9NyD_g7NE} zF?J~louZ9v8o#Ha*DHbL*7`l^V6G%#R+LK0kBz=We!5t#tnUQ|Z@4PA8c$HqJuLb8 zJ|&nuaD%!9AQi`ERfNUQhX|#R0(mWziR$M=50R`xNs~OnrPh7hYTVWSl8g0l0fIbg zv#+1!4U8Eg!v+&g@!{?QpaR~L@|`oLE6^6JMF1$I>1HKZvH1_uME>rfX%3V5N3(l_ zUti7Qhz5J+2ns1*pLf!kGi3!?Jk+$_YCXJ%r=8BVyyR_aZ++F=jHRf|wp4{xt9#oC z^^IZt%uSWA8hWK3A%wD5fd5b~A7W0hYibdH0XD*?3616aDy2IeL{))4M&9(Dcz2&a zybo?i7r$&gBR51K`BW{cabD`LIX1{OC{swl^;xaolX)ET6vsimNUNkdn@ z{Tstnqyva1Khc|cyE9`Vx(fRld?5csr9mfvR6G7y`=oB%{I!N!Fz&Bkl zv|IOn#_G40Mg{XqJt8bLL9CUvHIe5^wiKRQ*s+L+ZqkSmx=%{0+}{ zOh>Xj(|{3u7kWuTYL-vB?O%Uj4C`8?B8Y)d!+U?u(W*wWZxb=8KpTEd zTbXWWbg|E*LD7iB7lHrD*kN~UjZ*@?Cr$z@G?%3k<-=ON*{|d4y^n)vus^H3W;JRvVFQQSbtZ=ial-Rgs|E}mmV&cikbfy(?hs7Yn_xJ`cEaXiQH2NAcW+i?ds zZ@(kyov^12Je$Rgsk;(2cvu5$Ef`?h@L!NLK#(3v=Eg1G&#);^9nM*itnyhSZ|`>h zZLmhrodA(KAs>_J50hAFk^hRH`E68_HMV#md7F*j^2vonv0TI+Cp|Y}FSe|=?i{aG zTXk?&eI!L+-=Ae50LOak^1Qrkqc(Y8p%a-E!WivusEKwa<~+@!eiEq(r?g`ARv*>n z4IN7S2q;4j6<+FG9t#c2#7YV1abY`Z&tgOTiIoNHe$khezoBcdcOX@*WFhBS>z@+R z@z^<2xHNvTv%LLYRUTzVv*c(G%l{KRagttH$}jOW&x3N!Z*mK0^tJ@~=t z3;|`1=x(MT=8G+S?!NHg@Ja-*d0Jd?{_?qb;qJ0Gl@^BRZWM5MFbY*x00wLy?IRg@ z8FSDI3C+gZZF^mj5H@oyw-|kYG4Z)^l!ULrBo?T+q%J8tDjr^!L)U2aagmOuyPJGhRab z^tJ6-qqUl6s-ej!$u!ezZ7hg(W6M$@gtukSQ#%A5L5)T~Awn!N)HnS=Q5w^}%L15aSFVIYnEOF?)mTKJ_k=k)+GB zkB+1-vM7!-vRdkhUEs|9BOym(yRaqdRh3Vj#qL?V4G%K_$%(DBkwT2s+V2~c*1^+O zs|}wqYS8AY>bd)h^(uj(BpAlGsg0My=lYz%%Y`C8UU#BaJ)tR9Z>0p=>g0_9@!BQG zIXp`?4%T`XxZ>wjMey5ZR|fO*%KQt)I(CYm=vS$Es!aPZae25eA1f@uwnKFNK8|b9 zb_RE@=es7)zkZdb9}XIy=D=$yZTB?_QkHEvIXUqzEiYF(8HuQIeTQ$?U##)!>>=tk>UBjT7AbkZ@ikpu8vHjvXoiXTXqUQ(^4f3 z!mA)$d)*f>qn12Gx2Fa}RzR)Xn-9of8&o0f{ z!66rW5k-p~HU+bd4_fV_dY~U#8Z3XUzfMajZ4jj~r*d}sEO6}Ose$is$McBd-NMTi zOj3;SQ-))W3#RI@_TtU`r_bNJ#h1VHO<|t&XdK(}cZ)7l7=1_e8(qH6+DYe4b>uU2 zr#W)Dr+YWrCsjYQjGY6+DoexW0pM8SIscJeo?*E5XlJoggOlztnf=aL_xrLWt`B^t zWyZQqSgiDIzQ~!B4}AD17psRJ=NUd7C%m#?%5gbIQ?phL7aoyu@fop)Ye-+m?zPSz zTb+WlqpXefzw3Kva!y%FR{9*~WwhD14Fz;JJ+8T*o6ml`Zmr^3-do07AZuIO7*ASD z_NvN7TNqlcz>Db{1>b;rbHtg@d@G-=fBTb*#eae*wxXL)HJ(xHFS(j4I;_wv`SNEQ z1Dq>W;0T4u0+Cggb>`n(_@FPPbzxO1#C+Aiq*iDAsg_rq~w zay=t4YP?#>#SkF0hsyRkiMN5b>g=O_am*$GMDbWLw(6!SdbYodE$5)!*_?3V=_n1r z)Plxjy7lGFdfA2HHZNM}dTBO^gKqcgAwT%g{FRSizfu9)Y5SnpM@4WDsN=!WSFb{x zQSW+h-MxHNw&y3`gWTdMm|Ut46?D`E%d>H8ywM_QHKAl@@Q~Z^uoCRqjt9Qr_pw~? z-B_`;S?R)C}y`NdaN6;Y#Rco z3WZk&L0PuhhNq05)>*N zZg+7~vXyyqK*|&ARhVMq`Mlu0ia*e5$0nldv7g&j|I-$Jydn#Gt<`*heRe`Qk*}Kc zek({i+qN79~a;AV^BfBar66sp@&I+qAUQy93mZt>Mr4(qptN?3sa* zh*o8I?n)-#M?tXGT>1`V}s7R`24IBTXaP)u*we6pok-{d55^^K2Gd z0zIm;xF{GLktxI+`%f;w`ThW3a|hXD6SK3P&BDjtX*8cEupSm@I%bO0oxOVp&bTcm zzwBF$CTDwMxek+E(}|s(V0Fj@#hO8G<9uu~mwl;xtT_+N@ znCp|Fsoz1u0;g|)2UIHE?B_ABcj(pI_UI}juJ+~joc$udZ zYQPbqLSh;kgNm}=&$(RbvU^|Hule0CAn`F(v;;g6n+%XqA6V?v`oyVJP$p(FztZ92_V|@qJVer--4}DzT)5|NL z2XKWo+Xx4`A>LDHHG_5C#A`JH2Rx*QZaTrwGQ^9cM2V59PYoLfb`8?+Fes;M;~P;l zqrDp);c+69Kojxu{NLTG_fwLY_r;XNCVCj=a7)HXDk7-z02P?``6 zMNg5ejR!C99*tOByNDb@dJb!ZVNK}xCp^LaD&B-xE6u)HTn{|z&Ua@avl!2qJg?6U z9S+{pdaJ}M{r06|i`?G#^SE}8152YV&u{%8zGLUH>*w}Qj`Ryh=lV~p=Ighug?xHZSqgSY2SbMCo*Dx+1<#mHc1QuwVbY<-TNyz{wO5A63yp98Ql}#uF?ni z8}bOJVmT)e$dTH_C9gBXkEG^8FU)-f>(Nmo)@tsru$!Z~BrZvb&V)j66Re7lpyYMP z8ZN$l{F+yZ`DB&D!MtgxJf&~L$A_xL53IwT(Hzn7=14eBROBGPCa|TWA+9rN<7(Ri zkI#ON48J|C@g>WA^6JXoqm+C`;qmvZ4~k7x;P^aS6g4oruwYFMF^}|qP2drgRujm# zu(#uw<|3h>+;B3{dUMnX5hlS5hph`mg>V6Zf|a3$ydPR~gT~d~B+p1IxN+b4l7$%g zx?*l7rz!XTf+sb06aCVov$2_5nhKRXdN07DiUKhPGivAY<6c;3m5|RO#b!JhHiBS@ zg!zgC78(D)nr#rhAaRp|{SbK>@=GJ!2!9tI8W!4Px3R{7KO;|temk5hTZyPk31MY^ zpaB75+`*Vu-;cgLw6op#MrO!bM7rj=;J4QA!rO9Kh>B>F#8SPyHLH|0EAM1>7_t)y zC(mcZ+x$ZtA!*Qic=F%qEI1X0=&glgSUGjr;P!7FLYhW`*>S^=}5T0`d3tAXC^iqz!+= zS*-uaO1z~ei% zgS1t)Rmb~-bYK}^S8~-o=wMj)f*1~tdw^Sb{N)z>vRQdesde=f+SD@a=-B5P{q*Sh z3SS{T)tBhldac}~>}BF*$nT}^WL68VzwhJU=Ajz?5Y!eHh76J4SJF~ekfjr+BOV8w zE`b>shWV6q7C`fK`wshl7oz8k{5&IR5RKkS-xu<(c4jpN?y8PvLXfE>nIgV8d*3mmE*593qUdd=u&z^h63ivgaXMC z?v360bSxI!w~8u*pDC-oQ!CIQ>!$NR2ZW}BEDRLvbbrOu6SDqZLZs$Cws3tPKSE4e zYdlW4bI#5TTFH<@5qIxAr2~T!qcEcDXY|%rE~8BQ13l#0+OcD&L{AD&0H2>cN^?lm z8U0MDD_lD^=e~a^sL<~Jbp`FshgznI6zXno_EgZu=?-n~j|jr!cqw=TU4ea8==SqI zRi0QnXsgtCznf34g0b5qnD^HZ+`OHzcvVC+XsNn!RuD6ly2e zH~U9Z?(Bo{ihVa$qrO-zY_C*4?ES)U~qbC%G)%e!I zd_1M=goxW4=v$T>6xZDy*-@lCIGYG&6Kcz-Q|yp2VMnUukO%RwiDS}21 zq^lv`T-HM>q=O1qw+3j_TCVW2_SK75rIeGnR_dO*uJMPkvBygaB_9nMZ!b zX1#!R@C_%PpaJ+c%k`hIk#`PKxt~fW^CxQbs|gC>CR(n)dJdp3!&eP)RzxX|T9BP_ zu@pgJvU)q(@6M2V8%;!z){>l&(bl)@rB~(>p?3W1-4zi0oKU&(H8?ZxhW`g@$%sCxGu|e(tu+vGwJw|adKB+RcpFbDa^jk%zbY|{AFyEZ z9-$LzC$7Yy-t?GTxX(lf8M#wNTuL;$GI6L^?Sc}iQr&ij z*aFs{-#U=4bk~#cwmfntMAc3^DeQSN1*mPy za6RGq1yE?;P;{2v4>g8P(P{#;6|;cq>OWH87S=eTwS2cTfxvi6PcNQmHb~)FK^^@^ z_C4dppC49T3#D|Ga)P!?920oRsJDs7Yx%GoiM`{$NhL>6FrgPjRYxa~UNOPjtaRqA}lH+_J<6-3kxHc53}fK_>T?hU{<%j7OwxvV&<}F<%v~)c-_OzNOnQk1u94f{0w11~B0`ld<`;&?3|SS)!o3 zl)|>Vp&_U++o5q`2j*{dm`o`@eDEkFk~*_TeS&{N_9CRCqX>K+DP_YOHM$Gp0P^!A zlC6(AvwTu*dtxm;*X=r`RJ@!Af<`z8nX`sVh>~|WjMK|JV(~T>#jqXFT2iS;>yxId=W5 zGontZ!;561T}O<#Gp70^dVx-hJGoLsFw%xUTvEGOWKkY>mEX;-jgaupVF&dcF4I94 zZJG<`nduk@QIY)3@*faJ;e^6wK4wsGtw6zEBpx&{biIe-f={85v2teaqE5|}t<*0L z=)5RoMgMU#X@nV$v|weR9P=(oq#ARf+2Hc{nE^;Qs7tf);$v6r6<8?J>VT9i%5p%{ z{*;?m{4iGIjo!SU^Jf}16=)uD=1N2l1LS;s+WstrxZ&b~%VMF$#9E@63u3Iqk9>jgogUITT7+f+Zg55>kNCR0f&L3Ea(23?Qdj`8z`9! z&TXaLot^uO{R4MoFVAF;b-q-x?JunE8hp$ZjTN>|zFvP&*2uASnl=RLWxd3|JV!1R z*C0nlMt=I;rMnFB41c-2!@c_7??gHCf;zx&-ElM0qUCvPHZ?k4z8V_fVbi898t6rP zROiOh>O#*993DBRxQ^h59PmlklNv3w*jGFHA(R$6M-jg}*Bs(0to?bfVedfav)41a zNb{dtVqRhQpX-Z%FRX(a>3`qRec$>=uUSJsmMQVdK?b|;+xOP2DO*yJxfjAcvU5h` z`>kg#ahiT^vr-K|-9bsd=?;jieNpdXRNKzA=D)~E$mtBX`PKNV#s58V28@4}vgGO(5TH$Se1D zVnG&@xXd)lvNq%VYCXh)iUW7lcs3rxa!LHHDK>70Y(7k6=#8Bjc1Mua(A}_ic-N4YTBi}8 zRv3X&fs+%duQcT^fW260R;Pr|e74%XwGT<`<&0zoF-Vx?gl_i6XCXeYmHj1dzin^6 zkt_VYoYB&T#+R2r@zc&viAo!7^%>04nH~>6q-3s-FBcl*v!wq$+m#!P)+KJx-Nn#rmLUC);yz9Y*dQes=*r_WAXazBj5y1}^RUG|F*(lkjG-L+WDFg)%B)L z@19wHCi{uAHZOpcXrtV8o5#-7=3L)R|LWT2e~a=AOwz<_qop|IshTrlj|-}6TVV$( z=(LglKqn`w|BCXih4zjdQu4~zF%NK~{~zAoGOW#QZ5O4bN|D(XC{UzDio1J@yF+j( zuEAX@6DSs(;1nnpB*h&{X>kt_oKgtEDH1$k2Ri3k>-zRu-}%nI&OYNuuGl;59pf4I zxS#tS&#dXsWD{E~SaMF-E`nP8Cdpkx1n#wK*gEn$uim;a#og?AfoX7g;WOy}hGrOO zGkkaV^U`uYeM@i)=;1)XiS2-RK%Rv;9FcGv$^05~SfOmI z^%SZNIimwkdbfj5lYg)<(GN#Ha;fi7N>FLuTS@Zu*}S)?%%g@$KBYd#Ax6?L)oC=l5$-37U5X%8Xk~hryR(!VUOXj`eeC zNfNowu(?VE4OH-@y*)LDC>G=8x#~aPaREq)GF4E>`{m}ejJXYD@ILJBm>>W4iLi_$`#%6F2^x9koDjRIY%LI-+fD_!&4>-(?5|_WlX;TN_yyp^&&Q95SrF>gm@j(skAyGCVn{-Ez6_FmT&LAM-<{1*G;h zT<~BnYC;DnIRFs_aGm!&Zt=Rf;325$FRI$;LYzdCF*+_Re-}LZJi}l&?BcC@D9RZx}k(K5G{WR%O!`2UpCijn`98W&g_E#Y@dE}C9xC6iWoSv3( z-Ym4<uKW~{BPV8`WLzpS|Bg5%5#d@^-!LFEQVeRHR{Co7Z%*xrkPin2WBJQkMKWf{k>X} zSQNmbDfn5Ixlt(86)jE6qfh_nz5@|ep}W;>KU1O(*FSyb@BV`_+DA*^cT%R_I^iFF z_5EUZ59sk)r+r^&bED!deVakoMMzVQ{f)bX2e-U%sbYT@!LNXY2Ua7aO0K66Ui|kL zFWj|25K~(lt@= z8(PZ9gt1{&DSv;EvFg#fGQ@wU|L=Zu#|q%EMd%t?OFdd00QIis->}nx!QJxk3s;|G}rqhMp2XA#p!Zz>Sc3 z{joEdl{VaH=kj?!M8!$8s{%~DjItEAn$?_11RK`@jMC*^DbBn_$X4QSTgt>78csF+=eDc$hkN+Yf;OxHa9k|`Q3bQ)_>2zb(d>aHJ)Zj zzBXNB2tKtDpS1qa$T?S#n99HD{Q|_+g{)h@m-VUb%w*COv`zZ zUJuH)FZfG5McDTt0L+Zp*_h2a_&o+HZv3^m#ERwwyrK7hRZA^#VTUyKV|m99641`i z23DJcEZ}_D@&S9xo)ml0>pP91)=8q4#`_i2far+ji`(#P!j9+Js4=O@a=SUVpCD?` zv+eJJ{TG~xL()xk-#Rhqa7}%gy-S<;gHUcTC@#64WZA1ABD-t}?FBtpx}WhcdY5d| z^6h^Wyi9cZAq#3_UKes?hCyxEv6=yinc*%*tbJu-Rzx+}uM z!kJFa+i>AZ5TO#@1J3Fi3q5u_&SM^zK;J;!js5bDrOzZlcM@HWL?Rgu0OJH&FH@jTM+*@+88=;LeINd^<4sceTnBENEiCVS$8bl4uHO=2Lp(k=HXMAaK>rZ zfvwALBa)Lroye`zhhuqagDv_zTPo~+b0aA2DNC2I4^N=V)Dfn{1aAPqxBo&vqU!) zh>11LrR3*>2}MiE06Vu-l%O>4kv+kLT|7D1V>L^O>ywX(UQVP| z@rIyx8|SLwwPVa$CF8e)+)LbM|A9FZwrd1J&l&{%(+j1~?d|SAcDTrl+1+6fUzO`x zJz8He^(=>WoCJjQU7nj=#$4{UV={BlgQzDvAIBX3zV95rmzR5=*dJi!2+14g*^dar z6=#}yWe)5n_MOvpD&)LD-_DyM>L=Z#jer+A@rc3ahW^zPBoV!Mhsl_6oO|1I#wG=)T(G z9^h8uW+X4L*X_mI=s1ac;Ty~wAmJNMKtsbY3AWAfX6OGWnfT+KS_6~)f8`P}HNPVZ z_q_be5AdOTdBw)|G3Y4BBkDJCxJW24XVpv~qMe1)&^@@k!2BX3`;wnVu!|dNG(ZH% zM%R9PpT2?1W-Jj=dA_XTijCM}i+up_Z!JK&FU`<-0+pDGi7Tn#B42tv5zUVarfs{_ zVgtoj**D6Ic)x&J0x!J(bPXViKzls;F5Yd2RZjekONF8M^17?;&JSk2e{3xYeo~GV z{Wm-%#uzq@ZWMPVAx^NByZ<`Lt z`0eAlCFT5ZAB_pl!pegmJBUj52c#(Ws`_ww4Y=Yxh$QnnP;q%W`bs+JV4bhTBHL8R zNeJuPOP!iBNl5GMoCr)I>z`L<>{xJccx=0{hG^l`XFM_QEb>${?!r}eL7Y95#UAv} z<23H;k|BhD@Sg+(5*VtFMP%h&;(;?_??g#etvxGgV!P!#ep%c)tJ0tTFJc0ib!e?u zgxk}FM=X&+R?SX7*^BPIFt%zwuZsWhst&7vUoJ3TAx@d+e>>imMfu@|9vwNoXgY+tXG!;2K_7F^wqwW@^dsG>!FNe%WOtmI&zwJ-B@l zjF0~=SA$62Dn85T+ov?`Mpn)Ttp1VjGce!I-Yeofx+`!Xhj?vsxqaL?>zttU?E~L7 zeXu}omc$TtSZRrfU=?^>xZloZutynx@QOS(4JNVda7vNndy>;nOI?Q8egglc zXvAr4_`iAer)M}9>y0>=cgp^EO+mmk$sEXSL;u5Qb$frlkLc&u?Blzp-POC3nWh#% z`Ds*_V-j0NKb$68Rv_yeUHLf8)(hHAvWZ!u>Wv|i0g3%vKz>i{MOy)lj4f&F-^i@u z;kEmmLGNGO=lJoZ|H&nuhn-`F$^9$m?ZfO|>c0-do#6{EbpICJ8cUaXrfcTQS&J36 zwVD1VsiI_PUv1}h>VV3g4R1at1O2hPhV@E*MR;O^?5egchFhd6y&>`=WLXV~4as<% zf0o>B0DvFgEhHqXjy}Egl!V#vVIR?Jrb{qH25@_*?^ zkB_*2V7(3=6 z2lT6_?pPA^eDSrGCs9C#2T0+Bj{E}$-+Bp*ye^RIWTL%4Ie5;W5f<m9w1k;uZ0_ z7f;GFyfo5aMb49qQ$)3L&CV!}iu3j1+{0^dex?B`nZ@GmW| z)M{o0(JcDOoItCl(AJFl!{u9zR-h%7^tI(*DHM5tybI+W?Z@(k;);~A_^jMQ`>QS# z`6bE?LjaZfZPM0;wvBSOZDzWw0d0m2^>pp2e=A1QA@SnNFkVn-@6YpcDuk)O(Z%(m*7%y7${%2Obu=Rlom$B-G15xOE;jV~bCoKE%1?AUFV zA#F42y`~3^6~g(uuZevgqoZ%g{AQpp?X<^vo2GOgxXv|c@yoX@X{X|dx6{h_^Ao6E zAEETb+@PkTb&O|M+j<@0(;IX-;+x+fO=q>|5^lqU$GL1Jk?A&x+yQ>%i z12i+cFSVrS4z=`jrG84YFUFL&>=c*D=B4LA1E}q1 zga1}NA4)w_53h68^y}0&t_8Y%&L`sb1OS@j>{)qh)Zr3?#KQ}j)LjY;Q_t%zmlOpk zt3NwO9o}xvqn~a)yWB^n^VK<97@$Ag|H6hC(hcd1SyC+veoezJcjGaV!**)=uCPty z`N7WFVBcZy55I?bvY5JAzHlteO8bLt~jD;e6n@*<^7|Lf1LJK2j~-h-EZ+g<;S zAb;B;KNa8FWMm;IE&qCvfxoCezKRgMqU3?4vL94`ApcEeW98fXewRJN7(~&de{wx){Z`YdqS_iM!f)T$Mn;eKp(XVIi8n%W#Bpf5X5A!^+oUFK{M1Jdy z?!VE@t5^h+*R4JX%QFP8%-(j#@ zSLds|O7EF>+nK?iKECxCkivK?a-UC@+4S$hl;Z*-o9oYRelt=ZqXa#CAXw#LOBL~s z7H=SX7QR-_Ud7VrR@U)WJY3Wny`%ww!ZO@a*B^ zH^NS|f~5Ra+vTxBi~7|)A)nE{HqC}be{rTW zRjxuRS|tPb%PX)d@0tmtpL2O`v&t=1n*-TD>Qt-Hhy3_Znj8{Z-v}bpt^WgUI;VGx z3l#BX?{v=Hab1`!eKc=b~|twfz8%?2vN0)c}0N5I>`$IQd#}(t+J{CCF?>JZs03 zk$2sykY`;{OHfev7<0pCN1d0SzcI_xXKaUFO$0RS-MoFoQg3CD0_dG7$$G>b$@=mS z(HmmNcb$pvzquugM}HWs+t_#WEi!OecoFIMg_DTzCR}-7`sYv$#>+Q^Oywos>6N+~++Yc9%U-a2~qg7E-!>f}l{x z!ND;v%)dv7^M&t^7&(Nu2nl{@H=3dzR$}Kl{^C(Seg3Q4H*xdz-loUL(WVGPevyx< z5>J%1@g%2Pgnljj^k)-MP%)S&sI2e15o!)LY%l)Y15F_VHXkM6Xu^ zCZF4qoAD+%vKbo&+gAT9heFu9j};e$R>{M-`7nFEB(c_d)~l45vY^C zfn!c_4<8@$71_VZPa=_X6W0<@%EsW5oZ??`iFE6AQCL@&KU7uE5|F6TeBcK3HDLkWA;SQE?`qXL|);@;c^qYmj6pj9KB)! zsj-R;D8ux9HeQID{@iC%-Ak*znml7ww^zGL@nD#i9SGW(iuayBNqa-dZ520svXY)r zCY(U65i){3yy<~10tIQxHOwB!(2A8TeCP+>k;p?oDXm!_b#^E@=w03`ne!00=*rO+ z6qF!0%W-xA?l)L=&qFNV-f<3eEniIzSSimgZPZ;hl9lM|*=vi~yXxseQN4G#I9voL zxHl$rbRly{?PsY0talYzj!&(6;w1kdTTUb8ce%txe?PJyDiA%y#D?UyqUX=B@p7!E zD^1h`L!y+*rSY<7%R?}T8&oG-nc2-qa%a)Y$E`kYE8GOaPvPs02=yLEnQ<@o*x=Kl zhoSVs8-R_`ZUCgq5=>4r^4)TGvwSi&31mOa+MZBpnUQ_c(Yikai#$_zL~@$J;AlF% z8bWF~yr{0UWIq*jn3^zML??ejUgv-*-hu~Ftwb@bC!nyM(@q6Liw8QV@wpayM9u%Jl|BcnWnau z$m~gQnl+m#ykyln{fSs%Ru&zA0Qup0B6oK;ZIoMqdCtxdx8U^IuVjhKU#x?EC->3F zX0}Mw7Tl3D=p!tG(o#ZCWgYbNU`Gmi)Or>feRpR|3`|45T)VB+^4pe&upK!U~izVU!z)%c#*GIHp)-? z>r5FVX3JoD5kqsPyLk%_$U9iR1=XxTEuO0zdL1#K=exz>KE0{qWcbrclubc4lJGs3WbD)<-sUE8@dz#a>Nrv)Sxmje;DE%;mo7q+|rPN;tBtSxWW`Eq=l| zu*u0TC0Fc-it-h!fY}b0*zZs#C;P7u5wcK3*)ydj&D$jQuj_;kvvz(aF2n&bTkF)U z4TYIf1(youIOiQWeKLI7c8=>@N;%%xy1VuO?+0&`W}#@EWd8O6>x!E`AKz3t?_x`C zJ)suPU2Mtj77Rjf?8B3PG|ZESsXI#%ho;`!D91&bq zw4t>UdxFXv@;*LQ)H!WT z@ZX8akhtUT|I0?v3jOuo#O#qjuHRtqS)S}e%D>)g)HsD+lyy77Gw}6&P2EoOX-A&qUJocR!P#GyVCo2?^vbVEgzol)xfdq ztP-nxiu3Y}3#jXx0{ls$z8A@I`@G=7msTs1=AY0_uqbX{G+T?CBD{V5ZyX#s7Isu| zQN8-8UGz;~Y899cABDC$Fh@yQJd{xW(LY*A_T8qIg*57kNHjSsX;i;}YF+$Q!M_vv z=bM2)3t?0L<5pf@78$lQR+b{l2X_Qd&=zPbey4lCvF!v12vJ#=>IPWN%*=EJ68@tC zseGi<%1(IoG^3R}f3kTO1y01Ix4Xti=Z8;_rc0QS3BwG^Cf&qi|Iz6xJiJ*tJZVV@ z&rx+|ItJUX{lvYQlj88f8>D=W-f7Be8M!(&%H4z}8Y8RPmN3c*aI=-*V~VZj;%a07 ziJE~1jSQ7qDJ!afc``BwU6Rfa0E0YhtACtc+l2@$D}6t$I}ku{>ho&#&CEeSvx=8`UKPfIJN|4Qcz> zG16vZwTx&5oywl%4|5X`l+1+RXQTIS+L1nxd9$MLB&G&u7qYDY;eXy|okFQ6MiVo< z^yGTeCK7|`f@b|0FcH@mA5}Ih2m&IM1{z*RY=*k?QUm6gbR*{DXm6mxk;Qd$B@g7% z`W^*|z|1N_5vB%rm34MN#g{r#HZ3Od!vlKS%a6*lp6UXTw`)!Cn5{WABfjVRu}<3U z)XEXqe|b?V^N*>>6}&zk_cNlu*|~d}+vJyyqi!ugjqamH7&1fpJ_CMECPTt&Fbyvy zVX~b<#B*&eDRhvS`O^4RnUlR%E;}jWb#+E>{5~Z3S>n1;RvcQVzQ)=4j zsm&*Vi3Qk(pTBrcmo~geOVy+F6UGH)HmxMKv#UL#3tgosS)|bxSp{5b6r@uqlk9A_ z8;jOABRs%8Hr&b4vc$>;R<(v!VdvwIQN@)drih(K)7uR0eq!#1^wa%(z&$Dcv$E;S zkUN$Pf153p^qR0o%zmqLC0-s3yjkNKVi5C11FH33wsUy0307U>em_64sd`{7wcPZ; zpLfoOHmCgBD}u8M9|e1zB8vwmpbN#!X_}~`?|io2QYJxQu#b`WM0)#2IhSTx8=hQ^ zOTVlgbtN0E?ed~eeldm(Wtt46%;XP>%TYBy-67*fkfcQxy7<$}g7I;pd1CImg-hR* zc5$4S7XPxsIU3Zw>{id_@FctHL#}1ju3f-E26BC1x=t~2?TF8$D{fok@9zEgHu()c zekYUXJ>E%A3ekVgQYoI~1lT&0CmC-FY+ZwgU%X8v@gH+0`VYKNU2PKvaKCW59>2Oz zm_-l59a7k&l&jG&vZRpkmobO`!>=j#``(_%t zxUms2gO!Ys!i>TAoh+Nl>0gt&B+9bNVpZir+#3o!JgVhZH;7{g3Eb1H3*IVPZ^4#N99oLQrLA({6M|j9h4Zz1#OtJe zKqm|@=Bv$sfg_MOgO3d^wN~Jv+Kd@7sOeGEHbr`0UD!P~59B)`@Y}QgAk>a;~p2%}HBa;IT6+OpKHYoDMJ3we)OX2xv8V*vY~xK)_+g z`#gtHR5F@}J>bWUa!6hO>r^Fz?e=I8XBGp&}= z?b0M^*%<14@h-z#L|MF^Yjnq64h{Zp~&Q|yU_oq3q|yAH_S z4{Qt^$-@q#^N#iXwr%+)w)uVM-ig-1&@9~V*^7^P9=k*Tz;B%6Ffb-DtX=t2gz#|P zP;T0xHt^I*nC(>~Wdf}*p*BYHwO6(*#IS(Epckm~f}0oAU$l3b`^U75DBSIHb< z>42{WRnai3mW2F)Ly&u_CMt6Q+Im-nSg+A=$Dk;MB4>^;YCvBDJVZ4C4e;<&RUh)y2dizv+oZw7tR|n%eb^>OFvm5b!(Wvk^{UPh&JNkzBaPL7ly~Ho z-)xfXN4uJ9Yubzp2%{2k%g@%bfaBU)r3H?9CDwY4ls5X}&hjV(rh1=|!C<3yX??IN z2$OzPQ&fG#;Gh&%t*5L9)#=~D6OQ@w&Tw$9&#^L(Qte>}(7uG8*Hs4Cn(_ST>79Z6 zMxSz+$w8^EgDNwHP=WX^jgF7VxxQR-Zr1T#o|^f5(d?$N98i_TflK0}=cr84PeJFy zj=%ceX?1GmGn4{K3M!>s91SDZKKiQ%=Ej0h{R5=7g^i<#yD8|6e6-uD!DQp9 z!?%ZF!(QRQXyf!RlxYSt4(k0{GsU`&V8>TkfV$jQw_g*IcY=dKnca)j2_aK^JV(1x zgaoQq160c&Lh_J?b(Z~c-(Ty(Ql5;{D@r2|N1=qhRXhh|i(I>p*Oq%MR}%IN6ZsdL ztOf?%s6Z((e&~T_NtzShRrxPzLDby?f{N=_QV}x7HnbIMz3&~ec;#6g`mHlrN52L_ z^V3$3YdstS_xprh-3}XU+b69hk1JYuj$645v%Aq8^+q`Xdi*ZFTE|I&Jqp`PaQ-GDhXO%%liOG@=%)J`x7uF7HN5!J6$uN5bz|N!7#iv>c zW$Cr6nysIE*#lU_elDcus|&W|^tqZ*oo3T2Uxr@}(w#SQO-|Vg?V8RP9lb`se2AmM zb2VjEj0$O;&DQ&;i5%vePNiRjlm4v**ub7u5y@Y>ae5Y%6_uKxa(gH+mq<;H7<)wJ zc*r z>=ZXrCH#D1-(eZQ+0San6{>6HK~zn9iIc)-?rkzYa~`oNg@&m0^PJ+4o)`7}71(&p zHVWMmf%4}8s=X?#$tltCl|+`#`h}=Ld#bZvs#%1JYO$(&hh*D6cAlas!ud4X^Pe%s zX~)vL8}mm=N`2|IE(h~Xvy1szws{Fl6F;$aNK%%Wui1PAJ*l zrHc&7=8;&6emYsJYUcu}Lc+-!lhS)AYpqY-htnIdcp_5>9PrG72S2u?H@m-Q2?LUg zx>Ez06asjUfl`(dLnn-$6$qiD+lopXbJ=E&KzTzRRdSRgN~P% zg$jl!fmOg)kF03z#VZ$wk}>xp6{2D5Uxau<$F!}#LK}B=u`0NotYz(ShB$CX8>J4xXaMPBq zEPlOLeBo?6{;=APX&h=!4>3pDXA#Zlnyx0eAsQnT6qXcZaIq2VcQ+qY4H$it>t3^q ziS#qnAlKQ%ByQaA=9}`ti+rw;PEXO(b)SbK@Z&5LP*}5dI$G8Ll;GV^tM%q(}^#EY-gk# z9YuquaXDB;cOt2mwwDPw_H!c+6y$c|o|E@H^f5f-{Sej=W5|~&kfT@QvNt_rs|qu34x)_Bc5>kN51Gv&7mB9yRX$3P~^YO58)J~S5BsY(C!oI6}NS9 zkW){<{l?+b1-bXTZF~3~V|Ln`RglMlWt~A_n!(`K_TWq>_&cXv@ha11_iQr;cacvr zfiIDu?BvyYJ5Xm_bBU~Kgto{SwVv2>;Y>nu%N4DifcGU+Ki)`<7T;+$^m;wj$_>b= zKmbzCH+m>3HW&Dg#I3iEEtkc2ac~4*Uu|w~gY_;e=VyY>Hf+F!VXr&!-tTc_H41$? zec&u|sS14!pb?yNFs?LYU7hGb*05ypSPP2qTqXbsnYroxob?p3i6M+WivM7-Gx7Z^ z+33c7A%d8TBaSE-dwqdcDRsarR;ai`Ps>W2DxKcJYA>Y_)T4vJA$@r?VmUXueGU<+ zn!v_UZ@eCNrxR|LMM%K%TBmoLkFTXEp_J1bY*gW?pX(O<5Ku7%o4<=1Mfy0PBF|A< zCb$lwn3y(+(Ne3S%7ONlgy$>_KNStA>iWOqVlO)U_|Blsjo&EK&BOC@pB!1rW?2)` z>A~pcQbnGv{5T_j;MB!U2%#WPoNXSM!iLTmNnQMQDze&`axj%IxI36^CJ5_}AWI&$ zjM1*!biLEr?Ob)1co0YiXe*cq@vN7Sc&z8ZRG}|c;^>oxU;nl@JKT8Bs4M@F`)i zwb>xsaBYLQdm6W_Wj>u!w`F8Olh@W@tmo^MHX6Zx{F3rPD2b{E!ciRZR?IT-lP9)8 z1$qV4(iANhlu<=GF1(PQ5Ac50`d|tv9YrA>bgIw{Lr`#05$03va?E?Bd zMddD%eF)ND z#0NAw^qa6$Dn^*U%>AUw;H|tnb{Y6{l}WiR%RWD>TPLmj@>?Q+B{$Mo7uM*?2wJ0tT4s;om(p-0)rIXPkgbkK76da^KNCX{$Oh2iuN5{35H5;++1Q$=+2{|Mhq_ObN0( zB0l(ZMd0VY59MeD=PXBvg>jR55y;2Bze?3`6b)+IxWD#mN8PH-w1PlXug_VPm3m|R ztx15FQURo*WK^SBH7u;6JcVZqPE#+#dwDs5%!v2S+BV58IAHNw`$1M|{rZmA*0Ok2 znL&vv5hs|AN)tF6ye&2ojIdk?V+->WuJb%<%cP{lREr|2=t*`&%Cef(Hcl|w5QAn@ zbvC}Fdzq7rG+XfRxlb)61JC>yx9U!t0?>iUqUAi{UpJb6)k-+3E3C_aj?m;Y!dz#S zS>!3()`=Uij@b4%=WQ)#KhNYX=~vj`+Wx=x+w$rn+1yO2W|lmbcb{5j9sompv&rTk zr)9tdR~;5l4(77UcZFBi!UA`xQUEp@-A7v~JBB6v$Mrpy;Do);7syVf^aMVCm*brW z*6ZiLFj+kz10E|UF?&eroWR&19f^cT(_xGqU716u z1-dNsOfpI&sj9yaJG$Dbrtmku6}2}%KeXauj_T(q{WLDKGfQ*VgK%)fsx_x?>@v1Z zpxX!dAeQ?G=S{|Ir`Ah12>`CS;r&z2zHN3^PqHuDomx-=bzsW&0lcP2`~Xb6;4rkx z?(g8IfISzm(0laD}1Na6^l#v^JUPutQk2g>BILXCq{Ps-YH zLq)XgFK^WstEDLJ|5Ja~e@7)=QJgsc(OEW)M|JhHsdt7dfmf}2VakxH7++` zd?YbliI zP*tev`%9GP#fiUMwdsezGR?idZFf=;e8nrT-4|jWd`rW?LxQWzT{l(1&fLuZ#oy;5 zswW(jyf2JL_1l}L9n0Bu3+LlKgP?;NZ!{jiZlks8(b|_?HOSBGiK?9tKr^R~0}6!V zId02U7lnlql3eBehWX0v_eP4RuV(A*-5SUYN0bE%KQX}fqx=&!s);4uV1^f-8vm6E zw9xKchw6Q zuT&HGJk@Agz13pWU9P7I^5@zS0iZPnYLI&yB_Ry6FcGOWJ0~>JD)WrrS*+BNK3{}Y zRF4{oytr#m z(Ebkf?eYo3I*Y6wlZ+9ga}i=NJ%g9aFtoOwjy-)a zYV;{4LvUl~ZGCMs>!*cm(}J(PMgrH2`sZ`(hxjxy4Pcf-YhMa>%7*!bZ2Rc zU-!csdxvL2Or_sx>-&W_Y~$^mW}bXuxb7NUdlb!ldF=3?$rO>Sr0Og|D0%WoIO)}v zLE-(nTm+wfT7*h1xdq*~5h2wb&??o6eNJE+9Qs|GrJh`u zKIIs0$3hj$oU$=lDJVI1zYcxpD#vJZrHzBTI@-FqkD5&)a-XA4ahK1iyhVEUmh7;O z8LIybk$gdMIy~0N&@sm5=V=&$towTQ(=(!crE^%w!T_`mRdP&oz8wDncrP2&3;3;i;?NtK+Jr$ESQ_D`I)OmHB}2J(t&KGQxMe7(i5n< zb^k8SKqN~K*xo*3u`+liv*0bVBKlGH$G%z8tdZUt7mmui6xj!!SZ}=)cI$ynOmEir zMW4^+USEuT`5(&#Qh5sP`&_EA+KsDAU*1S9G+6tC{@Smu&Gaayq^(X)0Porqx*C-* z9WXzN!Twe8QG5JNtXc6WDK)|xOv4dAK$r!w$hEZK3%hxGVcuw}NORKzsz~~)QDlxs zz>p}i=vFymaa9P8i=|We^_alE|Bp8Lf8g5x4+g)AL<9#X6^}m|5lVR7IXF0-hlh9Z z#yGGROtwVhiSBhRa8x+|f2f9owY3Dlz<9sS(?tf(G!;neLBgFo@3bk&f7hXq;;K&2 z%G_5}CMJdy~JEw`@Ut7p|6!xt$7LSGkZVeX;0t7=KaRaQj{1+cG#vGWPsz-Y@7}gGD;wh z>9(#m0Lt1WSR^{1Bu`D`*?r&Ub0jxiRCV3>xWuK3>Qe42>Cjz$D`(qjW z$Nhi2VKb?`5aAw$Tfep+K}%j_uLh&*&rXrJ6zYINokF+td&=dLyZX63wwxvWqaV*N z>0>3-^zZ@JS)4_BZ6{`4W5Ut4b4Z3f?pg2Hcz||1wWWq zTW|-ocMr%azu&oB@~K_%|-^PSYT>9_61MOn8o(BJVGf8t1dUU8# zgt=Pz>KU=qz$IW4UZE@N*EqvrOy+ZAj(b-k=<>TRPwdX*EN6};uti4qV0WzbI9Oh? z_|ym8*=);y6wg)#GImPafQ`=6AQvMd+Fay%xYQn-15Hb73m8$8nBX)ACIx(Wv`^cZ z1woiJUf2WEq3n;9-Oh5^%DiWR87sydzM_e?7maqh6A(sJ`CBk5Hb5kK9jLRufSw6( z&!TP%$d(8=cj`i34af#B?3`*SA9Qxo>HjGkDU&zT>a%-dYE?23b{CF4g^K`vB3Rzk z^u4)=}EBpoOD!EM6i@v<0xcD*{<4C3%=H^)%!c ze1?g6zFJ=L^!!27xq41AdiyfhEURqt3`qk!n42~CT?Opn%4Aj~Sc<;w7 z;5*6CkPxkXT{7`McyGCHCcfH37F=aylFha(tVd`79fm^XvK`@>&&v|!X2zUQ_VOw7c9AxJqsue< zA{TwS%;CW4lntYhO4YX^ZB1h{5QgE4Mru%t`>FP=>3s%e4zs4`e`KsWon{9g%48|U zeCEhHQQ2)f51oOs1qyZrP?1j$4F}Ys+7TawwF%K^%|UKky1&NGqSo8nPY14FvLG%ASMGkyQes$E9xG9}EAsek52(icLeb`B4tiM~^-A8b zFilVCAdG)SZ+lD0>vE^)%)n8p;6dHycgD&7_Dx;%&+Xt6m)7i%9SdjC06AcGGp0&s z^Xb{{4pf+}nuHV<=fER_@`$am_RGUmDP70IabETH_=R>DtGs)l zk)^3y^r&sV(q>MO>C=RqjoKV^^Vyb1&FP*zDl0tyY!9l=;=nwywQ6{Jd|@mp`6zkf zx$M}1Tufp*^{5Zv6KYQq4WzoKK%HX}Z!G&FU#j{k;PCB zwWXe*19Pk)fE7tK@`JjdJ+W-Ml$LK3K@imhtE_f|SOg4dflgQR08{8WWmO^*Y+^;c zC+E0XypF3m*QkR^;2{`RuP&vUlcilpdFS=D7~%bhgTS4VdI8(sC(2=!6tza-CHm(` z|MOaJf*D(TG+pe*Y-}j%vejS5LOEF=`dEagib`2|=OZs7&Y)Dcu}csj*4@&CY-Fqz zYfy$_R#MNRmDpR4?@u(#3ySX;w|M#mKFZ43fFtM5-gnc$XTYYTV03=0uxE+%{E%+C ziN%`At_qs(YNw(>SvUbFx$#AZg_(J@Duq=1vvbCr3%JgCfxZY<@;*Fv?X@kkA=VO0 zcV<}JmL@;)7k=JS8=w7*~Z{;Y=7M$$NW;$(M_yik0DX9Kn{>c zkA=Z^NI>|I&7N0T_y#0Io)Dm`MoA8!l6!duFFDc()S6bTObwg{R)3hEI!s4nonad*!S1M z3w0Oo*Ae6U*rB1(YAXSIVyiOfP?qd9H5}gU>am>G-f}L+wzJOX(>XZq!3?XcMu4#O zDz`t}g!xEJ_GZ5dy@N~9a|(~T|1E8uN%+9JtWv22=~T*bc$)<4ouR?(6l*;IJ60O` zt)lg}t#(2RDf{@_rhhV*m_ZN|;KTI*vo)v1kMCNM6aE%l%ciHNh&=iNe%BSMR<|0J zWAR!|RGQkEfdc6?G=(82Rmj^i@vic9l^JDv#y-Vw%W@gkvad5W* z1^tK1N*4J(GTi-4$-{KAbeaVSa@0&N#*{!mr3c`k@HQ~u4*(m7?u>K7BRIyn+IGqp zZdi^|pMy5Rfa^u)XeH&UlrtTNtb%jQ3Dk49)|Vj7c8(>U2O8HlE#zsL6Qh-*1iOJE zGUk*nxQWIywCP7y+GXmR6b$ctOFc%n8s_El+iIXaEB$$aJjM-!EfA#j2 zVQp>Qy0ny1TBH<;255l-ZE=?XZK1dpcPF^JLveSPQVJ9=?(SZoXz<_?2o^jyw0rMw zKj*pU{yO)}A4#69thHw5oNJ7C$b3f_i$bUfUPa^HY*dmxuy_9HD{H*%W0Qca#uek8 z`gm|ey@AW%nl!vaC9Val{7a zh%!>U$M$~{m^&^X--eaSH4U9)O@%BnsM}9d?(;fpb~=A{WY8=~{M3q_xs#BRZ38+@ zDENi>7N7GK8^c7^04MY<%q7f3dD7BF3M>(|wRF4RRee4rCKh9u=5#wecxh+TWVt8> zQ29zc1)3mH>>K|!z$&!U>H#oU3-H+Z;-OlL1wud7J`lS z-AQ4r#p(j$#6y;%!lok-sFR^3KKW~suD8;z$;$z=v=jg_rAZK*Q&Q4-6%@0wG_9)G zs9!n7U?HbuRJ~C;|FybOzv1T;U!kx`{Ko7iM#^P<}Oc32~EZrQ^)OS3NTs+>u4T-Os>|i1VrJk3=`FgIN zTrDLvQykx&zH4OMaLFIu347+(su=?TFVfpQ9367-6oB=`cEvPS;PO`UW~KT zS>m2;E(+4QvqOnVmpxVpYJ@ocM%xzmP4K@PX2?byo%w-cDh zB@kCZ(7CMn#8(DqcQG88qzxrQ=*5!Fo$gpG9sLyHM|57T1;Y!NjOZo>r)pCp+cCG( zoEJasL*P3Bf{SnR1M$iBRKNv;l`$MTJ*jwXU!jpc1Qu69H(M|7aCSABmj>dbF)nG7 za)G~PS1i%Vt{WMrhHOu^sOZGN+M3SDKEjUQ}c*6x4VK6yM1-T?rzM1Ml=vll#faA8y0!+y`m)T?W;ma-u3pUt#BU znFn^)r< zWvCy&9l1Yha&`UK6+nQ6<+MA*WxZAM8NV$oNiytUp|D}%V0ZerOV-EKH(?niFQZ=@ z16y-b(Xm+pHR--S(l?>dt*w?{VUy(63%^Hw*9(Pk6x=|19ZMV)Uy%ca-?waBBC%H^aAKJ@0E*yl z88o4nNS9IUw`{{t?Q&w4gnZA50Kfb;Xm|jTem#7q#m6UY2d&?Sv8FzVvI+!B*J#+O zuqu|{3T}yxmPC)%J>UO5A3h(DjQWYv znR3Whi*o1eDf!x@nK#7pWLX8x?|llZlDu{%M2*1JGq=Jmai=As(t2K{&@i*cLW8=t zn?d$AVHTYHaf*eYm~Uet{{V4|Y8DC@2QwiQ5myJdYSvJkLfGQL7CH{+priSHhVX3d z3|dV=RA=n=y+UkuXhNFf=1(vSGbqX zXlaRj0e`OCw7BQdnf0kF=tIRX)0^Wc)0@4=u3Ap7$$tiPHlA#t_pZr`S1?W1-s-2_ zM_kvsmGLw5|82v5MO;{=jn_wJMB&;dk7;Lc+el^45iq1^ysG8-{sdj%*Dgh-+|Tcm z4V&cCfjttgTFSXpp1jU3Ws6IWip@evI3Sk|(}~Y;(}l0<^$MtFf)y$Ud%*9d{?s`l zMOkjbX{lyP&>FMvaQo)#Pf3P~CJ-cH9Ocp!PyeY?IPHuS?6c-bskut*L9k* z*23!i5<@8$i zc58S6^n83v6>+uX8NW0m6Bw^klI5lDVflMe+B`vqkmP0rH~%t{nEZz6Ydsg^-_WL;v`nt@abLGYzr3iUXZ1jdQYCeNgrO z9&xklNKQkK#3}TmUYj>lPJB||(({DHb2{Z`l()SE%RdJ5En!fNpxuM$5zd+CLUbOFbJ3i$Hk|ZX;5%&P(<>3taXi`|cz2+dTH59;Nld z8uRw`BlQ3kiy!SoL&nM&)X`7H=yiF_+dxW*_;$bSP{I*Eh?H{5b*y zV2RcGa~XXzaesrX^yN8c50PCQTYC1e*Kv|F_yjtYDXOPs? zH+Lm**f8$T#Q9@)V%TFrpY5WY0`_f}O?ysN641tz$>Dwa06OYDoVEMOvr1AIf4=w0 zlKMM+u=#aCP4Z;tluGRUw(MbZ0%Hy0Ru=Gh#)YPA<*G>20(>YSngQ1?$f0?VDM3)I zIWS-N$*%YX$lSTyRRfDK&PRU8Gm5_h6(Z3$Y8!2aNagab&8UR34C$1|yW$NV@-VEf zV2_ZU``5y2be#o9C40SfFFtL^(07~nz@|M00*6n#%BIWI2AUj;Qn(6z<}GNIiz6$f>K_EePf# znTC&fi#}>SZqJEPj`VO14!YHU$>!8DxNZ6*<@wU6^$u_Hp^tBG+UNHG(%_ofr)V!a zZf~%PUGn@X<0Ri#O9Ow2Gsn{q&2?u6q5;*^0wKD=4uT`F%U<$FX~NWE+_5y8p23i} z`Eg*|$Qs@IAJD&>W^~5KYKHfedK%ml%xGtS0Iz_>$zLy2+9%gsJP0}lu{le< zq_rf|P9{tF$NDcSLE;Z%ryo>z{+uo!odv>}Tu)+V(--mAvl9$>jxWpsShF*kR*pmg zLpoRZ#|rMQ-kl^(%cvNiQ*xHYDiI(p!L4Okn8~@XLH37<%Ry3u07?5Sy2GAtFkYBY%pe9eBVu-Y z$8!a0=>9fi1M|q^VIUJu*5rHl&4d}Ig)x~nfKcYNziL@f9V6c}8hw}k^%0UHu)=k&8|t zk4+)aEfhs4Z}Q=)059E+Uhl|+7Av1&fJUZmqA4kEjI=6@y<&efLW_?lu)fS8d2Up| zVBA^xn9w_>$6~I-dZ$C{rEM+mP=)Kf#@I;a5;S|v8nxQvwp%q1=!g^7`hC*|&_+YB zLya#jgg-RiJW|B%;L{VH?TsMs>Z~dZD$x!y1lj>yXM$ z{|?R?s&{?q@8nzV?Q8Ygt`Ww9&@ue4TKN-(*giumsX5b3_1rM zU+Sl{nJ7WW53Svv|KVZN5P4Y_Y*-aJ^5Ru@fJ(q}woNjQz(v(4XMn3~Rn6(?C#kmW zo_#S~8K(flkiZ2CzSPm=p5}BJ$Ng9-YFm)=@Pl4vrkgU<{0WSinVaF{lH+tUPS-Wx z0L5zZZ?B+T5YAHiLEB~n@at!<37B1kJ+aHos6q!yrLm-}*4PsXaE%?8__r3! zHngdvow43@)1E`;G;2IOV{7Wdz7}4o)$2cml`R?esufKeXb=|8dOHb7W~$17^U6#g z6XUy-4OP{SsMvpZB*)>eK|yTxa#NJsZn~DMk51S&>pUWQsTP-X)YXjL;<5W2TQgWM z(mR<#@M8F)%jA10Xnki}sxXR$VV63Kqw8`EI(3%7Va!rQu^E77;^$9>hEo&r+kIr3kPkrdIW_orJ|_QjHec>?ce-COu@>^=i;8Al5vf^Kh{Z~2U$$8p zEoEsNEUoifJPX0c&LSmzS_JM9#Ulq@IN$P{&(jpR_%C^hg1G{= zMoH%d3{975%83kVy>Uz0A)^U2^HW3R46O#cx0NS6&P!(N$V;}l7``%Zsg3sFqNd8I z`sEP)gIaR{aP2{AAZsY{!LvJ`}teRT?U=7SC2D6>!r=>Kw^+*~D z5NvG&XBLL6?-o}`^K)vY=;#R=@-d|7clfp5#KW6%6MB+_N;5d->Oc!ztKO4SIJ)8!!WwDebO^cb)^dhW(^H1t&GY0C7yEKU3JCC4yK*8x5uw0L)d_*W4u`*-cx;Ypo zgcz-nKSx=*aC*f-DzN5qyQ;TeBlt-cMJKU-zWv_$TBoZ10A_ zS|uoG`5e{0=<2T?EzC2%tVB98JvoGe8MA7h2Z=wf&O7Y7Iw=|K@J9(I1>5h>?e?P zS2FOf)uS#jvb7J#F#e0=-LMWRK>i#?zQ%;-KK&P~J8PnL_-iB=J1McC@rhW{i{Hd$ zl(F(iG=#*+G*&@L0e{wTuptS<9VPnTjaU+?F#c(V^vKEir^S~4KK-wwVm+Ubiu<4T z|MSE?EN)n0_}3YG`;v&J5PA=rhq;m2C1yXYrW>g3w=;iFATjadJCgggO8~@m?TYE> z=l3*8=-&7D7pPG`T>Q*~pOB`%pG;uO03o0tpx_|iNx%Yw=R$zh^nu^q9}>&656|L0 zMUZS$3JW(#cKOxK&r)dx_Lb;GuCBCRXtW?^Se5BD+%8&km29yoc!ey!?V>V=CAXN6 z{DS69S>rS{Kc`khh9z?5W>vr*Wk&3|FV7Dx38tr5Rq!BGw(;jR#(Z#KQIz{K9rnx%X zlikY+M;k3Mk~hMwN0w9+BaIMsI_#e!QIBh$HeXXNcQ}2#Aw}12?r3wgD?3}aPrcIN z>H$Z`d4@Q7zQ_$|@(|eGAc+*wS<8G)UWnry;5I@$dI%qt>NHAD4jhKxnlcj6V0ZRh zw#(XBo};Cu(qkUDkZU%FqA3gYxE>s1hOR@V4h`~R|FoF0q*7|rZM!x z9ZNDeQTm4)9)ZIqoW;uvET9n_b9pk(sc^RnRKbr z@^$!7jx#U#NmlDnnc2iSP04b%;}e**XV{X*Pwe$4uDA8Qs$Lbo5fR!0Z^KL$ZXcJC zOGYaJ6O3em{mzwmO(%;XnUWRB-Sq0MnXWMx3n*5EF5x;*!f7+KGkR7>qvE+V<@1 z2>RCAo-wieSFcxFj*$RnTc~pp%y_rK%=M(Dtg`?we`V~=8!e7>F+Vl=ZvSGM7L#z) z6VIDf&u~b_;Xzugu@#M9Dx##ICs%$~3~cE7z?gikZyp3r(I z;xz!2MZg*+Si->%Mk>9%QDI-7g)$;`t>S_oV2JuvDN?Mu^u2F_04&>ISe_z%0FDak zv0=8ROR82Adx9DC}|h_5K6Kj4x^eY4rx`vllQK zk~u$z%rc}S!7N!IX*+3Y!2}QM9OGk$!)52UL1VVE@zIf}mgV#A7umY#88KExOgc)C z;Yr7mmQtbO>_idJ^NBYZKH?Yg{VuZ8c9eFXcc(YG7gs#B4!oesy*4`VQb=w2aVHs| zmFUIH>_C0ZBN4%?{b_jNRULLGKkaY1b#te@C@HB%RByR*KX9VPI&LHEXhk6@g!PC8hI^UDR ztCWCj(}uf&S(R`PeEU_%_5NkcttrKf!zWQ~0RcWKy7|fsG7Mbt4E;gGT-)L@3bt9T zg2F;a#Vi}$V)N(7?cd_C*OEk4@Eo1sex9lRjNmFlbG$zjt95xo&L^73_p1l$T%+0F z#;ki3`W-JmPoPKEy^I^~gS7AF6SHrJ%e=|-0fKV9JC2np>ZC@2R}a!6MX$z6ol}0Q z=)jMak_?l}8j&4g>HU-p`srB`;|q6>o2ath$ec+1g9x~!2eXknYX0F6J&r&Ye877V zp!qPGBQimDh~~$>5U2O;%dB+L!PH*kI1ozUEJx#%&9Vb8OL@7q+x7$WT&0Qc^dnTQ z9wbG|cjn=vUMimq${0I&P5E#z%B}}TkhA7tlf1n`q@@Xz2XW7`-s+9*e3YUedDZIiFse8et@lg;493@QGb>m(K{8&KWsaUB zneAUeh*b7=IA?NP4+99*I9~7O?KTWxl?r`@p#(t`)Q;CIzVp2EY@*nA`<49ipNGX6 z*?)AV#7dW8eVU~8mE-4f+L=)hn#+9!xGmYvKP!gq4zGwH%R7X6cY3Rj?NjYyW;LC- zlNbwjc*bO0@4Q2=!3yH^Z08r$9w~fH>r!h)N+Io%zP@w;FSbqlwu3Pv;cW-o|GE$T3!ys(G=~kX2Te2E3GudY^nQ3&fty593{eL&MZtz)+EndMI=))&q zqk+{&6gZvm&r;0PEo~GPS>JdB?k|AQz?L4TQySdLWoz3M44npO zCZ)IWSZTY#Cys9l*epDEg({}#H!iY@JIJha7%Zc$TC2LkQwF~mvZ$h$JqSZBeS$Z! z_1GCQ-H45{UAYH#_C+g_a`Idl;(D^6S-YUbVJxA8tP-lV>1DNbCwH88@9VU{2sU!w zs=`0#o&&`1M}W_7cHPkzt#umUT-5ONJD?OiPygEzo2U++M~00nUF?pLc128MP)?|$ zcP;reI-&zyy-j)`D3Ym~1zqTQiF}z?ag6&_wDkH6QZ*9O#SF-{dB*B^qdu-RHTlIGXvJvt-X(Tu|ms(~|So6zn zf7$LkZnvg2LOXNay|1)B*Khuo42D10@$P`RRY4!jjD%dPn;#;udD7paox}4;L|{T0 zI2ald;Icr|zl=tLeH#MD2|%$~=fQw34UU=n{q&kNivO|IC}`*^AKgPnQ4UJ>(^tui zTlR&VXWkMEB1MyxswmTR?vm9}15Oh3rk)0K^)ChYenQFyw|?J*<{vzd`MjCvH(l=U zjtR3S-ocK)TfgdWg!t!>Ftx$!|Ce#`KXl^AAA_brDvQP1+wEMj!IW2W4szg?W+v)b8Vj)mQ)xy10Zje6-eP~Ox0vh{Lq%0ppV8fwj&5cB z@^eevjYSO1&KG=OX;X0)qKEtYw=s<3zeU#X6@z5q9^5>(E3b|)Vb4SHK(PQL{fxHd z)mT}heB5^gKs{wu$_^ z_wNOGp!Df7v;~TxCcyWiqO`Y>k>DLBlfOrs7N)d4pfNKuX{WML?sZu0X z?0Eb8NAkYaMUTholgM)6M(wI(Tn^i;obm<-=zkM!NYq>J()c9dv<9$@i7EZ7M1t_c z4|je(U@ds~TOmf3qr*?!N1D|PDH1W50gwDY;IFN-6qwyVr6oPsdogdb%KqtFvED&& zM}T*KYnoFy;s%M?(0M`@<$+D6RTbk)1G&M~Pz8NL8R>odYw>nFr-It=a7PlPM z3~H&>yH>b?3X$HY9j!OUi{I1X}JsdJta;OiPJF{2n(emNtTNt&fn@(bR6{q0JrgA3mnEZ%0Mh z2*fu`Hp9ofgOOI3=A75AaBvE_IaU~p8G>zCGm)_&$9VPnYPl2=x;`XQ5 z0&{l3i4Sz+S>fBgt~MWt(a6#Jrxq++s?owf5Fic_x-7a{^CL{&^%2KQKx589)haiE z#RfsxxO=rnWm9$QjnIe#?|JR0;K1h~9pmHr)y!V63$~FBS%dY|^?AYU=;FGpL@{iU z+K_P(tLKs`Wx6B&&zh9cXX_^4Y{68%$vA_!Hc<^ioaa&&;BLC1NCUUp)U>eL;U= zq|krb@FE_CD(FaDDZGF5CD=4Nvc~4b2Jaq-JOQuglYI2&L7Ar(e1rWHCH@mMALF2) zLI}S5?wr^?we^V<4f55)72^)hWHhCrGz+;_1g415bBLs;VH!b5AKFe~8pe#S;kp7( zc5Foxpkj}kj3K|k8cNMF{+VOwcR*>dzdt*-+4G$xWjT>icQ@B`_DZ&e6fU8FcZ$wr z9!y%jJ#3d?b?K6z_2LWJ0O8TKeN_3iAu1_pbG!<{Si{Y8ZT`d;MJ{g!GhJd2jA>oA zoAJ8B^$AM7Gd~t&G#wXlnc7FJXIIM}?)QFeI@yE>OH&vW4jfv02dEV0aL+$2@AF4|Tt< z;kuh7YRVRxTyIDAJW~>#IZUm}i~pEX!}WMQ$3Juvc2X&O?6S+`0#UWD*5-4;h-^AV z!15uc7T^wjpm~|4!IG}jL)P2V=@IUOSwvM!>GA1EwK_6D@@LgU0c-fr;|_u+2wK>8 zBk1jp?SnH4R>aI7cit1PAm%rEoKtKM5VYGyz-5c|d;HnacWxf=er9GQESnX{Uw^?h z{h10(GmWwG&6jpMh{`2W4r&5rsx}pHi%uk}o2PkA%6xYf*7bg4Go0GEAx49NcyYy# zIPzf5`>hF{Pg1C~e1iLI?2ysllQw0rL_PyxL-*FLN?h2_A1Mh6acqHWFBb1&w9z$} zsK2TjUNiJJSEbfS(=X?<5iRROv^l-(FgJ&Iqz3O*dT`qJR#hBBGT5uowt+gGc?^@x zo{SUCDwm-Tul*_YcyIJ#lLRWqwPe%E_?fe-2m74iQfdln!5+>|jEyXWEk-ur=2t(I@d?us#O*zNRrV=_C`2*V1sJmbI(wdQ z-2%eH`xRq##fe0=Ru4bn)1IFqi1xiGBO1@cWbMaxc>V_3N5_D71Q)Jq{=BHv3{M6f zV&e9@e#CZB+J5p`d7V8(x<0@C_1W70F{ zuVYHz|AiWmZ-%Odmr~Aut2w0SGVFf?Nc>w}|5xa;4%oi`PyehiCf=W&U)0%$F_Wc| zKGw};SZ#OG&p-1^AeYnVWTt!jwmU8^!qg0S4_PbcS%mFM$43h=@=ydw_A~J)G?3xJ zX#YqL zscd|S({68PN5}Z4Yuh1OEH9Y$ld99R!3t(+ya{F`d|10|`u53mZtg}nXDplXt}Mmx zw)O@(|KYwbQAk&tF%a|y94JgF&HR*#sVv%8Mny>%tiYN;2?$v^HN>ea>8Z?b4+l95 zk@zLy6Rr%N;zsm55_R{oq#x|K|0&7%GpIg2J}K$h<3JNjbBcjaf8Rp5RG(KWRvc}4 zT7qVRs~Q+?n)=wnJw__m%8Umu0(4;I1Z*U&c+1cV5kaV=HC3`(uD`PB}SSTQfP+DDW5`k5)M* z4)T(=x3eom33xoD;KIL1-dk>&X2LFFE5D-qm$JWG?!-j)m^cDg4~_={4PoI!PC*fq zUyS`W4M7kGUN=vS4bikC%!gIj*DGWyh;C$4@3d(pEw zwV9=lOfZF_j6R=kwmpafU=*}OvW-WqtoBMljoF(sP82z{eyTqb*f<(zDi8o9oP|aj zNAvB9w=}Y6rACxho(?TsjSs&MSSBwE60U%^7k%GSzi)IEnURzvINM@C%hYn%v2NKc zPOae5ME;+!fSu^>WjKEjFv8aWE#)BU7ZW=1EJTy*KsEg?&j~yWd1K{If<>#kS_-#shMwhX^j5p_$Mc0&1$M z&+N;M;^VtXM{hG6`U+BGYkU+nK{-Cv*HQxJc6o_mi~%oGYxi7tb*apVeq`5T#g*p# zYr=KA-ZzFVl?R96cQh>g0a>+%tGxylhV?5PdbPG8mX9ubDAJRBvlaQTA@}v+=d(k7 zJl$ubl=P~eIBa1%GZS9hk*s0$)~Ao56iPm$`)#2YrlsJ~q(<4FnLE8_Mcf7Ir({!x z`^!3lyo(&}OZ)+}t+mm}?Le@LloJO2gGJ0Y51hF(RAIucXT$ydda$n_Q2_i-#iKX$ z;Eol*$rbP4c7m`-c+R)r0&Uc{4!#Vc9~??tb@6zXhBhPCJ)9*t6?)yy&(ogHpOo8u z6yPc4=HN4P*)&Wa%0$H$x#gxIc*T981X)M9HY2bUtvwovVP^4=(yj>1l?2)D?4vqF z3(318)7}@?hT}{tLi5Xy#@6Yr`FpdXKDN;0wiS+r!4W%T4=ixtOT)`-xhOCeZ~7 z;NgY7RDP$g(ZacF{OGRHLY(X;b#)0#ONJ{Pz?QwvV1=zFDDOWjYJa59X@#W?yLYSZ zjX>og`l>3COQjZ35-B&V4oj?uXF6u+90kzUH}W#=QMSzzh;-MYn{dknOsaJ# zS);wMOE)Kv(@94-hxF$vM=p=yzZVF#!fZLdJgLW`#SvBm+R8&TS1TzC%5rMX($c6B zW{wDEQ+;xrvP|C_c`OYL>nOFV&hE&MAu*r1dVLlNyjVOH`468y$ybz%hEQiz^s|zb z0lDi!KLRtmwxOYXSYd--7nP3$|aNJxS&n>kP?h&H`0be*VIOk=5&?O@OF_o*A-n^g@c$lmlwBBQOjq zO%|s;z)dp_axYzY6FS(X=t~g+048Em?H+K##k4>9ZABpgY)dLmi&SS*%pB8xkF}-olGoO_c4jP6B$y

    #@9+~@P^#$tA1;G5AaDQz1Hgsbrb?{RTkU(#B=39oBv4GsFz z)F}&Ep7KqigY|_$HUmjlGqq^@w2`sYf-o9YLY^NGA_a1d{)uh=y+R%#(fOWrhOZrX zU&!$~Q97AzxyiIFFE8@sicTN&A``rz6+Bf3#Sr~pZ4lp)DLjCA)^JlUe7wHVcj~)z zA`^O1PQp9hkF4uotG-1S=W#xB-qH}S?2$H#y}I9cdxF8SVBFEz%d~#+N+CtrA$h?I z1^uG|E%U(Ahd#9d&nL8cnTs+8@seRCI@a!^vwOwC6 z9Ex#&C>?e0{CQdCbuNVBbu;jm3uv4;7}B~Rm|XD>h!D{P36Tj#JydhF=9w6p!7PdL?j41j$ANUhjDTBdN2I zwRbN*Q|(=uC`@ne60SPVb@9p`Poihpd^^4`ij%2#-6X2!au(%bdn*Gt1<*)S;N;iX zo_hqF)G}nx2?5e76SoxxXKIUf*_RrxTopLJMlHic% z+8L#Aj}P9LC;Tv2zu*I(PYo zB5ThmA&S(p)eTfJFJsXuI=L$9+E*VW=rL}igd(WQ#g@5%b(x!Qx$iYFC@G%T;aLh_ z$Rb`2)QgUbla?IpZcn8Crwf#|erjDevi!q-9rz`*ts9*sLZm)80q=vB$4uhonEgi~ zFNs<%5-vS60Uz3*j&1F83jgO^;x04&!MCj~7yByv-~lL?S2r}fz(O@y$ToVa#woV{ zLA^FkpzZz#k!cXoL*(avL%*q-vurxizt_e$71Z!j=wlMReg~mveyHhu-o9egAGAx8 z=v5Fj$;dHVTXzc)rbK?P_g&%+0{(8>?GhSwnvr*-2C?J$F^=ku@y$rBF8#B%2_*zM z%Jh;D9>u?~F`&WNzqU%V3t470Yxfl`IAUU@jlHpfMH(-^^Sw+>+O;MVV}4v>Vp!_E ze=;pP83|0NxR}z4>4S^~Cpb`nZwKF7X>*pp1N(r3I&qsaEzoKgkoQ4;=-?{1sQL@t z_r$Khb@xtNf3c24q%b!m)`Zw_Bg+mW_cxAjvyZ8!BOe!b0@BETJc`0@Vj7&8g#m_} zga*8U4pv)agAy8Dyx`#U`G8KqOx(Re2?crW$m!jBAjX*$NR42{#{ZasA$g zwu|1AyAa2pW<{Hr&?A#C+7J$oU9p*0G%14ZW%SsaEDX6g<=3D7J#Tg@%+lxtx*7yC zsf3Sx^mLOqq|w4jMzu|VK~pb!D*65eJg1Sr#AKC=d&{0Fgd9|0RbBYs;x0J&e8*62n2!?+(WS7?hxGFHMrBbd$8c{65JuUy9Kx4u8lYD4MXyOp8MW+ z-uq!@e)FZfPxm=>YVT9EYu8$9_jd(3aU=vh1ONblBq<@H1OUKx0|3x%@X)W{6sv4> zzP`aY3Q4NK!^1Cc%5S_L;yQ_HI4J{7om>qZOaNxKKpPV}MIYhEwkGtzf6eMA zD>*}$S9(OT3SU{%nfwDL0~y~Nv8Ia(bvwcRYn6E%>{t$}&{K-w7xS&B_upK*{u=&j z!x7wkg6Mx4h=;$Y@bBG80|&62WEa0ClrqZ7WT;TU0YX;imRBv9a0^Ko11B$YsCsHv zoW#%Za?Qg`77n5eEzz*uPx;yqh!YLvTVQ@(4_X8;=3@ilTvfj z=QOs~)>f2MH7ywjBZSS93wapOI zP8*i>Yse84O~H3NkouD6y)>dhX{_ai{d_ioyN!xZrCI5bh1f*A4765bHz(TjRa&Xp z_`BBSvn@r3QWq<(zR#Njtc9m?t-|LQk@Iy?(0`qmMkW=MF|qCL-62_}Ns$=ZPZmAM zLtQWXl_*T<0~S_JNwZ@w_!fnL>F}|fLU`^Nmc8tQSsn>%VkoPNTz4Fog}s4N)7HQ0R&o1V^-Y;6{9EJUJw*mE}Fswn%Q~A_zQlK79rKMs9&y1`W`(3B|z&0hg2o{OO}Y< zgRQ2a@-)=km=QNtBm%Q)*yk)yA&MB`slGnv1`YwaAMei|A(h2&gdZPwDDxPUL4eR$Pd%eRY$V!Z)qv*x-n+2n&3u7oxA{l_~$8Z$+${v56O zeAx3RBl7RE5j+0715@pv2q(P0A%P~@UA5mTk(N(!Mu|KnM9yy)vEHp>83}wwn948i zSH8~2S+Wx|%X$K{2jdKueVw*hI6wJ{;_bL!M%_yLX8`HRDQT7D+_QI92IchJ8(f-f z)&})-POVyH1&+QEP(sC$zLs~BjG3a|WiAjJXDqK==WKq53E1G2n+Ha`M^UEP0h~Qq zB)ntQBTHV!w-hI8)Ry_q0=F(k@K-$J1m&B z0j&Z6PAjF^FA$oq+!N0?6N$6{z`M+sXMGT2SB_1S&%??zosdt&zh5>=!rT@Eds0pDgNH>;T-L`C0A`SnT*1 z$>L(g7upEd8KOA!?yqK~wG14l=6WLFgLG(fpXRb!!dO73R~}G+H)xBW!!ByKgg+&$ z+tlvkG5C6StPMz_V^!(02x!ug618r2A23X?M)Ki*p~b4A)zS0F@hT4xiRI!@9==)e z{WUV4#>Jq0eYV$?0iQzwJW1=v#iKT>t-adbDs8LaNun$>hCb8qIHDQPEIGUkiw|$W zGA$L}G30NO&2;9F8a}<@53@HH(BW{zz(W+eGzXy9Y~*!n12PIO!q>A{DCxCzQu@_%2i#r>4aJ#NITt7cOeQj_+g)DPD<72*@eL!lL?xQ`*^mw+m!HzG#0v-Maz=1?Lx* zN)rPBc2QYNV(rOnhixkxBWcdK+*djxhB`N;6?3QSdiy5sX}dt6e&Nkg+9BR2NsCMN z_FfGi_33{2kIF3QWH`!Z$|33-%o=ZfQJ5j#9u&G5?QWn(5e_h4u>~9QxX?Q_l!(wk zVsiG^oZ)G5A+T6sU~=yF*bI69Zsp?PK4cY^?z80jU8d}!Qe)-jmrM>a79I+IdKvhQ z(6RM4GP=Gw`zk3E=GYVBU2(WJ-sC$b*!@+$l^6YjjWjU5#ok;)YL1LJzNYrm@>!#G&kNu~O6 zmhg}gxS1?YTW&FriIGh_0P}{JvzjO@Ga&7nnD0GMR?@cCIU=i;HIsztO`^q>>o=<&gJR;W*IHscd7 z2u56(N5a^rh(}|n+m-UvLtUL`#6{p``co{Lfsj7{V4fBh6#=hSp4aM{@nK-lT#VsI z%t)Znm+a?7U|y;qa=%6GPy$U}2XMhYRcZI{#UJLmN^k<<$*W>G&|06rs=nKNj_DZZ}Ed)`ueSgnIwLFUhKp zq`=Cwo5mzUUbPd{{4UCLmg$+ikrr+!fM4zJ41Om`o}G`ZMOC~`B0nq5Pa{S@r88q= z;~&uz@Te|sZ$@fOD91{`46|^Uj79^&(_emnXC1veSA5hqqVL@h}{Z1XDhy?jat$6C@ryGkKXW zs?{Aa=3DJ3C#BbL*j9)ORgP)pM>Bv*6Drw7&k9+xp?#$?&C??U>mBJO0eZORJ)WXc!VE ze`#cypL^xWbRYEPhdrp`eL&-gP5W;gsM=REzf)VN%_w77yYcGj2uWGZ^!h7k9a>^2 z&n)2`6%{a`deGU^7a48&tf5X-8jVb)}AH)wswNgZRb^kfTIT9+<52 zG}B22Q@2Ofnei`Wk2;rk-y(Y4TF(!Hr7!nnf8KJoj*UBzpu)qu*|2ku1;I*Tfz%#+|nh$h-!CRU7KNfKBy$O6rMaIVKu;KHY9!T?1))|K)| zshasTdL^uhn)ELWt}$`(uL%x;1A~0$`pf9&7bFCBqoBdOkG;JXX*Em745xZT;X_|1 zZ%xNi*B9puYf}J%l`8$8C=lO3t7-(!TEE?R^3k8^Jp{djCuMyi!At zvFg^{KXe-l+gJkL%))Z6RwjVh?=@|QMkUF)*ohh3J98i~2NKcQ5G)iW84Q9fe3azG6!^7vtM)VqU>rVx*Q;s@1+8rMuaI;1$zdp(g%O+!xTr?dw+eafyDLI;j zrrWqMz{TzFE0nhTO3VlDR?rVCXqj0gycKmk~0sv|n$5M7kP6a*_y{zki zIbog+*lA)&$rPKuoJ(P9dk^488GpX=WoefJN_-Qy^&Hm&xFHR7k?%>e@A#FVDgZ>_ z{dYH3T}?Qi{<5X?!t8L5uvspjfAW&t+g&Y(F=+pl*R;*s`>cZ4>V^sM!*%t}%GEiI z^D%_fLX_0;)Dr(&g0VLN0Bx9(DbuiFi4#zugM~}PPi>J9OGK$a%ig+sk50unb*<2{ zq-~>CMnOSOZ9*|pgWTF)UoDrTVqv%q^`pJnesn?-KIh$KLqamI%vxNm&easd-gUZn z?oYdBfW{0Y?lYlJ)Z77qj`c#D4LI-+$Jgp$X!*;j!+GOsD{xo~hs_m|_KQ9~8f!%7 z7MbYay@w{Z%fTRcR|x_!#r}*iQ*1H5zB~g$)Iu>MBpRZ-bTh&aV_D($5UMtCSJT-m zw@Xj=Adpv@3W3d`__oS`F%6*YjRMU_j_lHW?&S2qRg_XIed9G&^t@fx`kI5}X1tur zhi@y_C(aP}~V}i{?XCyaCTJ%Q;qbID7l(DGL1S57| zqyqA0L3?k)A`L{D_~*8pAwZWAa$0|Zn0bX^lf$#0Yy6OWuuVBKN_zPl1m51X8mxGO z1@-~8+IIlf>T`gOCky?zfXV#ra<;)2W3XNaIR_hs4Bah{6WuLX?{nwu!3N-|Vs~9f z9cw~PLPnYU@x38Jz%I2H;U`ZN&#;XkTgFnY{IqjQX68GAe#jCKlbg&a1MI9jYUyl%GtCxuRDW zW@gPmoHLo1pxb}= zCxCfIv9R|(4Gua)ogP|&Cf1qljA%`mjWtmLU+-jjr+@oAmwjAQm3G9~R_?_O8Gl_< z+|uYXTdQa#lt*AYV);07o#SG+w~PiX3G>Q$n?@Sk?gOs+excR}I%^`?WSSyFHzImv z`imL#{C(z|0lfb{^Eb)Sf1n)&Kt{JaD3taA=F4MUXSjXAC* zc82{>a=xgjY{F?PuXvlH2=J0pEA_Y}d*5h^zKjSAMN;i~-%>`qK>M7q7kIa8hx~=2 zCf#Jl*9HKSt82`fs-%Hy=9t;n4BfYct9H@u9|EGl(8zJo@Z|T<-a=m`c=E4MlkNK;(x~ zN){D34hYLS<^0>ZNmc{g@r5^Y;|EdOvLTlWdTMd0=>qpVKmi?``*LBCgo9%F|LyQ=Za78GYSQve5F;ZbSK*f$7CoP9$I5|2H26J@{8eiJN4*y@oXP*af&e6Q3Rp(fn(hOKnH{%}vlS zyYv|{DX+amXduw*=0_-}N(JgKHv?t_r{miBZ>VWLm?(fg=3S>j|G)h&3>mS-b(80m z3q-Bw79zt^{C)INz&%nUm#kehhtE7q$b474x+2B!iPEr9l@GQop*`D% zwaGT{ArRk|IRWR7qn1^^)n%%ub5;;#7o@<+@P4+;v{Tgo_%&S2v^;yC8s;5l$jr%Q z=QA<qmgZuZ%JL zWJ>CSSJ=h*dVXYLZPqhr>fY+Y(eR^?3GbXqll@f$7qIt?83r36d8AKh82FkmI~VTw z&mjT?^O+D4u_w}V)DUo_AFp9TP7fDI)QP8MN_52RlLnSuf#M>2W;Et$Z%$FfJh#(X z*!VXJD(}l|EH*7apgeeYYjG$zo1c36a;XF4Y-UbgQKoA*=!T`(>p5}!xRkWKY;Rrg zCsKD}pBmaFFUNVP!BP~&?Ff$Nx-y{==uh$*T6LTZTr#8F9{6Ri*pPEGAlP|+{*l3H zGvUKOlf|RHo$D2hJG+M<7irU=wfkAgx~WYF;=uwMfXlRK(RgHvyQ5LN_pM;P%C_a+ zX{N>6kJJE?fS3ihdZ~?LTTAfuFgggcy_H&7GJpt9&$#;r3D$xJ=&Bqq857g^P+>B~ z3)tY*i`JfB(^>s-In3Hz7LFB&K^7q)8y<<;?3uRA{ctTN{o~bt=q;~DbwrZKevS)@C}=5MhBKO-@Oa=^_SD(h9}S=jCoAcyaN%IPVI+}|2-|{^z}U{C8edsi z;&2K>WT^Q%I1o^$Fg`hJu{~(Y@N$zx@WFp`)ueyd3hh5pYCln2@i%^)AnwNHqyDI_ z^h6Cq^vo{*>w|{4x|Y-Gcw9J1{xo!QQmah6U>EQ*ub!M;{cN~py4$BS=Ym`g)uV|w zL0mS85XbJ_X5n&CPCMI+;JdNSA!NE+V&S`-*h_gt5I}yKw-u4f!n(_sSzfj`n)A93 zj?UJ&dTy;1o;AR{LRL}oy*WZS>52&ZVe+@RL9FMU<>nkFJgzCOEyq34^M$priO#kX z-#Vpt4EzhT#2hNcQApTOp?O;(J|{sy8qdTM#N3>+oRYzNC#e9XF&#$WhWPjqDs{e> zox_(yFdmg@C68mi5OM9(Ab4D@Ut~x!I|zT#(hz8QsDqoFl7Klj6EYfF*gdUKW%LDN zoU(29+W*3%>8y6wu{zUPah{89M~B&2Y~7D7i2oIV{duL4Mai%#^jn9&vL+|$;}-1Q z9jknRMYit=tDhplyz`@)W{G2PVMnIhopU){Tx3pF66+$kYf>P^Kog?;@O+0I1cTzh zTao|>WeuOhq?dY^eEtpqFrc#RlVvqZG_Yakfph5aLm^S2>3c)4q}Ll$p!ZD=g7)QN zI`eb9gwg$4aOhUO=160OB3|xg+$cyZ-6I%w8_0bDUjNMqZSoXA$a68B%wSo}H^r+4 z0dy^$AR}XXK?z8Nb80&}57zYU^wo*9(?kv8;+J{i#vob2aymg?_n+%kY(G(HRDZ!Y ziACW5vpkXpLZ{mOvDaq30T(c!fg*~N9Z&I5(75`*y*e5>EZ$K`BvMy6Y${CQ6V$kg zD<7YU(J%Yx)q`D5pY>HEY%Kzq0*#_5QiDsxFy%k&r1N$lFvstxyb`C~gms+rGDw{fNN5gQ-*W3P| zdf^Qd$06n&8f4@~vjVigzS23&@tNx;W~8-S<|uSomK_Dl(wu9Y*dmi3!hbqoo^-&&pCZnbmx2RjA*8+Gh~8^Bwp#= zf1EI5V91qlPN4u0kvu3dJgZN7HubGX0{BsZY#+}{QxZmvEwBLqMU(PJwNPEWOgyQl zr2!8Z4o0Bij(unIUI(?!7vu4kS+rFOV!9-5a5m=>ELqYvCmHfAd7pG3f=?IYf_;Mf z=(^rz7ptSs=oX5A%zlHN;TQdb=dkgcE_Gio*zoZUsM*ngEg_ReZQ8R(sJlRHqU_@0 z4j^t4PMFqDpD`ISCDB2V@UHdcCBxmPsHr1jVED?|EZf{~cT$A$WuKy@KBT=MBDRXW zhbVp<$>TT_0f}Q!35H7Fj3z{IFu?1I{!0~!`)R9yPPSqD!$DE#v|e>_WcA#0eOIK; z*{H@#^F!%MJ=Nu{((7RSWHM!#cHKxXvuf=4thj*bz=DZj zy8$;H%-iO%t9LdBi_s?9QJJpl?TGM^u->&)ykV-U-EAMg!TdZUKZSFAQQ5OL|0>J> z8wvg^XZk*~W)~YchJ}Jl-|+YZ=I=Cpe`ZV(H~~URB9F7H7b4jX8lg@ZB^YK=l}^ya zZ={p8UtenntNjS<%QF<-Cce1jJj%$Rh(8n6W*?om+lvau;wa#N&8qpp%bP56r=RZ+3b)5$*f*WyEaBI#_10K>r*3;=casZl@!O;$kl z9jJouyfvO~6L#JE^UZTsRVk5dE{4hJUHGS@DghpWric#(a?*$gK2(cmwVg;B!Wb|B zGG{d(pVQG4M%-xov~_j7nSZqa9(Z6?J?}{# z&t;w%R7Rx_$DOK3%?g)6AIGq>=n3x*<;h$c)U#G~?_UXnMmd3N--aTuiR|HTDyU69 zRxu4Z@HdK4s$ffWZQa zpf|`~r}lO6QKKo;Crx^ewI`bp5;l0FaX~T8L>Kc)zt5q5mmqNVCj(c_pqmcv&2m3y?uD|&2ox^uqv-}C8dRBp0(m}!aaPq%f z+zf*#Y&I{p>VMC}RmnbQT+VmbmQ#nLroFXZAHxVKC6FilIDIE7Isz)P#DwmwzrN^z z;kXtiR^2(d^RaI`A1=z)n@0E__(BhWVBAl)leGIG%XjAsNGNi??uA3b)JjPedP(Ux zq}$e+Y{~M;vsaH|W$Yh?NU_7II_rxnw?>=hivZ9m+;v zNszHF^Q5PE@%#d5@Ako10JD;(twzx3cc?@6G==y^m$9w)kqNbni=?%z(5{7yw&yJY zD|Zr!5fjZi_tIe8Z+y4Te6Dgn=ml2a=_i{h|p;qa=3R03(!QGGOtHFM3oa_BY9 zFjcmwihMR#-h2wtf4>60Dn`flg9d11k8IlUvfY0R9Mfe|pYw2;NDcP)7&8@S04T&x z%zfYm79%({f*TK30AFkIvRT=?W{Ed7ZYl_QWW;9HAdj%nP=$(rb~RT^MqWhGgS$6P zc)+!&F%9AptZ(B`CeaSdzQ`wQ<+Hcw=t|%PoXp`Kd(~m1uJbOYG9$TyeUi}ozuf9yC z{}u5r(Qa-$EvzOz(| zR#(>9KK1MS3A^^04AW-F0EI{ij<9x~zY-0HoLdu_5JY?DMpcHQ{aP6$wV_ zG5>}|QfIq&>Qa?esZ|1b!PxQ@veCV+qEaWI(PoYY0+ zbv$)(d066K>&+EkI&}RHB&5{Odp0P<=yJ#XD%LF1`(>V_lJ2?XweE1KVNFP7z@rn` z#xW)(#F+?mT2?jF!fBTLnZ}M!SQ=3|%(XI=?iP0`{R%a!m;g`MZ`?RAwgmSbT0}{0 zN$=;Bd`LBwqWRXb44aubdo4h42bXI|rg!K8t7tkQJ|4sIQfT7~0kNKr2SU|}ko4Ij zr=*0ERB>5#+bq}4kJgHYsno0tOb^ZF38V^giQ(Wt@(K7`R$U91H$Glo!A?O{jm?Yg z4PP%E4wo`Rbmx9ZwiF>f!7^wy_Z&D8@z@7MTl_^Z+DYLB$hp{}fEK@-0f0~yLVVL^ z?;VM}baYf~>^SWGdt&z;f=iJVJf1*QdOF**vHqYXh9g|23r!PHpT6MZ~aFzLD zqCF6UBj#cX`r0|0!Oyz3>+mhlFv9ET6UgO3f z(`TwJW5-Gt$*6pqSz&hj1wG9Lg`xrWJe4|sS7(swHU=$Lq=(BUs%W{F%NiL~x(^e; z(uPjsaquWGLA>ue(F=6RwlWIUpnV&%dTyPGUi=y7vZP9<`SN1V_Tg(#*`?2JVj0R~ z`Fx6jF5j#PkP+TrT&RkHhWn*L9t+TqeP%JIq^`F5atFZyRcjO4 zzFiRvGBYWWRec0IX>j`Oeg42SWW^HydC9Vs`|(Y!p>T;@9yk5;6!2YmIF<@WxS`Qb zOR#OSz>2)IDyg9%V_GCV;75-V3z^LA&HU98*H86T+Yws1&>gl0*+Yak%CN8Ezjm^e zB#alw^+`|ne5ry^zuKZ@#wj+Q6~0VvmnfaW1dN95hg9vfNcTnj^%44M)ocNemM_%U z=snW(&j;(6D3~BO<{?gg-Wv9@NSIW?E;t;`lhs(tP{WJ)3eAMlq{}~>xne~u=~M-S zSIUoOR|tBXKQj^L?5G|>8#s*V04?l5ENtYHsV(&kTG&Vj^3OAy&Ypl9y?sH;n1=GNc`#D7?p*i^Ctb08yB#lLys+yZ-}sg zo0R)*;X~H~cNx8tnr@sqGvZv;8k*3vR~`M?Y{{z9|kVC+Y6oFp!Nt>Ay=bH_qQ zDRBHZj~}{(O0{EB`GVrcvi2I&F(M~fq9j-P?s*6A3iNu;beePf7uZrXuf7%W%DoVMqoGBQtO#kDQZSfugAgQxf(WC$b-x< z=zp^}H9g>;j?OiggFg>iB*owoQ_-vhWuW7P*^N(L$a(o#51D*wDo4fhWzx}RVkH%$tEt>H{JJFR z%+RbLL}4rAMBo=R01zgBDe0mmF@~c(!AM^=^yH>b1j-XI%1yX>1Kd8J0>f_6+RzP% zHrK{gxv=w(fBGI@qx2~$P3QTs0X%xE)x=PTB}_~{!9hu zTL~3Mbrg-*$%VxCQJK7*Tm6ht^KWYF40C7J5_Xel8G%&luKt;!M9qASOlpast< z;lpjPu&NLMn?A&``i_;dNmuA6ac9aEf=-huiFoHB%QG;4XH{`AtoE7|@#vr7_PXb7 z^<7V>CvoY&?Z}=sG3|%8IamuPv<+FEK$|^|Jo32J#nppT+_hdHvP>QrhyUnv(#s7a zPWi!G1J#mw0m4j*)Wuw0b+YEIJl9j)d^9iOlIm5bvDe~yCIRXTAk?I@n*HBtMUF9A zL;|#+0djJQz~S!iBr7p@oiy%GwKoZ*3Y(kGS#5kfY8bwcnKa&W(@h_Uy)z6qL_YgJD0md03R`WgTS^Zs6=882^xdP6bV-vFN5U8;-h=Xsj1RCUE$C5Z{LAWu4^005+@5=R!h zFZdg62wIh=&<-3w@@2M*g+#}dvec4s86~E|>TQ$>ta9j8&4Vu4*x7xa&IemvP7F0~ z9wO6uS4!aiz*SWr(-_ddYlJZ*giwx+y}!O%W3TO<|7rAyZ+W%oKH_k#jyKj;-1dY! z>5wxE3&^ObFEN|y*>!k?U{DN<);F;;q{|-xb!zMd$qf|A8mIQ`)8DHBg9Qa^31yuJ zj+;juXgRbVbTb4gOvfN+JMO-`#J!fgBe2J3v;UH0bm*;`DC^f8b7tNs>gKa&BM7t9JUJM2Zj*od`-( z#v>xdG$S}EeHZ(1mA}v!Y#=`sx00WNYp~I9nEo|^M;96+s(fxD$=6X=lb45-N%r8F zCG`8j_`T!dY`D_QMe=mSgvr6t?^#&=!ej2o16h^)Ja8LFZqMTx zoRXHN=yeHe2laee!vd97PGl7%(`&Um`iItArB@Pm&T-!b&rB&TcQDE=u9)xmv2d_!?oBw)u`Y4}zKD2i zhFvi-MPDyDjj1!#x%pkM@H(-F?gXI4R(5L7fk?RnN~aPazM%Z}DdSGIbvQzap;b zTVVlBNpbdBad8>utlCA)#mRE!p}EZkC-+ANxD=$Mq#ME~CnsMTl0{y(s{jcJOR@Z% z%C$S*=4i%i-0qC-Xw3dBYwlbq#^rkzv)ddLifB46?D z4^QR5nZdB3^@onkQGc6S?b9Oc_7Szpb0cJDXQu`c8`I&w+Gw!j;jpapVV9vc$!6a3 zj@KU^0G~rm6ph;U`7de8Kxm_{uVS39LX%TG|I&`|DliFAUY-|Myi(D(8g`&^+A7Sp z&7#}qyid<_%@EK2s}+y`9i8%`5%wlWno|Hjv^Egj5kg~&C-PbQ0bHSftd^92Wweb)CfDf zBKy?xKe`Y#m6JlZF4mV)N(>)AM`sPZd3CugrkVBIq|{TYHBM~$gqKI+TcUP5(8vsj z&s`pIm`LvHs9>1L#wUB5)ZJNSaNNuWU5KS9F9nKTr3& zL#}0xiJ8ecI7+#MI+XFKLd@^d>hzPylldf+qg4W zVqXRUCH?adZ|}wQ3l=gVOmzOH_p~mSt4n>9F(V&`YvJhJJp&POq666fe(z zKL+%1JXxA8hi}Nu4LrMVO8bve-V{@`7g6$an_{6G5yFRh>yc^l*!I)o>UigdZbB0G zSlDF_%>0tJRasezFG6dFjY*=HU5hH~Cvac3B5?RoO$^)8em)Ff!3dDklQOI9AKRX? zPHi3_?wJNPwJss?YZ{Lq_OziwXABGqT;~`{aS}WUKG`Q6e-lt+`Q5XJMS(=h#~vpk2fdjEN0_l>5YJw zAAf6E+G7hjLxcj+nV_obtJd$`@VFU#)UsZsrm6(|nm!l%iQF9TGP#6>{qw3T7h&Rd zaK8`aYKpVqb!q(DjD8K*CD;02NsYn5I zDqQh1EfysgHQ!3UAG18NdQb3+c)owpMlK4*KSsXGtk%;n^v(-UQSq)L3v_4X()jiTFlmRIs8@NSugl1iRG0`P{1qzgXeFq&x3?y{_$V+tN(hq z(xk>$U97#WY_Gy>ME4lR=N35sH~xnUX|BWw(6#K2W8}2w&-}}&j+BXg1(@8wASV6| zwK>UizriEDT-w8OSvD^IhI=hYTn3nT%T}l9oZQT2tA|1NmzPOcv?GYu$h7PuH+;p` z*VEAa_Vp{3wb7KI?izwYH2Y!-Qhs)=ZsG^jKkUt1OD5P>2UF_FJM#MNf75L2uA=gx*g6{Qrco=j`}9vj50noH#gx>e%`$*cI#HU zCv!`mRW;R;Kpl=XF%kJDys`*9wN&4wq$F!-NxnX94_-K@A>?7J5dIS|{(z*D_ePQ)CWb22HtrU&Rx`+OvDR**=M`t zt@8bcJQs@J-AxS%n8e@2-TPN-gX+N~mK|~-H22>$Cm#L(@AW8pN@zKxGlZ`tS~-;e zM~&ST_oieon?W3P2mGeA37JP212ll4nCl;(u=2MZAOlEQ-S-1k*H`-pAEUR&M&FE+ z@e-XsE}kc;(LLQnPapa`-Xme$(lWgj2{EZy)kqDtO>Hx+AoV;4eF@BJal}9%pl+3#-wAoTI`M7pX#n4XS_aZZ zpi-_-&T3Y+>RC<-JfHK%h1@cm!$ly~3Ja^@4IN^1bBB^Spt1+!r9>>9Mf9_6g(waG=l<~I>NVLY2ScWZCM+LU>u8z9 zENkSqk|{AELbfBgNQ6WM6oh7F^*8<;UN=k9$xwhozMshvBD9v>uk%Ydg;vd3=mtxb!2Mggtf2hFR`s2 zy#eH8z>${z?}w=GPL4XOZ=r`NbvQB4UqI#c}=dYju(Ftv_5t$sr{99qF5OtdFdtEGtW5ikKYNw+Ig1pGDp0d@#;7X~t$~F;Ep{W+wO5zg+S=l!2FASR{SWgEkHq#WjS?c& z)@-_3xpyeCDlb6T?~@f+<<;ihSteD}zBup?D^knB98N^3H<=AwXQ9>z@V1Pwari#x5(-ec)UP%x`JDTY7ma7-9aKH_p2#7>C0VKC zUo?z|ZqD*a3M%;{z`vhzX9^Bm*SBJ|2YiJA@B{2dKca>aO~mYn&W z72EPa`qUNfBb`dHkXRRIuEU(QR~;U`5xZ6iPEbOC{S*B=oRru4jn5wgCsFG}KF~NF z$Trd3s&o^H!RK(S_Bl|=B|o0UZodlJh=6!Ov+LaMTTz!KMm@zDY-OMVaY@efZ{Aly zEQ+H`&jtn==L6X;s#j0|0AcHK(Tg)KBOi#LPsL)7%Drbgx8Hrpz;JGASwmIHrRtU4 ziWt|A&&I$gsWuuV1{m)d^8=6SxeX^<=DC7NH9# zzKM7(T9Qf(sMRFg_85En{=Mu6`-eGswV8r!!czN)+l22YF%W{_J}fusWc5rii(@k{dQYweLT^V!b^gt*@o`dI zd25DsQq#<)fw&&uW%dsdosuf|@L7M|(x422V3~%AuNI)QG;?lZa{8)ZBrfBFc!zm4TG}Q27BN3Lq-uIg zA>b?(anEET6glx-m(3BlvVyjC=8+jfLDvwGbJFW<;axz%U&BbI=S;WWGvIdvp2&2j0h z#G=B~N@>rVHMW^FRpOIh(Gx?e>iVzI(k|(tR$pBP?1>v#7^P4iF+QZ%L?c2&!k^x8 zGJd|D=n)n487?|zc7(&bNod?mw{WipqOXqI3RY{d(Qk2fA1nfKJNqN-R}%5cRM4+n zbu;6h)HdioIJ}(T7c_3q**;7W3|DksUT4J#nqBJ)c*T@!RqsK9q)6{Fk~*|%UGLxw z$ij4gde2dC+263~E&3J?@Yj6G*nHURbvh5DBgU4{uu_*DTAO|g`ehhhZNv&fE;igU z-MAL*%kKc2^qP_+ z?c|OF#-{I_6LN@koflU?-zs^Plqr?IJ=+lycM==@M2Q_M?nMQDKtsiA(t^T1ue6GRIJ zF-IvV!tV&TM|}UowsosZ@yXJ!?ehBFt<9uxdBV$EHKM19VMT;D+zT2lt<_gUzU@%s zTLgsjQ77+E`(mVB^`5sRATwa!lsSx7!L9tP5wO+4c>YYEpf?QZ9;`9e4C$`|Mq~X> z4-6$!a@;e%u$0$1!qW*H2Dvn6W-MED>iT@-%VX4&4V%i8gFe2bsjTQytKPoFV-+~> zl4*MdhIGvk;J0*G z@h%%^l0OFC{$GrJ1yCH_x94ENgA**cyF+kDaQEQu!CeP;3GVJ5+#x`4cXxMp+eyBB zZ{P0!)z(%~RLx9J&+Wd_=ltZ{QyT5b!Lu?H%_YZz2?#*fG~yY9L)vRe>(fMLHb+ws z1uR)uYJ;JkQ>(-;uAB0^3eD0}M~LUQA2}F zrHAbVfEbt+0SHnUWEZa>g5c8<4Ow1g0Y_fXBW<(lg1BtY7V1~kgy3$#AVQ*VpD zCxG-e42u6qbBy$bs%UZwL8_8uLa3DxfZQY{0-yv481@qsWU;0?-UY0NYXuf@mMd0S7zjr+akX&7H? zmtjr1Wb8B&i#@K>@rQ)_9jFfR=ru`Jx>aH<50B6P3#?4a6Q-+oC6(aiJ^jPFD6nhwM2C zj)K&M1biP!Ne(+V^JqWb{ygKaoE9TLx7slWr&-&cZYOe2m_qohwUlRw)Q;QWwNP@H zP4eB&@OT$djq^yq+zj2d|A^^uevDPLVz;~*ElF$;S><2Deg_C<%X}P4mI3n)Wn}^C zFJE*$H5;9FcoH|Kfq$;u64|@2oD$1PkH{=-ALXl}=FnK2#DSuxW6|2@x5m}#(`m)d z!0)ZKTN@%H26!tKdhujJSZLo(w%3WE{w{`OwRm-hFjlu1)*)sIH ztP4YgNcZR@BB_SXNTXr?sl9QJqukx>Y*DFmVP>_spZaUFLC3oLnR*u=xj%w+EO^A1 zToe->cZM0m-TXxBmD7)$ZZv5fSL>0e!qW>2)0iyi7#hrziiYDTx+7DIAPj?7c&ap8 zs>Qo2X|CPlhr{+&t!XKrdwXenuW~h?XE)O7;4yZLNzc)%wC8(`@5Tl6z?&QNmY>d= zJobexrxk4u_OrVUz@)wP;U+55Nkvr)G(nc~a}=Q(10f*V^|$ZS`3xPJ$^|#|%cXpe zExj2`E3`?+TKrFE+%Vl$tcKPdR}XW}%jnkwW9*15=|oReE>m`*fXz{Vtx`!V4TDM? zw8CG;wDDW2KDymA47e5PESM@4YHd$_%2I3PQ+@3RNh;1_*Wp?%PQvtwCWeLxZ}V$w zz>`HKEgch-n>tNC3)h|e6`HclIexczaXNaACJVkYf^)@l)wKi7YL2-sog?fx`VnSE zUV8g_vi0)BuL?G8HG20S#L*!I0l{zH;>+ia38SChN;3K}>|h=#5GY6U zFez3ST$&Ee%sx1y@Aa!|7!;Ht6r3%!UqnIBO(Mu5MdLCvBSr!7Khb~NjTuyu+3$E9 z*sJ?oW;ApZq++BLSIBqIjsOtwv`my;iB!UW?o6l^II2TaUFl))0$R5-(Z%aIN>VF+ z%D(GW-BTBe!F%i-&G7{vLbP~mgcwayIp&ocGz%9=PYbTNl?lSaZ@qVgM-GfPv~=B) z6P7TCBQXktk0V|5+SwmS2)1f!>L(`nxEiMc0@T$Q+i>70Hayz1r%dR{mmmTtX&)Yt zI#|(3E%8Eb(%VFm1SGH9yadBx7@5W$M!j5b>Zd?B2LE+AT2MIqvp~H1$Fi zzS!)6f4Xh^o|1Ctz{Q~5N*HSIZjFA>WV`WN`s7?$Kga74LOEkT+j`K#zrcCPlFe%; zUewZEU&SNp96K<8zzUp-ZsDeoX3iRAqWQ{KcE8CsTNU0Qh(cv$Cdc39CQ| zBX2m8p36SN!|i%dou(RHH@3KJqPHpr8S=WKao6X}*9VtnXP%P}{1zRY?FT8&Z>l5R z1Vxo6hdN6YkzP7@hppFYd-qH@y=4K&LSbQ?He2by@)1gnDyN%`jy2rFM&RA(%A=F2 z;k}hNlH1DZfN^KCUHw7w$oG$ZMP^OOflO=Y{3)=h5;04&N~YudUKlFz+ST7iN-%cJ zgk(?BYu;>gPV_>@J$kRI?Ds~$EmWTj##_61;fHe!E?H?84e-@E8ij)~fJ%iy`3b$X zb>LTiWXWbXv#znE9bt$wyx`q?Y!=fs)7JA@+&<>qlXO{SqK*iC2aye{*aZzC7*ni> zcCG->W#wW+y!RcDh9%%{Z4wQ7Yz~@@Pu$TwJHmU3(2U{crdI6|&}zH7A;ai-fx67V z)ryVh#Z(T=3=QT-&i%K< zd3T3_66Px@nCm&6m**AW(_V-6L43SQ`A{VHjf3Wk)Y0ey5-Y^Y=#Efb9 zfyhkvSYuhf{#0m=RIGL(i(y=aR)S!8{it1r?SZcYq%ZW^f6k!&@{+T~`)lAH(r3*1b&mAYd24EIL(7a9c3S3^jCl* z9JL8NuBQ~pF>4b12qZryZMX@sFOiZ$IGcqArlnSiP56>`>~^$&>ahEJ*cW<#TXNK`Fc2_BxoCNc$63)7^~sO~ z;j|HSmNl&?UE)TA$CmsqyoIMxz(&K=fK(rOGz$Kg-ib{XzqPO~U!Fu0(}YcN%-FW8 za^4upv$Vscs1BHSZT01C_Ufg>`YKy{q0xh!64MX3ci(ocJZ%a*JvI!$jOGo;m$WiS zKV*C;yi@#z#nIYKL9vM!YDa~wCX&zT@-h{5M*iYr0?xwOjUp5lN(s}{)MUGMczDbB{IyxzG0)p`GHhv{#G4Cbi z`6F>IS+6x|Ugbf7w5M)D^B@JN3EWe57PdS2iyX4sC{N{!+-}3e43ZI1mlvfy{1b@g zAm?!9N5}i`4qo%GzZva4hzUk)M;;x*C(F_1yWYH6dGLRn>~CXwuU0%?>_0*Y!FLMqzfwyF{$Ocp z`&CA6ZHz60iXTihV*ZLE1dl)a$7@|1%!oh(E+_AQ5S3pI3M#RT-|0*ksKl~OAyB{~ z{X#eX^ahjN1F-nRMXGCJ1wyrkxGgf4UP0o+fC^qI+sl6@Difj#dDqp2_YF6@FHgbD zO3;UlPP$m7iWVB+`xE-bN3gW6w2c=hV${+5U&d=U+C=-aysF1tVGCT4)yszLT=`U* zO8EYuwr34>pZ!)_)aina1oO4wBr|hDh2|%#P_%>{R<3lB!XX;kvNrd*P+4@6zYLa} z>8v@W)b1!jd+li6I!v&~{9d&qs}j(@bg9oq!77kN0y&_wEWV^ki46kO$+E!^og1_V|i;21Xu>aX-PKW)8 zrnI^`KJ#^ro5fn8cJ=-$lZ#caB_8Nzo6{po9ZRRxWVam@Tz(+q`6l;OS7~=LKE5es zf(49Tt7&q_L4+i_2?p(7*6*2lXzVh$UZXE+4bivNWo-;85jzxqWTsuz8g;5U^Vu}F z`0djARsE#y+v9?U1tRZ<*B!qnJ~#zMwV6mZ3^g~h?x1Hr_oE1dy~XF0e9_g4L8q1H z?#v2}{3dQBOKJ}DX*lfeC+HOGOdbu32yky==k7>ei_2lS;CIV)g^?NN-MG4}B353n zTcR#`kHz>|R%gPB52ptM z1`x9X!EY0( zss(pbAeO?e+uNU<)0OD#pA2fMxc8fk#U4b(8bMLa!6W*k>Ob5_Bnh!rbDJR~>FY89O#N=~X;PB1Id zh5sRCLA4XBQf!9q9Z&+OD7gDbqd1#O89ZKBIcAxzu#xU0k{P>bhpG_3n0hHbJyh*q zJy0QsD1j5+E`QSE#gd^~dfQ!kJ8y7T#oE)qG`{xOn54dI{b68lmG^4pOxRSR@b6T> z%v7Uig3;1>eVkue-}(Rp1t7%h0~esh$^TizhV!m9R|W3oM*U$qy!vF#k0*$Bh4Y4$ zuRG%X+uWSXZujhwnIyXvP)~UQeyJsu&k}*R?V}L903-7FzJq~|fni`Pf@SIm-F8W% zExhdHG>ex@5VAgdY8>3B?qRzdv=MT7bieE$BgTaeZfx8_VxiiF6GdtX>G|`!p@cAe znQJE(`Z98t=e5a*vN6i7LSzQLiQc3eK1s{p_6Ue-v3QQGa9B~#uj2M;ZqMqxT#U2& z=!^?NXk3Mxx9kjWS-jj{+gQhBYi&MjX)Emv0nztkPHMonqc;!6#~*9m?gQn997WEMh~&we@KdD<`t;>UpU-N1^nSLE#@#Vb@8 z95J3+&$3jfDahNOq0S#Ug$W{oKj(6OV5!~n<9UZnYFyG6L zkUY8{m2i8=M~kt6Rsg7GrnU^1jI+c2;HCaF1cI>4P|QHAF=$`Ccm=){j2ZLzl~b4i z%takG2{TIcdTx;8&$hY2^8ej-vIUD&y}1q5mKunbmT zUp~NhznArw92uAZTU%Q_DijDZUwzSGBN+;R?Pz(7daH5Uek)&lF1|@EY-2GM3=tu& zb3UukY{3LzeI9sRAqz`2DnJ@rDAsulD^tn!7e&I9{M> zFr8$^<9-himZ9Ibn4{*OTWqHC=N9kod@n_y5P_0*vq}m7<#AhZ#4)yPr>CQFjjs0e z1X_FR9CijbRw>agcy!$FD(X7ku%U04nFa$^7TUo_wpyZ{GLOGS^`i93zXOShy-sy| zTk5^-eGB{xN51{s{;hn7O-f`#Z-2Xl1~&1`$!7(OEUul|aoWMd(H3 z?IR(mmusDzOi;>1@YWF|G!3zrDHl+Fkp}<*^{!U3hjANT?|8Q~g91U*o+$@G60zxf z%4bJRVpVVe;?vKCzU!IjAJ!GQAj!t{aw_Nt{WC&LSr;eg=O^bm=X`kj^1^kCi||Za z$_38vos3}peoC`^*cs5(vUKYa!8(1C4z8%1CYX>F9fHX^!wNnG$HA^23FC*Z5+&l`5{w|oQa48N5MZN3iU!}e zH}UrAyljXz9B*nu`+=Gh0J{9~;g@FhX5hZlzzA-XwwaT?PQAp|o0;AuM@PG}TBxr< z5mwl{AiS545i@Lbw}l+_B=R55mK(Sz6z&cZ9Y2RXB=}KQC(sT|{D3U#@9XL$>J!k( z0v}s_o9W zK%9^4uy9QJ-9g&Ed4o*Sd~ifE#A!~sh1ee~BSMCzWUv2zjXQJ5>ZFE$p<;AaP_4fx zm&N70N0az~_wF?Dh6tcbi@WOL89(cI zG=*gK2~EoaW`i?<)CKei&%pg1Fpg+`H(f1F)NJXc zqQ__yS2jRPEA@0ZzcV_n2q#v;mU=xXXgmQFG58vJ?|z7nAOcIHjLi%eDoGaMc=9={ zITT#LlNT|fJ~}&+62tg}FXQ|Do^H+@8n!)NJe3*LgArVjyRNKNEjf!t@)a4Nww};vkndfpSzFj-o$^RvSTtmD{8VUw<1I!99pe)_KX%RkCVja z)3xY$8i{|Wf#AJQeS55tS*|EyI&E!T+3r@{$>bq9TwwjUF~;G;cs}x^vy7YbpKyE~ zatC;3Fq}~Mp3h$HY`dUAfLbN#XRq&v)tA-7>H%>gJbo*dZL5^>#&O$)r8^3dU__ht z*Y!?KUFd*ddUtW#6rsWKuj5lotDlgOb+5ZT`i<;`;{%n-HH8fL+?^#GxP^SAmVap$ zZlX}1Ps}HsW#{+i>@-O^YhCF=k_P(jxJs#NmGTxyF^rCl_vhn%e)vAeG`_HffcPPc zbg``Un6*tvD3{L!DB1urVIv3RGx94Iez*SugUDBe1m4d~J!=dY*9A&jTCZQwUC+-o zxs*plJxtghe`Lg}W`o<*9m(ZTU1C9R_?SbZuKdeEiKE5z*^hX_aM!r7kdlnh|6_Wc z7FrkX`&82Y-o`c=^moXCKYC->L;%QmNG0ik7{XGbjy3MXR-=1U#_B~s`|h#Mt4ul9 zZ>}V1?Ci8wjXxlX9~<~W_2R{48TybOCWm0dHys=K5{9Dt&mK0tH>pZ`9OU+}m7OUv zLdCgIUpmuiyZ9Ms!XmWq>iuV`#~*zzjclb>#_`_D@e<|KMS@P>R@gH6-WYg^9D%S} zeERiKp_rVTBED)d*mXtnX%gs~B>q|O! zzuUX^x-eGM2$3|;lQyN;6IfVho(?4(4ho^IWI_NXcJB7{WESI0jtZaFJZ&{9#;Q*UgjYbQY% zteuQ${Z`p9LlaR0yZ2nKF8opJ2gJYsBI!i|;Lqn&7&`bzM~2i72zKrzeV zSPU~)JLpS!&u7knRec4){*MKO1T{@mOCiAJrtr-e1g>%QH5}xxRA^g*iG;_H3s?nM!>Zf&$Q~-?PS!9#5O<~R`*;LXHu$Ga`41;k-`Ub2w%5ZhAQ*bLR=TSrYUtdO0 z2Y+Oz)k%$_CQA{^G2O0{pS1JO3DVJqo9(nGN`kD5#WF9AeM-JGXZso7w=a4;z4MHX zm94n*3J5$_f@RBz{CD|(XO;!ojaiJ9Kdy(9D+7VofdNYdKyYGL)&g3+B=4kS0!*fL zR9`WWIOU%`0+8h8`gfQC?DpbD)D+h`FWXm(M6=a9H=j$HsRtDaJaFFuvfAs13ay(a z>suX*6cVlEQCgw`HR!!o!Tt5f)HGH(m7-%(y1YSkLaytzT3ps7!2t7VWbwsm!AnPUycubSkco6HYXbz6jZ^~Ooi2Hxz(xCLH{_EF zcQ<|kAnQk)hWpNOt&1~EQ--Wag595=kK;aPjif5(eMf@ZsBq~+tUa1bohI7+Q~$r&F&EgH^%m?*PTwv)c;A4m9vZde#m`N^jBC{z@^HJ4c2JZH};&z*&oH{b8 z6rJK^gd(m)8+?3xTd1^*8f(KJYh?8D z#jMoee}WD7-~XjQv*KJld2(xeX`$!DA$emN7-E!xDxcfWE!od4cyMD*UukYf48D?) zcd%vM-=!{ur0B;j;Lh$21@9jm+JyjK1^iJ1CW?q&wAp9kghV9B4Z^RTzzC@%*{$hi zKztte#JWnn>ItPhH~_{Mw96D6M0vWuixLqnX#SiK?_>G%RZ(z zhqiuOkptBOH(;8WbF7@;dK^vO->eudF#M1z?!4t`;cepJN)tvAi7ur#Jo4Hvvh_`W z75TxGli7=yQYBVdH~9KSUQ(vQtjKZGyZj4vEI7dyl~Im-PQ0XEW38wmGu5x0s*uck zs(k-nO?p^YToGh5DOh2FV)dr6z_ZHN_{Y=ud^hDJ?gSsKVS9*A{DH@91tn5C zhn%&c3jGO} zVzV_@NPbJ9-Jf$?;bm{6ozc=hb5t8NtmbOAp{+{zE=@`3vyV+qRGFb+oNk~vu zE3!4()vktJmz}~ut|{f%6>;tWl~}|ztHYA1m|AqE$u&E74ygKkvGj!hvwV)km<(Bl zj57k|85Y7<=Br5vtx@FM(P42Y)fO7|jR$nlRQU9{L>mQUGT(v7{<=Kp2dkb+o>G)9 z%CTyTB=OS>UXA&RMQ9~bAY6Hhbt_L-6Gu$m!}1n=zOOb?C5(nfM+VW}g?EBa zeupVR91*@JOAN9h8nepACV5lqy7o8mrH=S1`>$dD6D03*_Hw()d$M~OKI|bqe~^G? zbEm^=OI>a2=$b&LDx2%2y0`h%BHCRqlj>>)vd>$}S}W3Q8)GONies;LXH*o_+xXJI z_id@vN=(#h=ZPXyTF)g~^3Q;_<-iQD3GsJKF$p)VrkUkC#1Vc;XN$l$h)gDEw2qPk zXqaT0nWgFe(6KU9cHi!nlxha%OQ`ssRx)kNyLzB(VO$%LC!_hG3e+fpoVPi$?MZ!fj zBspM2^*?DqM2I)U+(DRey5GGri{**lE9Pp^w`9k7_{zEO?96ZK04egg`HLS;kzDWj zQw<^NP53>FiimVRvqhWv52p$PHA8(+zgAUfsN%3$Tq!EYM8k)Q#qHwNq&+^GSL&46 z>I))+dX;d=>0{CnR*bNNQDwVY{8rP&s_5Ofu`>cS#~x>3bE(b#EWxY8%H#7XR0>r` zi%xOK+y1XOIQUD=jO;?(F^2)p3cH@g*(IH%S_em`yk%5Hb0hNzrTh(m0Q#?=a>FMG zp2{@b4+2E7G~0F$%kOxsv9A~FZ%56_6~1RKt%9lqYz)J*%y%vf4iu^RWO{9lf$M!$ z$r&i4oR~j4boZ65|8T{Pd$nJyCSd$M=fNfbr%%~7Nx8^BYi;~|L9>r}wU!=?+;8>t zlCgf#c`(;SVPwBzSkXPwUGI+w}Gwc`+t%lDXVu?>g8@GGYKFmz`M^I;vbY~ zxi4=!^+#P_a@VwR@Ls#cSS35|oVhQ}##B4FRd{nlhJw3vXC-DdOHzC&O0$ubjdx}v z;(LYt2^u%tg|{TH(CD8fR>^JSW>1?W<={1ZTcZ^tFvG^%N; zl9p!0!fffL9@?DQV+W(ID*+cXmhI+f6N^Zn9{BT6}sX&vY52FKr&3Czf^Yjes@x%;VH9lTE-HiOI( zMQz1oO0}%{HsXsnuU;s@&3Ux3ex{0^sRZ5=yOs-0UTPKci0!L^sT2(CT>60O@Q5dN z`XOfQ=`<|6)#u}|+p-h)+3jQuWW+`b*^j)I4BVGa%JoOP=ZcKsO=-EZvs~*u_hLM2s#V{tMx6*Kfkn8dR$!8y%Iv{qH~d* z<+7N4A6a}HdaK9qf1T=h+g_4;oWJL9-5!aYB2=f`yyZyF0}cw2MN0&QQSDfN;FMy(d+RUs~g-r40Z?AJ*6nQ&rmlH452shSk+? z21Ty+(+wx#L)rY@aOs!#2@ck216yC`hjH@2EV^GFTk1a6!+iYEL8BYFM5r#N?XeR- z@n-C9pF=6pD9nL>=u5i6DW7(W7Sc-Czf-*sY{K__$f%X^#Haql{}ZYNDfYm;bt#`` z25O4my^NO7g(Pman5VA9?Mq5le~M91N$BydJP>q;Y)s299j0A#eVIc0AdA;BiA5e5 zlXD&9BWFETJSNln_PUV5I0QakR9V^dcwME)0p0gpg=_U?zwL3frSJ7}^a7WjdQ7eU zSv@IYD9D@1u)sn@nI0=Z0gUi5u+`wrWwcCiV#V(Dx1n(L)MdVNTmJcm zDn6DqcpL!|TrgfCGBYB>`7ga_(@gXD0v5}poc*2Qhjj=n5nRBsq14S2#FUnE_AaC} ztZeGSIjLF?jZ%!U2do%~2OJo20`Y)hol>t|)EJkE+Vdw4uA@4w%meyDK+gzAS7r5y z$!GF2R2IpVI}0}h0Cl;#3{0xdO_+`{B7^v+c=N74tg5}y1M?wCn!(!+wfdn|m))={ zwp{#yXtNnRaIjQ^VDR(zrHYV#5~bvfhkDo(dsm9%VtFz0Ba=3i2wAiH4hSv*h2y%! z1E5Q){R#~|MT;3PF~ImW+&wZR2MY!gM1CT4%UB3EEJ4JjNQ)$-uZCV_{-q^koO__s z&{)ZMERDOvYeH3vNJs8bzyEJ))z55BE)MP?x*Hlyw?xkftmw&0`fRs0jg0$Fp0DyKgK|04$Akly~ke-I6p8MoV+-p3miMQefVSr3>c{xZ6-* z-u*_*%$Jv(uq1d^ep}}Zci`v8h3nY+XTV;KFE##BZ@Uo+hj#9or-mktnh1=b>OvqW zoy;XbVikcNY@i#0DPL`bU&ypGRU6R=2MQek;JVH#(32buMQ@7>Bv^J`2SsfjsxO|- z2cXi%AMTPKmzh+u;a2&*zI8o=eOsMvsNd%u6_6q^0DKX|(<)wXIXYdG*M9k}0$Bx3P2!&zQVOL&hW1_Np%i&emy9F1lP%iVKSWC8305opQDB&yXk{ekv6EKd$?SlyZWfVFD=+%rNowg$&fSynnMGh z?-%M3_uWKdbV=RN-ei zOVDO<$ z0Tt-8I3ACLKV?Av9A^4Q*6{a4$SFAgkpBPtYC$0AyZ`=vcJXiU_urSM=2wk@LSF+U zMteQO^!99*ua-#FejDfi94@E-%}Q`UvyahtfAIa=ex0YVhr1tJR>}S88qfq-HLo;v zRG5pYZ-4u`9Wlp#_;}{fXx3G*JD${*WQ|gSW{AQ2dE$pGaqQTCyJcB%hc}On)~;>Z zR_c~!b%*K78ZwzpSO@`yU*p8rUO5=b*r_oTF#U_x49?6O?KhTWD!nj4=-K(|CDh*|7JAceKl|1$WpcaOSNV$jz=3JhphHDhhLyI zf!f}4rhrY@I9=)7Y2|)D*8O%Gk_pM0(Bg>UZAk_BQTFXMHg$8W?MLWOQ@e)aMbPGq z%0%zpsh5mpR30FL_1in+FDhA07hy05-XXEB@wwK|;-ni!eQSs$=)i>}mR);Xq*Sk-!oC0|gp*rTNwG}LlFYe3xF}=aMidzEJ zkXcR7D`RTw0s)cNjj8vFsRP)5HfK>6@Zf6sF@1_I7x`t7qoX75rR~nDv49IMG~fEU zy840RY~?n>O`6K^|i4`1iB zSKbbr9p3qOrtZ<-T{Rmib5m2_p3*9~9d>Zd;jhy!MINuIq@bQySUO7DtDd+TSiFM< zl$i}#1Uab|3_QP#SgK@lFzz%QvFchj>Hr(+yD_odP5MCsMJHX2VjnJdcaNB|!4qqI z^#mbru^Y8dyXb0-9pzIv^2T)KZbrGEl1T)+A?7L@-ce2L?4@9NL$)wZwzJO9EwUji z@0Bm#v?V6)_c}fV6KMRXD~^IT)0QuQ45nx3lltN=*`k;;Hd=>e*x6o>&tXBU(a{-gao z0`OjMe4V*DO|rW2NtcYvSfZ$`4fGjOYaSfFOrPWDwY~UNMH8W?Pe~1hJeRs%xhW|9g-Dllc#AC8>8N>#8 zX!+^t;ljD2i~zj%dvb;NX%%MY8N3{!U4Sp?a=^q%2S_7{LqG|ippqB9AdoW;P8VT` zB8Q2-GoTb8j2Xy9z{+)y`!34!bz{a0<>%dcDiS}RTYWtAY@D8POo-uT2KgXvD2;Gs zp#U0&T%c=UAmw=6Jp`fnHuKsDNZ1N|%>=$}eQ3bzwX|-lYY_msPA583Xq??mZa{g- zKR4CwRr*XVLr)^$Isbzbw^qj0hf1j`$~Cv^%=WSmdCh5#m2LGU-<|?@1GnnBowvoK z{D~B)$RNS#t*artVYDc`JdaQ3^My?e9QPj66tL?!){a5|-cqFrXkELiFPo~$-9vIR z`NV`%W*Cs*vtWDs`Xj6c_#v9017POyKBId(e@!RGQc`F0ktc)r8?B0~Byy(9eD)3$ zB1*CO&2wE8R<^fIXU<|2v^7)i%~9pBLkPx7jpjO8|SM;PK12* zKq9b>3QMCX^Kro84m~1w&TKgrQ!cP6DDavqV(29DuApDEYa?>b%N&^zcTyVZrhUHP|6E*ePYVCZ{@?W4qq`!V%y_OTaSA2`caefV~u?|AAqp8 zuJTPkQH{=xtDW~@W@nUXMK#Z?RC~FhomCp6W;Ww>Q>sk^65u-948dSU$t2gM(z0gmt41&C6pbhAx5a^OaS?N8W-J!3C|HnWqo2 zuL__CB$N=0&oI_?`#6PoN2EM3n@%?Qou87U+|A5$sb%g21;{8-Yuub1xNh3DVYQgCEeqCqnq!0&jD>trI>+!xp z=c(9sB>L=lVS3tY5DZY&*+Ri*epfnli|6H7dDW0P!*8w_)9}=D^<>8A-e>W2 zr{d)4vc^C+e|1QH^TObD7cH7l_qqyvy$>VRsdTEKJd7{V+SyUQ`v@rov9f zwp)khS`4BL@WF3LN>_J1Z#e|xbA0Cf2mlC>{O`zm@5n-v>}ZPPdA)o%gUEHZo5^UQ zHT~^@TM~o!1MtNw!ui^h(?I*_vU4)}GU&ItXf>tH**balZhfm`+Nj;jaH>Enb&d=X1C_VGQ(i@GjE4Y}# zUC{;$w3@c`qG5<_SxeEaFUzvjdE19kbkI#i;nrY46Abww# zP+!F;A>LSl=-9q)#na|SB0?I{yOXAmq2#uLYKW2&BS$c5W%Vp1qQx)LNt16bYe~~^ zQp{i?;fer=u~g;ds_m4VECPP|sx9gbZi5G{gb>udHA@C3>D6wu4J|lXKuf)42s|-Xnyl2UjHBgY z=Cu@H1xN*l|0AoJm^%8O9YGV;r9>#ymaSXDz-qIiKyKh6P4k zAS}59pQqF^h{$EBfY&8o@)IoJUw1nyuok@Mv%hqH-`gOSTbX+=!!POsY8O3N^vMAoq8UXK0=+7Z- zvs|7}z4Apk{4n4z?L0cyzXL-*=O~x5N*KBC`OAyWZ>j?8rtV(P#%{v^fS6&BTcj-q z`t12MRemcQVeIR0e%zV+3&vI({~V?VF#g03iQe&DoJIRx&E}#`$C|>Wi#WOEo@_^= z+ru1zb3E|v!|#Yq&$8DCxQzR}-mvE`n(p|mQ}WG5falhlV#yUS5X13`vd1p+PkJ?? zlS8<@yW8toT3TvBeswvFlqNF}0G>XBged|BwcCS_67h*Uw~1(LU(ZwTb>ws81Xm4%n0gdLTh;9qjK|(N8RJ7;!FR^3yhKT=a0i>+U=FD%* z9ql!qayPsP3_x+#1FnT5tsLLB<8|$Fn@3ZD^}TpT(2E>S4bt;@4_UDtOjC2IY$oSg z>C*XSSZY|fL|4%B>0;%pM>U20TrBKwIYX6LzW5 z4Ez&&LcT@gyxbl~W-D-t99%3s-d%fHJvl!yWP`~4r5H(;L*MoNKck72L3$Ml3Y2{F zDza2$gQ5j;n&B~fHy+y|O1E-$ezi{-%0y1GC8zfaW(O8v*MC5nemoSIhtz~_G&N=H9-*2?qG82SCi*!%zQT>dv} z{CDd74-fz(08l1Xs4B6`1@|`$6Ea=x!hr+NQG0v=mGjrZSIY=3g!p^;L~#I)^87k= zka3p|v@{|Fb}7;h?zTM-`O)O9{0_jZY<4e37*MB5+PE7MQj}Q7*KAJ0YNYA)j={U# z%L$`&P~6%dM<%#mO>p-dPy#`Yho13g0T}U#qZ_w$A##u`a_>Qo^zg!E1s^Hj;g90- zceApgEdDPFp?HWA9+9c6%q?4CO~>=3-eaI1gWJi;+3S)J)kF}d*6C|o_YOwq=|-ky zlBr@F z>UglIo2x!Bu`Xx3*1S(d zI(;J4-h#!skk_qs)o`lNNw84zt8CcV9SDnv!~#&-aU9RrkdKvloBq^tKin^_7j@42 zk}uCPy=1qy`Z3mM3zcq&e7}Wg(K?g!wec>3)?lkMVyIf`9UDbp8b?(6b=e|66D;?8 zD_V|&Itf_+v~onPiR;Zt2R7J6+{%on=3W%PMlc#xuRYPHtDHN&$E}d}1Ct~`cgoy@ zHX!#LedY7&m@}ro`P=2$hvxVu4JS)=o;zIxY zq*DSR+h+UEC?5A^0(oh9^soa&a-x5f520kGEazPBxH~nu^S9#6nCv7eLOQE10TL5p z>uL|x*f+QSq`>-^-z>|^2ahL}-B*zVy`0;1hBfVV z-J@6MoZl*9ON^}E_PP0Nv$Ab%b`~R`b*Scys{NcR>PY9Eds}aJ{PKwb0<~95W2sU- z`D)~yOH;eS65aIH{!xkk$C_b+HqLd3R5kX4v)E9X~POSMf*FRGVI;5nnn8R`2?I z{kLyFgLXotylOaJh^HYie|X-nt6*e|HG<%^@c-U=TxJUuHxZ~aHZ*E(Ws!L=hs0$0 zx**$tyVUXg##aOj&iKjw^$KaW|A_BFC$je#)5OKzC&G5P(9+gYZJW5n6d zP6@-9Xkrq1Tq)|N;iA}|!xof03;-y>r0U$@U$ur;k%*F)!=U8F`MO?{-@d+=sfQjl zK&5cKRq-8@*P8HNo%8F-^UrS%+C;rGl?1EbCvP9l#%@BmfuctKWTs(m3^1$yxOv-H{}e1TO&RVC8QqF2lV=XsU1oL zLv~#7@x!sqJDR32Icy~c{4`t;7*h|`mh~a0&O!ho90$`S=xwVzPGjbbteeNDwxVDF z)1N3Q9(q+rT?DUkeXj2^3=Q+XQlk6m5^}nN`LLC{zlgeDZX?4tr_1E9ZX20yP|e|q zoIQOfVU{Er2T4^%^2pLjPow^MsAPX)ip2?4AOao)tjHwpJ@?Q|X((p2>*>q{3gx=p z!lFFJ4ZDR=-#$oK$mUJZwJm_VwG4Px{hTo()sbeOR+#Kk>}gf7dHGWarLxvQJ^drM9}`a2&m?k2wL7Nm$F2K^;*;^L}2-$eE7a@tm)_Eikg ziA-4t2IW&o4pfM_QP}B%ogpPRw?L>vY}!sH*n3ef1`8ANfN#S{+G6 z(c=Q89==#DO4U|V)}Dp++0z}IbZxs-<@a$=koEsxL9K~OTT z$$YtAta8{UT+XKD!;DPW`vE8_=9{;%eW7?; zj#IpGQfJw~kN&iZVfE#sVc`>>Lkn_2O{?|!a^<5Ta7rPNW_lt{NmSgV5{wtODp}9Z z>See&YJv?$D(Pa9t%>DF=z3X&bqKRwAUA>>W^9?p^TI9{r=71A% zS%ER^IlOAdfwBwA>&CiqNww}pgX^lA1{xR7u_jF<{p(9JJ5X7po7u$C5fk4TSn*MF z&3t*RqCgZfL! zcyt>3!oqPf;Q=O8shUMsaYbf%-=##`?b&}j$1uE<@nH>@tU1uNt$S^Cf-po{R-;Y? zo~ZSy%-9?@x%|unNCT*J7&!I8$L8gffNOueGFuAX|MqZ-BnbE%E0ww0tbBTAb8Kjc zre?WLzp&14J-qNZGu%Ytp{8Ubl$A#~W((&v&#-WL@}39)({CXzyLL$#iL84RB`Xy< z$>olBtV5F4#}I{cEDC|2-_C-i3plbQU3%rGg?x}0b;UDH-g=&gRD zCa*qE?uBR)rBA(=H!pp>3^5-`y>9%4kkKQh-`Fg4+LmGZK{x4U2RXhCEMw1ELlngy z0vVHRLf4@uy`6-{>G7{r}_Id|sBzB2CpsR^^ ze|Jz7rp&aozIL}u2&O$MSn#O8UNfuRWey!8vmVd=*o7>G$q22WdhHj5?!~#$1!ssmg zt?|Rp{gr(W3-pFJXEjr0M;wQeyQ%#wZSZdiWLB>QW=RL6wZFOtp=n<3V7ZHeZIN4=+OhZX79Ov`s(`8T5@<; zrF7#?9oqeIKsJsjlyff8M_mgEpe@|Rn5k8I>DC6iF3a26Namv| zC(zuyl5QxWb`3|8Z$ho=t+LX3Hg;#h_2{UmP1$*?IR>f;#avzgd}T8H%Da`u*<`a? z>&Yfi0RNzC8`94trStT73JMyr%E9pL*~^SG(d7Pz%K<^^jN{WVb2k%&(2sZ?Rmz#q%BPZp23{(mdp!i!X=SsCU1NjEw1IzA{T-(EK#<4~Sg#!_KpPEfmwDg?9LA1$0*rodS!jqf=s;a;`Un7&?H`|r9hA-M zw8v1)nYDtdJY;Kt)Y}0iWZBI!8P3>{8@(iGwmhpsT&U1tJ2{k+iR8f}Ad9b~j9Mrx z8o9rt{$HuOh<&CGo)@!|)ThG@1nxJ2NRjKWH)~QxoH}nCZ*2n41rJ9pZ|+X_HWbwx zL8H`!0evHfXlQIG2VW2Ini2ZueXb^gIR~KbZuRhp_#9EzrW7weN%bA9>c|wVS@2-C ziqFh?Z!SDxi&?eUJ)}u^$XJo`;Lwc6P-edlzCEt@_|zx0KM6|N3?L z5d{zEy|x7<#rdcgmS_ZQ@EvB7M zuAuK%M{M< zZWW|;HohP?Ak8O$w`Ht)nkq`3E%nxC-^k;n2%k7LgVt^nM+J9OM-(q(91$<)meI`} zYIIa|^5!*;YSQUbkID@sMk-+lwtPNl zwJ4h_eT+2!<5?KyPgVSgF06Pb_Vq801*T)`H*%BjoMRXi`_5lx>)u%|^=FmJ|#oxnZra%5;xz^#K_*fQ;s&1bvdVGuP7)y}0}B6oDWz zkZHv5+gyBxedhoAX#Rp zNk%8sJpk}J9!}CazqLNVUUe7EgY2G-V0}F<+oLhrTn~2j`?KGv$)<;CbkI?ojcOk` zXt;YsSi^0U^SbeAD8=JuC2k!YB)T(1d%J%4ocVV;f-818Zl*3kn*FdFFJZIcfpkdQWBF>cY41zL;i zw>buA91{@+ro3Q(t_JkmZ1LZX2!96nA&?^YpE|`~-wpj6amW7Oz`pnY8zZE+qneS2 zp;h|4xHty>4<0DIZnk1c$%MP>PxS1m6Lvbq3skvZ!;OC)-GBbA0^8+RDb7m5UnSbX!-?*-+nbz4!o({cSbz z`z}q;rL6H`BrQ8^Y^b$33p82m$3Y``W4d#MH56@?PykT!`CrmTaVH#1-(s{HMkpg_ z>_(eaxE-8Wx)zsR>rQrV816)u#lMr6(=AofQ7b|T6g=!z1q`INO%MNbX&}3UHE9o- z#cUQhfV2UJB$KxC>zUQV;pWW3>{skQ6HLAae%^?{H363S1(Rhs#oWNxw0ZMmcWKjL zpQW;YbV!6@R^vRH7^6o{x$SGEvCHWhv{_e;ngWBkW9ZhMoX4T{JZtwS+|Uy!j2Xj> zg{_F3m`17rGiE^RM)&7%BkU);NR9uQa(?1FMUj}1JS~ng&Qv)8^78K#=a1dm&!*W=j zAqUKciA6);KdNkX*$ zr@!)|W73j%m50LuR(0EJlCSS}hogptqDsjSPh@zJ@yW!DU!JXDjw z0r+7b@EiO7{q%zA_HbT-GqVF_$DRcr1Sb!B>-~`?ZtG~?J>wuS3Z!jxZ}$ipgg^gF z4koDvEUBsDb-5yHUX$n~b~q>aZl}1^xdgT(`uKCq2b)icDTj0%dwoN*`fuJHrx2p)XLPS z@mGf`6JW`}k{#Xe@OdH^{IAN%$!FuUF-jJKf_CqQxebE^g(|q3?Jl1SlLer_kngOx zcx;r>tXC8O0N^s0%YXtTi|stc^czvSELJm>)wk8K8iSc6PpGt;*(6vU%!;^W!2_*8 zLJWT`gpT@%klDcm=s)K_z6F)gzYqc{H6lTUrPQ}yKsY)dqSTl!)3f_iiurc6=sI}m zoiLqc)&8Io#7@;=(VPs45&YNJiLls4B-fX||1x1%Mo zBz5+4HjVcencl<(Zj3L~$U-=LS94kgkC;OiQgBIRhnW8PH|C4kN@YlJmg?@4{r-It z28I<)>*SEqiZ$iu&Cz;{po`Y<&PxMu8*>K2?I~n;k_n4 zYiiqIfJ1+?x2C~%pp7_>;|C8O0hUSA^5s?rUR_!^F6i?23rdqk8js!KC9NhvVB6QM zBGk4Dw5=_csXdToh0^|*OmoeK1NZweg#>g88kf7dl?A2*X$V~@GpD}nYAsVjz(Q{h zwhKeJe3+}a&-Nney7mcyCPYxU-c#;6A8J0?So=5lfhe6LJkFRev8V`!o?2{PPqcEO zQ60@4bMFA!m-TASpQZGc_3&Y0F#o(E$l#z&#C_pn6%p}_a-P2}v#3#d)!;_1l~X~q zF9?6EwWDB+axQ<@X7SN~=I(J`CiDBUQxmUC1%k5o>zH>gmG@0O{kV;N$E!+innFK? zcV)&pDJiyW3Y+Dn$3=jQDPnkYH%j1A^lRs!`F}tcFEXs9$ZbW*)Q@^ zKS#~1HNItwXJKtrS_hd9mOU?eLIS!)A)o4^VXfAad308(Uqm`W-}$R`+Ty0Y=BTV7 z0DyTfM2xcG<`?=)6V0g6c1yBg_Nz6wOFdYul2PB}7532+O|+gl`;yhSs7G0k31Gc4 z4ieh+;*XdnW-#l5O{=1>D0>W_W5Ai1hc5EUidKo53%W>ZytA^D4xQ|`98#g^2?4eo zSu1xBhqs|;UaT#>h8O-35jT*K_D!YwH#9}c?zzoB3mRPDf?4eP-p+%49zYzs-8-M> ziV91aCI=0S8=g|<;L!>DO-1+&bZqYHz~vd6$|mjlc8ht<*3HNB%{QI%fU=tmv9$b( zGf_ACtY#)F$9zjTQk>rVdOrFaD{XuC_t2f9qf#o4Gn`EngK)n?j%;W!kXhO_%!ZW} zc66N%ol>tUwqV`O1Cy(V4FTXg@ko8t9w%<8^iNHRP7F_8h2jMNK1Yur%{9Yn<|=c@ zcj)EUlJVx`yao5Wf*6Q`6t$liVrX~$N6}jCSyVofhJ%5Byt}Q_ExF)J$|x@dW^t-5 zIsbI>oXd6RVPKh8xEPA5JHFDpKjje_eXto}aN&QJ3UuYm#AmMyug0=mum1EQ2|wcJ zh>D65uku03O3PbwBsd^nVE?{F_R6|Jjtm_Pz;smm9NS&mXbU;;R20Y-;Zt_OQ4;V= zfd(d`kW0n}A{fGIWL0}rQ!y6Tr*xH7P-oKp=OlMs>7N}ol^YZc9!z%ewp3)4{z~p( zHbGK4zPdmQiU3PKD5ogZ%*`8Prqz#Fk<~~Gkbs*qZxjZ2T zG`}wwdK&8R_H^q_{UBXC*F|<*3(?-whxw5-Sn{1Ou+`pV!;D)ByVh(_tKAAt@xEzU zN#T63JdIMI-HnHj-e+D3CFZu{A1*)(hx+TI$u=3b6hA__Zbv2xHvZ39C~!ZU@pP=f zqP0bejd~3_^tGwOTZh=|tpfYxu;}&1m3`Aa>(|*a;#pVt%bJk6~N}No^RDrpb5*cws4O@18DO7AncekUq|#!r3frjr~|sadV`WSejm< z^fiZN9-Gm(+2Ur*P69?XP9`%xrC6!xn%P~$XB4p~eKt)sPqYvdPQ_KaRu!UKXta)S zwU{0fSHV0;xJ)JF=aLBCIizUwmyAH)32ZX^LN*MD!o&VWp1$Hy?$}3s85c7Vh~ux7 zgQB>&MA@-nh09#}w_$l`SQrlBE@wBm8D!&L`+P;_ z=PY50RDCRHP|G_?;x-o)Rht&&2gL-{eEDybJC<5mxQ$L_UFVkksI z)5DHgmL5Cq7}0|G9JbZ7Lb({YcT!!)+*aCfgLZbyk??XkJ1-p18V^X;h3@i{YJ2L- zts5SratgNbjGh${vmcqdTo7@LMK`w9Vm+1cha6pt@v^C&8^Rp8@W|*Zj*#r_O&v5y z02Jakxm%*-y^qq`n{wW2u1_%&I**Ug`=wnjHyr6askKcT!5u492H?6$UgxQ4;Jy|= zmSYvqr`IiwA(N`w9tXvDBdwDkVZ!q5z2=rMkJ$~om?xAkK7Ea2bkqWPjwjH*qYX=e zS8KTs{U_!G`|xmFKkAGG;}y;Ii{C!M6bfHIF6;hAb}~kgsC2)e_64;+B%frsa5~(j zbYHgZ;nV8rB1g2ITrmCMXW$vo#e+H=p|CKu`4Kwt@0~gt-ESWq9X&u`c5Us| z_Lqo(y4Xg6`^Pti4rNVaWwo8%3w8fi{$yrWc&s&!d%0oY~qEnQM*({ zeE=AwG+i+`%|bR^9f*W~smWSuqLIL;M7(x>>{|-?f|+9LB^}B`!6Uuc6FZ?5*nUOS zK3{x^a0_Y5;`BdB)~XGwrpSk*h!g3i38mG+Q8_uSR8&OU1~l-DMPo` zPNP(zI7}wpIk{~6@MUpSfCvCk=-tCA*G$AKLcN;1z4EwILxkxpjGM#QH>EsE&<7T` zxz@IhZ6GJ~>sUHkmWIHz?F&Ai7l(q|lAsEDu1Cv*f%!&iJ(UQSL$>eVYdtYWt&`BL z+$b8f9&Y`WwTFt_3crt0P_MQ8n65eov4ZrZKmEWc%eGuZXJ<0`%|s%G<(zwzGn#;J zj_(QG^`9&(8whI(WfWI=(r2grqvhy2sF=_%a#Ztu9{^Ob;W(kwW)t5!Ft=#9Y+$wJ zWWPNpmX(g$17JwNP9oH?HQZk5X3eustZA<@Z7B7FQf%v>Oq41PkhP=q*5Oy{>&UEzsmIP_C{k8O z)mqiT!0%w-;1l=wWZ?ALKR1D!R?wcys`-9nBI@a0KO$c6wa}sp-wsXyk^3w$X%&q8Ns_mJ|&lC2sf(H5v2Yp#TcxbRuUaNYa z-$?~D%%)4SPKL7uaF5YxCdde=$;UHt!F!!X4pE zP95$Lu&bKKr_sj-0ATj|?g8%B-j~{5E zp8#l)nqr-c^A;e-r83d7c(iT`?AOZ<3?$B8Y77Xn4^udPoSd0YwHL7z&SzT*ZY7HQ zRtu(wp8M(aqMblPW5(zABPcNU?~GJ8FnKE8ci`2T*!9otv&U>ieXgsp6FVEs-wD2kyrMp&{ zzk&U4WnWFa)D1AehEuaA2n&hP{5j(IRL-dzJR)9H*l{#sW3#R#Zi{%nft=EBC7Sac zGM%BLuH|(G*6niT*)>vjyh}gC7Zg?lND@8|+A4mm4|Ht6K07OK7urgX@ZbM1L>xM~ zUNk1}p>t>^lQ4O81;?>#Y)NxaC@8<5$@N#m^`BMfEH0%u`*R%Y-caYd`&Qj}@hM1! zqsDQcaemb+)adQQ{bXz%ySU*q~C)ql-SYwH-LHAt8IY`?XbHH9OFiB}|n zkCu@BE;X}V9*9d1DnL%B*Yi2gN->f3J)f|W)bVNy!AgDWfow)#R|ouF=R9ZrUKLLeB5t3hlv!oLQYg{!Hg z%3Y|tZepjVRioF#fSmKo^!7NI@~bGZ1jf`vis_=KrK05~AnD*wg9>e% z(>DPECXSMlo)NK%C}4p57LlKzD&TvYuT~9;Dx#jkwNXyDGdfFeyR%?;Jo-O!x6)|o zO^aouB_d(fq*92reg^(k;=A9&e>>LG^SC({!v@@dihO8MzAO}826H*Cq4{M;$6c$QY>om~1T4k^sm~#?@cg@3tu9@GHL`@rNDk53`6+WB zP&b!wCI47Qe+VQL44@d{C!+lq3}trS&UZk_{GWA^K*)Gt9q{sBfa;4sdwj6mkNxWc zqKwQ_y8n60*`^T6etSv(dB(2Q|Du%s&z0`{TN5hxzcryE{qH8!xPNOx{g1y{*Q0}~ z=WK|9-%NaX zN(Dwu=TpYqYt+#drrFV`-&4$z7w`8_jk{>Z^2znGl8X$J3NPD9zKfDeRNRlhSC4BP z*DvN&m$j5W>fgK6e9pa1)=Ry!@S?x4IP<9`>vO+dtQGqO({Tp2)2b2?Nbp3d+;N`` zG#pAW(eZZmXmsOS$blXlG79XUvx+}Ju%ieaN19j>%(S_T>D9tM45iu-lx*A8kV^1p zRIDVOMw9*NlS~)c>y_yQHrCGvH0w1D!yL*S*{$R3Up0XLx~SwyJUE43)3Q;mWGw8T zJK(onnUBR%1vb}B)F@8#xH~ zIolOy6*mAtQtN2~!PM0J?L1Wf=^;L9aAgFQ#T`*Kpzv<5;LW>GA+@nM&$X}hGq=rY zF}KV0PNX*xAaroC-AzR?Pj&1O5nIr^!Fg<~tf|U?CMBd95mBY#eGG02EDv{`i)zOG zmS{j^l-xK-m#+I#_fd(^m&tXn><%%Pu-&OxFQ&CV&sHK<_k+4-MIr&u?2+%}Y5R*+ z0RWJL!heG{YmB<+PcT|E1+MiL?J~S10-(n31qbe)8;*)&*fA;wdsgt#kp*$8AZ&HQ|gcb$L&FneA2b>#bwfkLai!` z<>5x#ga}OS{`w<_e9Ss1K|t=PHmCcx{gzIVSL~WhGbOYS=_km8^QX z-zSK8xb}w8dK|&5aNe5G@pE@>oC7C$o+#0pL+L2J!hmQnwFk(L=^A{}RItuLC6-Db z|KRjGybg7eW-IL=;No7o-wO3{%;#RWWSDi~4&YrN{-yZ8;BxD0Ghq0!+oE+c-ugLl zalIJ@%dG$=Z@KM4AI$cncW)0Sq;f^XFwH9&Eox9Sf<9&)3K$*k%ZdA(O?q#|lcQ8d zaipVWYd#(QqmrGUNU;aLA;)*T$nsZ6Q+wWqYCH7#Ax9+>gV5M=8OSpF;M8{?@gM>J z0yf8uBiv#BE4VouY3*_!UL)u#hr2pFMB<7LpEZgl>vOG{0EuB96AsAkJ5MG7caa9leHw z5tvq8oqfs>O{rLrMuvqNTwq2n^{cK8y?hWaXS-AMzW}RIh&)&g%5g+EeCVrTpu2I2 zjnw8-IZml+&%oFVu`Gj%iEYhw^_t0(rJj`7VR8(wxPGk1`4FdOL%@3Qak`}I=Ifub z0NGCk5e>CQv3x}WuKU>xmcJ=@Evv76YU>fJTJQBL1z6KB>Qy|e?mRoNL-+)M&~l97 zI@*=ZKWl!$13LT5US^5r!Pgz0%U-Y{0RXi2gP?Uf%z%=L!{N#8d5=~ANO<r>{-1-2emc(x!}K(|kYXk>It}yLDQ^azm3Z-3{@+4KXP?arNX13=l%f0vDc0 zA2L0h;=61>WXbc^7i!9z@P7)5ME5$Z6Gp>UM=tLGjpaHP)Si+=W4=}S?UA&S(c7t- zL4|HbVNq8yoEPNL;?-roE_a>;n26#1eP#EIbOeM{DDeyk3iF(H4+7Pe zfCgR$ZF7w(c81utvyF^V$~*S;H#6P(Nr-UkvAVWMlBOl)A1WO4 z6{VMlC%wy5Yajvd5>V9nw?6jB&C%P)xpcA8K_5b9 z<76M&o_65i>semoTkMe{*~=gJbUrs`8X$MVjHt(p+-hL^T`n?Iqy1Q7X!qEu?$i`G z!J54#bS~|`0|koROCzO15Vl88N87X=g;%<}3({X~R1shEvCZ@oZ)voKmig z(6+kCCr%=C>dS~#EP(BHqn{JdYI=}iR^K$JixS_bW|3vZeah!B94(b+O`@|25# zCH|{v%rY~)jO<$kKdM>DF2m}zS7;OF#bot5f4|VV<7@X;6oxH;r-+XOiL++pnpJ9s z((@%z*f%2dB@%3rkX=FloA?Z2i0s_0I8uxG{f_fxr*ElO>xnvN%}OaLn(J;2%apO9 z8-BluVcCk<00bmF!~Ncsho>=Xx{-6?!r_n!hqJgB&i9?4l^=H!@atcUYk)UBql5qe z%i?gQ3$N^sWRrf)0%htZwj&$45*Lcl|H8IGez7v->c8p_bu734hTi*;n>p3pr{SXh z%x@NGe(jq0K_z~6Wie14-E!pT4S>mBbNF+FHUl)uiR$qx@)cP4;>V8^NfN;VCGdYT z;^s|o++uC@qbS1C_Yw5>yI0{ohPf(v>nW8?l(C4l8QkYi8A|EWK8mp^iFitD)1W0~ zM$_lyO2J}6v1c|wFN_1rq`(y3m#YeAq!+E*|A4H6*I2oZD!G&MY!SiGApxrBKYu!>IczP$ zeQaNZvWbU_uU^Tx6&K872&SFzzN{e9BXs*poc2Cvl9)e36Jot{6rE_Dk03L#xkJP+JMliH76if zu>@G(X$pF$}cqs6B*zJE{0f!4R%vqOmbJ%W@ zTld^&BqHFSH8$!2K?wD1phkMGIP??efm1#WkeWWsYiF{SHcWDR9F8n+too0(=R6)%uF#zxnUVgSVJU6fEG@Vv&XMr`Nim1nl zWjOvL@b$=|?Jq5x$7t_teL*U{1^Vh`;NE0w(>9Trt5lko;+QgwR^CB^Tk`KnYinti7=((l@RKVz50 zecv!bz3iOCsnRY|MtCdu9ts2F#Xb+6d&#kvFIJo&X{8)5#+Fkyxe&5*&6S~vo}jDE zm1R|I?Ffl`UDT@lC%eS6S<*WU9;WIGvXD*8f>jX$1GG2P4OQ8OQn30QmU&@AdkGoa zja;!B2QH;*AqW#kK@%&6212|jxO{m8ImOR!UMkQWRXkoUFLTbLYQIBY36J}XQSCdu z+u%H(#q&WfGY!O&KIFzhz@+Sq9yNYW{C>7~cy@LKPc}A0Zrv_sdgdl?g% zGP^9YfZWWF2LG*IQTNT-NL%hBPBNQ6m-}R*RX7O-$x+?y3Jt%u;FgSKsuyK!<-$Fe zO#luLVK0feX*jtscDYIkWn){FY8i#lFD$9=`(HYD&qc9cPwqYupX(NwRMy-cM~|_& zf>6kEBL4SHWe0~zSNR(*%QB}j=uu7jTt50l8hW)C;!Sw4_d0X0n&Hvl6KBQnRxNWU zR0podu4a{0OhH_>7!>8_lpVCK)2c3q$3*F@i0P{?zKinrz2O!KrR#IfN5CwVRjU%S zoz4F&;vfNr?muGlbxrl)U;Tcsvn9SiJ1v`1Rr5GZOUeD3MmefV`6Uo4TLEezYJV7g zT4&>3=(T#Q^$P7a`*Mu4^R8?+U(IV#(A~{-b--7|SaUnMAL>pCX zwSVn@$nthQU`L-^Zi(FJk@1t>!uR)B#p3#8@|y=glha1-jQkpnj&0B-usDfQjB*p?oTd)1K`;Ay`yVL0TFZ5ysdYDNGrI<(2uLIbK=w)<% zgf4%em{Yn5QV*h&m9>?WWXL?oF(PgC^y2;<80x@K-V{?^ z7|Nc9&flHLU-m{<_~L=M|HgaH*%6j|pakl47Hxi^OAq#MCl&sj3_^6wjnS9~?EHi} zPj58nRBQTJhRiwtU`W|Rzvlir%r|t;RvHRsP2uO;uE*i<{G>`>f0X7os(gx?MPrU} zXOcfZ_X6r8?h3$Or@vn3PS<3BG&cXFg@LAn*JoD$crAf^RbB%B|Ir!;H1=NwYck#m zuall6_@thKfR;a}ScM0T=bsNB*!~^rib^|$0DUL(?gN=LXteAsp~>5gLc|-lk91fi zi-y_pW6sWh4#Pk88!?MU2o;TuN0BSiuU~|Y5c44>-r`D8E}jqibl?QiZUXU1>mAaW zMf2n<34?<>k^;Dc1cZ-{*qhH>R9U|mk0D#VW}`pJZvRHJuD=`RCcS#rJ0w#GCn#>b z+o^hPQ_0_B?`$OOj!uuh`RemMd9C6T+Tm~d8d@kBIrord%?*BpZk8Mh1jx{)>-b9J z6p5IOgJQ|l<^1_qdq8C~q*kVz>3*V9P*bR%?Av8h=7{~w4AP@ntpWh8{xY~jb7ZY` z^0X;9cX5ZF5f}k%SGM^{JhE^x@|1ej21)jQ0Hzzlrij#m@ZnAwd@Wia3h$u*sQkxn z+V@behKt|#G?hPIu}l^Jn!056@nBSBGN0Rri1x9;hP?mKJB_jv4C1T^sxrxF)-h@XURHzJ?#HU<1sb_NW`F@Y zIn_Zj^6kOC{|m9(eBEK9*zh{oKJas1>(M%D{4;9zYko&|46Cp!J^R2B%;9n9v*Q8A zxwmd~!eiXo4?XF9K}GJ%P&rxr0mfQ++X#crF$11i<^)lU4pHy#aUf2f5eRc526 zaY&4!xejkXPG0|c+ul=V@OkaZA)Hq{C)z=(G89^?>0fcuun;3xd+0U@Y{>=W)XD^~>GQx+Af zXI~Az2`V~ z81*Q#pt{m$%wh%)gMbeJF&*jf(n~NM;Hd54uw?eI;sk@>;i}6$b8uVDnrciYT-DBh z!1}1&erI}E_aoa|$~va{s{osz|LDravP`*G1)&A@fA9g9*PW?j=Mym)B&KK~q>g8+ zMG7@ zf)~dbIix-U|8Jl(qXc{-9i_$8}_O$$&oGIE|1CIQv`u z8TbvKjt8rQ*Wai%zbIijUYKQ+OH(qhW6EOXRD(9DfC0hU7|nBLi^WL4JTjpE+z z%_=oK!Fa(XP2xh?N`soQnM@#>_bAPsX4?-`rL_@`1}P-9@W)^QY_#kj3z`68b#fm8 zhSNBxIrP^_)Cu*guQQ`)&8`Vf%z&HlwI@Yy zsrOXcCmO85YB17T!8;@PTWbIStQ!~L+}rRjB12i2%+J3slik6U{KGenMGFsH^$9o+w$jET z|M0;36q$2ByIjxLG4%4N7HLfq9f3&1cXQ@(114d7n@FI=ap&aixeBUH{R@Q@GJHIR zN(6ekBWk~Hy#%xo+AaOW<`ku&OqCw|HyjeOIf2)O!Aa%B=P6O7!SN~TGz}5dzL~FC zb37DOANI~>l_mE4;gg)`NP%;8h;`rCD(wS&@S5PlJ~}OT61JiL>Cccbc+PY;AGr*< zQmK*k>Kn)+;7vu^^H52HDSUyTd)Y8JT-{*bJEpFw5?nPRB)h2vVlc46-R@wUBq#WI zIFPz>InnER*ec}F19=Ol_3&5kw^nB3yL-PMywM0Sq3Z^oKpf@?;SjFeem0tWS4e&j zr(9jY?>#j-EV$^Ka9|&`pHR}XJ2Gs8hr>RUtj_i`p!57#wJE8QjEDdmH>A=woA>s1 zzidr)5nm<(J@ACQ{8Y;GhLSuWu>T;?4{vw9`C|@EF*K86U0=hi9bvm_Jp zgZ>~mo^YJt?Wk?6=8>gyxMZ#7HS-BQ2g0cA(k3Htx0CtEgT1I&*=tF}7hEog-L2eH z_fn$B^ZPb@Qj<@j$m>ha;3o<$K3AXlQv2PjSTD-mRd4y4-gjN9{s@z#KD91tBB#0(wT=D=V85OhdUet zXqK*~>?^9oULP@`YTL0@n>eo>o*qAcMd=~+|VCkh7Qd`e5NXT;g%T%#cwJkzyYmwPBH#&c6#4!g?*_=p(3bIU!olZ5SHkBT2p@iqyQcwbz>Y%E*o$pbS z0-V4AmDpO1vDzQy^be+s21eCa0M-}n$In@+k67CK4Dg`lQ=xAHx2y*3y9U2fjJ7zi zeWf0)8h}m7fcZ~=&QnuMU0=JT#tGDcy>G0T17wIu0R8rM+(FIVk!FVGgJ4)Bxnbw$ z=+bP#p*qP~KLP#P9y@Dp0KgKIv6IAK@Hb--3nYpaLKvDLs)7R|IMfSxL`9~>Ljq}h zt0L22eJCTDSDQ*&g>SVoj+sxydkNIdhH;v%a@iTV@(gv;Yf8Bl;MUVF% z#8zppATvDP^@fWK;rD2Ut^P>mIHq5$oc}6vW~bbs%*t=Yc}_A+?o$8&A_av;elBkB z+ZH8pU{&P%*}ONENPg*UP)i^jkau1Yn>1czk-j+h3qRxGb{;$&N5q@scwbQ*|6JAz z^rp#Nl7YaXR#ED=eIjK7>eB_z4+AJ#1B_iVo^v_Afde2b?yTQ$v-$Y6Op|)cU#?*; zRChl3&>NP|k05bYt!-rBjfK01q8FO4#2?D9!a6O9q&F+H5iM#&Lnjv=W-&{ycu!Ob z0jPWjkl(`x!lcAS-p^F`wS4*^9=&{;D3#AKKnBkSYVvI09pssuS(!5&(~HlruP!s# znVvClV3OFx1E+uklu}5`oO0|p()=>sg*kF=PEn7H^>w-~_a7gS!eD{Y&yir8*|mjS zl6$?`9w9XyW}ei9jw_u;OSXkQ`wN?kFi&WH&p;s{Eu$aHdmYhT%r1H4$VKgIv#}Q% zZIg*4H?n>+Q;wL}L1+&pVPo%tPlSIyqUxuZ*z)3|FX4Wn#4X)7V55EJ!0N#HX1*`_ zW`WesN`QH84R>eZS%4DEWBGA__Fw}%jZY%(_j-<;AN=!MH&h}eOlj}kH03w!qBtgu zSg%bhw3^@rSfXs4)bCzNY;#uu81B#U#Z%G?U+#!hp&k$h2O-(Xosj_`F~}DFNs)83 z;LZ%5oWl1HCjKc?tI!b0Rp`2m(6#^o6Wm9sP?Ktp<$JG)p`i$Ag>y8@O{eW6Ui6k_ zQsTDLDVHVkM|B{wL&kD?u~(*kM)P!ffQ6%LBKbo!Qi#}`m9UdIahIIOxe}*=S&9db zk>m9`=#_~kTzul1Q1ZhD{($Z`tUGoxh?|q|o-q$#9+YttI^frHHhO&QB({5uvz4aD z`@}s>%@9$uswDEbu+h_EGq(Hv@urlF^>AK-9@R(jua3>jF04ttzVq1TB~-`S$#pCx zS6|%HlIG0GwJ3>pKpiOR3(Zll;p52**M~zoqYR&fP0#4|`m^yEvmNb*%=IYu?=*N% z{3uoENau!wIE~j@E4nbzCJh|Se~zacR@E!=sQ&mGh9b-i7v%qa+2v>AWADnoneY(i znO-*V7E{FV=}X2s)6ImJKY~O1j@%j5>NGB>hiC)LL*1ULIB)}9;n(K>$K6{-<cemi~4#C}B-{20x-GT*ocXxO1g6zG|*Jpp-_l&-$#~tIYKPhUw zDOpu()qLih&$Eu`x6GfeR8qG++}sU4Jt#p<}5Yr*kA*5mM zTYey7V~g0)!U!m_5_MGOm%f8YH!M_4Nrexxqlrm!#Ow_YTP}b1%A~G*LQ*LdzaDk& z_)(O|T6$~0E#<~DPDYOiZ+-A%B(fd9RvwuZ1Wt&|Xkpf3<9DvFzRVl%1gQ?=0 z6MQ`<9o@j^_QX$mC(kzal!TFpB~6MGn?1`BGbKF7!&i(ildP8OJoXOWCWG8~k*--Y zaCC*0-yq_rv35pK^Dy}mCJiyyJ}%QYvP>o&+HXU((@*`@nf4iYzb?y;zs#^uPQshf zqWS@pVUN}i2)!-l8O0_h81to>*oJRy^&s*o;*Rfyg*UT3yCw_<_DA|3;)SXOc?YiFx3fMEdcdiv zNsG%U#!fA_b8RtUYQl9`5EZo(`#mFd+Ow6NZGgc@HIratGqDld^Gz(mF6I|L1|)NoS1wo;wHV(m`YK zPPnISuh7Q*bXFv8^Noh$mL7;NVA`5!Gl!E)G5)g{hFYzMFZR@BC55u!*1cb0u4aVx zU_8EqH6~m#5EX+tqDr5++nE>Xe(@24im#mv+NAP1dg zJtgwBWqnBpTbRtcJuV*|2!PshQN)MRCs=Xn-3hqePbly_9xAyIyP)ACLM6GKEY2&X zEc?jK13`m-tEmJlCXWEZ+a1d+Kqmk_WpUYfX=xFc3Z5K54k#ZTsIF9=hlgQZvlp-0 zY~7&{L8wHUo9eWX2G@7?A?|TQ`jRa;`Ed>f^fQ6mbb= zxD_a#`9_-`Go-s zAqrQ6;g{RLorSHNW<^B8JvZ#BHpt7)6%QUN4d;j?H@}U+cP{`q>ef<_x1_K6$8xYDEY6tOW z-lkTwp@jI}PP=9?cL{`otfPt=_7xsa$6I{H_ z_{El@8!OA$)I43ahs{s1`eO=_h7P2B(q9=kV(fP{GiUL6$)j-;Csbn|0C8TEyXDsP zc+|ZUum7CAm3J+@Cmon`re#h$OK24x{CMGCw~PD$@ZJD*%s!OdzSl>S94856vljC+ zy4h>K&;^cJNJO3htx|R;{qw?q^yzp1F5XyP9G>B=OUFBWmW1(?Ek^R6+c93bnU8ng zfq3M=k}xxZ7O|jQ>e^L zuMl|DU`&S2VhD|-AER<}J9hKFS2a2cM(S?P-WSma3lI1d#dF;q-|5>~Po5G;N`{R< zlx&&+MRN*GKlz0xC)Qq8G4%2t9X7$GmRUIoWC)ikM0~HPTODUwnwa)YL#8{6|0WhV zLB`jT++de~eO7Vc9Y64=Q@~o=cUF4Sp>b{1SWbHgYT~yIC^Z$Oj`s${MhXui>GyE=eOh?1YYsS( z*{$WXnd(VpGk(jczqxyHL&j$AX5Yz6Jof8i4>@|YlxuNmS5|`JdL@Xt_`dgL`~vsj zNX#L}g2>8pMdYDE3da+$U4Oli+ewizw73K0$ZHxI@eY2<$TZUVGM@<3)!7~Spp>W^jfqt1hd>F zHV{@Ipl1Q~J*l!D6ScZ4F3Pf}EasQq^&@>bI48&qF1}o=Qq=l`ztTUWNB< zAgdjUZtbBU5_VE6vdip;yc3>J{4_MFM8JcZD;a@R;0gZcDSQ{gDkweGnVTuSRNGnn z$p>A_&$E|H(bJO_i&`uXffJd%OTyEUGX}!$@7Ju~2xV8@s5=U#THI|h3zBj;uP9zZ z2!f?qMuxx{%sCTG8uZ8&PO3NuFJwy0m%O|_cOL1f`(+-&vvbZmqU~^r2+Q0Mou)NB z^6gu4SCG4hP`&~@4{;MWm9@elr)lRuh6}J}&hvZTI5fbL(vdzE)|mjuCqhfGGf(40DC{ei;OkAim=qBDVXbUDab z-Lfd`8muE(xk3q9e(UyiJBSsYxb}gtzfi@Udk$>F9k1Ypck?w*Z(MB~xdkJoTL^%} zi;ITiDP@L$;?LOJy>j)0m3EpSiJ0XapHxZB!s00rDb5`w& z_cy`p1@laz^Ore`=X|n$C3^M>R9HAq6q$EDQ>ZW$Hb&aU*?ZvFu`ck|G3gy!OJ zMV@8p5sblsdsJASG+FP}YRTeMZZOJ7y zb7RuY>ev0Mm)PS{{57B3QTy7>F9RnkATzCx2@@qI=FSE-=(nlv{mS9j4*UWYa zyZyG#7T(j7Yy{GILrl@G`@~=tN^?C)_J(V$I_@so^I9*T9r*PO495#<`YBxx>%@I; z>Jsx^#huRFfXRmhv65Is8;euvfprnl`F2AZYg$`J+1}bYX<^6osQkSbw=^OoP6jcs z;om1tOiH5dHMW851AeXk^C-sU_)sT`D4=qF7g`_-u7ct<1X$uXy}s35qdlm?#X za2FazwgbVM^*1)5YEB{aA|>s;|fQK5k~Ke!uYSHH^*&_;83obrxtNBnBw+$AI%G57#Ia_USA{8ZVQZAlM?ZJrPI2~?H zNo|A-SdiPeU0$^hWc0U#7khL+>}NgSOgb?s1;I?ORmvEN>W{md%9!=tS=Pj0=e+4o zss~$T8ANe>oaM3_rZ^DEO|u`yl7}<)4!(yL!j6QNF0IpHx-=`L4UiN!gDL+>-wRN$ z5plj{5zV?Zt^dl1k2lb`+5SdUP7K@*>?>U5vT%IBQl(0)vjzD3r&M6;Vw!1T40lwRPcK3`Xu-*ays0*BC+pYn;=IVjQd>d8*Jo@8$8nJ=0k_%81TheS>2xLMtf=NN{xX44HMp*{EW3&bsQeUvHtss z8yi_Mk;O49tE;dzrguC$WAVuAgOb4`L23`#cy}VZ3l2$Hs46T5eaSWuk*^iG?vC6T z3dRjSoYLlW8NC&>>CE>QEUg5GOxHmv(tHq8NfB=MsUJMJ|3Patmeh}5p-~*;sy>lD zHE%_yFHvcTuPAGD!WCSY3Ljm+pDhlhYbVmSpmFv9q%2pxhXl}sLDT&fIZwx6^jx*W zg-dO5mO2};#AwUHRkI0vd&p>8(su<)YgSGhQOP{~R)$#YC5QDSb=2{bmKaG7x9HPW zRhNRdBGKiB{2H5;kj}o_4l^p0Sl9cudv3S9)jfGNpAx_B=sU2A3p9zr0P1l7>gnCR zM$eI5Dp?)-*49~0$4Dr}=yJ3~&%nnS?gm~Kw}(B982_hJy=)L{hLGmnt$_T7Cp_h|$ARcd=p(TySzW_ru{RD^E`WmKJ$#ukRO5+S$`k&L)4Jm$w62m~5zuN4d`ugNyo;#AlTuYKB~FR_H9i%3l&uWB7?w*o z{;#RcrQ<@xRgobLuFRIkkV8gE8ec_yQ53@feO|D$z6;xHBkrr*|HVL+=cU?G2PdN0 zs9)l^x>h5~lEFaS^cts9ZzM-t(ka~IW|5(0BmV+ps`Sv=L6Lt+UD9i#;ps||!3#ey z!?0(*QV-6<`RGnlC6*+33i;77)?#mpfm0Q!)v-a^tJbjS z@f{8ZL9V8q8G`j+Ts22V7lPud7o$PU3l9xubt=W?H8Z%#XSWYl$f8*?A9#27^N~p{ z2dH{d&p95sZSdxQEacOTJFXEbN2V1OHNxSZ`ztm4>L&< zl8mlv0~A7Lq_Y}_Q38w#Z21$B?$~3^+`hMT0-gJWrle_x+i;XAk)`2`z5zo zRb9(^R?4PQZ<~{{B!$r<3}X4xww$i4QakGZ~crfH~%cbc^IB36Om>(O3A*O#kk7_*Z ze7#qIj<_=xjpQ?YBAaVyp|EfaV<6KbHh8$@GL!?GZ#ScmvA*=>%_b5K-)0jm<eZ)Of>3eEv5PJMDY+!7AP`Pb2{9{0{LG=AD)r?3@Hp#V1h~*GEWZ7!Q_*I2Ayq z_FKOnjnT{PShf@2V-hT~Kkj&D_f=?KySXcNCLV>U8NzHsvl7xAO)$mVp=1;1OCazE z>|YYa4E{i1NzTl*^Q>Um!S{|M7JA?ej+OzM7fPpAE_mAc z_KZqYeHN|Iqw#mcQS_<`wl=)pds!SdCR~`L((1kthJF|c(9E&F*QmkOH zNBEYiHqf#6Tkc!7eWu^bSHHfiN?g3R5C3>^AYIGbW#1(uH{{--y{PAN#i&*XmjIAN zvt|0>Y9D#S8J zoRwl$2riiqLOVp?d)?aEPlFf-fryR6qW$&l^8QB>8|X zqEW}3XnR8l9y)4?7fzoSHMEu)9l{#KjKzoExpihFN1Cg8>9U839^1Qh=IbJV-jFJh zyLMkAII5vhW;#0X#_rWj8-53ymU*ooo#A8B=&qNYO^*DHemN7&)U{A;G?DMvDk{hEM_Mh71)AfgWBF89tte~9kNmV9$qwWOMe7&Wh=D3`uokrlC=4_%6VP+{ zva8X3ikwz9NAgpx1%6nCmPca&9B7jb%~!RLL@JNG`d|u~+Km*EOnU%G``(QiSNuBU zlWmMZ?%3u1SV1fz+#G2y>sp0^zIY(rwr$R}W2VficjG8++b@`V6HMqHl zzSPcn;?fg%5tMlNLPZh+P*ppYRDqI!X<_YXY^|ew*SeCoLSeW>g4Ty8MYFP|dux;a z3@`p@a%bK9{tc&!o{K(txaQ@)bRf`qp{EIJj(W&gO(n!<`$>?SI03*JnZj6Hxz0E&-2mF3O~JwJTh#^E z2)fE4Z_d-W-YUW>4`wmr{2Wj*6%4nP74f^3r^MjH47Rle7rZL4=#Xvito^UXUsY#1 zRU#zIK!p)Qk62K^V|2r%6q)s8Q=?cZqTA(cCg`XM@sKb#>Z1Q}L9DI(qUHBwz~E*O z9$RoBxZ6!Axs$wxz7y^wNNuUpRrfN3HL0cRT?j%IQ>%A)olJ~Sk7Q3MylVRVAel+;rz-; z!s6(5>@T*IFPbZs+%b-gIpuKs{N{su_YP{ZP11m|3;c=iJQ-)U9!oz}E(l^5(xCUNP+ZS9FafB(^60U#qR&Lh0yJpQ$kF-L%{Z_S(C!yFc308SGJIu8 zG5aW>RHetZyKXjtJNOX6Gj+NUv_c`}n_j}Pz$>m6*8N2G$L^rfA-6|G=!;L9_qgKg@uQBYrKas zN|=Lcr}A&Hr*jH{)Zsg%if!L`n+)}jxiD$i7jJtrjhX4y-9Et0??XJKL8_ z4S%7SyFSM0jS=PuMHxEOvldOl4v`^!s1iZarRnZcLN{l8_uA9NoG%^F{+(2d7o{N_ zVK1VGp7hOFDTEixsTOal`HQ3G)0UO^gouhAFS^kPlcH3B`N2Al_x6R>#%-@+2LoGs z^YXqi#}}R`6pkIhoUr5IcbrMoG@K}qZCQ&;Na`wIY9wpR#6O+;2P2^JKu8ZwUpFk7 zCl)ttO}j`VMydqWJl=WSUnF-0`j$4;)25;wrZ=^nhep8ikRX<~^!mYQn3CMic{~o) zG#4X~7guFrI&(6kIWeKxk)q}F-0>wqCsjCv%NPkL=cT8~tcu zT$$RpB20rj^t+Y%(LMS#eNB{%*mEcR`4wztxRBfy9eavzP4s#K8=xG|FW!$?YJzG;Y8R{@)YzYDY5!#bi@8mr-g6I?WagVX@ja&qxMXPuh6=Ug6x)Q2EtAe|;yv zsP4fsPJH>^M)xatzcSSmOE7HN*?P4Zfmzea5+o;~P2Zmw82?pC{{3|`-qb!%N7;+| zfeOI_j3KM9#R@fZrf|Vd50A{jdT%de{;z~>wF{aA9%prLT$0s$JNhSlhe}WG%^b1~ z-i|m-wWU6Ey9lcA3B&txqnrbp!T%zt5}E@75MU$&T8q|aEkl)vA=qV z!MlxQ7C@W82Li_8JCk>;?t@IPC#k`p7FQt`YKYzYa^r9{Uf-8#my7%Xe^UD39r!STTk}~I5 znNz^B@G3h<5BTq7>Vd(EdSYP=hE=!QK9D)-lde*vO~R!U{E})v?Qg^$XEy+L`q^Z` zu>qJY3{wRPr=Wwp&qJkbr&E$D6J^Pr-Nbl8F3lB6U%Cw%<s|@MtB5ltuRpVedSq zrfGA13!H4;=O@A@Qb{UGp}fee?qU=EyTW_EbI^R1ze;4q;f9`b_IAY-)`RO2LGt|U zr=GcyU*dx|HyC7SBPM3#T*oJ6=-4=X*72D0*fsVu6{Y%xLch1l85Xx&2#Nt!{Z~%4 zO(%-1Lh;>&>+F(~(@_{+RhxD=$@87HLP)>x)bGD{2h6#PW-^7@AyQM8k+ZRI4D?!+ z8zDxwY0)GC$l$eS>vqk83uw8(Wj;`z?&)SKt!S?LA!RMSHcNoxs=Fms@#?VKpw=Jv z^Yd|0ZT=JRSmXTyn^$Zhl$@Y5Zge0KKXmlzq){eas!&efJ1t}TF7_*$o|woZ*;Cve z#e?;pXMI@%6HIE%Q{fh!I5cm~WT^6sl0iNAf+u|Kh%Lj3gJ_chCRlnvfCTYF+LoK= zmu{AQKn7M4dzm~eC4oQ~VCr#%qXqy9=0F$oMRsk~1;5&O`2ld50not2_@@D@bH1p} z&wu^*>=vV$1kTe6A%&>Nm?%b=nG`BRjL1H8_nJG*W|~DJDyu9EP=uf3&1aC(TH97` zI@^IL41XY@=s$tJ>Xglsu8^-ozB!F5+CGr;^^4_DC~+lC8L36#1lxyKOW?aipr?UZ zTa~CrJR z+i|busavzfC`IXdwvcQraRqC3F16VW-$&|$?><#~dIME8;==*g)0XPeWFR8Ls>bte z0&7S-BhWQ4erY3;9)+;A6p5MF3q!ft_=;1LJ!<2;|0M78U#IWCBu+!(B-!1$z!tWI2$3zRsS?4)MIk_DeGwnFPnPd+#kf<*b}O%b6&`kmqG1fZ@HN*@Ufhy|>YhhRWYNin64HQkuzbHev7ylXYpIh>vBjj%(c#WJ^V% zt#5w+KzdZt^4S>CrNKtG6*i$lxxH@eA)%kbgf_b0xhm>yZO-Z1 zU6@)$`0DEyp&6Cvd5EEcj~m-H3{2ix8Yw8~@Vv&sr@_%SQkbj}4724ry0}{-kAoW* zRirVyxsw)ZE%kc~>PX&K=Gg<$MBTL*;r1VEy#)42 zDJXG$63Z+dF(d8=wqW+n>`4&l6j3-^y3T4AV$*&Le$4Y`y9>Vxs|<+3|3IsV498=% z8kNB&%6a`W$Y5;~*_>Q$VY0HKpJVjp`>NIWY!7*XEZb)foQ#YDmj>LhXsq-4E4J2) zR7?Fp0v+y6-O&95r zVI5#R25$1v@?ScXUCGTRZ6w9UV0qDDoeVGq{8^r!L zn5r)Y9)~Z=3kxXtumkNJS-~b~uelge+{ZmczfF9yc_R6VTs`gK*U?!6>7c8_I*-j) zgJGILr_$!Sq6T7qVY?(^p4)GD#O)!!P@ss$-7l1-y)F0-V8ku|O9+QT>3NnxjsNqG zxpIO8vaRb~N@Q8AZf%d;iHRgYhZH%|`L4}B10ny9;SPZZIUCKDpb5P3)6Gu$tS4K= zJf2=gpF?7&Zc>&R7K(HsPZct zxK8#KkyyP?9Yn;okP~r@P*eeIoSu8kFD6c8ZyI-J4Zy@H;1n7!RbLyU)FeW3Q-pc> zU8a*(N3}Dyq@%NtmarSWQpL^o*IU^oBn-L!u|81LpvRfI?ssWo#1DQuj}%#{F*SN? zqk;Rs!Tn@*#GQ*Nomai8`V3B|C>32G;pWhjcSs}+as>D2RhsmrB!!kZgJ6 zJopYXZ4Xu^@f>%?)j>Y4l&Wi?kIAz^6b`r3Y*a@JR#}Y9_b&ir z`GiMrs}yq&6$}f{{Ei}Ykr|MtYdgyK*U#z6x_fe@#ol{&ek&-pfOz{lbIJZl-Mz5O z6+@;G{f&a4E;l04oPk{CthIA9m^X_5+_Vvcx-*W*Ojw=e=Z1>xJLxzt}wTfO&^!_&DWs=r8eYs z(oO?0-;0;QoA}pGXzo&P>?3eXFL=!V4d8qLTl@Z3o&4da4YAm6c|0RU$OOqd2bX~> z@MexFQgO|v+xHtQEw0KtL_Wl$Q_aoN^5>WFvG+fs+-ULTOa-`en)R2KTADX^VA>Za zMjwJ0FA}{PL-MWA+eXx^c9%!U4!C)?um2sIK=o3KgA=>mj(W}C7}2Oi7Pi=a(-dw> zjw()X5Vo1@^BBbC+h?yk@XpEgs1SBqF6NN`C4`IP!#L2dnaah~nYGS=iQ;g?>@Ewz z>xB=@TMDO*0V+|g_$T=AybU41Q+-b#2Rl>pmSsk6e$28s!} z#N1?7c{9!;shWJYa);#Tglef_vzooieeHHa{phfsQu7VYUj_3o`3@+M(anwnY9}4t z7V*}6CQ{D+y$V8)n>OH=j14h?iG@%g&9$4k!(PudSm~t%z0#i_5VroXJl|b>IP_it z%$r}%yPMLf2MDjDH^2}2d5kLUv0(c#qaIpKL!Em3Lk(6nJ-((RA}zF zA$plHj{fn4S^Z6W=Gqpy&@QXnwr%RfhG8MQYo%Ae5_P75w;ai`eeL{UNqxoEURK9C zv)^wf@$P{{(6C+gwN7-qZYkS^8-p+?DhooE*I^)|^^ASVp;iDr5cnV>-l7KkeQ-8S zosYPSgh;)R7gr#fvTwRp%BJ23G)h|et|c2i8DXO7-k_zDrvU@+mimzkT(OsLel>QO6O)n2tuU)UYI8r%p-d| zPDMcE4?wkq#22m>>v(*ouv*=`Ucle-*$q8u>=@<>EnKL`#@US@DR&uZ+=mk!9*8@x z{=t8G0scncw0P?wZe-V1&oWlvN;iYyZ{oTldKt0*(e85J$%Y8qEbnlxdfmQ$r_vCQ z-xMClhbHM`RNoF-%xYb9T7;1bAilb;jX2nASYELB2*;OlKhsLkw*!o)LjR`0HWxtl zz!+%u8U{<-vT?w}d2@SC6d3XNMGoy^+YIYfEbi#n^5Rat2m)7cN`Scy75pzOl)uUF znC<+0Cz>og`3Mcd7KM7kwuSLNJR}Yx@O+2`(xrx#|1OwN`Mm2ovF{8>`-v~~>wo>x zT;<;dO>~`ie%n7;7>ww0mCkPyd{7S#V!y0H-~lN)f91C@SL@M4vVm3L>$d};CMiKZ znhk0P1bn6@ra8Insfk#{V}=*#_QOGlfuBxA`rbl``i8zlUsybU-o@#EOGByUF6GOo zr?H9CCub4}JPgC=ep0r@6M}%019CA`Q_rHO6w2wbkLy{f?&_oQ{vx?GPz^$=o-!VV zde1r7Z%``#JS6I4_&~F~Yus#KeycK&xX_U3rMKr1SqzstfFx*-tmxu@xb-6^aN5dx z3d@*(us%M1CpKe9!{z*}DgLuI49b7f4uKpHb}D5-MB#BCCts7TPUBdaR;xXgk;ejR zwhW=gFl2M8g)d*c}%Zby}7_3t#;Qqr`HbG7zaR45Bm4W{`n_8Gu{=~~Ge zKF_qMFr;iA2TI*w$Ea3w7Dne?Wnr(o2>vb~0@m@kj6;I{4CHapQ*Smm#DWzhYCLY^ zaX;r|cjWHs=R*AJ86}|}@o@`@i^saV2s z^uOoe9})V&PW(SHUl0xVi-NW?kELlt^fb^5Dopy^&lk$B0q|MNo`4)yD~QOSC{7sN zlc%4F_~G5qS@YM3wa@lp7?qNL(icLYpYb6(E52~~%mHJAThW^r_~y93+zbdne_ABq z-1^7nbC$t>?{1PVR^WiBuYxiFmtxO1xe93@QEbae^UH557`ATVDEi5fmn&lLedg%2 z=CzdVXJdM3kSqGuj2b7Ln@XAiZK`iAuq+{0Jh8ug-;h3IxC>v2K2v(^A%mVUOJZ1B z7wxrP!oBU}zLGwb>;Wr9IeR~W+)tTa!W7q?o0XRpQ$@PfhkikBw=auAeOP(YfA~Ivpg%;v!0xc%WTDw8$lCZ9VyyF#>OcEoaSLeF z$LU@_xa=AbeRKdjy8Q}t<9GKz0rlV5P2*kEO*yOAf=APi9-?5+1@22Il*mLS=G9xn zX$iFl$=%um(XTir=~h>=(Ps9{{$*x0f5gIbp8mL>?^62)^{}=3^p*fPQ7y_J$U~U9 z$ocJccJjgwJ=%q~H8CHw^TMHLAtLcXM-h?}n(SIt%#!^^t3SWnBs2BDa1=va$bbn7 zf#BXm$aWQD42YCfV+INLZ*ba|7*01M?!)^^)Z*V0nylreS&Iu}S=O_kG?x02A4=7c z+bNqgZmlA6`DTRrqPa;=Mp^0GBk-+uG)ytmKYx%`}7+0Lx_ z(EADf+YI{O!eDRb+xXL+(j}~~;=LJ2PKjfL+ejHpdM0&_%N1kAZaLNoZ!FF|sC-iE zfhPsV@fRKsxh!GoD7->RK#EGQXSz}^($aqElEbWxIQ19C7f9>Q%9EZEb)uT1TC9+A zu|7(*GcVHGi)4)S^G=h^AR-Zye8`U(G7ORKd5(fu) z+oK^k;{p@pGghMkdVUs4P>Ku?|&Q&{BB-SJTx4RdH`jrwNot zV{gsH9y)fhs7QDPXui4WSNG2jvM!*&ZTiPCDEF9ljqBCmU(hU8xETj)93LBQ`2=X$J-G}JXfF|SlxUu*x0yM`&PM$6%N+h2F#Ak|ykhFlBNXe|`_RhVI$ZfB04^93z|Sk3(>v>p zn$0)4T#tL8$LrFk)7zvTXyB4S6<>OsZ|7tgQYGRu3ny4RE;wGa(v;MXD3?g;iv3Ak z>f%{a)LFybO7wEWx_j&Q|KuDgny1%~r}re>G{r}A@h|lE+&)%O?01|qCs7ARN2MHG zUJD~A^Pr85h7?zYdj2o`o0W$)vkMyG?T3)SF(oeLgEIpn@_ zb)$}C(9C9?&hmq9JE5adaY=1bJtiZIRU8qA1H;bIxX@yQi-n}#CoN`^^r_mo_qL}; zTD*&->_EPXQio=nZ*X%PQefFsg0<&Ic3}S`Cy5D{uCGbld^)o~@G+ zVF673&ki5~NSm%_Ky%yn;;;eRvP}Hw7tr}a<=!Dh{MVS=JK_H$ZQC6R0^dMhPgZPm z*Ga}sK3=Q1(8oR*P7i;0X0@fW#4?CnsAySg2RQu@`v(fJsrZ>sgO;b3cGAt3N}S} z<8y!_E*pgphim`)rm>DJieV4sV_=X^}tn$+|p1l7ZonVi4L-zVU~ zuM_&L-Q|(BC2AfasKCqY+IOrkuI2HNbNxlz4Mxq;Hx$G|CJL_U*b;jKG?)bpaldTBI7>4mNyQ^fe}c?tYfjVTBR#>{rd?C``_VgK%E zjQIKtqwih=(H9nR5wE8U-`_hA)0#MdYkKs!Jgi^~BO5@tM}XVGgkNNX|MChw;_cV( zF!7C5@##NY3CGV+>read*)3T<4IJ<*->J1CrTvRw@sk-nN!6f=qn&!>mbh4<-D;lQ zx6<~lH+RE=cD2$w?u4WI=ZjEc)W2JNi7%v9!?rbHwlQNSR_is;TL**5oH` zKA|9^kg44$8WqFf)Cp*h^7Aqy*wNmyJvh!GU^a|K9{;0d>}ib@Zwg>8+LcZ8j@ z<&I}U-44{>8$^UE*I6M=-Tdr9{Srm6iA2a+Q0S8Ky6kp8<8w|`M!ay}V8|4)(&84n zalt_uWXJD}(ehDvTam=&DrozvOC`79h1YQZQI8-XK(?zxz)B-?Op=d})+}apOjS`A zg8K7~aAZ_+a{m?66n%rT_-@eteUX-4;f#Kjte?UFdNF(ML;zCJ+FcuHJc0i^gJ_Q1k=Gfl6Z?p*o<3p1*U zMjFW#w73C=;H53=5i;MRWB5OGSjuEm64-R!nl_gY&~Eg@3Xn!aYJ^+RH{m)qX$as& z)2^2%r0hUC^D`kJZO~OGp0hYp7{u?$Q_2QQ9$$`EW$R~epcvGCd{{_*6ZS)nP2q`q+&w3DrtI$kc0N9!usvSO z5Ebl=n1F%4t1USSQf1{Vc?gv-HU{2QZGW)_?uUA4bvr)|e%syMlzH-_Xylfqp*c1( zjQ4SUxWouQgMr$He;PTVU#t*;OrlzPsBo{C)cemcLzQ!<5R~mdWD}!eixhj;cN2<2 zlxROD-t+NkRE*?^^@b5e&$PSr6MBd#By|~4I|T?8jOKrXSAcL-OZ(DiRkTbG(=cJA zEbJUBMjA^pVf;=MKeSgZHacgG?@>v_66>EsPc-=I&TIGFjsOk+_*Ki48C~_%WfFg! zBNF?A_<*T`^I<)G;Bo~#2~3PmA` z!pbh74DUPSR^PP`rXyq0_mE^Wy@rz_Au*d&O; z_WpZ(K>K{|r~rjM;!pC8jS^EsbM^ffLP{&0qkXFtX(rL^AoUD!Xta{LA>^45`O|*= zr4$GIzbbTS&_lPA+e1JZ{AIfMjw12}RgQQ)7_;-2H1WFUG7mXN@PAA_ohz1I-JPVd zK`4)=h<@5JBK)puMeQqU-*=y9lka+XR1O-!v502_-YQ^uk*6D;$r=u}n?7TCj zwMM%VKFny?%x{~G^Y6NPYu>-ttHe!=@-#Q`VYY-C)8O~&LlB|Z5rmL!Ba(yY{s@o#}%U+ z^^=4)`dHQXk3MuuG`g%d)m#>h47dyjvoq>XQAOXK--sD+)t2GVJJ88zZB}&M?5Z)E zKOB}bl=ZC#eDD>YbzPT|UOlV2PZ`pO;(P#r0Vv6~RGc^GI7Q`&Pg*Z;4OdHgMftXXj7|RrX8Gp;j_+a9-}E zW32NFGKypRVUBX*<^~{qC-d%g__8dR`?@y1;suXyu@9SxZ0d`-lB5+i*kq9$EOyx= zRX>jmY&erC?xDfJfE-k~vu>_?lUW=U zl_U;8p+<(dJuV{pVVV zqAPL=Y~qvEi^TFJd*;*{Rf$rXCJ)05MUp26GkFc`LZXEzvfp@^Q;Wn#$qQKYTkICo zhuNp$Yd_q|v6#sA2C6|}3<8}UObv9l&hv*!3vKy9BivxsLN$ccW-eXluxAE?LV`Q8 zdc%@N(dyB@Ay|0+r$skuQ`Fi*+~VxrCv>q_IvHoZBB!hLq%1^^W=+NFly1)YUJ{hG z{;Fi=ikGaypqfm4DvjKz3a@U)Vd<;d`abjo^f#GeDw=XXX@zr_Q{PY^ITV7kC(SqA zOYKAY9NevIr?99cck{%ge!Nbwukm_Yv*O+TWXHET{`CfI>J44i7?!&;3aVB$a z-NrJneDyP9;qw=rXduH--TEmwndAPvb^bL?kk9?Ek52g`AG!=IJSE=< zWui+vPs8!bM7ee1{L`w5?YP>2bnh0=B* zrM|~OV4*$hhsw#MMKi_9Q`3FfXfXi$3g#NpVll#qeKbcJb7>n<`b3U3y$+aFf$n6E zfry*!aqX^C=Or+nLfMm= z4Kf60>Ul|`?PrlYSHc7Ri)P=yOTjcwl0YLmV>#b&H@SG z{^mlCn5Afbp?m{x$osoBR;gL84NcAAGziF9mfmh!ah1!= zR5Y>6t9YILdBeMN*6;GMoEWE`x8QHjo)yOy)A?KS*>T^Pn3k%xsjFMchu8hvr><7R zCn`(Vc>~!43yofTCVR+5SZrTW9X@{ca%J`-!vS1``(67o*I#Xr)jH$IhCN}ZAq zA^*I~lvc_NPktvBC-KcXTZ-U` zU{=XzTsFxhrUD7c)Bp#svqP>6d}fFEC~`u=<)dBdH!{49A|jbjLgJ8kO+znwJ)Ldr z-1O9@afmxykdL*rzOv_Iu3{RwuqnK^M;Gq+_6-Q)jq$jk3l7Fn_E5Nar@mHe3E@na zPM&1V41_x&wPj>~(EFICN$!B#;86_p;+-rDH7{p>NAceBw5BEAb$`!AY=E0oU{#VP zC76q2p>b|S-)Sb7x0_OVXK#V6Syc`v8S3@cysc9+293g{BVu*m z?RV7db>BJHBj4;?!tQRgd+8+LFgYlm*(O` zh}nK*4`{Y=G}SB*y5N=JOq`osnl+By&5p}PC~YK=OB~>VCI`0X0yeN(pE6J-Z4bt? z)OCk$>gV??>Z;BOOVZe<=7UeWOLsHj%V)3$)3hV&OAs%vXBjhTF+HJSm-g&=_=LPv z| z?IUmDI9jk0=ML;{ufNsGhr}iqa!_)lnB5Fdnq_Hox2%~=IK}$)^-d=55py9;&&$o( zMd^=@!jEajCu32GPSdZfh3I`5VkWxQW5z)|yy>6)IT zF~2(0x>>igXH>?kzuT7Q{E*kyXRi}q97GNP9xdA7sn64lW_vfMiT321@mXyXz2}G) zV>Xp5_E_YZ;+?kr)lId7YhV~_sBHppQf!XHaaPQlofh2A5N!!(%{4pPEGPqVS%kkr z&v5Jvf(vPB2qp+$UHg{zD|XoOpujR8(|yN5EIvMQ!?N(e-ouMrwKsW2Rtg%x-no9^ zvb{U6Qc{_{dBi)F^Nsv|)wfuk?H#&xz{VgM28<5*Gc%yKvnG2nRSt^OVr9JMH`EPj z@w4`N#N>`Cqk1>o%N9;s`n%#2n@;}n_3ux{9{Jvr*!Kd0<`e`9Kd6__Fa~60^WgS5 zv12n;nAu6V{?IDXa+<6~gSf&4+Tq_g^mTs6C;g<>#A9`%zO$PbSSY<3sv;#)qL{l* z=(4rF+1znxV4(aVuv=h1>>Z_YQC#yF%NkEWR{OEAvg%!YWavvl-h zIxKF4*Xy`wq(*ZNSasX=zM|3T&DkIjxwBWv6f+y0hOc!UGYvrn+*(zJMCB&m#&Jz( zgGV+IZ(E3L^_&=ieDC??=|Z|Y0uRwhD?^;J;5P@iP&9L9LonjP97LF?bJNTxL}$7 zJI|lLD+}B2rMzuSWW)x)E%37uhhIj^P$FIYv5OrYljOJuEOkcoWFu*NlZ$&4sK18M zaeIb~^lya92X>s~ZhlkAs)4u{6jXc4>FN84S{Dw{b9V4S8x_il!|cf|Rt_h{bE1^) zE9Nw>(PW>5;*|^IeS7$ChF&*Mt-VK{$Y>m0Prvl-eIGd_=P0BSSXMcNCzLDF379A1 z6v{T~Wkf|Qo-B9^vixI`^^>Jig9*P}frUL?9QEx_HJep+I1E2`4V|`81^0$*F<@P* z)m|iN&y*{l0q;<*Jgv3IN)|xyF=%+t&`?<_FwbRYeAf2r9c8yU!W7<0e}-|ksNUBe z(MhK2Nmb=yqNs&Yrw zqUY%r-1;)%;3SHa(9hw5->L$Hha1x<+z%6^7l=qXQ9tIe(wvpVj$T)zwOq*pOg!!} zp6K?Yi7XOeeqa+lOMcYesTFEvexnwD>LW*tX4e;%OsL-V7M<`D@4n7jmBAG5WJW|| zq3^NJ6xa?bBB7;W(8*U6&$pic)qd%G?h!(b3h&T}lNLwPK0jj;rmfk`BU-LV9XFd~ z7U3@u-CSuk*Z6j4%%D3X`4J8+dU=1B)r_s`TxMH}3T=>(A+O**tJx?`5t?rjP8v)V1KqZJjYw|o ztxU<_FA9TEs88BNo@XSUxmE0)s0|vSG|4SHYqd?T9b3FaR5+JmFJ(${ZzhXRnl$-m z08fxpF;_XNhliCAKpsR@YUY*NP(4R8She`OcH=TaO1}HDlv{&xTn&>KwR2Ic6Ira% zzE{%NiW&72=_v~Pq!Uu@6gv`ZNbu{&-%7N`q#1p}9Gh${S0QnNYvj09_Atv7erM08 zIRVbHk8dq}v|_y~^b9SQ4$^mnLVyUD1PlqRLQrDE zI^vq%K@1DzA%2O4xyErdsRNkap(I_L9%WXmbJ1-7J0sqakg^9#`g5UqY5UE-d1^%0 z{lEpme06p0fge5ao($Z{GCE?ab~P?2R)?m=e-P-)k<2ooOhTLXwPIqaz7NZK+QqIV z)fJbAj#2e8e10m(`0dYNx9GN%gEjfG?^Un1^dK9S5F|{7ldjwz2b_%Di^;A~fu}J& z3k`9hJKrVqeQ(e59`R=R63?^sQCceg=6OLcLCW`d#WsAuK9RC*k>0&rQX5(Yk;D}sQFT54doO+$&baIg}Z>>1ah6G!`0lF~9 zNI2!hXBYd8d*`y5-X?&?Eho8o6L0D3_m@MAfOZX6$3$tjz|9XDc!x^l1oX3Y9@|B- zP9>p8C?j0hI_r8Lx%+(;-^0Ek+xv=8m&dExWBC5<>k`F&G+46KKHF)LtG*|zBd@Vl z@Tppod5lw_83Bx2A2aV2k@h|gj1DQXV}=xd?X&`n4Cjhi6v8(kY14k~MI@c+t!neF zRXl5|QcJo1>*I6f&qXb-B9HzbJ_+W_%Leq%2mk*; zr~fxxrc&RBwz4exDPAH510zlfwu3p05K02Uz%+}z6|!sMfAAB2{G!*o_rgzQ#h-cMyKfh1Je^r4yt2K2-by~aG=HT<+so*VyPU;X-)I{2F6leQj43b z3p^|PwJspkzG8K4nU8Ge1!Mc~Bl$+uwT1nqxnEwM3DPsQWBlVk!P%yJn;eoJ5vfRO z_~ofytn|`q-)mTyM47NtJJOs{=w>0WNDb5y2514iVZrx=s;%1+0OzLlM{KS;%J^aG z*hy^65}8pNx2-SIT?@Ofq9|RD9yuOE&!%PBQoZf{Y<+3Sg{I8PEyEpG!RN)j z?eb=qrT}*PlaoiH_t8G>E-&}5$CJK=M0sW)E+o>qKM!!Kgqo2z4L5wah^ZGbOBPlAo{>ACzc@%#7f4O>?|D3}A*X7M0pWqeWA6`5UCzvopeH%dd zGiN{eDse704wdOSS39&|X*tCWZCpZ^jq3{N!#nEf*->+|=o_oN`%e}qgl{iaKW4c5 zpI=mMm!LQMTm^HK9mBJ@=ehjymuXRk2AoK z4Tw8I`f}<=N>!TIj8~~~&o7607}~LIRV2}NndsECxvcyQ@xk*tA zjx>;!;qfH2cuuM}wuKRrBb%#LC{I(wEiwFe!frPBf?CESxjrYcYp^^fa#G(nh;NFI z4&-8oB=w&=`V4U^6NVmu9?4tdqg$ina~dnJZF7aFNgMM48kD!JO18(ZQm@+oKjF-SM{XeA`rvm+ute*ZU>r%bdhH!QIEDrl+C?LG|UP}4Nn(ne;c z3BK}u?j3^Gm4MYb#nHo@U8aC0CYi|Wx5|}H!Trknouwh?(^p`o?W-G8WamQm%@`cF zVLr;Ojx)sY8%74w)t%U1gb>Q3hZWFS6Zn2vrrNLu>Z>Vt-(hn`{5W-U7`TT5^7PR) zpAhE?!lw6zKG6?Te`vhADpd_Fg3>8h7uVs`FVUulH;W+=Ul%UesOAuL)b~T7F-(rU z1Ruwq_@;<%jp?~guupzh9^OU-8-#iebg{c1k&;0e87J8@%9!8B@yRQPr!*kB=P&G3 zaBuN*p;!I_G%CGY9L0+rW?|lJsWJUnmfbKNQQm6Ee=`Ss_^#;FoVn`a*w+q8z8b0- zPQ`rQV%40W8#%o#uDQ8;v4b|_)x{jhbT(3U+Tpj_!uiB7*oHveqQmMoZ>s;{K=Tfy z4E8bqRJMLS!T@!|qUdP~C*%MzX%(}Ddjj>dK;BQfb?7G@Ts{}TLx|5)-uWQddyzo( zb~1W&+^kfQwjN0~{vy)9`954NUhk-^`Ftan5+CTb-(xE^e7~nUSp4M4r^|DjUAqj` zLOwl|2oyjVc`E?lRZ>$xHG-{fyBRuV>_!(K8fhEv|1SDEwXiP}c%07!O*M*Onf)?a->4|f zpYx1m3P?qzb!S-Mn3B^j;eyNOSS~L^DatlFKPGA_yc$UsoZs0ZvlZ@3aecgF z95@mif?GLVy6*8SlYczWq7rP0%0mkOnLi;hI?#F+YZ!vp&HdNuXubiCpNN#yWHZ~u zz?>Mz<&mqBInQavc2{u`aRk}G*?y#WKzF8=g-&CW1En!;Fb>1xj}trE34i>A((P?# zd(`9ne(Jq}t)+I;x}6Ts)MB8r0`xuWnL`b+ddd3gbvXqU)lE%4dfy6_4(IFQ^^=N0 zHtsEKrC<9*%C#`JEb9NV+LtQ2S}OY)THDCYZwNUXXoRn9!Vz;`8&wv&5DA=G2OMqb zg4}{7D(3GF?yv#wLd$+}+$yQGBpfE&yLVt4L$NWFDGQZKaJI>fRoDp6tm-jGiBeqkvuiKAZ`1K@}7hF1|O=n;UQB=5Dwi3;~F%2eoRq zEnQzP(J|yqN@`~bbE-W*Pjo@Y|~#8Bfj%Z;Rr%8!DsY#ukGofESZb5 zs(0N{08NaNn>uz(lA?10>&uuY?6&5ifKtP^84wFnhLr_Ul!-;a4pT!J8fU59!f^YH6)0xF~G)Y<4n-W^Hl9?${#jU54cIL@MlXr-m5_?^!D>DxIsaIj{^uDORTS z8#%A2V%;x(n>f~0;Eb1mh|!A6ikFr$&&VYoYooFXP2OhJD%bIgA||+*h^b40LZmes zOflML$!2Gt+jB`-m+lSzGl*f2mlh~JbC#VEAJyFkZ%vCkGS0?pqB-DSfg2&$p($gy zSMZJjx@H!AuVy#&{dv@QdBG85{?a}Ordp%d0k88!7<_KCJ z81pq_vJx;L*9>la(|yXpN4y}`{jvyy^$*-@C^8|mz7@jV*rSeIo6}>`Cd&Z~Vs^X> zRu*xAnZbt!UuUU?S^0CHZ5(WGhWMSaH)zE0iQCQ^<8h-6uW=!Cge zF^lacJ-fK9pqg`<##o2VMLwu+s#I2n2xw9x{%-NxVwT{A1qq0PP*p2$aHJ!ulFa+ zD;o#IP?fdL^XP%@6yRnED^U7N6ig~G{CCCW|j^ETO z2gV)1Nvm}4jayjDIK=3zhez~=_(M=8mCk#txhsrCOE_s+e3sH{$G?qyegK}Yw~U!# zjIPywC|u@5PHs^Q(At-yYHsjhM$Nz>-qHR>shUafan6-w89~A@)?j0B9V}k?9(GRJ zA;!>fm6bCNGvBR|7YPH5%a#KFCvrTMV{Mo8pH!MMhR8dK=`hzxHpb&W@<21cxco0G2h@7An7QT@miD66`vFVc)b z>U<(xi|JK4hkVp8JzhA$)8e7A=6|%E@9XCZZe1JSP4|Aif*y-;FZ@9HPjJ=*o>b@w znjQ%s5&U#st=mF?TUAE5Tzu5UqE#F`A6OXH@T^*I zda7%YNmtryx$&Yb&r%z>e6S!sF*lHQn^^&k6K&X z_j&3`bQmz3CtGh3^6^EPR8E}Poh4ki@*L8%qy71EUkNr-*B!OQU-3j9xf!ZXl@Gbf zUpLw2z$bsj1eKK->Bfb-BGzi%oqiq2$>lea#78DZ!gulCEMWm(9~)UEZk1kZ=?;zPsDwZ-)OFZi^&#l?DYcd=avG{xJ& zDb>Ko!BSb5Y40LB?1{fXVX5#ZAqRZg!F9pq{m`?!rO{*5rykd>rST?8SyWuwi&6f^ z`Uss%i}x4DEmg43slml*Os5&b;zPU28WmVziO@!!{CVSw7Oc^h7Zn$@OW%mvM+dpb9McpnG* zTT8i>t@7eeM)ZrCc?0Gdw-jt~qrfI0ifYCD;n8b{hQJ(_$BV_;AYdPK@_p74wkiI6 zX2(qi3~}0Ms9_vCZ1E65D$k@9^gnmd3|jw`|5m2(e`X%L<}vqb|Jrja6OuS8Cmro8vhj(hwAC=v5g8SBu)TZf z(Go_OO&!9+sI#)m)riIWi@Q@|!eVIc_$@Xs>OZ%M17$4qW_}H9&{bE{y8uje!H|_> zxYr`;C=v&-d1Y9%Hd~L{7>?MvB|iq}f$6FI>C&RrVl;O4!uDYd z>{)E2!1~JSbP@b8qnjYYAhIypye9b2p8oL!S3X+FZaEEn-zV>L>GL!o|8xRJg^Zb3 zL>g-TK1cpzgShvxpX!;?3P`Ku^-KTie0oM>C?g&%U%nQ+?S~J8Q2s(KoeF!PDxNU^ ze38Ph`8`AD57hwuTzs*C@@}ugy8+yRfY0y6(i^q_OACn`MFNhe4?a&DM{>&3qy0;F zk3X$8{&Zi3-v=h7q-?Gc?m#IO_ zkOKzjpB8~#CwS(6S*AVr2Dz^8ygDfpTAg#)IW&snVx~s59S_F4JRE;XG;XFnwGNy% zy+HQ*d#=Zm-+Qq>yiFT&ore`Sp zop;+BieY>iqRX(*&woC-rh%E4h~vUEwS`SWS>z?x)m1g1NG zwh~R>qUS;M)%9h}dXco3koo3hOj5#t4`+N!T22fqY>2P0yxh}e^nz$32i&5^hMxW& zoNGk*GwQm&wSBB+`6N&M`M!Ha_{{=U#^zQ3x-PX3t5C!m!6yrzg0V2g&5{; zT4s1Tb&G`L+7b%Z7q=WJ1@W*jblaWzq2PN~O)K-F5Z~1OxjHM?pTAk1 z%D~IrnTsOwKKgyPJ;T+6;qVAJG!GP)*2vbC&B z9IbP6Qz*uSCdsOMQ`~V{42EW~(VI;W5Cg9qxJr9Y`8+8b?*HVb{#y>=y-#!4fh>6` z8)GPOmwUQKo!|D2UBvi~XzUW?NYT+S(G5nbo?fN*yEVe=5sHcpwnQ* z*LB+eqEMw%{Og#=&{8&*&1Ryg#*E@D85VFGG}-Y zYlcMg=rl&6bABwo5xJhgLj8?hqNA4 z^cQnCKcJw!w*k(qe258?kP?9c!?&;RJ85y_H7Gt?BYQi1LI%dh(Najqe$f9eHQ9qS ze{(L>B>KsL-DU2ogp$+%W71lRbN+54+ot%-oiU>M#DjGNfXdaoNDP@osu)?Hn0#2 z&97O(+Rd=dMd(!;N85U{HuZ)`eJCBHX^jIB>9jR}<0GM0?dR+5ePS@tsU!zF$aOt= zhk~uB-l%0|vWFP-c4CHi@$)yM2FKkfY=*dRPW!!!)@f;5fq9^pU8POwWl@CqE;r$+isAcSFY}279KMo?fheTN% zo5<^8&DyiJLuYdq3(3Dsy~%mz#W`bP5H<-Q{uk}~O|BNaNEt9Wh-_Zff$C$&# z@>dur_qMr~es>uees{J=;2V>|B&$zl6e}I8FiQIM(SV(Yqe0syeH??!L zd%%R92Pv^?OI(nS*lX|^heB!`Af9%>pm`CI!`*Oo-7ZZU?wzVcu?@d7iFW{AC_L}L%`etmODRL?7(XQ!DzkW)~Wil12T%s9&oWMy1js) zpo6&4%`SgAcGZ;JuyF-~-eFuI_FUO9E(fCCiNlO+m-e46(u=@KlGmP)g>Tn4c=vg{$OmFo;?9o-iv8 zb(W|YQQS2PgeFJ@-;3y!M}6+gT6Bg6KZL3`P@u=Z1h}vXB5ZvAbYbW@z?4xdwN<@F z&XieB_gjJlX`5qqVds!TYoNgd z`{Xbs^l`Nmt`1SFfJJJw?oeGCDIYH_b}0W7l%SymS~z>ll~iVo^e()4w-Cd^mQH%TbzpEbVPPrBW~j$gnG>kuW#Jz`fOK^km%@XKI_`j4Y*U4IuDhB z+436queRJ*u>Fdl!@kOSpSJR)22Njfoc(z)0|2M`VgSf^SQX~^vCmA0cyTnH8ecuSwIAFP3}1% zvY3P!-}2X93_GZE5yJ=WhaC26`@qYl0f{rdf6>{PUbbVw7>fZrvA5W}G zq5Htv!mz*^avb<_idVV0H2-q7Pg<6AAnN$d6%)UdpxZv!%7DKEQ`gh2(s|!RXmMzO z*xP8jp?bR)umL^!neUs|-=EZm3Pi`cyLCXT(!Y!cpQepcbKhuBw)2F^e?kwm@jm6Q z_L-_YO0>*vo}2f$iPGh(6WG%c09KAq^!9PC(Y)4Gl})>X@Zb6V?EZex`d70`l0qCr zTO_A@l%D5(+^gJE-utSMhnG!7+EjRAxf`<4<)^v_iHU<4yN`R; zb#ZWJeBvOoRy8cOU)$sdMsV%IEtF_bBn6Sts&~32 z6Qa$Fy@(ccRQ?wiDE>Li4TqclefsP!(iE|gJ*P?!FH1ns)Lz;ncz`JJ-{y?12(}WF zJKuo;?U|W5t{oc2y}u|Z)muLHjcgVRhhB3k6k>fdKZXyORWfeI(sa^;alBUMd}{q# zZsr6Rxe!D|VsN4vW>O7(06(5K6Z3gTH?!LA9!Fi5AO%m?u|1UONd>+ju=48XtCQrR znh_0+H{m=jPOdXhhll>(E#)VV8~C-ttsx*>yaQwN{ged&XSq~pjJxdSZ=JD+izk64 zw7B)~#14z;)e*4MWVphC1$!ZyV6s1=O?lZ$vj~jvELC zblxl&)KGFTS`AqgsQfroT!;jIS}0xFYRo{yXt~im%AH8N&*Qe(Oa1s+m|=q0n`NxD zl1g7$K>-~+hw-UF!0|5AVWMNnTW2rTi~9`iWsRa|K!_E7cHJ5XncB0qFprqrySOdz zPcjP;fhJ3thuYT7I5p{45}4J8d=K&;!A}j-LiF5%d@&Oj%d2Z!L#`4W=;E@#-M>rs z%(L87uz@AHw~~hIk{`rC4m~4;$qKZ%_;!e{4ie+{eOV0j?VKp=}{0W zM6h0dFbMOUN&BDjAAb5@)cD_W*`HLQhoYy5bRlJ=lzJh7co`i2i0S?|T&6QsrUw3u$oMhWQE{I`ns6{OboX zi?Lo@3Wp67`!T}^Vd?3h0GjyW!4>6jzNOk~U01yh)L1lCjjG(UZmljGafJ{0Dl&KG z;v;hsX*8BCW@xv1RyEP%-6Nc zTkbkUSLDE`Y%0#y zogA0OM0Y2^QMRXBcQRQ^3jGU9pR306d$5xcY`?N3Sc)KHD{s=g+gP71 zUHJvPJzWru73qovksMH+lT530eoBv-7vWfAQBJ!Vu7>E0#B@Y_xtsoSTjM$bGMOt~ zxPMLXMq(eG7lxAfU?x{y6fQEy(qb*;@VEz1xcBmk)U zQqZER8}pFq!{Yt2tLY*C&S}0i_cts-r5U3SGR+A=5ev76x^Zt0eJ=aBKut!LR|%#X z#TF5x^&+{orI}+qE`0&ZPQ_D)8arN!Y|CV;NJt=?#e)fJ8JnAHT|oiY9#oLJ=Ed35 zbrCtz;6pGlD4t8@}w)3bul{aP}cri}uNc%FX#cDds_h?wg#g?}~+V`-KK z8U%Bu5CK$d)t3wWNa%_u%U6t7I%^P7BgX0BY%Vb630lNSos`n<(CSZ+om~`%P^M4E z{dvHDz{DrpEb8|Za8;1k?^b-6Rm$|WkK*Uu-SMZ2>+FFkpb$l;$~%1yudks z0tKJ%`chrA*-hiZMzWU`%1=;T@(njhWPF!a<>HS#I;6=8*{{SP*32j=R*v zlv!U}A?0Rh1|QPl60~6896@23u0m)Yfgx*4A+Ko|L=JFH@eh_AgebUj)YX5j$?w%+ zs(dX9&GW?IIB{yV+W1FlEzQ=33uSI!MHoENHK=wfLuS_un_m8$niFOd|3%7vd;OEw z=k`2A_7kblF?UZZq>-mcqZvOm=Ry^bN;X{42&G*1brP|%6W%`frkWe%VQpNv(TLHK zoJQO;M9Z}tL@pUsRNe3(3Fqa@LrseRwhs!J_;bdGQ!_KD=-0P)R~UPxKd$gse-Q~6 z;Oy6DzX_S%R!f^OTj@bqXUMBOgZIUXjgXxvR8MJEW6X{iJ*Dgj51SQJTl=0>x^7cy zE@<~j@Ifoz6k_3g2Qe`fIcQKqNEP7h20BG*q>pUZG#eZ{#`my{aCuQSlWmqZxefuwUQ^f;E<&vy!+QbywXtBg&&wvN1h;ow`SPbL zK22Lr3V7|@<`ps9ke)(3Pdf?NdU_5#y z{Q$hrgU?}wz~`HRFl3+~Bs9dJ_xuUunm??N`aZoUgKxKNR5?cKhd*PdHFFT`^rq9B z!@84$?PT+-aML_PgUIcq;E0Hb2RKRtQ?kp@nF#0ds7h0i*PJ!i!n?IVP8`36!CXxV zc=Aj?+IS^X6=jvp*5wLva;et~o`UW8x#=Edv^l*Q>06TD;WLf4Op;f=IbC~I;zo6E zz|Po6&Kpm4Piyem9hjUbm`GX*Ox0Kp_jg5{7}rU|rL1Kq64<;`aoaLo3z|v!oy=tz zoum~5qzKXE9+T^N+FdnPhj! z-YrMPWibo#WrH#PzlrMYx_422Eu%{Bn z4*%_~&+V4aZ8-qH_LAvo%I7iP$NS(*lm7X5>Oucfy`^EmRP2G~Wi}z52-N#}``8AT zKjPxyjPpQ4H)ZW~ok?rEc0MKgCaU#*j4*z(5_Bz`n?0ylbui!6xw;@<`q6ny10C8Y zqvzozcAdlBr7Dybn-PbzXH#B47h4Ubqz#v?YtNZ}Xy3FS;MQk=pbVMbX(iNy*+ihh zZBF;G$r{wk$^-T|m@1|7so`(hXX=Z?vlP!>r*TWaU(MXg)yo=4k z*{(}eS1_C=vez-Nn$%TD(mtz?R$CS^(sJ;dq3m6qEL~{ixf6E6ARDjcL*BR0&@EBk zs6`!A{dcW*>lnsUm!?l1VPo*l0TkVa?-tCCtNnjYj zf4aZICjAO8oq#6*X!QPTeZQa)cgodzx;xoyH&^+Pf5@9&VN|%{2st$Mxfw{-SSct) zOshof<~zff=8~RqTZHaZKWKV*KI%z54;E-Kp&5G7IKsg6h9kaQf%(M7`cF2YAA`Nn zyLv9HWdG9a|KEPexe=<@#EH#Sjvrfiu3aW7a5KR^K9QV;i)wDoo-UMCQagovbjRs4 z!TU>;q&)5!>*!3Fwi1@br8MZ*linPz*qS#qaN8tSUp4BEp@08HFGD67v+trQ)T%0> zsH7nMy>Tq(&25xAXK?W)-D{D`!g&6rfeW?IH{k)}l z2_5tu+E+=kR-BqMf6&L+eKYNBKm8hY4lCl>zx1@V5o!e;SO7>_rm*)Vu@a?6NHshf zd09D&=)i46dmlRUn#i8}^bjBS1GD9{RbBsS)fXQhA8MyN1F5O+(Gt|?eSQ5!^h}lw z^PJTNA0?G3w7Dot8t0LGZe6AE9?zvh*j;A^|3jXp{s(vOW~ttz`S6)rAy%W zQ+sk2whJxX(rta_wzyAg&;7lw_Z+J<>$CO*CL8)9P2ePB`lUjHV5$8U>UC5U=f_7q zK(hR&%~X$@TL|E%i8(4bO0TUbp9$l#W45(8gJa%5u&oM&EG)`dE5trJ;iy=?WADeFmKr@pUI zqR|1-lNgm1;Nt9Td0>U0-w=Zlb=&?gV65Q>#~PT8z{hXYa|iv9z8wU)TgQ&)>zh6BqMzHs6bHB zbse9?KPfc39Xh>!+>vOOSkz?KwQ|vD?yKK)VTKjuG^Ws@A!`!6g1!abbt8bUE7CU` z_`t8+GwGEk)K#_}((=}7zxM3a2J68)T3$JJJ5>QX`M5TMuE*7WvLuBSw_W*MSX=G{ zp=by-69jj=c4>kX{-`m<=Ofy@Ma3V|c78_A8s4F3Z%ck4!7TB*?1@Ui-25CL_q5)0 zbPiABI#&E-AB)<3kzEe<&bbpyVZgSTuU(utzp(^cHrvZdRM_fn{Wt|N9eAFv;=?sH z3)8xMY2S)EWK&VIor*x z7*b7@)^lQ&5Bijhtxrp>j)MF-YC(oMD@Lgq#NMTdrB6QN^fyoeuI~MnJQGs#5gN}R z)3feo5GF5kuaWUQ7`&$8vSJW5KuRh}!tEKqflx*0qAb+|*k!5<8ZTL`ipe4f>XHe3 zGsUQTAwK4yv(XV2PnQpT-H58PG+Nu*+Z9Hr@V%FNV-HJ`!IU?5^>p+#NSiaJaxrf< z@)r%crHj3~y?#Q61?4TEtj-CMJRk6`I~Y2-2nmqI<#lzt4OnF9&OLfG3fJkieoft7 z;M;QMEyT}xH<}6`A5%SDie?;JyX|yQfplyZ<~C0;x1f9KgPic_u6FYVm3)hVeCuVC zbjtd|@gHgYi#4$O+1iiX^~!voQ&ahF-8*YXEf*$gCPX5yyMx(!0}PgIrKAU{$0K~7 zZFZS4i6sqW>J1gfp(qYdXY*sB;*$gfq-ad#uv3(a`amU8&nWQqpm1hKMzap_uhRtE zrSIz>zrvFMxLS|@G)}KXEfqw$P4VB|R|{S~WklfxI_n*q#d2ia4-W&!^2~9v&Uf0o z1{DHh?Y%Y5M|O1`wydJ2S2U1;(1o&XFcWI{oRK0$m3>d*U*S%0xl*$CQs0Mz5mli4C_X+ouWuu096c<4{MoCR=*=gF?T`qiq*}%RObk%5{f{P&7 zYY4V}&H6ED;n0bj&;^)9T~xH&m<~DAfR+6!8e7Ph#bL1S$#Mm|~*<>;ljVOWB$GARqvipTFgwCJtJmO?0e4 z29%X4l1DKl7nr{X>i1UBOUFP=&g!)r(~-|%*G{eFdhlp=#T( z_w7>(linDV<)`;noLn*$1H@Bi0I{#1f(bcQx5ujURmqoQ7U^_o@OIF3l{Yt~fn;XG z>l!up*N1*8o)mQV%>zYfs<}%tl-S3_Hg57b(ad4Umc;=CdZh|R{z*7mZ*i%@8r!>f$AkuBPn=HiKF;SC&T%EAsq9KSAQkP( z4$U4No0#xlqs(Y0bV*X)IsUzJacMjfJ^TBcb5922ABtFr`st&f`D7YTp($3vpmpeE z?HR`DQPp>mQ(}o(+TD%dT^h6g(Z0LnNZwdXNzf4Z{SMQNz0>*@2E1O}L~(H*aIkBM zm@8zVe9J!(_XY`P;|D`zikqy=jhGdW=`RK*g2P~HlThsGVsVGKA3@Oc((kW9SC}WI zk|oq5T=oZtT)HB+nSH7Xfb=^wlg#uZ+^YEU@LIy5aC2-&^-|e*_U7UY)Plv25aR`C zT_!T*(Qqu7oDdQAc4f=^q$#G%;Y*#FuO@nS)9To(+3pn~xd)F3VUW=bqD47oO*fQA z?;Xxf8tMnXEFd)jI&t~{vMF`{cY6W+r*^`b{L>kRG(eM2j^^RVLj9h&9P#s~n$xJE zgpDcQGsgOZg|V<{8@t*!;YNKQT9@#KsD=HWu^%i<$etfNN&y|BVRXCKwgvT~d^zQp zxOXDwIWHo@6T&MM)9g62+GI5kwYUiMP!HVdW>GVquS!x|eCok{a4S8f$*Cabw;J3Z zIy_R+UAvGJA8UKuuZ%QyQanuSGcHI7#(ccaU=&Cmykq^OxUC?2NMqIBr$a zOY;#4jIduzg9eea8(T_(dKO8#Oa*Q+Kv!|n`B;Hx1d%r^7(m7!pRyAA=9NPu-2USp&T647+l`Agy+8| zHCI7x2{Ya%e!Sa8$g6F*50YD`n5g%P4GGwfudJCAf_-gtG5Xz(1`S^$);yoYT4fa3 zwtBbzMW#EnI(IhLP1_B}3J__a-jjKIYr|t1G9?wEl=tpFrO5rqGS}$ql(oV4CN8#~ ziS;Zqv$uM@^F`I-^xQQry=R+uY%K2axs3cnUJh7B(MzMFqe&!E-NN9M%?HIh@Hgvn z2ibUX0_TcXlX1FLzbEOdn&c?!#M1-E>#OpXnq*6xC06Z?aMmLSJ5D(X*XReuD0m&) zbCi}yv8yikx$CwtKiO=hl3t^K9eDD6K5W_-2t)}{7qaD){ zB+ruvv!n=*ND#eX z%Oll)e>kx?eMJano4Vd{_60gDTVb%j!%U@;!PvY zmS2jLZ}lfd^Gp-Su7cNSpbR(J`y^6)kxAY~14!$EUFXX3CilFzM-mBxdoiB=b3#xZ zkTyMEzeor*vwgb4N*aDS(FTXHCppb zz2kbEA&Wlrek)1m_N`_u*C+EgXR^jD?)uskKqMPN@lS0pf8J8cu)aR;-*l_*?>+jc zRjdG_g}vbc#y=QwbnvqS9ioc)=BTk^ht76&OBPP>MmXT&UwnB8y4rn7%u8)P>YTI3 zbmXwv-p{o71#q~V%|4}mB`d$MqdI(bh5C&Y+?W5@EnVl@*&#<{Ushj)~bA`LX3eaK=v7^YajR(3;6(l9|e+sncb_YKMC66Fy;V)+$DM~+uTY<5~f zjvlBM9!@9couHaTxjA3L&?D;1%@Ffv;DfLTNvU%9lCCG;dqKQ}icZ za1)=)Vyh0|t%Q^OrbJXe=u%kQQF<>bA?ATVjDWU&3SvsDN>~v5GXL|s>!TPD6iGI% z0FD-xiRX@!rfwh9?1yKmP4lJHyzZb)=V+nr$&YnyWb2CB!is9xb#8W+Aqr{(s`L@X z8t;CYOB0W59S+#a1%pevg3zWX%Z(v2NLF!fN@)pozYL;f*!Ya3wm~7G{Sf~JFRlu` zSzFAF&zppEW26lL@hv3_+a5>c5|>i?szk*61l?{blC^`5|D}1e@x;ua>5rAi(qjJV zx!)Jn0Kfg!#Z&#HCGvX<4v;+8ldN73*xH8eOv9eeANxHiR1K&>3qhVG@o?t!T9KJS zN}rqoQUgr`q)DUf2Jc^?onD*Lu|2YMk&H-xI}JomDNtDVo{7%OLRsH{$E6hNmaQDgmW08)T_Ww{S=yjWxL{4dc$U5zbnuJ!bj4w+4cE5DUpJldZkVE9GiqDb(qNhlkk#EtYAGgQpH@w3o{7Oh2T<@ef`= z{|VPgiy19@T>JBZtRjv%?&#oxGz+G+>DeU}BHftOrG zXczLya{*Lq9Yu<0+?ga2AuQAtx=JiOf%=Izz8QB|0gwGeZhgIzvhitR!q6<^+C0xQ zw1Vi&7ew|&tlvTMxXg8MLOMLdiZPxhNQX<&92q7J(s@tPo?|jw<){Jqu+?3AfrMIx zx+`wb7@a|{c$;1xnsQy@uv>?tn{NMdZ(La%X7BKDy>;XO*K^VTbJE8CA6`8sK*ZUU QwF4^yJrmt3ZO7>U0nuZ~`2YX_ diff --git a/doc/modules/ROOT/assets/images/intellij-code-formatter-settings.png b/doc/modules/ROOT/assets/images/intellij-code-formatter-settings.png index 960400d823fe0ac859d0b7c00716dcaeb463dcd7..c975ab99a0f6ac39cebe92de9e7e0b131857fa26 100644 GIT binary patch literal 104103 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⋙9M>`yn~=wCQxmsMbZLO7e4n0bmI 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 VkE)-yWMQC-f{f~`@|VUT{|hW8hfn|j literal 104099 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

    xPH2 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
      qbJ$?dbDpW(ZqXt>(C(5?$&9# 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 diff --git a/doc/modules/ROOT/pages/intellij.adoc b/doc/modules/ROOT/pages/intellij.adoc index fce2a42c0eb..40568594cdc 100644 --- a/doc/modules/ROOT/pages/intellij.adoc +++ b/doc/modules/ROOT/pages/intellij.adoc @@ -72,7 +72,7 @@ Type in your Eclipse installation folder .Set Eclipse Path image::intellij-code-formatter-path.png[] + -Choose 'Eclipse 2.1 [built-in]' as a formatter config +Choose 'Eclipse [built-in]' as a formatter config + .Choose Format image::intellij-code-formatter-format.png[] From 0964f688a6ce0d78b62602dd1a3a682a2a6cc172 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Mar 2023 09:51:06 +0100 Subject: [PATCH 07/23] Bump fastexcel from 0.15.0 to 0.15.2 in /cnf (#2101) * Bump fastexcel from 0.15.0 to 0.15.2 in /cnf Bumps [fastexcel](https://github.com/dhatim/fastexcel) from 0.15.0 to 0.15.2. - [Release notes](https://github.com/dhatim/fastexcel/releases) - [Commits](https://github.com/dhatim/fastexcel/compare/0.15.0...0.15.2) --- updated-dependencies: - dependency-name: org.dhatim:fastexcel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Update bnd files --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Feilmeier --- cnf/pom.xml | 2 +- io.openems.edge.application/EdgeApp.bndrun | 4 ++-- io.openems.wrapper/fastexcel.bnd | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index bae1c18cf3b..650735b2725 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -257,7 +257,7 @@ org.dhatim fastexcel - 0.15.0 + 0.15.2 diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index 5a94e519be6..be5326a821f 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -40,11 +40,11 @@ bnd.identity;id='io.openems.edge.battery.bydcommercial',\ bnd.identity;id='io.openems.edge.battery.fenecon.commercial',\ bnd.identity;id='io.openems.edge.battery.fenecon.home',\ + bnd.identity;id='io.openems.edge.battery.soltaro',\ bnd.identity;id='io.openems.edge.batteryinverter.kaco.blueplanetgridsave',\ bnd.identity;id='io.openems.edge.batteryinverter.refu88k',\ bnd.identity;id='io.openems.edge.batteryinverter.sinexcel',\ bnd.identity;id='io.openems.edge.batteryinverter.sunspec',\ - bnd.identity;id='io.openems.edge.battery.soltaro',\ bnd.identity;id='io.openems.edge.bosch.bpts5hybrid',\ bnd.identity;id='io.openems.edge.bridge.mbus',\ bnd.identity;id='io.openems.edge.bridge.modbus',\ @@ -272,8 +272,8 @@ io.openems.edge.evcs.ocpp.abl;version=snapshot,\ io.openems.edge.evcs.ocpp.common;version=snapshot,\ io.openems.edge.evcs.ocpp.ies.keywatt.singleccs;version=snapshot,\ - io.openems.edge.evcs.webasto.unite;version=snapshot,\ io.openems.edge.evcs.ocpp.server;version=snapshot,\ + io.openems.edge.evcs.webasto.unite;version=snapshot,\ io.openems.edge.fenecon.dess;version=snapshot,\ io.openems.edge.fenecon.mini;version=snapshot,\ io.openems.edge.fenecon.pro;version=snapshot,\ diff --git a/io.openems.wrapper/fastexcel.bnd b/io.openems.wrapper/fastexcel.bnd index 1f91429a216..e072f849601 100644 --- a/io.openems.wrapper/fastexcel.bnd +++ b/io.openems.wrapper/fastexcel.bnd @@ -1,9 +1,9 @@ Bundle-Name: fastexcel Bundle-DocURL: https://github.com/dhatim/fastexcel Bundle-License: https://opensource.org/licenses/Apache-2.0 -Bundle-Version: 0.15.0 +Bundle-Version: 0.15.2 -Include-Resource: @fastexcel-0.15.0.jar +Include-Resource: @fastexcel-0.15.2.jar -dsannotations: * From d2312fe00324156be7d37f68556ded960e2b2306 Mon Sep 17 00:00:00 2001 From: DerWahreKlinki <102486171+DerWahreKlinki@users.noreply.github.com> Date: Thu, 16 Mar 2023 10:52:43 +0100 Subject: [PATCH 08/23] SDM630 Meter: change units for reactive Energy (#2104) Added scale factors for energy counter to match unit provided by symmetric meter Caution: what was kWh is now Wh! So, if you catch the counter values via modbus for an other system you have to devide by 1000 Changed units for reactive energy counters * Format java files * Fix fastexcel autoclose warnings --------- Co-authored-by: Stefan Feilmeier --- ...yHistoricTimeseriesExportXlsxResponse.java | 6 ++-- ...toricTimeseriesExportXlsxResponseTest.java | 6 ++-- .../sdm630/MeterMicrocareSdm630.java | 7 ++-- .../sdm630/MeterMicrocareSdm630Impl.java | 35 ++++++++----------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/QueryHistoricTimeseriesExportXlsxResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/QueryHistoricTimeseriesExportXlsxResponse.java index fc9a9afeca8..5cb1f161f2c 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/response/QueryHistoricTimeseriesExportXlsxResponse.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/QueryHistoricTimeseriesExportXlsxResponse.java @@ -130,8 +130,10 @@ private static byte[] generatePayload(String edgeId, ZonedDateTime fromDate, Zon SortedMap energyData, Language language) throws IOException, OpenemsNamedException { byte[] payload = {}; - try (var os = new ByteArrayOutputStream()) { - var wb = new Workbook(os, OpenemsConstants.MANUFACTURER_MODEL, null); + try (// + var os = new ByteArrayOutputStream(); + var wb = new Workbook(os, OpenemsConstants.MANUFACTURER_MODEL, null) // + ) { var ws = wb.newWorksheet("Export"); Locale currentLocale = language.getLocal(); diff --git a/io.openems.common/test/io/openems/common/jsonrpc/response/QueryHistoricTimeseriesExportXlsxResponseTest.java b/io.openems.common/test/io/openems/common/jsonrpc/response/QueryHistoricTimeseriesExportXlsxResponseTest.java index 363c54fddf2..d59804bff2e 100644 --- a/io.openems.common/test/io/openems/common/jsonrpc/response/QueryHistoricTimeseriesExportXlsxResponseTest.java +++ b/io.openems.common/test/io/openems/common/jsonrpc/response/QueryHistoricTimeseriesExportXlsxResponseTest.java @@ -64,8 +64,10 @@ private byte[] generateXlsxFile() throws OpenemsNamedException, IOException { final byte[] result; - try (var os = new ByteArrayOutputStream()) { - var workbook = new Workbook(os, "Historic data", null); + try (// + var os = new ByteArrayOutputStream(); + var workbook = new Workbook(os, "Historic data", null) // + ) { var ws = workbook.newWorksheet("Export"); Locale currentLocale = new Locale("en", "EN"); diff --git a/io.openems.edge.meter.microcare.sdm630/src/io/openems/edge/meter/microcare/sdm630/MeterMicrocareSdm630.java b/io.openems.edge.meter.microcare.sdm630/src/io/openems/edge/meter/microcare/sdm630/MeterMicrocareSdm630.java index 3a940873586..3c13cde5c49 100644 --- a/io.openems.edge.meter.microcare.sdm630/src/io/openems/edge/meter/microcare/sdm630/MeterMicrocareSdm630.java +++ b/io.openems.edge.meter.microcare.sdm630/src/io/openems/edge/meter/microcare/sdm630/MeterMicrocareSdm630.java @@ -8,14 +8,13 @@ import io.openems.edge.meter.api.AsymmetricMeter; import io.openems.edge.meter.api.SymmetricMeter; -public interface MeterMicrocareSdm630 extends SymmetricMeter, AsymmetricMeter, OpenemsComponent, ModbusSlave { - +public interface MeterMicrocareSdm630 extends SymmetricMeter, AsymmetricMeter, OpenemsComponent, ModbusSlave { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { REACTIVE_PRODUCTION_ENERGY(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.KILOWATT_HOURS)), // + .unit(Unit.VOLT_AMPERE_REACTIVE_HOURS)), // REACTIVE_CONSUMPTION_ENERGY(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.KILOWATT_HOURS)), // + .unit(Unit.VOLT_AMPERE_REACTIVE_HOURS)), // ; private final Doc doc; diff --git a/io.openems.edge.meter.microcare.sdm630/src/io/openems/edge/meter/microcare/sdm630/MeterMicrocareSdm630Impl.java b/io.openems.edge.meter.microcare.sdm630/src/io/openems/edge/meter/microcare/sdm630/MeterMicrocareSdm630Impl.java index 2f66cfb826a..5302ca17a6f 100644 --- a/io.openems.edge.meter.microcare.sdm630/src/io/openems/edge/meter/microcare/sdm630/MeterMicrocareSdm630Impl.java +++ b/io.openems.edge.meter.microcare.sdm630/src/io/openems/edge/meter/microcare/sdm630/MeterMicrocareSdm630Impl.java @@ -16,7 +16,6 @@ import io.openems.common.channel.AccessMode; import io.openems.common.exceptions.OpenemsException; - import io.openems.edge.bridge.modbus.api.AbstractOpenemsModbusComponent; import io.openems.edge.bridge.modbus.api.BridgeModbus; import io.openems.edge.bridge.modbus.api.ElementToChannelConverter; @@ -26,12 +25,10 @@ import io.openems.edge.bridge.modbus.api.element.FloatDoublewordElement; import io.openems.edge.bridge.modbus.api.element.WordOrder; import io.openems.edge.bridge.modbus.api.task.FC4ReadInputRegistersTask; - +import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.modbusslave.ModbusSlave; import io.openems.edge.common.modbusslave.ModbusSlaveTable; -import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.taskmanager.Priority; - import io.openems.edge.meter.api.AsymmetricMeter; import io.openems.edge.meter.api.MeterType; import io.openems.edge.meter.api.SymmetricMeter; @@ -42,8 +39,8 @@ immediate = true, // configurationPolicy = ConfigurationPolicy.REQUIRE // ) -public class MeterMicrocareSdm630Impl extends AbstractOpenemsModbusComponent - implements MeterMicrocareSdm630, AsymmetricMeter, SymmetricMeter, ModbusComponent, OpenemsComponent, ModbusSlave { +public class MeterMicrocareSdm630Impl extends AbstractOpenemsModbusComponent implements MeterMicrocareSdm630, + AsymmetricMeter, SymmetricMeter, ModbusComponent, OpenemsComponent, ModbusSlave { private MeterType meterType = MeterType.PRODUCTION; @@ -93,10 +90,9 @@ protected ModbusProtocol defineModbusProtocol() throws OpenemsException { new FC4ReadInputRegistersTask(30001 - offset, Priority.HIGH, m(new FloatDoublewordElement(30001 - offset).wordOrder(WordOrder.MSWLSW) .byteOrder(ByteOrder.BIG_ENDIAN)) - .m(AsymmetricMeter.ChannelId.VOLTAGE_L1, - ElementToChannelConverter.SCALE_FACTOR_3)// - .m(SymmetricMeter.ChannelId.VOLTAGE, ElementToChannelConverter.SCALE_FACTOR_3)// - .build(), + .m(AsymmetricMeter.ChannelId.VOLTAGE_L1, ElementToChannelConverter.SCALE_FACTOR_3)// + .m(SymmetricMeter.ChannelId.VOLTAGE, ElementToChannelConverter.SCALE_FACTOR_3)// + .build(), m(AsymmetricMeter.ChannelId.VOLTAGE_L2, new FloatDoublewordElement(30003 - offset).wordOrder(WordOrder.MSWLSW) .byteOrder(ByteOrder.BIG_ENDIAN), @@ -165,26 +161,26 @@ protected ModbusProtocol defineModbusProtocol() throws OpenemsException { m(SymmetricMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, new FloatDoublewordElement(30073 - offset).wordOrder(WordOrder.MSWLSW) .byteOrder(ByteOrder.BIG_ENDIAN), - ElementToChannelConverter.DIRECT_1_TO_1), - m(SymmetricMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, + ElementToChannelConverter.SCALE_FACTOR_3), + m(SymmetricMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, new FloatDoublewordElement(30075 - offset).wordOrder(WordOrder.MSWLSW) .byteOrder(ByteOrder.BIG_ENDIAN), - ElementToChannelConverter.DIRECT_1_TO_1), - m(MeterMicrocareSdm630.ChannelId.REACTIVE_PRODUCTION_ENERGY, + ElementToChannelConverter.SCALE_FACTOR_3), + m(MeterMicrocareSdm630.ChannelId.REACTIVE_CONSUMPTION_ENERGY, new FloatDoublewordElement(30077 - offset).wordOrder(WordOrder.MSWLSW) .byteOrder(ByteOrder.BIG_ENDIAN), - ElementToChannelConverter.DIRECT_1_TO_1), - m(MeterMicrocareSdm630.ChannelId.REACTIVE_CONSUMPTION_ENERGY, + ElementToChannelConverter.SCALE_FACTOR_3), + m(MeterMicrocareSdm630.ChannelId.REACTIVE_PRODUCTION_ENERGY, new FloatDoublewordElement(30079 - offset).wordOrder(WordOrder.MSWLSW) .byteOrder(ByteOrder.BIG_ENDIAN), - ElementToChannelConverter.DIRECT_1_TO_1))); + ElementToChannelConverter.SCALE_FACTOR_3))); } @Override public String debugLog() { - return "L:" + this.getActivePower().asString(); + return "L:" + this.getActivePower().asString(); } - + @Override public ModbusSlaveTable getModbusSlaveTable(AccessMode accessMode) { return new ModbusSlaveTable(// @@ -193,5 +189,4 @@ public ModbusSlaveTable getModbusSlaveTable(AccessMode accessMode) { AsymmetricMeter.getModbusSlaveNatureTable(accessMode) // ); } - } From 405470b387bcdfa06ca24a46ec885eba05399469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Bl=C3=A4ttermann?= Date: Thu, 16 Mar 2023 12:47:49 +0100 Subject: [PATCH 09/23] Edge/Backend: add Apache Felix File Install for dynamic loading of bundles (#2085) * Added Apache Felix File Install for dynamic component loading * Added documentation --- cnf/pom.xml | 7 ++++ doc/modules/ROOT/pages/backend/build.adoc | 8 +++-- doc/modules/ROOT/pages/edge/implement.adoc | 34 +++++++++++++------ .../BackendApp.bndrun | 11 +++--- io.openems.edge.application/EdgeApp.bndrun | 19 ++++++----- tools/prepare-commit.sh | 14 ++++---- 6 files changed, 62 insertions(+), 31 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index 650735b2725..2b8d599b2fa 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -187,6 +187,13 @@ org.apache.felix.eventadmin 1.6.4 + + + + org.apache.felix + org.apache.felix.fileinstall + 3.6.4 + diff --git a/doc/modules/ROOT/pages/backend/build.adoc b/doc/modules/ROOT/pages/backend/build.adoc index 0063dce85a8..7cf4edef961 100644 --- a/doc/modules/ROOT/pages/backend/build.adoc +++ b/doc/modules/ROOT/pages/backend/build.adoc @@ -9,7 +9,7 @@ :icons: font :imagesdir: ../../assets/images -This chapter explains, how OpenEMS Edge can be compiled to a JAR file that can be executed outside of an IDE. +This chapter explains, how the OpenEMS Backend can be compiled to a JAR file that can be executed outside of an IDE. == Build using Eclipse IDE @@ -31,4 +31,8 @@ link:https://gradle.org/[Gradle] is a build tool that is used in the OpenEMS pro . Open a console and change to your repository directory. -. Execute `gradlew buildBackend` \ No newline at end of file +. Execute `gradlew buildBackend` + +=== Building only a specific project + +If developing a component for the backend, it might make sense to only build the component in isolation instead of the entire backend (same applies to the Edge). This can be achieved by executing `gradlew :io.openems.backend.metadata.mymetadata:build`, which produces a JAR file. diff --git a/doc/modules/ROOT/pages/edge/implement.adoc b/doc/modules/ROOT/pages/edge/implement.adoc index 17de5627954..7c5d314ed1b 100644 --- a/doc/modules/ROOT/pages/edge/implement.adoc +++ b/doc/modules/ROOT/pages/edge/implement.adoc @@ -67,7 +67,7 @@ image::eclipse-new-simulatedmeter-bundle.png[New simulated meter OpenEMS Modbus ==== You can see, that the Bundle is by default dependent on some core bundles -$\{buildpath\}:: +$\{buildpath\}:: applies some defaults defined in `/cnf/build.bnd` io.openems.common:: OpenEMS commons @@ -114,7 +114,7 @@ NOTE: The `;version=latest` declaration is not required and can be removed. Also === Define configuration parameters -OpenEMS Components can have several configuration parameters. They are defined as Java annotations and specific OSGi annotations are used to generate meta information that is used e.g. by Apache Felix Web Console to generate a user interface form (see xref:gettingstarted.adoc[Getting Started]). +OpenEMS Components can have several configuration parameters. They are defined as Java annotations and specific OSGi annotations are used to generate meta information that is used e.g. by Apache Felix Web Console to generate a user interface form (see xref:gettingstarted.adoc[Getting Started]). . Open the btn:[Config.java] file inside `src/io.openems.edge.meter.simulated` by double clicking on it. @@ -154,7 +154,7 @@ import io.openems.edge.meter.api.MeterType; @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") boolean enabled() default true; // <4> - + @AttributeDefinition(name = "Meter-Type", description = "Grid, Production (=default), Consumption") // <5> MeterType type() default MeterType.PRODUCTION; // <6> @@ -374,13 +374,13 @@ NOTE: In plain Java it is not required to add `implements OpenemsComponent` if w - This enum is empty, as we do not have custom Channels here. - ChannelId enums require a Doc object that provides meta information about the Channel - e.g. the above ACTIVE_POWER Channel is defined as `ACTIVE_POWER(new Doc().type(OpenemsType.INTEGER).unit(Unit.WATT)` ==== -<8> We call the constructor of the super class (`AbstractOpenemsModbusComponent`/`AbstractOpenemsComponent`) to initialize the Channels of the Component. It is important to list all ChannelId-Enums of all implemented Natures. The call takes the *ChannelId* declarations and creates a Channel instance for each of them; e.g. for the `SymmetricMeter.ACTIVE_POWER` ChannelId, an object instance of `IntegerReadChannel` is created that represents the Channel. +<8> We call the constructor of the super class (`AbstractOpenemsModbusComponent`/`AbstractOpenemsComponent`) to initialize the Channels of the Component. It is important to list all ChannelId-Enums of all implemented Natures. The call takes the *ChannelId* declarations and creates a Channel instance for each of them; e.g. for the `SymmetricMeter.ACTIVE_POWER` ChannelId, an object instance of `IntegerReadChannel` is created that represents the Channel. <9> The `super.activate()` method requires an instance of *ConfigurationAdmin* as a parameter. Using the *@Reference* annotation the OSGi framework is going to provide the ConfigurationAdmin service via dependency injection. <10> The Component utilizes an external Modbus Component (the _Modbus Bridge_) for the actual Modbus communication. We receive an instance of this service via dependency injection (like we did already for the _ConfigurationAdmin_ service). Most of the magic is handled by the _AbstractOpenemsModbusComponent_ implementation, but the way the OSGi framework works, we need to define the _@Reference_ explicitly here in the actual implementation of the component and call the parent `setModbus()` method. <11> The *activate()* method (marked by the *@Activate* annotation) is called on activation of an object instance of this Component. It comes with a ComponentContext and an instance of a configuration in the form of a Config object. All logic for activating and deactivating the OpenEMS Component is hidden in the super classes and just needs to be called from here. <12> The *deactivate()* method (marked by the *@Deactivate* annotation) is called on deactivation of the Component instance. -<13> _AbstractOpenemsModbusComponent_ requires to implement a *defineModbusProtocol()* method that returns an instance of *ModbusProtocol*. The _ModbusProtocol_ class maps Modbus addresses to OpenEMS Channels and provides some conversion utilities. Instantiation of a _ModbusProtocol_ object uses the https://en.wikipedia.org/wiki/Builder_pattern#Java[Builder pattern icon:external-link[]] -<14> Creates a *new ModbusProtocol* instance. A reference to the component itself is the first parameter, followed by an arbitrary number of 'Tasks' (implemented as a Java varags array). +<13> _AbstractOpenemsModbusComponent_ requires to implement a *defineModbusProtocol()* method that returns an instance of *ModbusProtocol*. The _ModbusProtocol_ class maps Modbus addresses to OpenEMS Channels and provides some conversion utilities. Instantiation of a _ModbusProtocol_ object uses the https://en.wikipedia.org/wiki/Builder_pattern#Java[Builder pattern icon:external-link[]] +<14> Creates a *new ModbusProtocol* instance. A reference to the component itself is the first parameter, followed by an arbitrary number of 'Tasks' (implemented as a Java varags array). <15> *FC3ReadRegistersTask* is an implementation of Modbus http://www.simplymodbus.ca/FC03.htm[function code 3 "Read Holding Registers" icon:external-link[]]. Its first parameter is the start address of the register block. The second parameter is a priority information that defines how often this register block needs to be queried. Following parameters are an arbitrary number of *ModbusElements*. + NOTE: Most Modbus function codes are available by their respective _FC*_ implementation classes. @@ -389,7 +389,7 @@ NOTE: Most Modbus function codes are available by their respective _FC*_ impleme [NOTE] ==== - The _m()_ method also takes an instance of *ElementToChannelConverter* as an additional parameter. It can be used to add implicit unit conversions between Modbus element and OpenEMS Channel - like adding a scale factor that converts a read value of '95' to a channel value of '950'. -- For Modbus registers that are empty or should be ignored, the *DummyRegisterElement* can be used. +- For Modbus registers that are empty or should be ignored, the *DummyRegisterElement* can be used. - For more advanced channel-to-element mapping functionalities the internal *cm()* method can be used - e.g. to map one Modbus element to multiple Channels. + Using this principle a complete Modbus table consisting of multiple register blocks that need to be read or written with different Modbus function codes can be defined. For details have a look at the existing implementation classes inside the Modbus Bridge source code. @@ -433,7 +433,7 @@ image::eclipse-edgeapp-bndrun.png[Eclipse IDE EdgeApp.bndrun] Select the `io.openems.edge.meter.simulated` bundle in the left *Repositories* list and drag & drop it to the *Run Requirements* list. -Press btn:[Ctrl] + btn:[s] to save the `EdgeApp.bndrun` file. +Press btn:[Ctrl] + btn:[s] to save the `EdgeApp.bndrun` file. Click on btn:[Resolve] to update the list of bundles that are required to run OpenEMS Edge. After a few seconds the *Resolution Results* window should appear; acknowledge by pressing btn:[Finish]. @@ -453,14 +453,14 @@ These steps changed the content of the 'EdgeApp.bndrun' file. You can observe th The `\` at the end of each line is required to announce bndtools that the definition still continues on the next line. -Also you may have found, that the existing entries are sorted alphabetically. +Also you may have found, that the existing entries are sorted alphabetically. Now switch back to btn:[Run] view. ==== === Run the implementation -Press btn:[Run OSGi] to run OpenEMS Edge. +Press btn:[Run OSGi] to run OpenEMS Edge. From then you can configure your component as shown in xref:gettingstarted.adoc[Getting Started] guide. Add the following configurations inside Apache Felix Web Console: @@ -493,4 +493,16 @@ It shows a Production of `500 W` which is what is provided by the simulated mete === Debug the implementation -If you experience any errors you can always run OpenEMS Edge using the btn:[Debug OSGi] button in EdgeApp.bndrun. This allows you to stop code execution at any time using https://help.eclipse.org/2019-12/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-add_line_breakpoints.htm[Breakpoints]. \ No newline at end of file +If you experience any errors you can always run OpenEMS Edge using the btn:[Debug OSGi] button in EdgeApp.bndrun. This allows you to stop code execution at any time using https://help.eclipse.org/2019-12/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-add_line_breakpoints.htm[Breakpoints]. + +=== Alternative Device Development Flow + +Instead of adding the device to the btn:[EdgeApp.bndrun] file (as described in xref:implement.adoc#_enable_the_component[Enable the Component]), the device can be loaded dynamically by using [Apache Felix File Install]. Copying the device's built jar file into a `load` folder, relative to the project's root directory. Apache Felix File Install watches this folder and handles the device automatically. + +The folder is configurable by supplying the `felix.fileinstall.dir` option when starting the edge app. More configuration options can be found in the https://felix.apache.org/documentation/subprojects/apache-felix-file-install.html[Apache Felix File Install documentation]. + +[NOTE] +This functionality can also be used in production environments albeit dynamic code loading without additional safety measures is not recommended. + +[NOTE] +Same applies to the OpenEMS Backend for dynamically loading devices. diff --git a/io.openems.backend.application/BackendApp.bndrun b/io.openems.backend.application/BackendApp.bndrun index fd9ac7ffb24..7b944a9af99 100644 --- a/io.openems.backend.application/BackendApp.bndrun +++ b/io.openems.backend.application/BackendApp.bndrun @@ -25,9 +25,10 @@ org.apache.felix.scr;startlevel=10,\ org.apache.felix.configadmin;startlevel=11,\ org.apache.felix.eventadmin;startlevel=12,\ - org.ops4j.pax.logging.pax-logging-api;startlevel=13,\ - org.ops4j.pax.logging.pax-logging-log4j2;startlevel=14,\ - io.openems.backend.application;startlevel=15,\ + org.apache.felix.fileinstall;startlevel=13,\ + org.ops4j.pax.logging.pax-logging-api;startlevel=14,\ + org.ops4j.pax.logging.pax-logging-log4j2;startlevel=15,\ + io.openems.backend.application;startlevel=16,\ -runrequires: \ bnd.identity;id='org.ops4j.pax.logging.pax-logging-api',\ @@ -38,6 +39,7 @@ bnd.identity;id='org.apache.felix.webconsole.plugins.ds',\ bnd.identity;id='org.apache.felix.inventory',\ bnd.identity;id='org.apache.felix.eventadmin',\ + bnd.identity;id='org.apache.felix.fileinstall',\ bnd.identity;id='org.apache.felix.metatype',\ bnd.identity;id='io.openems.backend.alerting',\ bnd.identity;id='io.openems.backend.application',\ @@ -100,6 +102,7 @@ org.apache.commons.commons-io;version='[2.11.0,2.11.1)',\ org.apache.felix.configadmin;version='[1.9.26,1.9.27)',\ org.apache.felix.eventadmin;version='[1.6.4,1.6.5)',\ + org.apache.felix.fileinstall;version='[3.6.4,3.6.5)',\ org.apache.felix.http.jetty;version='[5.0.4,5.0.5)',\ org.apache.felix.http.servlet-api;version='[2.1.0,2.1.1)',\ org.apache.felix.inventory;version='[1.1.0,1.1.1)',\ @@ -116,4 +119,4 @@ org.osgi.util.function;version='[1.2.0,1.2.1)',\ org.osgi.util.promise;version='[1.3.0,1.3.1)',\ org.postgresql.jdbc;version='[42.5.4,42.5.5)',\ - reactive-streams;version='[1.0.4,1.0.5)' \ No newline at end of file + reactive-streams;version='[1.0.4,1.0.5)' diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index be5326a821f..52f790c28c2 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -22,19 +22,21 @@ org.apache.felix.scr;startlevel=10,\ org.apache.felix.configadmin;startlevel=11,\ org.apache.felix.eventadmin;startlevel=12,\ - org.ops4j.pax.logging.pax-logging-api;startlevel=13,\ - org.ops4j.pax.logging.pax-logging-log4j2;startlevel=14,\ - io.openems.edge.application;startlevel=15,\ + org.apache.felix.fileinstall;startlevel=13,\ + org.ops4j.pax.logging.pax-logging-api;startlevel=14,\ + org.ops4j.pax.logging.pax-logging-log4j2;startlevel=15,\ + io.openems.edge.application;startlevel=16,\ -runrequires: \ bnd.identity;id='org.ops4j.pax.logging.pax-logging-api',\ bnd.identity;id='org.ops4j.pax.logging.pax-logging-log4j2',\ + bnd.identity;id='org.apache.felix.eventadmin',\ + bnd.identity;id='org.apache.felix.fileinstall',\ bnd.identity;id='org.apache.felix.http.jetty',\ - bnd.identity;id='org.apache.felix.webconsole',\ - bnd.identity;id='org.apache.felix.webconsole.plugins.ds',\ bnd.identity;id='org.apache.felix.inventory',\ - bnd.identity;id='org.apache.felix.eventadmin',\ bnd.identity;id='org.apache.felix.metatype',\ + bnd.identity;id='org.apache.felix.webconsole.plugins.ds',\ + bnd.identity;id='org.apache.felix.webconsole',\ bnd.identity;id='io.openems.edge.application',\ bnd.identity;id='io.openems.edge.battery.bmw',\ bnd.identity;id='io.openems.edge.battery.bydcommercial',\ @@ -173,7 +175,7 @@ bnd.identity;id='io.openems.edge.timeofusetariff.awattar',\ bnd.identity;id='io.openems.edge.timeofusetariff.corrently',\ bnd.identity;id='io.openems.edge.timeofusetariff.tibber',\ - + -runbundles: \ Java-WebSocket;version='[1.5.3,1.5.4)',\ com.fazecast.jSerialComm;version='[2.5.1,2.5.2)',\ @@ -363,6 +365,7 @@ org.apache.commons.math3;version='[3.6.1,3.6.2)',\ org.apache.felix.configadmin;version='[1.9.26,1.9.27)',\ org.apache.felix.eventadmin;version='[1.6.4,1.6.5)',\ + org.apache.felix.fileinstall;version='[3.6.4,3.6.5)',\ org.apache.felix.http.jetty;version='[5.0.4,5.0.5)',\ org.apache.felix.http.servlet-api;version='[2.1.0,2.1.1)',\ org.apache.felix.inventory;version='[1.1.0,1.1.1)',\ @@ -386,4 +389,4 @@ org.osgi.util.function;version='[1.2.0,1.2.1)',\ org.osgi.util.promise;version='[1.3.0,1.3.1)',\ reactive-streams;version='[1.0.4,1.0.5)',\ - rrd4j;version='[3.8.2,3.8.3)' \ No newline at end of file + rrd4j;version='[3.8.2,3.8.3)' diff --git a/tools/prepare-commit.sh b/tools/prepare-commit.sh index 332216c174f..3c93794d21a 100755 --- a/tools/prepare-commit.sh +++ b/tools/prepare-commit.sh @@ -3,14 +3,14 @@ # Prepares a Commit # # - Adds .gitignore file to empty test directories. -# -# When Eclipse creates 'test' src folders they are sometimes empty. Empty +# +# When Eclipse creates 'test' src folders they are sometimes empty. Empty # folders are not committed to GIT. Because of this Eclipse would show errors # when importing the projects. This script creates an empty '.gitignore' file # inside each 'test' folder to solve this. # # See https://stackoverflow.com/questions/115983 -# +# # - Resets .classpath files. # # When Eclipse 'Build All' is called, all .classpath files are touched and @@ -50,13 +50,13 @@ for D in *; do echo "${D}/.gitignore -> not complete" echo '/bin_test/' > ${D}/.gitignore echo '/generated/' >> ${D}/.gitignore - fi - + fi + # verify there is a test folder if [ ! -d "${D}/test" ]; then mkdir -p ${D}/test fi - + # verify that the test folder has a .gitignore file if [ ! -f "./${D}/test/.gitignore" ]; then echo "${D}/test/.gitignore -> missing" @@ -129,6 +129,7 @@ echo " bnd.identity;id='org.apache.felix.webconsole',\\" >> "$bndrun.new" echo " bnd.identity;id='org.apache.felix.webconsole.plugins.ds',\\" >> "$bndrun.new" echo " bnd.identity;id='org.apache.felix.inventory',\\" >> "$bndrun.new" echo " bnd.identity;id='org.apache.felix.eventadmin',\\" >> "$bndrun.new" +echo " bnd.identity;id='org.apache.felix.fileinstall',\\" >> "$bndrun.new" echo " bnd.identity;id='org.apache.felix.metatype',\\" >> "$bndrun.new" for D in io.openems.edge.*; do if [[ "$D" == *api ]]; then @@ -153,6 +154,7 @@ echo " bnd.identity;id='org.apache.felix.webconsole',\\" >> "$bndrun.new" echo " bnd.identity;id='org.apache.felix.webconsole.plugins.ds',\\" >> "$bndrun.new" echo " bnd.identity;id='org.apache.felix.inventory',\\" >> "$bndrun.new" echo " bnd.identity;id='org.apache.felix.eventadmin',\\" >> "$bndrun.new" +echo " bnd.identity;id='org.apache.felix.fileinstall',\\" >> "$bndrun.new" echo " bnd.identity;id='org.apache.felix.metatype',\\" >> "$bndrun.new" for D in io.openems.backend.*; do if [[ "$D" == *api ]]; then From 70e168328ae99c6d3f1985752deff3eec6c361b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Mar 2023 13:07:30 +0100 Subject: [PATCH 10/23] Bump checker-qual from 3.31.0 to 3.32.0 in /cnf (#2096) * Bump checker-qual from 3.31.0 to 3.32.0 in /cnf Bumps [checker-qual](https://github.com/typetools/checker-framework) from 3.31.0 to 3.32.0. - [Release notes](https://github.com/typetools/checker-framework/releases) - [Changelog](https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/typetools/checker-framework/compare/checker-framework-3.31.0...checker-framework-3.32.0) --- updated-dependencies: - dependency-name: org.checkerframework:checker-qual dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update bnd files --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Feilmeier --- cnf/pom.xml | 2 +- io.openems.backend.application/BackendApp.bndrun | 4 ++-- io.openems.edge.application/EdgeApp.bndrun | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index 2b8d599b2fa..ffdfb8454e7 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -259,7 +259,7 @@ org.checkerframework checker-qual - 3.31.0 + 3.32.0 org.dhatim diff --git a/io.openems.backend.application/BackendApp.bndrun b/io.openems.backend.application/BackendApp.bndrun index 7b944a9af99..242f2e1e204 100644 --- a/io.openems.backend.application/BackendApp.bndrun +++ b/io.openems.backend.application/BackendApp.bndrun @@ -58,7 +58,7 @@ -runbundles: \ Java-WebSocket;version='[1.5.3,1.5.4)',\ - checker-qual;version='[3.31.0,3.31.1)',\ + checker-qual;version='[3.32.0,3.32.1)',\ com.google.gson;version='[2.10.1,2.10.2)',\ com.google.guava;version='[31.1.0,31.1.1)',\ com.google.guava.failureaccess;version='[1.0.1,1.0.2)',\ @@ -119,4 +119,4 @@ org.osgi.util.function;version='[1.2.0,1.2.1)',\ org.osgi.util.promise;version='[1.3.0,1.3.1)',\ org.postgresql.jdbc;version='[42.5.4,42.5.5)',\ - reactive-streams;version='[1.0.4,1.0.5)' + reactive-streams;version='[1.0.4,1.0.5)' \ No newline at end of file diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index 52f790c28c2..a51cbc0b3fe 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -30,13 +30,13 @@ -runrequires: \ bnd.identity;id='org.ops4j.pax.logging.pax-logging-api',\ bnd.identity;id='org.ops4j.pax.logging.pax-logging-log4j2',\ - bnd.identity;id='org.apache.felix.eventadmin',\ - bnd.identity;id='org.apache.felix.fileinstall',\ bnd.identity;id='org.apache.felix.http.jetty',\ + bnd.identity;id='org.apache.felix.webconsole',\ + bnd.identity;id='org.apache.felix.webconsole.plugins.ds',\ bnd.identity;id='org.apache.felix.inventory',\ + bnd.identity;id='org.apache.felix.eventadmin',\ + bnd.identity;id='org.apache.felix.fileinstall',\ bnd.identity;id='org.apache.felix.metatype',\ - bnd.identity;id='org.apache.felix.webconsole.plugins.ds',\ - bnd.identity;id='org.apache.felix.webconsole',\ bnd.identity;id='io.openems.edge.application',\ bnd.identity;id='io.openems.edge.battery.bmw',\ bnd.identity;id='io.openems.edge.battery.bydcommercial',\ @@ -389,4 +389,4 @@ org.osgi.util.function;version='[1.2.0,1.2.1)',\ org.osgi.util.promise;version='[1.3.0,1.3.1)',\ reactive-streams;version='[1.0.4,1.0.5)',\ - rrd4j;version='[3.8.2,3.8.3)' + rrd4j;version='[3.8.2,3.8.3)' \ No newline at end of file From b5e82035b2affbed0a264d2c6cb3773ff26b3115 Mon Sep 17 00:00:00 2001 From: Thomas Sicking <91258335+tsicking@users.noreply.github.com> Date: Mon, 20 Mar 2023 23:05:06 +0100 Subject: [PATCH 11/23] Implementation of the Webasto Next electric vehicle charging station (#2081) Implementation of the Webasto Next electric vehicle charging station. == https://en.wikipedia.org/wiki/Software_release_life_cycle[Software release life cycle]: BETA This implementation has been carried out during OpenEMS Hackathon Q1/2023 and is not yet fully feature tested. Please consider it BETA quality == Compatibility ** https://charging.webasto.com/de-de/products/webasto-next/[Webasto Next] === Technical Data * Rated current: ** 16A single phase ** 32A three phases * Charging cable: Type 2, up to 32A / 400V AC * Max. charging power: 22kW (three phases), 3.7 (single phase) * Communication protocol: Modbus TCP == Additional application notes The implementation includes: ** Reading actual values from the charging station ** Setting charge power/current set-points via OpenEMS Edge EVCS Controllers --------- Co-authored-by: Sebastian Asen <47855186+sebastianasen@users.noreply.github.com> Co-authored-by: Thomas Sicking <91258335+tsicking@users.noreply.github.com> Co-authored-by: Stefan Feilmeier <3515268+sfeilmeier@users.noreply.github.com> --- io.openems.edge.application/EdgeApp.bndrun | 2 + io.openems.edge.evcs.webasto.next/.classpath | 12 + io.openems.edge.evcs.webasto.next/.gitignore | 2 + io.openems.edge.evcs.webasto.next/.project | 23 ++ .../org.eclipse.core.resources.prefs | 2 + io.openems.edge.evcs.webasto.next/bnd.bnd | 15 + io.openems.edge.evcs.webasto.next/readme.adoc | 29 ++ .../edge/evcs/webasto/next/Config.java | 40 ++ .../evcs/webasto/next/EvcsWebastoNext.java | 218 +++++++++++ .../webasto/next/EvcsWebastoNextImpl.java | 349 ++++++++++++++++++ .../evcs/webasto/next/enums/CableState.java | 36 ++ .../webasto/next/enums/ChargePointState.java | 38 ++ .../webasto/next/enums/EvseErrorCode.java | 50 +++ .../evcs/webasto/next/enums/EvseState.java | 35 ++ .../enums/StartCancelChargingSession.java | 35 ++ .../test/.gitignore | 0 .../webasto/next/EvcsWebastoNextTest.java | 28 ++ .../edge/evcs/webasto/next/MyConfig.java | 96 +++++ ...UNITE_Modbus_Register_1-00_external_V1.pdf | Bin 216052 -> 0 bytes 19 files changed, 1010 insertions(+) create mode 100644 io.openems.edge.evcs.webasto.next/.classpath create mode 100644 io.openems.edge.evcs.webasto.next/.gitignore create mode 100644 io.openems.edge.evcs.webasto.next/.project create mode 100644 io.openems.edge.evcs.webasto.next/.settings/org.eclipse.core.resources.prefs create mode 100644 io.openems.edge.evcs.webasto.next/bnd.bnd create mode 100644 io.openems.edge.evcs.webasto.next/readme.adoc create mode 100644 io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/Config.java create mode 100644 io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/EvcsWebastoNext.java create mode 100644 io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/EvcsWebastoNextImpl.java create mode 100644 io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/CableState.java create mode 100644 io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/ChargePointState.java create mode 100644 io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/EvseErrorCode.java create mode 100644 io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/EvseState.java create mode 100644 io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/StartCancelChargingSession.java create mode 100644 io.openems.edge.evcs.webasto.next/test/.gitignore create mode 100644 io.openems.edge.evcs.webasto.next/test/io/openems/edge/evcs/webasto/next/EvcsWebastoNextTest.java create mode 100644 io.openems.edge.evcs.webasto.next/test/io/openems/edge/evcs/webasto/next/MyConfig.java delete mode 100644 io.openems.edge.evcs.webasto.unite/doc/Webasto_UNITE_Modbus_Register_1-00_external_V1.pdf diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index a51cbc0b3fe..a4082d15ae3 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -121,6 +121,7 @@ bnd.identity;id='io.openems.edge.evcs.ocpp.common',\ bnd.identity;id='io.openems.edge.evcs.ocpp.ies.keywatt.singleccs',\ bnd.identity;id='io.openems.edge.evcs.ocpp.server',\ + bnd.identity;id='io.openems.edge.evcs.webasto.next',\ bnd.identity;id='io.openems.edge.evcs.webasto.unite',\ bnd.identity;id='io.openems.edge.fenecon.dess',\ bnd.identity;id='io.openems.edge.fenecon.mini',\ @@ -275,6 +276,7 @@ io.openems.edge.evcs.ocpp.common;version=snapshot,\ io.openems.edge.evcs.ocpp.ies.keywatt.singleccs;version=snapshot,\ io.openems.edge.evcs.ocpp.server;version=snapshot,\ + io.openems.edge.evcs.webasto.next;version=snapshot,\ io.openems.edge.evcs.webasto.unite;version=snapshot,\ io.openems.edge.fenecon.dess;version=snapshot,\ io.openems.edge.fenecon.mini;version=snapshot,\ diff --git a/io.openems.edge.evcs.webasto.next/.classpath b/io.openems.edge.evcs.webasto.next/.classpath new file mode 100644 index 00000000000..43d68895d03 --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/io.openems.edge.evcs.webasto.next/.gitignore b/io.openems.edge.evcs.webasto.next/.gitignore new file mode 100644 index 00000000000..c2b941a96de --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/.gitignore @@ -0,0 +1,2 @@ +/bin_test/ +/generated/ diff --git a/io.openems.edge.evcs.webasto.next/.project b/io.openems.edge.evcs.webasto.next/.project new file mode 100644 index 00000000000..e97169c9320 --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/.project @@ -0,0 +1,23 @@ + + + io.openems.edge.evcs.webasto.next + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/io.openems.edge.evcs.webasto.next/.settings/org.eclipse.core.resources.prefs b/io.openems.edge.evcs.webasto.next/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/io.openems.edge.evcs.webasto.next/bnd.bnd b/io.openems.edge.evcs.webasto.next/bnd.bnd new file mode 100644 index 00000000000..5138da876f7 --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/bnd.bnd @@ -0,0 +1,15 @@ +Bundle-Name: OpenEMS Edge EVCS Webasto Next +Bundle-Vendor: OpenEMS Association e.V. +Bundle-License: https://opensource.org/licenses/EPL-2.0 +Bundle-Version: 1.0.0.${tstamp} + +-buildpath: \ + ${buildpath},\ + io.openems.common,\ + io.openems.edge.bridge.modbus,\ + io.openems.edge.common,\ + io.openems.edge.evcs.api,\ + +-testpath: \ + ${testpath},\ + com.ghgande.j2mod,\ diff --git a/io.openems.edge.evcs.webasto.next/readme.adoc b/io.openems.edge.evcs.webasto.next/readme.adoc new file mode 100644 index 00000000000..c55d1e618bf --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/readme.adoc @@ -0,0 +1,29 @@ += Webasto Next Charging Station (BETA) + +Implementation of the Webasto Next electric vehicle charging station. + +== https://en.wikipedia.org/wiki/Software_release_life_cycle[Software release life cycle]: BETA + +This implementation has been carried out during OpenEMS Hackathon Q1/2023 and is not yet fully feature tested. Please consider it BETA quality + +== Compatibility + +** https://charging.webasto.com/de-de/products/webasto-next/[Webasto Next] + +=== Technical Data + +* Rated current: +** 16A single phase +** 32A three phases +* Charging cable: Type 2, up to 32A / 400V AC +* Max. charging power: 22kW (three phases), 3.7 (single phase) +* Communication protocol: Modbus TCP + +== Additional application notes + +The implementation includes: + +** Reading actual values from the charging station +** Setting charge power/current set-points via OpenEMS Edge EVCS Controllers + +https://github.com/OpenEMS/openems/tree/develop/io.openems.edge.evcs.wabsto.next[Source Code icon:github[]] \ No newline at end of file diff --git a/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/Config.java b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/Config.java new file mode 100644 index 00000000000..8b41dbf11da --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/Config.java @@ -0,0 +1,40 @@ +package io.openems.edge.evcs.webasto.next; + +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; + +@ObjectClassDefinition(// + name = "EVCS Webasto Next", // + description = "Implements the Webasto Next electric vehicle charging station.") // +@interface Config { + + @AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component") + String id() default "evcs0"; + + @AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID") + String alias() default ""; + + @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") + boolean enabled() default true; + + @AttributeDefinition(name = "Modbus-ID", description = "ID of Modbus bridge.") + String modbus_id() default "modbus0"; + + @AttributeDefinition(name = "Modbus Unit-ID", description = "The Unit-ID of the Modbus device.") + int modbusUnitId() default 1; + + @AttributeDefinition(name = "Minimum hardware current", description = "Minimum current of the Charger in mA.", required = true) + int minHwCurrent() default 6000; + + @AttributeDefinition(name = "Maximum hardware current", description = "Maximum current of the Charger in mA.", required = true) + int maxHwCurrent() default 32000; + + @AttributeDefinition(name = "Debug Mode", description = "Activates the debug mode") + boolean debugMode() default false; + + @AttributeDefinition(name = "Modbus target filter", description = "This is auto-generated by 'Modbus-ID'.") + String Modbus_target() default "(enabled=true)"; + + String webconsole_configurationFactory_nameHint() default "EVCS Webasto Next [{id}]"; + +} \ No newline at end of file diff --git a/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/EvcsWebastoNext.java b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/EvcsWebastoNext.java new file mode 100644 index 00000000000..fe1dc68577d --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/EvcsWebastoNext.java @@ -0,0 +1,218 @@ +package io.openems.edge.evcs.webasto.next; + +import io.openems.common.channel.AccessMode; +import io.openems.common.channel.Unit; +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.types.OpenemsType; +import io.openems.edge.common.channel.Doc; +import io.openems.edge.common.channel.IntegerReadChannel; +import io.openems.edge.common.channel.IntegerWriteChannel; +import io.openems.edge.common.channel.value.Value; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.evcs.webasto.next.enums.CableState; +import io.openems.edge.evcs.webasto.next.enums.ChargePointState; +import io.openems.edge.evcs.webasto.next.enums.EvseErrorCode; +import io.openems.edge.evcs.webasto.next.enums.EvseState; +import io.openems.edge.evcs.webasto.next.enums.StartCancelChargingSession; + +public interface EvcsWebastoNext extends OpenemsComponent { + + public enum ChannelId implements io.openems.edge.common.channel.ChannelId { + + EV_SET_CHARGE_POWER_LIMIT(Doc.of(OpenemsType.INTEGER)// + .accessMode(AccessMode.READ_WRITE)// + .unit(Unit.WATT)), // + + CHARGE_POINT_STATE(Doc.of(ChargePointState.values())), // + + EVSE_STATE(Doc.of(EvseState.values())), // + + CABLE_STATE(Doc.of(CableState.values())), // + + EVSE_ERROR_CODE(Doc.of(EvseErrorCode.values())), // + + CURRENT_L1(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.MILLIAMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + + CURRENT_L2(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.MILLIAMPERE) // + .accessMode(AccessMode.READ_ONLY)), // + + CURRENT_L3(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.MILLIAMPERE)), // + + POWER_L1(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT)), // + + POWER_L2(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT)), // + + POWER_L3(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT)), // + + MAX_HW_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE)), // + + MIN_HW_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE)), // + + MAX_EVSE_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE)), // + + MAX_CABLE_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE)), // + + MAX_EV_CURRENT(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.AMPERE)), // + + LAST_ENERGY_SESSION(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT_HOURS)), // + + START_TIME(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.NONE)), // + + CHARGE_SESSION_TIME(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.SECONDS)), // + + END_TIME(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.NONE)), // + + SMART_VEHICLE_DETECTED(Doc.of(OpenemsType.BOOLEAN) // + .unit(Unit.NONE)), // + + SAFE_CURRENT(Doc.of(OpenemsType.INTEGER)// + .unit(Unit.AMPERE)// + .accessMode(AccessMode.READ_WRITE)), // + + COM_TIMEOUT(Doc.of(OpenemsType.INTEGER)// + .unit(Unit.SECONDS)// + .accessMode(AccessMode.READ_WRITE)), // + + CHARGE_CURRENT(Doc.of(OpenemsType.INTEGER)// + .unit(Unit.AMPERE)// + .accessMode(AccessMode.WRITE_ONLY)), // + + LIFE_BIT(Doc.of(OpenemsType.INTEGER)// + .unit(Unit.NONE)// + .accessMode(AccessMode.READ_WRITE)), // + + START_CANCEL_CHARGING_SESSION(Doc.of(StartCancelChargingSession.values())// + .accessMode(AccessMode.WRITE_ONLY)), // + ; + + private final Doc doc; + + private ChannelId(Doc doc) { + this.doc = doc; + } + + @Override + public Doc doc() { + return this.doc; + } + } + + /** + * Gets the Channel for {@link ChannelId#LIFE_BIT}. + * + * @return the Channel + */ + public default IntegerWriteChannel getLifeBitChannel() { + return this.channel(ChannelId.LIFE_BIT); + } + + /** + * Sets the Channel for {@link ChannelId#LIFE_BIT}. + * + * @param value {@link Integer} + * @throws OpenemsNamedException on error. + */ + public default void setLifeBit(Integer value) throws OpenemsNamedException { + this.getLifeBitChannel().setNextWriteValue(value); + } + + /** + * Gets the Channel for {@link ChannelId#EV_SET_CHARGE_POWER_LIMIT}. + * + * @return the Channel + */ + public default IntegerWriteChannel getEvSetChargePowerLimitChannel() { + return this.channel(ChannelId.EV_SET_CHARGE_POWER_LIMIT); + } + + /** + * Gets the EvSetChargePowerLimit. See + * {@link ChannelId#EV_SET_CHARGE_POWER_LIMIT}. + * + * @return the Channel {@link Value} + */ + public default Value getEvSetChargePowerLimit() { + return this.getEvSetChargePowerLimitChannel().value(); + } + + /** + * Sets the EvSetChargePowerLimit. See + * {@link ChannelId#EV_SET_CHARGE_POWER_LIMIT}. + * + * @param value {@link Integer}. + * @throws OpenemsNamedException on error. + */ + public default void setEvSetChargePowerLimit(Integer value) throws OpenemsNamedException { + this.getEvSetChargePowerLimitChannel().setNextWriteValue(value); + } + + /** + * Gets the Channel for {@link ChannelId#POWER_L1}. + * + * @return the Channel + */ + public default IntegerReadChannel getPowerL1Channel() { + return this.channel(ChannelId.POWER_L1); + } + + /** + * Gets the Power on phase 1 in [W]. See {@link ChannelId#POWER_L1}. + * + * @return the Channel {@link Value} + */ + public default Value getPowerL1() { + return this.getPowerL1Channel().value(); + } + + /** + * Gets the Channel for {@link ChannelId#POWER_L2}. + * + * @return the Channel + */ + public default IntegerReadChannel getPowerL2Channel() { + return this.channel(ChannelId.POWER_L2); + } + + /** + * Gets the Power on phase 2 in [W]. See {@link ChannelId#POWER_L2}. + * + * @return the Channel {@link Value} + */ + public default Value getPowerL2() { + return this.getPowerL2Channel().value(); + } + + /** + * Gets the Channel for {@link ChannelId#POWER_L3}. + * + * @return the Channel + */ + public default IntegerReadChannel getPowerL3Channel() { + return this.channel(ChannelId.POWER_L3); + } + + /** + * Gets the Power on phase 3 in [W]. See {@link ChannelId#POWER_L3}. + * + * @return the Channel {@link Value} + */ + public default Value getPowerL3() { + return this.getPowerL3Channel().value(); + } +} diff --git a/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/EvcsWebastoNextImpl.java b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/EvcsWebastoNextImpl.java new file mode 100644 index 00000000000..6b01a40d14c --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/EvcsWebastoNextImpl.java @@ -0,0 +1,349 @@ +package io.openems.edge.evcs.webasto.next; + +import java.util.function.Consumer; + +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.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Modified; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventHandler; +import org.osgi.service.event.propertytypes.EventTopics; +import org.osgi.service.metatype.annotations.Designate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.exceptions.OpenemsException; +import io.openems.edge.bridge.modbus.api.AbstractOpenemsModbusComponent; +import io.openems.edge.bridge.modbus.api.BridgeModbus; +import io.openems.edge.bridge.modbus.api.ModbusComponent; +import io.openems.edge.bridge.modbus.api.ModbusProtocol; +import io.openems.edge.bridge.modbus.api.element.DummyRegisterElement; +import io.openems.edge.bridge.modbus.api.element.UnsignedDoublewordElement; +import io.openems.edge.bridge.modbus.api.element.UnsignedWordElement; +import io.openems.edge.bridge.modbus.api.task.FC16WriteRegistersTask; +import io.openems.edge.bridge.modbus.api.task.FC3ReadRegistersTask; +import io.openems.edge.bridge.modbus.api.task.FC6WriteRegisterTask; +import io.openems.edge.common.channel.value.Value; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.common.event.EdgeEventConstants; +import io.openems.edge.common.taskmanager.Priority; +import io.openems.edge.evcs.api.ChargeStateHandler; +import io.openems.edge.evcs.api.ChargingType; +import io.openems.edge.evcs.api.Evcs; +import io.openems.edge.evcs.api.EvcsPower; +import io.openems.edge.evcs.api.ManagedEvcs; +import io.openems.edge.evcs.api.Phases; +import io.openems.edge.evcs.api.Status; +import io.openems.edge.evcs.api.WriteHandler; +import io.openems.edge.evcs.webasto.next.enums.ChargePointState; + +@Designate(ocd = Config.class, factory = true) +@Component(// + name = "Evcs.Webasto.Next", // + immediate = true, // + configurationPolicy = ConfigurationPolicy.REQUIRE // +) +@EventTopics({ // + EdgeEventConstants.TOPIC_CYCLE_EXECUTE_WRITE, // +}) +public class EvcsWebastoNextImpl extends AbstractOpenemsModbusComponent + implements EvcsWebastoNext, Evcs, ManagedEvcs, ModbusComponent, OpenemsComponent, EventHandler { + + private static final int DEFAULT_LIFE_BIT = 1; + private static final int DETECT_PHASE_ACTIVITY = 100; // W + + private final Logger log = LoggerFactory.getLogger(EvcsWebastoNext.class); + + private Config config = null; + + /** + * Handles charge states. + */ + private final ChargeStateHandler chargeStateHandler = new ChargeStateHandler(this); + + /** + * Processes the controller's writes to this evcs component. + */ + private final WriteHandler writeHandler = new WriteHandler(this); + + public EvcsWebastoNextImpl() { + super(// + OpenemsComponent.ChannelId.values(), // + ModbusComponent.ChannelId.values(), // + Evcs.ChannelId.values(), // + ManagedEvcs.ChannelId.values(), // + EvcsWebastoNext.ChannelId.values()); + } + + @Reference + private EvcsPower evcsPower; + + @Reference + protected ConfigurationAdmin cm; + + @Reference(policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MANDATORY) + protected void setModbus(BridgeModbus modbus) { + super.setModbus(modbus); + } + + @Activate + private void activate(ComponentContext context, Config config) throws OpenemsNamedException { + this.config = config; + if (super.activate(context, config.id(), config.alias(), config.enabled(), config.modbusUnitId(), this.cm, + "Modbus", config.modbus_id())) { + return; + } + + /* + * Calculates the maximum and minimum hardware power dynamically by listening on + * the fixed hardware limit and the phases used for charging + */ + Evcs.addCalculatePowerLimitListeners(this); + + this.applyConfig(context, config); + + this.getModbusCommunicationFailedChannel() + .onSetNextValue(t -> this._setChargingstationCommunicationFailed(t.orElse(false))); + } + + @Modified + private void modified(ComponentContext context, Config config) throws OpenemsNamedException { + if (super.modified(context, config.id(), config.alias(), config.enabled(), config.modbusUnitId(), this.cm, + "Modbus", config.modbus_id())) { + return; + } + this.applyConfig(context, config); + } + + private void applyConfig(ComponentContext context, Config config) { + this.config = config; + this._setChargingType(ChargingType.AC); + this._setFixedMinimumHardwarePower(config.minHwCurrent() / 1000 * 3 * 230); + this._setFixedMaximumHardwarePower(config.maxHwCurrent() / 1000 * 3 * 230); + /* + * TODO: PowerPrecision need to be tested if it is really a 1A step because for + * limits set as power [W], is is normally PowerPrecision of 1 (Anyways, Channel + * is no used for now) + */ + this._setPowerPrecision(230); + } + + @Override + @Deactivate + protected void deactivate() { + super.deactivate(); + } + + @Override + protected ModbusProtocol defineModbusProtocol() throws OpenemsException { + // Cannot read the gaps, therefore there are so many tasks + var modbusProtocol = new ModbusProtocol(this, // + new FC3ReadRegistersTask(1000, Priority.HIGH, + m(EvcsWebastoNext.ChannelId.CHARGE_POINT_STATE, new UnsignedWordElement(1000)), // + new DummyRegisterElement(1001), // Charge State - Set already by the WriteHandler + m(EvcsWebastoNext.ChannelId.EVSE_STATE, new UnsignedWordElement(1002))), // + new FC3ReadRegistersTask(1004, Priority.LOW, + m(EvcsWebastoNext.ChannelId.CABLE_STATE, new UnsignedWordElement(1004))), // + new FC3ReadRegistersTask(1006, Priority.LOW, + m(EvcsWebastoNext.ChannelId.EVSE_ERROR_CODE, new UnsignedWordElement(1006))), + new FC3ReadRegistersTask(1008, Priority.LOW, + m(EvcsWebastoNext.ChannelId.CURRENT_L1, new UnsignedWordElement(1008))), + new FC3ReadRegistersTask(1010, Priority.LOW, + m(EvcsWebastoNext.ChannelId.CURRENT_L2, new UnsignedWordElement(1010))), + new FC3ReadRegistersTask(1012, Priority.LOW, + m(EvcsWebastoNext.ChannelId.CURRENT_L3, new UnsignedWordElement(1012))), + new FC3ReadRegistersTask(1020, Priority.HIGH, + m(Evcs.ChannelId.CHARGE_POWER, new UnsignedDoublewordElement(1020))), + new FC3ReadRegistersTask(1024, Priority.LOW, + m(EvcsWebastoNext.ChannelId.POWER_L1, new UnsignedDoublewordElement(1024))), + new FC3ReadRegistersTask(1028, Priority.LOW, + m(EvcsWebastoNext.ChannelId.POWER_L2, new UnsignedDoublewordElement(1028))), + new FC3ReadRegistersTask(1032, Priority.LOW, + m(EvcsWebastoNext.ChannelId.POWER_L3, new UnsignedDoublewordElement(1032))), + new FC3ReadRegistersTask(1036, Priority.LOW, + m(Evcs.ChannelId.ACTIVE_CONSUMPTION_ENERGY, new UnsignedDoublewordElement(1036))), + new FC3ReadRegistersTask(1100, Priority.LOW, + m(EvcsWebastoNext.ChannelId.MAX_HW_CURRENT, new UnsignedWordElement(1100))), + new FC3ReadRegistersTask(1102, Priority.LOW, + m(EvcsWebastoNext.ChannelId.MIN_HW_CURRENT, new UnsignedWordElement(1102))), + new FC3ReadRegistersTask(1104, Priority.LOW, + m(EvcsWebastoNext.ChannelId.MAX_EVSE_CURRENT, new UnsignedWordElement(1104))), + new FC3ReadRegistersTask(1106, Priority.LOW, + m(EvcsWebastoNext.ChannelId.MAX_CABLE_CURRENT, new UnsignedWordElement(1106))), + new FC3ReadRegistersTask(1108, Priority.LOW, + m(EvcsWebastoNext.ChannelId.MAX_EV_CURRENT, new UnsignedWordElement(1108))), + // TODO EvcsWebastoNext.ChannelId.LAST_ENERGY_SESSION: This register remains 0 + // during the session, + // and set a value at the end. But for the UI we need the + // Energy charged during the session is running as well. + new FC3ReadRegistersTask(1502, Priority.LOW, + m(EvcsWebastoNext.ChannelId.LAST_ENERGY_SESSION, new UnsignedWordElement(1502))), + new FC3ReadRegistersTask(1504, Priority.LOW, + m(EvcsWebastoNext.ChannelId.START_TIME, new UnsignedDoublewordElement(1504))), + new FC3ReadRegistersTask(1508, Priority.LOW, + m(EvcsWebastoNext.ChannelId.CHARGE_SESSION_TIME, new UnsignedDoublewordElement(1508))), + new FC3ReadRegistersTask(1512, Priority.LOW, + m(EvcsWebastoNext.ChannelId.END_TIME, new UnsignedDoublewordElement(1512))), + new FC3ReadRegistersTask(1620, Priority.LOW, + m(EvcsWebastoNext.ChannelId.SMART_VEHICLE_DETECTED, new UnsignedWordElement(1620))), + new FC3ReadRegistersTask(2000, Priority.LOW, + m(EvcsWebastoNext.ChannelId.SAFE_CURRENT, new UnsignedWordElement(2000))), + new FC3ReadRegistersTask(2002, Priority.LOW, + m(EvcsWebastoNext.ChannelId.COM_TIMEOUT, new UnsignedWordElement(2002))), + new FC16WriteRegistersTask(5000, // + m(EvcsWebastoNext.ChannelId.EV_SET_CHARGE_POWER_LIMIT, new UnsignedDoublewordElement(5000))), // + new FC6WriteRegisterTask(5004, // + m(EvcsWebastoNext.ChannelId.CHARGE_CURRENT, new UnsignedWordElement(5004))), // + new FC6WriteRegisterTask(5006, // + m(EvcsWebastoNext.ChannelId.START_CANCEL_CHARGING_SESSION, new UnsignedWordElement(5006))), + new FC3ReadRegistersTask(6000, Priority.LOW, // + m(EvcsWebastoNext.ChannelId.LIFE_BIT, new UnsignedWordElement(6000))), // + new FC6WriteRegisterTask(6000, // + m(EvcsWebastoNext.ChannelId.LIFE_BIT, new UnsignedWordElement(6000))) // + ); + this.addStatusListener(); + this.addPhasesListener(); + return modbusProtocol; + } + + private void addStatusListener() { + this.channel(EvcsWebastoNext.ChannelId.CHARGE_POINT_STATE).onSetNextValue(s -> { + ChargePointState state = s.asEnum(); + /** + * Maps the raw state into a {@link Status}. + */ + switch (state) { + case CHARGING: + this._setStatus(Status.CHARGING); + break; + case NO_PERMISSION: + case CHARGING_STATION_RESERVED: + this._setStatus(Status.CHARGING_REJECTED); + break; + case ERROR: + this._setStatus(Status.ERROR); + break; + case NO_VEHICLE_ATTACHED: + this._setStatus(Status.NOT_READY_FOR_CHARGING); + break; + case CHARGING_PAUSED: + this._setStatus(Status.CHARGING_FINISHED); + break; + case UNDEFINED: + default: + this._setStatus(Status.UNDEFINED); + } + }); + } + + private void addPhasesListener() { + final Consumer> setPhases = ignore -> { + var phases = 0; + if (this.getPowerL1().orElse(0) > DETECT_PHASE_ACTIVITY) { + phases++; + } + if (this.getPowerL2().orElse(0) > DETECT_PHASE_ACTIVITY) { + phases++; + } + if (this.getPowerL3().orElse(0) > DETECT_PHASE_ACTIVITY) { + phases++; + } + if (phases == 0) { + phases = 3; + } + this._setPhases(phases); + }; + this.getPowerL1Channel().onUpdate(setPhases); + this.getPowerL2Channel().onUpdate(setPhases); + this.getPowerL3Channel().onUpdate(setPhases); + } + + @Override + public String debugLog() { + return "Limit:" + this.getSetChargePowerLimit().orElse(null) + "|" + this.getStatus().getName(); + } + + @Override + public EvcsPower getEvcsPower() { + return this.evcsPower; + } + + @Override + public int getConfiguredMinimumHardwarePower() { + return Math.round(this.config.minHwCurrent() / 1000f) * DEFAULT_VOLTAGE * Phases.THREE_PHASE.getValue(); + } + + @Override + public int getConfiguredMaximumHardwarePower() { + return Math.round(this.config.maxHwCurrent() / 1000f) * DEFAULT_VOLTAGE * Phases.THREE_PHASE.getValue(); + } + + @Override + public boolean getConfiguredDebugMode() { + return this.config.debugMode(); + } + + @Override + public boolean applyChargePowerLimit(int power) throws Exception { + this.setEvSetChargePowerLimit(power); + return true; + } + + @Override + public boolean pauseChargeProcess() throws Exception { + this.applyChargePowerLimit(0); + return true; + } + + @Override + public boolean applyDisplayText(String text) throws OpenemsException { + return false; + } + + @Override + public int getMinimumTimeTillChargingLimitTaken() { + return 30; + } + + @Override + public ChargeStateHandler getChargeStateHandler() { + return this.chargeStateHandler; + } + + @Override + public void logDebug(String message) { + if (this.config.debugMode()) { + this.logInfo(this.log, message); + } + } + + @Override + public void handleEvent(Event event) { + if (!this.isEnabled()) { + return; + } + switch (event.getTopic()) { + case EdgeEventConstants.TOPIC_CYCLE_EXECUTE_WRITE: + this.writeHandler.run(); + this.updateLifeBit(); + break; + } + } + + private void updateLifeBit() { + try { + this.setLifeBit(DEFAULT_LIFE_BIT); + } catch (OpenemsNamedException e) { + e.printStackTrace(); + } + } +} diff --git a/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/CableState.java b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/CableState.java new file mode 100644 index 00000000000..1c1d7c187ed --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/CableState.java @@ -0,0 +1,36 @@ +package io.openems.edge.evcs.webasto.next.enums; + +import io.openems.common.types.OptionsEnum; + +public enum CableState implements OptionsEnum { + UNDEFINED(-1, "Undefined"), // + NO_CABLE_ATTACHED(0, "No cable attached"), // + CABLE_ATTACHED_WITHOUT_CAR(1, "Cable attached, no car attached"), // + CABLE_ATTACHED_WITH_CAR(2, "Cable attached, car attached"), // + CABLE_ATTACHED_WITH_CAR_AND_LOCKED(3, "Cable attached, car attached and locked")// + ; + + private final int value; + private final String name; + + private CableState(int value, String name) { + this.value = value; + this.name = name; + } + + @Override + public int getValue() { + return this.value; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public OptionsEnum getUndefined() { + return UNDEFINED; + } + +} diff --git a/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/ChargePointState.java b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/ChargePointState.java new file mode 100644 index 00000000000..0112975f3f6 --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/ChargePointState.java @@ -0,0 +1,38 @@ +package io.openems.edge.evcs.webasto.next.enums; + +import io.openems.common.types.OptionsEnum; + +public enum ChargePointState implements OptionsEnum { + UNDEFINED(-1, "Undefined"), // + NO_VEHICLE_ATTACHED(0, "No vehicle attached"), // + NO_PERMISSION(1, "Vehicle attached, no permission (preparing)"), // + CHARGING(3, "Charging"), // + CHARGING_PAUSED(4, "Charging paused"), // + ERROR(7, "Charging error"), // + CHARGING_STATION_RESERVED(8, "Charging station reserved") // + ; + + private final int value; + private final String name; + + private ChargePointState(int value, String name) { + this.value = value; + this.name = name; + } + + @Override + public int getValue() { + return this.value; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public OptionsEnum getUndefined() { + return UNDEFINED; + } + +} diff --git a/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/EvseErrorCode.java b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/EvseErrorCode.java new file mode 100644 index 00000000000..b8656c5abd1 --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/EvseErrorCode.java @@ -0,0 +1,50 @@ +package io.openems.edge.evcs.webasto.next.enums; + +import io.openems.common.types.OptionsEnum; + +public enum EvseErrorCode implements OptionsEnum { + UNDEFINED(-1, "Undefined"), // + NO_ERROR(0, "No error"), // + POWER_SWITCH_FAILURE(1, "Error internal board supply voltage, 5V Ref Voltage"), // + SUPPLY_VOLTAGE_ERROR(2, "Supply voltage error"), // + EV_COMMUNICATION_ERROR(3, "EV communication error"), // + OVER_VOLTAGE(4, "Over Voltage"), // + UNDER_VOLTAGE(5, "Under Voltage"), // + OVER_CURRENT_FALIURE(6, "Over current faliure"), // + OTHER_ERROR(7, "Other error"), // + GROUND_FAILURE(8, "Ground failure"), // + RCD_MODULE_ERROR(9, "Error RCD modulel"), // + HIGH_TEMPERATURE(10, "Error overtemperature"), // + PROXIMIOTY_PILOT_ERROR(11, "Proximity Pilot Error"), // + SHUTTER_ERROR(12, "Shutter Error"), // + THREE_PHASE_CHECK_ERROR(13, "Three phase check error"), // + PWR_INTERNAL_ERROR(14, "PWR internal error"), // + NEGATIVE_CONTROL_PILOT_OUT_OF_RANGE(15, "negative control pilot out of range"), // + // RELAY_WELDED_OPEN_ERRPR(16,"relay welded open"), // + DC_RESIDUAL_CURRENT(16, "DC residual current")// + ; + + private final int value; + private final String name; + + private EvseErrorCode(int value, String name) { + this.value = value; + this.name = name; + } + + @Override + public int getValue() { + return this.value; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public OptionsEnum getUndefined() { + return UNDEFINED; + } + +} diff --git a/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/EvseState.java b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/EvseState.java new file mode 100644 index 00000000000..5b2882923fb --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/EvseState.java @@ -0,0 +1,35 @@ +package io.openems.edge.evcs.webasto.next.enums; + +import io.openems.common.types.OptionsEnum; + +public enum EvseState implements OptionsEnum { + UNDEFINED(-1, "Undefined"), // + STARTING(0, "Starting"), // + RUNNING(1, "Running"), // + ERROR(2, "Error"), // + ; + + private final int value; + private final String name; + + private EvseState(int value, String name) { + this.value = value; + this.name = name; + } + + @Override + public int getValue() { + return this.value; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public OptionsEnum getUndefined() { + return UNDEFINED; + } + +} diff --git a/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/StartCancelChargingSession.java b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/StartCancelChargingSession.java new file mode 100644 index 00000000000..6ea5ce87ff6 --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/src/io/openems/edge/evcs/webasto/next/enums/StartCancelChargingSession.java @@ -0,0 +1,35 @@ +package io.openems.edge.evcs.webasto.next.enums; + +import io.openems.common.types.OptionsEnum; + +public enum StartCancelChargingSession implements OptionsEnum { + UNDEFINED(-1, "Undefined"), // + NO_ACTION(0, "No action"), // + START_CHARGING_SESSION(1, "Start charging session"), // + CANCEL_CHARGING_SESSION(2, "Cancel charging session ") // + ; + + private final int value; + private final String name; + + private StartCancelChargingSession(int value, String name) { + this.value = value; + this.name = name; + } + + @Override + public int getValue() { + return this.value; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public OptionsEnum getUndefined() { + return UNDEFINED; + } + +} diff --git a/io.openems.edge.evcs.webasto.next/test/.gitignore b/io.openems.edge.evcs.webasto.next/test/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/io.openems.edge.evcs.webasto.next/test/io/openems/edge/evcs/webasto/next/EvcsWebastoNextTest.java b/io.openems.edge.evcs.webasto.next/test/io/openems/edge/evcs/webasto/next/EvcsWebastoNextTest.java new file mode 100644 index 00000000000..7369b46ba37 --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/test/io/openems/edge/evcs/webasto/next/EvcsWebastoNextTest.java @@ -0,0 +1,28 @@ +package io.openems.edge.evcs.webasto.next; + +import org.junit.Test; + +import io.openems.edge.bridge.modbus.test.DummyModbusBridge; +import io.openems.edge.common.test.ComponentTest; +import io.openems.edge.common.test.DummyConfigurationAdmin; + +public class EvcsWebastoNextTest { + + private static final String EVCS_ID = "evcs0"; + private static final String MODBUS_ID = "modbus0"; + + @Test + public void test() throws Exception { + new ComponentTest(new EvcsWebastoNextImpl()) // + .addReference("cm", new DummyConfigurationAdmin()) // + .addReference("setModbus", new DummyModbusBridge(MODBUS_ID)) // + .activate(MyConfig.create() // + .setModbusId(MODBUS_ID) // + .setId(EVCS_ID) // + .setModbusUnitId(1) // + .setMaxHwCurrent(32000) // + .setMinHwCurrent(6000) // + .build()); // + } + +} \ No newline at end of file diff --git a/io.openems.edge.evcs.webasto.next/test/io/openems/edge/evcs/webasto/next/MyConfig.java b/io.openems.edge.evcs.webasto.next/test/io/openems/edge/evcs/webasto/next/MyConfig.java new file mode 100644 index 00000000000..b27dbb8a1d5 --- /dev/null +++ b/io.openems.edge.evcs.webasto.next/test/io/openems/edge/evcs/webasto/next/MyConfig.java @@ -0,0 +1,96 @@ +package io.openems.edge.evcs.webasto.next; + +import io.openems.common.test.AbstractComponentConfig; +import io.openems.common.utils.ConfigUtils; + +@SuppressWarnings("all") +public class MyConfig extends AbstractComponentConfig implements Config { + + protected static class Builder { + private String id; + private String modbusId; + private int modbusUnitId; + private int minHwCurrent; + private int maxHwCurrent; + + private Builder() { + + } + + public Builder setId(String id) { + this.id = id; + return this; + } + + public Builder setModbusId(String modbusId) { + this.modbusId = modbusId; + return this; + } + + public Builder setModbusUnitId(int modbusUnitId) { + this.modbusUnitId = modbusUnitId; + return this; + } + + public Builder setMinHwCurrent(int minHwCurrent) { + this.minHwCurrent = minHwCurrent; + return this; + } + + public Builder setMaxHwCurrent(int maxHwCurrent) { + this.maxHwCurrent = maxHwCurrent; + return this; + } + + public MyConfig build() { + return new MyConfig(this); + } + } + + /** + * Create a Config builder. + * + * @return a {@link Builder} + */ + public static Builder create() { + return new Builder(); + } + + private final Builder builder; + + private MyConfig(Builder builder) { + super(Config.class, builder.id); + this.builder = builder; + } + + @Override + public boolean debugMode() { + return false; + } + + @Override + public String modbus_id() { + return this.builder.modbusId; + } + + @Override + public String Modbus_target() { + return ConfigUtils.generateReferenceTargetFilter(this.id(), this.modbus_id()); + } + + @Override + public int modbusUnitId() { + return this.builder.modbusUnitId; + } + + @Override + public int minHwCurrent() { + return this.builder.minHwCurrent; + } + + @Override + public int maxHwCurrent() { + return this.builder.maxHwCurrent; + } + +} \ No newline at end of file diff --git a/io.openems.edge.evcs.webasto.unite/doc/Webasto_UNITE_Modbus_Register_1-00_external_V1.pdf b/io.openems.edge.evcs.webasto.unite/doc/Webasto_UNITE_Modbus_Register_1-00_external_V1.pdf deleted file mode 100644 index 3c3d60e019832d24e45658e77f19ce95ba46c12b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 216052 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

      sMeE8>1& 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 &XyW+T40PK*8n5*>gX&`1CWDEDMC=JhSmAA} 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 Date: Tue, 21 Mar 2023 09:20:19 +0100 Subject: [PATCH 12/23] Bump postgresql from 42.5.4 to 42.6.0 in /cnf (#2115) * Bump postgresql from 42.5.4 to 42.6.0 in /cnf Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.5.4 to 42.6.0. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.5.4...REL42.6.0) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update bndrun --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Feilmeier --- cnf/pom.xml | 2 +- io.openems.backend.application/BackendApp.bndrun | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index ffdfb8454e7..037726e8305 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -392,7 +392,7 @@ org.postgresql postgresql - 42.5.4 + 42.6.0 diff --git a/io.openems.backend.application/BackendApp.bndrun b/io.openems.backend.application/BackendApp.bndrun index 242f2e1e204..5da85360b61 100644 --- a/io.openems.backend.application/BackendApp.bndrun +++ b/io.openems.backend.application/BackendApp.bndrun @@ -118,5 +118,5 @@ org.osgi.service.jdbc;version='[1.1.0,1.1.1)',\ org.osgi.util.function;version='[1.2.0,1.2.1)',\ org.osgi.util.promise;version='[1.3.0,1.3.1)',\ - org.postgresql.jdbc;version='[42.5.4,42.5.5)',\ + org.postgresql.jdbc;version='[42.6.0,42.6.1)',\ reactive-streams;version='[1.0.4,1.0.5)' \ No newline at end of file From 60c87da1606fc3e0a48a4298a49815f5e29e26b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 10:06:31 +0100 Subject: [PATCH 13/23] Bump org.apache.felix.fileinstall from 3.6.4 to 3.7.4 in /cnf (#2114) * Bump org.apache.felix.fileinstall from 3.6.4 to 3.7.4 in /cnf Bumps org.apache.felix.fileinstall from 3.6.4 to 3.7.4. --- updated-dependencies: - dependency-name: org.apache.felix:org.apache.felix.fileinstall dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update bndrun --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Feilmeier --- cnf/pom.xml | 2 +- io.openems.backend.application/BackendApp.bndrun | 2 +- io.openems.edge.application/EdgeApp.bndrun | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index 037726e8305..da48ae7da6a 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -192,7 +192,7 @@ org.apache.felix org.apache.felix.fileinstall - 3.6.4 + 3.7.4 diff --git a/io.openems.backend.application/BackendApp.bndrun b/io.openems.backend.application/BackendApp.bndrun index 5da85360b61..f1dee20aea7 100644 --- a/io.openems.backend.application/BackendApp.bndrun +++ b/io.openems.backend.application/BackendApp.bndrun @@ -102,7 +102,7 @@ org.apache.commons.commons-io;version='[2.11.0,2.11.1)',\ org.apache.felix.configadmin;version='[1.9.26,1.9.27)',\ org.apache.felix.eventadmin;version='[1.6.4,1.6.5)',\ - org.apache.felix.fileinstall;version='[3.6.4,3.6.5)',\ + org.apache.felix.fileinstall;version='[3.7.4,3.7.5)',\ org.apache.felix.http.jetty;version='[5.0.4,5.0.5)',\ org.apache.felix.http.servlet-api;version='[2.1.0,2.1.1)',\ org.apache.felix.inventory;version='[1.1.0,1.1.1)',\ diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index a4082d15ae3..685bab5550c 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -367,7 +367,7 @@ org.apache.commons.math3;version='[3.6.1,3.6.2)',\ org.apache.felix.configadmin;version='[1.9.26,1.9.27)',\ org.apache.felix.eventadmin;version='[1.6.4,1.6.5)',\ - org.apache.felix.fileinstall;version='[3.6.4,3.6.5)',\ + org.apache.felix.fileinstall;version='[3.7.4,3.7.5)',\ org.apache.felix.http.jetty;version='[5.0.4,5.0.5)',\ org.apache.felix.http.servlet-api;version='[2.1.0,2.1.1)',\ org.apache.felix.inventory;version='[1.1.0,1.1.1)',\ From 2a46b5936e2ff7bd5468c28aaff504d839dbed1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=B6cker?= <39899210+DerStoecki@users.noreply.github.com> Date: Tue, 21 Mar 2023 10:18:11 +0100 Subject: [PATCH 14/23] Script prepare-commit: autocreate missing files using IntelliJ IDEA (#2083) When one create modules in IntelliJ .classpath and .project files are missing. These few lines supports the creation of .classpath and .project files. Co-authored-by: Stefan Feilmeier --- .../.project | 2 +- io.openems.edge.io.offgridswitch/.project | 2 +- io.openems.edge.meter.sma.shm20/.project | 11 ------- tools/prepare-commit.sh | 31 +++++++++++++++++-- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/io.openems.edge.evcs.alpitronic.hypercharger/.project b/io.openems.edge.evcs.alpitronic.hypercharger/.project index 50f8dddd6bf..82c9dcb3d9a 100644 --- a/io.openems.edge.evcs.alpitronic.hypercharger/.project +++ b/io.openems.edge.evcs.alpitronic.hypercharger/.project @@ -1,6 +1,6 @@ - io.openems.edge.evcs.hypercharger + io.openems.edge.evcs.alpitronic.hypercharger diff --git a/io.openems.edge.io.offgridswitch/.project b/io.openems.edge.io.offgridswitch/.project index bbf159fc118..f7d4aceeb9c 100644 --- a/io.openems.edge.io.offgridswitch/.project +++ b/io.openems.edge.io.offgridswitch/.project @@ -1,6 +1,6 @@ - io.openems.edge.iooffgridswitch + io.openems.edge.io.offgridswitch diff --git a/io.openems.edge.meter.sma.shm20/.project b/io.openems.edge.meter.sma.shm20/.project index cf1499712b3..e4376cb13e3 100644 --- a/io.openems.edge.meter.sma.shm20/.project +++ b/io.openems.edge.meter.sma.shm20/.project @@ -20,15 +20,4 @@ org.eclipse.jdt.core.javanature bndtools.core.bndnature - - - 1603622766746 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - diff --git a/tools/prepare-commit.sh b/tools/prepare-commit.sh index 3c93794d21a..a2f456c4488 100755 --- a/tools/prepare-commit.sh +++ b/tools/prepare-commit.sh @@ -74,8 +74,7 @@ EOT fi # Set default .classpath file - if [ -f "${D}/.classpath" ]; then - cat < "${D}/.classpath" + cat < "${D}/.classpath" @@ -89,7 +88,33 @@ EOT EOT - fi + + # Set default .project file + cat < "${D}/.project" + + + ${D} + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + +EOT # Verify bnd.bnd file if [ -f "${D}/bnd.bnd" ]; then From 8384f5a8374c54b8a24fde4f53ff82c9ab3ac838 Mon Sep 17 00:00:00 2001 From: Stefan Feilmeier Date: Thu, 23 Mar 2023 15:17:50 +0100 Subject: [PATCH 15/23] Backport FEMS UI (#2117) This PR backports multiple improvements from FEMS UI to OpenEMS UI: - Add pagination to Overview page (this requires changes als in the Backend/Edge side and new JsonRpc-Requests - Add error log from UI to Backend. This allows tracing UI errors in the Backend log - Add empty Changelog -> can be used by companies to provide custom version Changelogs to their customers - Draft for ServiceWorker/App-Update-Service - Error message when History queries fail - Time-Of-Use: prepare for Charge-From-Grid-Controller - Improvements to App-Center (Sorry for this big Backport PR again, but this way we will enable better collaboration on OpenEMS UI with the Community in future) --- .../request/SendLogMessageRequest.java | 79 -- .../request/SubscribeEdgesRequest.java | 71 ++ .../backend/common/metadata/Metadata.java | 22 + .../openems/backend/common/metadata/User.java | 8 +- .../backend/common/test/DummyMetadata.java | 13 + .../backend/metadata/dummy/DummyMetadata.java | 38 +- .../backend/metadata/file/FileMetadata.java | 35 +- .../backend/metadata/odoo/OdooMetadata.java | 34 + .../metadata/odoo/odoo/OdooHandler.java | 55 +- .../uiwebsocket/impl/OnNotification.java | 52 +- .../backend/uiwebsocket/impl/OnRequest.java | 142 ++-- .../uiwebsocket/impl/UiWebsocketImpl.java | 28 +- .../notification/LogMessageNotification.java | 70 ++ .../request/AuthenticatedRpcRequest.java | 1 + .../jsonrpc/request/GetEdgeRequest.java | 54 ++ .../jsonrpc/request/GetEdgesRequest.java | 116 +++ .../response/AuthenticateResponse.java | 72 +- .../jsonrpc/response/GetEdgeResponse.java | 41 + .../jsonrpc/response/GetEdgesResponse.java | 105 +++ .../io/openems/common/utils/StringUtils.java | 23 + .../controller/api/websocket/OnRequest.java | 89 +++ .../edge/controller/api/websocket/Utils.java | 4 +- .../generated/buildfiles | 1 + ui/angular.json | 3 +- ui/package-lock.json | 27 +- ui/package.json | 2 +- ui/src/app/app-routing.module.ts | 90 ++- ui/src/app/app.component.ts | 13 +- ui/src/app/app.module.ts | 17 +- ui/src/app/appupdateservice.ts | 51 ++ ui/src/app/changelog/changelog.module.ts | 19 + .../view/component/changelog.component.html | 54 ++ .../view/component/changelog.component.ts | 46 ++ .../view/component/changelog.constants.ts | 92 +++ ui/src/app/changelog/view/view.html | 4 + ui/src/app/changelog/view/view.ts | 7 + ui/src/app/edge/edge.component.ts | 53 ++ ui/src/app/edge/edge.module.ts | 7 + .../edge/history/abstracthistorychart.html | 2 + .../app/edge/history/abstracthistorychart.ts | 30 +- .../edge/history/energy/energy.component.html | 2 + .../edge/history/energy/energy.component.ts | 7 +- .../app/edge/history/history.component.html | 12 +- ui/src/app/edge/history/history.component.ts | 20 +- ui/src/app/edge/history/history.module.ts | 4 +- .../edge/history/historyparent.component.ts | 13 + .../chart.component.ts | 97 ++- .../widget.component.html | 37 +- .../widget.component.ts | 12 +- .../TimeOfUseTariffDischarge/modal/modal.html | 2 +- .../common/storage/modal/modal.component.html | 713 ++++++++++++++---- .../common/storage/modal/modal.component.ts | 203 +++-- .../common/storage/storage.component.html | 3 + .../live/common/storage/storage.component.ts | 60 +- ui/src/app/edge/live/info/info.component.ts | 4 +- ui/src/app/edge/live/live.component.html | 7 +- ui/src/app/edge/live/live.component.ts | 37 +- ui/src/app/edge/settings/app/app.module.ts | 35 + .../edge/settings/app/index.component.html | 86 ++- .../app/edge/settings/app/index.component.ts | 178 ++++- .../edge/settings/app/install.component.html | 5 +- .../edge/settings/app/install.component.ts | 181 ++++- .../settings/app/jsonrpc/addAppInstance.ts | 1 + .../settings/app/jsonrpc/getAppAssistant.ts | 43 +- ui/src/app/edge/settings/app/keypopup/app.ts | 7 + .../edge/settings/app/keypopup/appCenter.ts | 43 ++ .../appCenterAddRegisterKeyHistory.ts | 52 ++ .../app/keypopup/appCenterGetPossibleApps.ts | 65 ++ .../keypopup/appCenterGetRegisteredKeys.ts | 65 ++ .../appCenterInstallAppWithSuppliedKey.ts | 46 ++ .../app/keypopup/appCenterIsAppFree.ts | 65 ++ .../app/keypopup/appCenterIsKeyApplicable.ts | 91 +++ ui/src/app/edge/settings/app/keypopup/key.ts | 6 + .../app/keypopup/modal.component.html | 53 ++ .../settings/app/keypopup/modal.component.ts | 417 ++++++++++ ui/src/app/edge/settings/app/permissions.ts | 35 + .../edge/settings/app/single.component.html | 30 +- .../app/edge/settings/app/single.component.ts | 173 ++++- .../edge/settings/app/update.component.html | 13 +- .../app/edge/settings/app/update.component.ts | 63 +- .../component/update/index.component.ts | 12 +- .../settings/profile/profile.component.ts | 8 +- .../app/edge/settings/settings.component.html | 2 +- .../app/edge/settings/settings.component.ts | 10 +- ui/src/app/edge/settings/settings.module.ts | 2 + .../systemupdate/systemupdate.component.html | 2 +- ui/src/app/index/index.component.html | 61 +- ui/src/app/index/index.component.ts | 197 +++-- ...form-field-checkbox-hyperlink.wrapper.html | 17 + .../form-field-checkbox-hyperlink.wrapper.ts | 27 + .../form-field-default-cases.wrapper.ts | 32 + .../formly-select-field-modal.component.html | 54 ++ .../formly-select-field-modal.component.ts | 29 + .../formly/formly-select-field.extended.html | 11 + .../formly/formly-select-field.extended.ts | 52 ++ .../formly/formly-select-field.wrapper.html | 18 - .../formly/formly-select-field.wrapper.ts | 8 - .../shared/formly/panel-wrapper.component.ts | 20 + .../chart/abstracthistorychart.html | 2 + .../chart/abstracthistorychart.ts | 18 +- .../shared/genericComponents/chart/chart.html | 2 +- .../flat-widget-percentagebar.html | 2 +- ui/src/app/shared/header/header.component.ts | 26 +- .../shared/history-data-error.component.ts | 37 + .../logMessageNotification.ts} | 10 +- .../shared/jsonrpc/request/getEdgeRequest.ts | 32 + .../shared/jsonrpc/request/getEdgesRequest.ts | 36 + .../request/submitSetupProtocolRequest.ts | 4 +- .../jsonrpc/response/getEdgeResponse.ts | 28 + .../jsonrpc/response/getEdgesResponse.ts | 28 + ui/src/app/shared/service/logger.ts | 18 +- ui/src/app/shared/service/myerrorhandler.ts | 27 + ui/src/app/shared/service/pagination.ts | 37 + ui/src/app/shared/service/service.ts | 157 ++-- ui/src/app/shared/service/utils.ts | 2 + ui/src/app/shared/service/websocket.ts | 70 +- ui/src/app/shared/shared.module.ts | 23 +- ui/src/app/user/user.component.html | 3 +- ui/src/app/user/user.component.ts | 3 +- ui/src/assets/i18n/cz.json | 67 +- ui/src/assets/i18n/de.json | 113 ++- ui/src/assets/i18n/en.json | 164 ++-- ui/src/assets/i18n/es.json | 66 +- ui/src/assets/i18n/fr.json | 66 +- ui/src/assets/i18n/nl.json | 66 +- ui/src/global.scss | 39 +- ui/src/test.ts | 24 +- ui/src/themes/openems/scss/variables.scss | 2 +- ui/tsconfig.json | 5 +- 129 files changed, 5085 insertions(+), 1310 deletions(-) delete mode 100644 io.openems.backend.common/src/io/openems/backend/common/jsonrpc/request/SendLogMessageRequest.java create mode 100644 io.openems.backend.common/src/io/openems/backend/common/jsonrpc/request/SubscribeEdgesRequest.java create mode 100644 io.openems.backend.uiwebsocket/src/io/openems/backend/uiwebsocket/jsonrpc/notification/LogMessageNotification.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/GetEdgeRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/GetEdgesRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/response/GetEdgeResponse.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/response/GetEdgesResponse.java create mode 100644 io.openems.edge.evcs.dezony/generated/buildfiles create mode 100644 ui/src/app/appupdateservice.ts create mode 100644 ui/src/app/changelog/changelog.module.ts create mode 100644 ui/src/app/changelog/view/component/changelog.component.html create mode 100644 ui/src/app/changelog/view/component/changelog.component.ts create mode 100644 ui/src/app/changelog/view/component/changelog.constants.ts create mode 100644 ui/src/app/changelog/view/view.html create mode 100644 ui/src/app/changelog/view/view.ts create mode 100644 ui/src/app/edge/edge.component.ts create mode 100644 ui/src/app/edge/history/historyparent.component.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/app.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/appCenter.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/appCenterAddRegisterKeyHistory.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/appCenterGetPossibleApps.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/appCenterGetRegisteredKeys.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/appCenterInstallAppWithSuppliedKey.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/appCenterIsAppFree.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/appCenterIsKeyApplicable.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/key.ts create mode 100644 ui/src/app/edge/settings/app/keypopup/modal.component.html create mode 100644 ui/src/app/edge/settings/app/keypopup/modal.component.ts create mode 100644 ui/src/app/edge/settings/app/permissions.ts create mode 100644 ui/src/app/shared/formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper.html create mode 100644 ui/src/app/shared/formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper.ts create mode 100644 ui/src/app/shared/formly/form-field-default-cases.wrapper.ts create mode 100644 ui/src/app/shared/formly/formly-select-field-modal.component.html create mode 100644 ui/src/app/shared/formly/formly-select-field-modal.component.ts create mode 100644 ui/src/app/shared/formly/formly-select-field.extended.html create mode 100644 ui/src/app/shared/formly/formly-select-field.extended.ts delete mode 100644 ui/src/app/shared/formly/formly-select-field.wrapper.html delete mode 100644 ui/src/app/shared/formly/formly-select-field.wrapper.ts create mode 100644 ui/src/app/shared/formly/panel-wrapper.component.ts create mode 100644 ui/src/app/shared/history-data-error.component.ts rename ui/src/app/shared/jsonrpc/{request/sendLogMessage.ts => notification/logMessageNotification.ts} (58%) create mode 100644 ui/src/app/shared/jsonrpc/request/getEdgeRequest.ts create mode 100644 ui/src/app/shared/jsonrpc/request/getEdgesRequest.ts create mode 100644 ui/src/app/shared/jsonrpc/response/getEdgeResponse.ts create mode 100644 ui/src/app/shared/jsonrpc/response/getEdgesResponse.ts create mode 100644 ui/src/app/shared/service/myerrorhandler.ts create mode 100644 ui/src/app/shared/service/pagination.ts diff --git a/io.openems.backend.common/src/io/openems/backend/common/jsonrpc/request/SendLogMessageRequest.java b/io.openems.backend.common/src/io/openems/backend/common/jsonrpc/request/SendLogMessageRequest.java deleted file mode 100644 index e733c9c9196..00000000000 --- a/io.openems.backend.common/src/io/openems/backend/common/jsonrpc/request/SendLogMessageRequest.java +++ /dev/null @@ -1,79 +0,0 @@ -package io.openems.backend.common.jsonrpc.request; - -import java.lang.System.Logger.Level; - -import com.google.gson.JsonObject; - -import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; -import io.openems.common.jsonrpc.base.JsonrpcRequest; -import io.openems.common.utils.JsonUtils; - -/** - * Log message. - * - *

      - * {
      - *   "jsonrpc": "2.0",
      - *   "id": UUID,
      - *   "method": "sendLogMessage",
      - *   "params": {
      - *     "level": string,
      - *     "msg": string
      - *   }
      - * }
      - * 
      - */ -public class SendLogMessageRequest extends JsonrpcRequest { - - public static final String METHOD = "sendLogMessage"; - - private final Level level; - private final String msg; - - /** - * Create {@link SendLogMessageRequest} from a template {@link JsonrpcRequest}. - * - * @param request the template {@link JsonrpcRequest} - * @return Created {@link SendLogMessageRequest} - * @throws OpenemsNamedException on parse error - */ - public static SendLogMessageRequest from(JsonrpcRequest request) throws OpenemsNamedException { - var params = request.getParams(); - return new SendLogMessageRequest(request, params); - } - - private SendLogMessageRequest(JsonrpcRequest request, JsonObject params) throws OpenemsNamedException { - super(request, SendLogMessageRequest.METHOD); - - String jsonLevel = JsonUtils.getAsString(params, "level"); - this.level = Level.valueOf(jsonLevel.toUpperCase()); - this.msg = JsonUtils.getAsString(params, "msg"); - } - - @Override - public JsonObject getParams() { - return JsonUtils.buildJsonObject() // - .addProperty("level", this.level.getName()) // - .addProperty("msg", this.msg) // - .build(); - } - - /** - * Gets the log level as {@link Level}. - * - * @return the {@link Level} - */ - public Level getLevel() { - return this.level; - } - - /** - * Gets the message to log. - * - * @return The message. - */ - public String getMsg() { - return this.msg; - } - -} diff --git a/io.openems.backend.common/src/io/openems/backend/common/jsonrpc/request/SubscribeEdgesRequest.java b/io.openems.backend.common/src/io/openems/backend/common/jsonrpc/request/SubscribeEdgesRequest.java new file mode 100644 index 00000000000..d2fd3adac98 --- /dev/null +++ b/io.openems.backend.common/src/io/openems/backend/common/jsonrpc/request/SubscribeEdgesRequest.java @@ -0,0 +1,71 @@ +package io.openems.backend.common.jsonrpc.request; + +import java.util.Set; +import java.util.stream.Collectors; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to subscribe to Edges. + * + *

      + * This is used by UI to get regular updates on specific channels. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "subscribeEdges",
      + *   "params": {
      + *     "edges": string[]
      + *   }
      + * }
      + * 
      + */ +public class SubscribeEdgesRequest extends JsonrpcRequest { + + public static final String METHOD = "subscribeEdges"; + + /** + * Create {@link SubscribeEdgesRequest} from a template {@link JsonrpcRequest}. + * + * @param r the template {@link JsonrpcRequest} + * @return the {@link SubscribeEdgesRequest} + * @throws OpenemsNamedException on parse error + */ + public static SubscribeEdgesRequest from(JsonrpcRequest r) throws OpenemsNamedException { + var p = r.getParams(); + return new SubscribeEdgesRequest(r, JsonUtils.stream(JsonUtils.getAsJsonArray(p, "edges")) + .map(t -> t.getAsString()).collect(Collectors.toSet())); + } + + private final Set edges; + + private SubscribeEdgesRequest(JsonrpcRequest request, Set edges) { + super(request, SubscribeEdgesRequest.METHOD); + this.edges = edges; + } + + /** + * Gets the set of Edges. + * + * @return the Edges + */ + public Set getEdges() { + return this.edges; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .add("edges", this.edges.stream() // + .map(t -> new JsonPrimitive(t)) // + .collect(JsonUtils.toJsonArray())) // + .build(); + } +} diff --git a/io.openems.backend.common/src/io/openems/backend/common/metadata/Metadata.java b/io.openems.backend.common/src/io/openems/backend/common/metadata/Metadata.java index a441e02327f..b634a3fafd7 100644 --- a/io.openems.backend.common/src/io/openems/backend/common/metadata/Metadata.java +++ b/io.openems.backend.common/src/io/openems/backend/common/metadata/Metadata.java @@ -20,7 +20,9 @@ import io.openems.common.exceptions.OpenemsError; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.request.GetEdgesRequest.PaginationOptions; import io.openems.common.session.Language; +import io.openems.common.session.Role; import io.openems.common.types.ChannelAddress; import io.openems.common.types.EdgeConfig; import io.openems.common.types.EdgeConfig.Component.Channel; @@ -342,4 +344,24 @@ public static final class Events { */ public Optional getSerialNumberForEdge(Edge edge); + /** + * Gets a map of Edge-IDs with the role of the given user. + * + * @param user {@link User} the current user + * @param paginationOptions the options of the requesting page + * @return the role to the Edge-IDs + * @throws OpenemsNamedException on error + */ + public Map getPageDevice(User user, PaginationOptions paginationOptions) throws OpenemsNamedException; + + /** + * Gets the Role for a edge of the current user. + * + * @param user {@link User} the current user + * @param edgeId the Edge-ID + * @return the role to the edge + * @throws OpenemsNamedException on error + */ + public Role getRoleForEdge(User user, String edgeId) throws OpenemsNamedException; + } diff --git a/io.openems.backend.common/src/io/openems/backend/common/metadata/User.java b/io.openems.backend.common/src/io/openems/backend/common/metadata/User.java index d4c3d3e5657..f458fbbb201 100644 --- a/io.openems.backend.common/src/io/openems/backend/common/metadata/User.java +++ b/io.openems.backend.common/src/io/openems/backend/common/metadata/User.java @@ -4,10 +4,11 @@ import java.util.List; import java.util.Map.Entry; import java.util.NavigableMap; +import java.util.TreeMap; import io.openems.common.exceptions.OpenemsError; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; -import io.openems.common.jsonrpc.response.AuthenticateResponse.EdgeMetadata; +import io.openems.common.jsonrpc.response.GetEdgesResponse.EdgeMetadata; import io.openems.common.session.AbstractUser; import io.openems.common.session.Language; import io.openems.common.session.Role; @@ -22,6 +23,10 @@ public class User extends AbstractUser { */ private final String token; + public User(String id, String name, String token, Language language, Role globalRole) { + this(id, name, token, language, globalRole, new TreeMap<>()); + } + public User(String id, String name, String token, Language language, Role globalRole, NavigableMap roles) { super(id, name, language, globalRole, roles); @@ -87,4 +92,5 @@ public static List generateEdgeMetadatas(User user, Metadata metad } return metadatas; } + } diff --git a/io.openems.backend.common/src/io/openems/backend/common/test/DummyMetadata.java b/io.openems.backend.common/src/io/openems/backend/common/test/DummyMetadata.java index f52fe97f832..5ef2506a57f 100644 --- a/io.openems.backend.common/src/io/openems/backend/common/test/DummyMetadata.java +++ b/io.openems.backend.common/src/io/openems/backend/common/test/DummyMetadata.java @@ -17,7 +17,9 @@ import io.openems.common.OpenemsOEM; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.request.GetEdgesRequest.PaginationOptions; import io.openems.common.session.Language; +import io.openems.common.session.Role; public class DummyMetadata implements Metadata { @Override @@ -134,4 +136,15 @@ public EdgeHandler edge() { public Optional getSerialNumberForEdge(Edge edge) { throw new UnsupportedOperationException("Unsupported by Dummy Class"); } + + @Override + public Map getPageDevice(User user, PaginationOptions paginationOptions) throws OpenemsNamedException { + throw new UnsupportedOperationException("Unsupported by Dummy Class"); + } + + @Override + public Role getRoleForEdge(User user, String edgeId) throws OpenemsNamedException { + throw new UnsupportedOperationException("Unsupported by Dummy Class"); + } + } diff --git a/io.openems.backend.metadata.dummy/src/io/openems/backend/metadata/dummy/DummyMetadata.java b/io.openems.backend.metadata.dummy/src/io/openems/backend/metadata/dummy/DummyMetadata.java index 490d8b10ad1..69808d69d27 100644 --- a/io.openems.backend.metadata.dummy/src/io/openems/backend/metadata/dummy/DummyMetadata.java +++ b/io.openems.backend.metadata.dummy/src/io/openems/backend/metadata/dummy/DummyMetadata.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -41,8 +40,10 @@ import io.openems.common.exceptions.OpenemsError; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.request.GetEdgesRequest.PaginationOptions; import io.openems.common.session.Language; import io.openems.common.session.Role; +import io.openems.common.utils.StringUtils; import io.openems.common.utils.ThreadPoolUtils; @Designate(ocd = Config.class, factory = false) @@ -93,11 +94,7 @@ private void deactivate() { public User authenticate(String username, String password) throws OpenemsNamedException { var name = "User #" + this.nextUserId.incrementAndGet(); var token = UUID.randomUUID().toString(); - var roles = new TreeMap(); - for (String edgeId : this.edges.keySet()) { - roles.put(edgeId, Role.ADMIN); - } - var user = new User(username, name, token, this.defaultLanguage, Role.ADMIN, roles); + var user = new User(username, name, token, this.defaultLanguage, Role.ADMIN); this.users.put(user.getId(), user); return user; } @@ -171,7 +168,7 @@ public Optional getUser(String userId) { @Override public Collection getAllOfflineEdges() { - return this.edges.values().stream().filter(Edge::isOffline).collect(Collectors.toUnmodifiableList()); + return this.edges.values().stream().filter(Edge::isOffline).collect(Collectors.toUnmodifiableList()); } private static Optional parseNumberFromName(String name) { @@ -267,4 +264,31 @@ public AlertingSetting getUserAlertingSettings(String edgeId, String userId) thr public void setUserAlertingSettings(User user, String edgeId, List users) { throw new UnsupportedOperationException("DummyMetadata.setUserAlertingSettings() is not implemented"); } + + @Override + public Map getPageDevice(User user, PaginationOptions paginationOptions) + throws OpenemsNamedException { + var pagesStream = this.edges.values().stream(); + final var query = paginationOptions.getQuery(); + if (query != null) { + pagesStream = pagesStream.filter(// + edge -> StringUtils.containsWithNullCheck(edge.getId(), query) // + || StringUtils.containsWithNullCheck(edge.getComment(), query) // + || StringUtils.containsWithNullCheck(edge.getProducttype(), query) // + ); + } + return pagesStream // + .sorted((s1, s2) -> s1.getId().compareTo(s2.getId())) // + .skip(paginationOptions.getPage() * paginationOptions.getLimit()) // + .limit(paginationOptions.getLimit()) // + .peek(t -> user.setRole(t.getId(), Role.ADMIN)) // + .collect(Collectors.toMap(t -> t.getId(), t -> Role.ADMIN)); // + } + + @Override + public Role getRoleForEdge(User user, String edgeId) throws OpenemsNamedException { + user.setRole(edgeId, Role.ADMIN); + return Role.ADMIN; + } + } diff --git a/io.openems.backend.metadata.file/src/io/openems/backend/metadata/file/FileMetadata.java b/io.openems.backend.metadata.file/src/io/openems/backend/metadata/file/FileMetadata.java index ed5751ad96d..edeee62538f 100644 --- a/io.openems.backend.metadata.file/src/io/openems/backend/metadata/file/FileMetadata.java +++ b/io.openems.backend.metadata.file/src/io/openems/backend/metadata/file/FileMetadata.java @@ -10,7 +10,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; -import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @@ -43,9 +42,11 @@ import io.openems.common.exceptions.OpenemsError; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.request.GetEdgesRequest.PaginationOptions; import io.openems.common.session.Language; import io.openems.common.session.Role; import io.openems.common.utils.JsonUtils; +import io.openems.common.utils.StringUtils; /** * This implementation of MetadataService reads Edges configuration from a file. @@ -70,7 +71,8 @@ @Designate(ocd = Config.class, factory = false) @Component(// name = "Metadata.File", // - configurationPolicy = ConfigurationPolicy.REQUIRE // + configurationPolicy = ConfigurationPolicy.REQUIRE, // + immediate = true // ) @EventTopics({ // Edge.Events.ON_SET_CONFIG // @@ -215,7 +217,6 @@ private synchronized void refreshData() { // Add Edges and configure User permissions for (MyEdge edge : edges) { this.edges.put(edge.getId(), edge); - this.user.setRole(edge.getId(), Role.ADMIN); } } this.setInitialized(); @@ -223,7 +224,7 @@ private synchronized void refreshData() { private static User generateUser() { return new User(FileMetadata.USER_ID, FileMetadata.USER_NAME, UUID.randomUUID().toString(), - FileMetadata.LANGUAGE, FileMetadata.USER_GLOBAL_ROLE, new TreeMap<>()); + FileMetadata.LANGUAGE, FileMetadata.USER_GLOBAL_ROLE); } @Override @@ -307,4 +308,30 @@ public void setUserAlertingSettings(User user, String edgeId, List getPageDevice(User user, PaginationOptions paginationOptions) + throws OpenemsNamedException { + var pagesStream = this.edges.values().stream(); + final var query = paginationOptions.getQuery(); + if (query != null) { + pagesStream = pagesStream.filter(// + edge -> StringUtils.containsWithNullCheck(edge.getId(), query) // + || StringUtils.containsWithNullCheck(edge.getComment(), query) // + || StringUtils.containsWithNullCheck(edge.getProducttype(), query) // + ); + } + return pagesStream // + .sorted((s1, s2) -> s1.getId().compareTo(s2.getId())) // + .skip(paginationOptions.getPage() * paginationOptions.getLimit()) // + .limit(paginationOptions.getLimit()) // + .peek(t -> user.setRole(t.getId(), Role.ADMIN)) // + .collect(Collectors.toMap(t -> t.getId(), t -> Role.ADMIN)); // + } + + @Override + public Role getRoleForEdge(User user, String edgeId) throws OpenemsNamedException { + user.setRole(edgeId, Role.ADMIN); + return Role.ADMIN; + } + } diff --git a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/OdooMetadata.java b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/OdooMetadata.java index c51454424c4..059c4b7429e 100644 --- a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/OdooMetadata.java +++ b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/OdooMetadata.java @@ -3,6 +3,7 @@ import java.sql.SQLException; import java.time.ZonedDateTime; import java.util.Collection; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NavigableMap; @@ -45,8 +46,10 @@ import io.openems.common.OpenemsOEM; import io.openems.common.channel.Level; import io.openems.common.event.EventReader; +import io.openems.common.exceptions.OpenemsError; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.request.GetEdgesRequest.PaginationOptions; import io.openems.common.session.Language; import io.openems.common.session.Role; import io.openems.common.types.EdgeConfig; @@ -418,4 +421,35 @@ public AlertingSetting getUserAlertingSettings(String edgeId, String userId) thr public void setUserAlertingSettings(User user, String edgeId, List users) throws OpenemsException { this.odooHandler.setUserAlertingSettings((MyUser) user, edgeId, users); } + + @Override + public Map getPageDevice(User user, PaginationOptions paginationOptions) + throws OpenemsNamedException { + var result = this.odooHandler.getEdges((MyUser) user, paginationOptions); + + Map devices = new LinkedHashMap<>(); + + var jDevices = JsonUtils.getAsJsonArray(result, "devices"); + for (var jDevice : jDevices) { + var edgeId = JsonUtils.getAsString(jDevice, "name"); + var role = Role.getRole(JsonUtils.getAsString(jDevice, "role")); + user.setRole(edgeId, role); + + devices.put(edgeId, role); + } + + return devices; + } + + @Override + public Role getRoleForEdge(User user, String edgeId) throws OpenemsNamedException { + var result = this.odooHandler.getEdgeWithRole((MyUser) user, edgeId); + var roleString = JsonUtils.getAsOptionalString(result, "role") // + .orElseThrow(() -> OpenemsError.COMMON_ROLE_UNDEFINED.exception(edgeId, user.getId())); + + var role = Role.getRole(roleString); + user.setRole(edgeId, role); + return role; + } + } diff --git a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/OdooHandler.java b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/OdooHandler.java index e0cf117a9a3..6011ea24605 100644 --- a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/OdooHandler.java +++ b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/OdooHandler.java @@ -14,6 +14,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -35,6 +36,7 @@ import io.openems.common.OpenemsOEM; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.request.GetEdgesRequest.PaginationOptions; import io.openems.common.session.Language; import io.openems.common.session.Role; import io.openems.common.utils.JsonUtils; @@ -150,7 +152,6 @@ public Optional getEdgeIdBySetupPassword(String setupPassword) { */ public void assignEdgeToUser(MyUser user, MyEdge edge, OdooUserRole userRole) throws OpenemsNamedException { this.assignEdgeToUser(user.getOdooId(), edge.getOdooId(), userRole); - this.parent.authenticate(user.getToken()); } /** @@ -171,10 +172,15 @@ private void assignEdgeToUser(int userId, int edgeId, OdooUserRole userRole) thr return; } - OdooUtils.create(this.credentials, Field.EdgeDeviceUserRole.ODOO_MODEL, // + var fields = Lists.newArrayList(// new FieldValue<>(Field.EdgeDeviceUserRole.USER_ODOO_ID, userId), // new FieldValue<>(Field.EdgeDeviceUserRole.DEVICE_ODOO_ID, edgeId), // - new FieldValue<>(Field.EdgeDeviceUserRole.ROLE, userRole.getOdooRole())); + new FieldValue<>(Field.EdgeDeviceUserRole.ROLE, userRole.getOdooRole()) // + ); + if (userRole.equals(OdooUserRole.OWNER)) { + fields.add(new FieldValue<>(Field.EdgeDeviceUserRole.TIME_TO_WAIT, 60)); + } + OdooUtils.create(this.credentials, Field.EdgeDeviceUserRole.ODOO_MODEL, fields.toArray(FieldValue[]::new)); } /** @@ -1041,4 +1047,47 @@ public void setUserAlertingSettings(MyUser user, String edgeId, List run(WebSocket ws, Jso } // should be authenticated - var user = this.assertUser(wsData, request); + var user = this.parent.assertUser(wsData, request); switch (request.getMethod()) { case LogoutRequest.METHOD: @@ -108,12 +110,15 @@ public CompletableFuture run(WebSocket ws, Jso case GetSetupProtocolDataRequest.METHOD: result = this.handleGetSetupProtocolDataRequest(user, GetSetupProtocolDataRequest.from(request)); break; - case SendLogMessageRequest.METHOD: - result = this.handleSendLogMessageRequest(user, SendLogMessageRequest.from(request)); - break; case SubscribeEdgesRequest.METHOD: result = this.handleSubscribeEdgesRequest(wsData, SubscribeEdgesRequest.from(request)); break; + case GetEdgesRequest.METHOD: + result = this.handleGetEdgesRequest(user, GetEdgesRequest.from(request)); + break; + case GetEdgeRequest.METHOD: + result = this.handleGetEdgeRequest(user, GetEdgeRequest.from(request)); + break; } if (result != null) { @@ -205,29 +210,6 @@ private CompletableFuture handleLogoutRequest(WsData wsD return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(request.getId())); } - /** - * Gets the authenticated User or throws an Exception if User is not - * authenticated. - * - * @param wsData the WebSocket attachment - * @param request the JsonrpcRequest - * @return the {@link User} - * @throws OpenemsNamedException if User is not authenticated - */ - private User assertUser(WsData wsData, JsonrpcRequest request) throws OpenemsNamedException { - var userIdOpt = wsData.getUserId(); - if (!userIdOpt.isPresent()) { - throw OpenemsError.COMMON_USER_NOT_AUTHENTICATED - .exception("User-ID is empty. Ignoring request [" + request.getMethod() + "]"); - } - var userOpt = this.parent.metadata.getUser(userIdOpt.get()); - if (!userOpt.isPresent()) { - throw OpenemsError.COMMON_USER_NOT_AUTHENTICATED.exception("User with ID [" + userIdOpt.get() - + "] is unknown. Ignoring request [" + request.getMethod() + "]"); - } - return userOpt.get(); - } - /** * Handles an {@link EdgeRpcRequest}. * @@ -443,38 +425,6 @@ private CompletableFuture handleGetSetupProtocolD .completedFuture(new GenericJsonrpcResponseSuccess(request.getId(), latestProtocolJson)); } - /** - * Handles a {@link SendLogMessageRequest}. Logs given message from request. - * - * @param user the {@link User}r - * @param request the {@link SendLogMessageRequest} - * @return the JSON-RPC Success Response Future - */ - private CompletableFuture handleSendLogMessageRequest(User user, - SendLogMessageRequest request) { - var msg = "User [" + user.getId() + ":" + user.getName() + "] UI: " + request.getParams(); - - switch (request.getLevel()) { - case DEBUG: - this.log.debug(msg); - break; - case INFO: - this.log.info(msg); - break; - case WARNING: - this.log.warn(msg); - break; - case ERROR: - this.log.error(msg); - break; - default: - this.log.warn("Unable to log message with level [" + request.getLevel() + "]"); - break; - } - - return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(request.getId())); - } - /** * Handles a {@link GetUserAlertingConfigsRequest}. * @@ -527,4 +477,70 @@ private CompletableFuture handleSetUserAlertin return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(request.getId())); } + /** + * Handles a {@link GetEdgesRequest}. + * + * @param user {@User} who called the request + * @param request the {@link GetEdgesRequest} + * @return the {@link GetEdgesResponse} Future + * @throws OpenemsNamedException on error + */ + private CompletableFuture handleGetEdgesRequest(// + final User user, // + final GetEdgesRequest request // + ) throws OpenemsNamedException { + var devices = this.parent.metadata.getPageDevice(user, request.getPaginationOptions()); + + List edgeMetadata = new ArrayList<>(); + for (var device : devices.entrySet()) { + var edgeOpt = this.parent.metadata.getEdge(device.getKey()); + if (edgeOpt.isPresent()) { + var cachedEdge = edgeOpt.get(); + edgeMetadata.add(new EdgeMetadata(// + cachedEdge.getId(), // Edge-ID + cachedEdge.getComment(), // Comment + cachedEdge.getProducttype(), // Product-Type + cachedEdge.getVersion(), // Version + device.getValue(), // Role + cachedEdge.isOnline(), // Online-State + cachedEdge.getLastmessage() // Last-Message Timestamp + )); + } + } + + return CompletableFuture // + .completedFuture(new GetEdgesResponse(request.getId(), edgeMetadata)); + } + + /** + * Handles a {@link GetEdgeRequest}. + * + * @param user {@User} who called the request + * @param request the {@link GetEdgeRequest} + * @return the {@link GetEdgeResponse} Future + * @throws OpenemsNamedException on error + */ + private CompletableFuture handleGetEdgeRequest(// + final User user, // + final GetEdgeRequest request // + ) throws OpenemsNamedException { + var edge = this.parent.metadata.getEdge(request.edgeId) + .orElseThrow(() -> new OpenemsException("Unable to find edge with id [" + request.edgeId + "]")); + + var role = this.parent.metadata.getRoleForEdge(user, request.edgeId); + + var edgeMetdata = new EdgeMetadata(// + edge.getId(), // Edge-ID + edge.getComment(), // Comment + edge.getProducttype(), // Product-Type + edge.getVersion(), // Version + role, // Role + edge.isOnline(), // Online-State + edge.getLastmessage() // Last-Message Timestamp + ); + + return CompletableFuture // + .completedFuture(new GetEdgeResponse(request.getId(), edgeMetdata)); + } + } diff --git a/io.openems.backend.uiwebsocket/src/io/openems/backend/uiwebsocket/impl/UiWebsocketImpl.java b/io.openems.backend.uiwebsocket/src/io/openems/backend/uiwebsocket/impl/UiWebsocketImpl.java index 9a19397a9e6..89afe0e1257 100644 --- a/io.openems.backend.uiwebsocket/src/io/openems/backend/uiwebsocket/impl/UiWebsocketImpl.java +++ b/io.openems.backend.uiwebsocket/src/io/openems/backend/uiwebsocket/impl/UiWebsocketImpl.java @@ -22,10 +22,12 @@ import io.openems.backend.common.edgewebsocket.EdgeWebsocket; import io.openems.backend.common.jsonrpc.JsonRpcRequestHandler; import io.openems.backend.common.metadata.Metadata; -import io.openems.backend.common.timedata.Timedata; +import io.openems.backend.common.metadata.User; +import io.openems.backend.common.timedata.TimedataManager; import io.openems.backend.common.uiwebsocket.UiWebsocket; import io.openems.common.exceptions.OpenemsError; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.AbstractJsonrpcRequest; import io.openems.common.jsonrpc.base.JsonrpcNotification; import io.openems.common.jsonrpc.base.JsonrpcRequest; import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; @@ -57,7 +59,7 @@ public class UiWebsocketImpl extends AbstractOpenemsBackendComponent implements protected volatile EdgeWebsocket edgeWebsocket; @Reference - protected volatile Timedata timeData; + protected volatile TimedataManager timedataManager; public UiWebsocketImpl() { super("Ui.Websocket"); @@ -217,4 +219,26 @@ public void sendSubscribedChannels(String edgeId, EdgeCache edgeCache) { } } + /** + * Gets the authenticated User or throws an Exception if User is not + * authenticated. + * + * @param wsData the WebSocket attachment + * @param request the {@link AbstractJsonrpcRequest} + * @return the {@link User} + * @throws OpenemsNamedException if User is not authenticated + */ + public User assertUser(WsData wsData, AbstractJsonrpcRequest request) throws OpenemsNamedException { + var userIdOpt = wsData.getUserId(); + if (!userIdOpt.isPresent()) { + throw OpenemsError.COMMON_USER_NOT_AUTHENTICATED + .exception("User-ID is empty. Ignoring request [" + request.getMethod() + "]"); + } + var userOpt = this.metadata.getUser(userIdOpt.get()); + if (!userOpt.isPresent()) { + throw OpenemsError.COMMON_USER_NOT_AUTHENTICATED.exception("User with ID [" + userIdOpt.get() + + "] is unknown. Ignoring request [" + request.getMethod() + "]"); + } + return userOpt.get(); + } } diff --git a/io.openems.backend.uiwebsocket/src/io/openems/backend/uiwebsocket/jsonrpc/notification/LogMessageNotification.java b/io.openems.backend.uiwebsocket/src/io/openems/backend/uiwebsocket/jsonrpc/notification/LogMessageNotification.java new file mode 100644 index 00000000000..2e3b8808d8b --- /dev/null +++ b/io.openems.backend.uiwebsocket/src/io/openems/backend/uiwebsocket/jsonrpc/notification/LogMessageNotification.java @@ -0,0 +1,70 @@ +package io.openems.backend.uiwebsocket.jsonrpc.notification; + +import java.lang.System.Logger.Level; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcNotification; +import io.openems.common.utils.JsonUtils; + +/** + * Log message. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": UUID,
      + *   "method": "logMessage",
      + *   "params": {
      + *     "level": string,
      + *     "msg": string
      + *   }
      + * }
      + * 
      + */ +public class LogMessageNotification extends JsonrpcNotification { + + public static final String METHOD = "logMessage"; + + /** + * The log level as {@link Level}. + */ + public final Level level; + + /** + * The log message. + */ + public final String msg; + + /** + * Create {@link LogMessageNotification} from a template + * {@link JsonrpcNotification}. + * + * @param notification the template {@link JsonrpcNotification} + * @return Created {@link LogMessageNotification} + * @throws OpenemsNamedException on parse error + */ + public static LogMessageNotification from(JsonrpcNotification notification) throws OpenemsNamedException { + var params = notification.getParams(); + var level = Level.valueOf(JsonUtils.getAsString(params, "level").toUpperCase()); + var msg = JsonUtils.getAsString(params, "msg"); + return new LogMessageNotification(notification, level, msg); + } + + private LogMessageNotification(JsonrpcNotification notification, Level level, String msg) + throws OpenemsNamedException { + super(LogMessageNotification.METHOD); + this.level = level; + this.msg = msg; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("level", this.level.getName()) // + .addProperty("msg", this.msg) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AuthenticatedRpcRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AuthenticatedRpcRequest.java index 63ef29ae703..2f7701a9a63 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/request/AuthenticatedRpcRequest.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AuthenticatedRpcRequest.java @@ -122,6 +122,7 @@ public JsonObject getParams() { .add("user", JsonUtils.buildJsonObject() // .addProperty("id", this.user.getId()) // .addProperty("name", this.user.getName()) // + .addPropertyIfNotNull("language", this.user.getLanguage()) // .add("role", role.asJson()) // .build()) // .add("payload", this.payload.toJsonObject()) // diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/GetEdgeRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/GetEdgeRequest.java new file mode 100644 index 00000000000..0f6563040af --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/GetEdgeRequest.java @@ -0,0 +1,54 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * JSON-RPC Request for getting a edge. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getEdge",
      + *   "params": {
      + *     "edgeId": string
      + *   }
      + * }
      + * 
      + */ +public class GetEdgeRequest extends JsonrpcRequest { + + /** + * Creates a {@link GetEdgeRequest} from a {@link JsonrpcRequest}. + * + * @param request the {@link JsonrpcRequest} + * @return the {@link GetEdgeRequest} + * @throws OpenemsNamedException on parse error + */ + public static GetEdgeRequest from(JsonrpcRequest request) throws OpenemsNamedException { + var params = request.getParams(); + var edgeId = JsonUtils.getAsString(params, "edgeId"); + return new GetEdgeRequest(request, edgeId); + } + + public static final String METHOD = "getEdge"; + + public final String edgeId; + + protected GetEdgeRequest(JsonrpcRequest request, String edgeId) { + super(request, METHOD); + this.edgeId = edgeId; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("edgeId", this.edgeId)// + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/GetEdgesRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/GetEdgesRequest.java new file mode 100644 index 00000000000..5ce24aa488d --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/GetEdgesRequest.java @@ -0,0 +1,116 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * JSON-RPC Request for getting a edges with a {@link PaginationOptions}. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getEdges",
      + *   "params": {
      + *     "edgeId": string
      + *   }
      + * }
      + * 
      + */ +public class GetEdgesRequest extends JsonrpcRequest { + + public static class PaginationOptions { + private static final int MAX_LIMIT = 100; + private static final int DEFAULT_LIMIT = 20; + + private final int page; + private final int limit; + private final String query; + + /** + * Creates a {@link PaginationOptions} from a {@link JsonObject}. + * + * @param params the {@link JsonObject} + * @return the {@link PaginationOptions} + * @throws OpenemsNamedException on parse error + */ + public static PaginationOptions from(JsonObject params) throws OpenemsNamedException { + var page = JsonUtils.getAsInt(params, "page"); + var limit = JsonUtils.getAsOptionalInt(params, "limit").orElse(DEFAULT_LIMIT); + if (limit <= 0 || limit > MAX_LIMIT) { + throw new OpenemsException("Limit is not in range [1:" + MAX_LIMIT + "]"); + } + var query = JsonUtils.getAsOptionalString(params, "query").orElse(null); + return new PaginationOptions(page, limit, query); + } + + private PaginationOptions(int page, int limit, String query) { + this.page = page; + this.limit = limit; + this.query = query; + } + + public int getPage() { + return this.page; + } + + public int getLimit() { + return this.limit; + } + + public String getQuery() { + return this.query; + } + + /** + * Returns {@link JsonObject} from current {@link PaginationOptions}. + * + * @return {@link JsonObject} from {@link PaginationOptions} + */ + public JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .addProperty("page", this.page) // + .addProperty("limit", this.limit) // + .addPropertyIfNotNull("query", this.query) // + .build(); + } + } + + /** + * Creates a {@link GetEdgesRequest} from a {@link JsonrpcRequest}. + * + * @param request the {@link JsonrpcRequest} + * @return the {@link GetEdgesRequest} + * @throws OpenemsNamedException on parse error + */ + public static GetEdgesRequest from(JsonrpcRequest request) throws OpenemsNamedException { + var params = request.getParams(); + var paginationOptions = PaginationOptions.from(params); + return new GetEdgesRequest(request, paginationOptions); + } + + public static final String METHOD = "getEdges"; + + private final PaginationOptions paginationOptions; + + protected GetEdgesRequest(JsonrpcRequest request, PaginationOptions paginationOptions) { + super(request, METHOD); + this.paginationOptions = paginationOptions; + } + + public PaginationOptions getPaginationOptions() { + return this.paginationOptions; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .add("pagination", this.paginationOptions.toJsonObject()) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/AuthenticateResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/AuthenticateResponse.java index 36fa1f4b45f..3a54d9a3f4d 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/response/AuthenticateResponse.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/AuthenticateResponse.java @@ -1,20 +1,17 @@ package io.openems.common.jsonrpc.response; -import java.time.ZonedDateTime; -import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.UUID; -import com.google.gson.JsonArray; import com.google.gson.JsonObject; import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; import io.openems.common.jsonrpc.request.AuthenticateWithPasswordRequest; import io.openems.common.jsonrpc.request.AuthenticateWithTokenRequest; +import io.openems.common.jsonrpc.response.GetEdgesResponse.EdgeMetadata; import io.openems.common.session.AbstractUser; import io.openems.common.session.Language; -import io.openems.common.session.Role; -import io.openems.common.types.SemanticVersion; import io.openems.common.utils.JsonUtils; /** @@ -28,77 +25,22 @@ * "result": { * "token": String, * "user": {@link AbstractUser#toJsonObject()} - * "edges": {@link EdgeMetadata#toJson(java.util.Collection)} * } * } * */ public class AuthenticateResponse extends JsonrpcResponseSuccess { - public static class EdgeMetadata { - - /** - * Converts a collection of EdgeMetadatas to a JsonArray. - * - *
      -		 * [{
      -		 *   "id": String,
      -		 *   "comment": String,
      -		 *   "producttype": String,
      -		 *   "version": String,
      -		 *   "role": "admin" | "installer" | "owner" | "guest",
      -		 *   "isOnline": boolean
      -		 * }]
      -		 * 
      - * - * @param metadatas the EdgeMetadatas - * @return a JsonArray - */ - public static JsonArray toJson(Collection metadatas) { - var result = new JsonArray(); - for (EdgeMetadata metadata : metadatas) { - result.add(metadata.toJsonObject()); - } - return result; - } - - private final String id; - private final String comment; - private final String producttype; - private final SemanticVersion version; - private final Role role; - private final boolean isOnline; - private final ZonedDateTime lastmessage; - - public EdgeMetadata(String id, String comment, String producttype, SemanticVersion version, Role role, - boolean isOnline, ZonedDateTime lastmessage) { - this.id = id; - this.comment = comment; - this.producttype = producttype; - this.version = version; - this.role = role; - this.isOnline = isOnline; - this.lastmessage = lastmessage; - } - - protected JsonObject toJsonObject() { - return JsonUtils.buildJsonObject() // - .addProperty("id", this.id) // - .addProperty("comment", this.comment) // - .addProperty("producttype", this.producttype) // - .addProperty("version", this.version.toString()) // - .add("role", this.role.asJson()) // - .addProperty("isOnline", this.isOnline) // - .addPropertyIfNotNull("lastmessage", this.lastmessage) // - .build(); - } - } - private final String token; private final AbstractUser user; private final List edges; private final Language language; + public AuthenticateResponse(UUID id, String token, AbstractUser user, Language language) { + this(id, token, user, Collections.emptyList(), language); + } + + // TODO: remove after UI is updated to new version public AuthenticateResponse(UUID id, String token, AbstractUser user, List edges, Language language) { super(id); this.token = token; diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/GetEdgeResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/GetEdgeResponse.java new file mode 100644 index 00000000000..b3460f96989 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/GetEdgeResponse.java @@ -0,0 +1,41 @@ +package io.openems.common.jsonrpc.response; + +import java.util.UUID; + +import com.google.gson.JsonObject; + +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.jsonrpc.request.GetEdgeRequest; +import io.openems.common.jsonrpc.response.GetEdgesResponse.EdgeMetadata; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Response for {@link GetEdgeRequest}. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *     "edge": {@link EdgeMetadata}
      + *   }
      + * }
      + * 
      + */ +public class GetEdgeResponse extends JsonrpcResponseSuccess { + + private final EdgeMetadata edgeMetadata; + + public GetEdgeResponse(UUID id, EdgeMetadata edgeMetadata) { + super(id); + this.edgeMetadata = edgeMetadata; + } + + @Override + public JsonObject getResult() { + return JsonUtils.buildJsonObject() // + .add("edge", this.edgeMetadata.toJsonObject()) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/GetEdgesResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/GetEdgesResponse.java new file mode 100644 index 00000000000..ff067adb6db --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/GetEdgesResponse.java @@ -0,0 +1,105 @@ +package io.openems.common.jsonrpc.response; + +import java.time.ZonedDateTime; +import java.util.List; +import java.util.UUID; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.jsonrpc.request.GetEdgesRequest; +import io.openems.common.session.Role; +import io.openems.common.types.SemanticVersion; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Response for {@link GetEdgesRequest}. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *     "edges": {@link EdgeMetadata}[]
      + *   }
      + * }
      + * 
      + */ +public class GetEdgesResponse extends JsonrpcResponseSuccess { + + public static class EdgeMetadata { + + /** + * Converts a collection of EdgeMetadatas to a JsonArray. + * + *
      +		 * [{
      +		 *   "id": String,
      +		 *   "comment": String,
      +		 *   "producttype": String,
      +		 *   "version": String,
      +		 *   "role": {@link Role},
      +		 *   "isOnline": boolean,
      +		 *   "lastmessage": ZonedDateTime
      +		 * }]
      +		 * 
      + * + * @param metadatas the EdgeMetadatas + * @return a JsonArray + */ + public static JsonArray toJson(List metadatas) { + var result = new JsonArray(); + for (EdgeMetadata metadata : metadatas) { + result.add(metadata.toJsonObject()); + } + return result; + } + + private final String id; + private final String comment; + private final String producttype; + private final SemanticVersion version; + private final Role role; + private final boolean isOnline; + private final ZonedDateTime lastmessage; + + public EdgeMetadata(String id, String comment, String producttype, SemanticVersion version, Role role, + boolean isOnline, ZonedDateTime lastmessage) { + this.id = id; + this.comment = comment; + this.producttype = producttype; + this.version = version; + this.role = role; + this.isOnline = isOnline; + this.lastmessage = lastmessage; + } + + protected JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .addProperty("id", this.id) // + .addProperty("comment", this.comment) // + .addProperty("producttype", this.producttype) // + .addProperty("version", this.version.toString()) // + .add("role", this.role.asJson()) // + .addProperty("isOnline", this.isOnline) // + .addPropertyIfNotNull("lastmessage", this.lastmessage) // + .build(); + } + } + + private final List edgeMetadata; + + public GetEdgesResponse(UUID id, List edgeMetadata) { + super(id); + this.edgeMetadata = edgeMetadata; + } + + @Override + public JsonObject getResult() { + return JsonUtils.buildJsonObject() // + .add("edges", EdgeMetadata.toJson(this.edgeMetadata)) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/utils/StringUtils.java b/io.openems.common/src/io/openems/common/utils/StringUtils.java index 30ad84cd1e9..a63b0863e8f 100644 --- a/io.openems.common/src/io/openems/common/utils/StringUtils.java +++ b/io.openems.common/src/io/openems/common/utils/StringUtils.java @@ -115,4 +115,27 @@ public static boolean matchesIntegerPattern(String string) { public static boolean matchesFloatPattern(String string) { return DETECT_FLOAT_PATTERN.test(string); } + + /** + * Causes this character sequence to be replaced by the reverse of the sequence. + * + * @param string to be reversed. + * @return reversed String. + */ + public static String reverse(String string) { + return new StringBuilder(string).reverse().toString(); + } + + /** + * If the given string is null return false, otherwise result of + * {@link String#contains(CharSequence)} is returned. + * + * @param string the string to check + * @param value the sequence to search for + * @return true if string is not null and string contains value, otherwise false + */ + public static boolean containsWithNullCheck(String string, String value) { + return string != null && string.contains(value); + } + } diff --git a/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/OnRequest.java b/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/OnRequest.java index 81bab721376..5d73f205c9c 100644 --- a/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/OnRequest.java +++ b/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/OnRequest.java @@ -1,5 +1,6 @@ package io.openems.edge.controller.api.websocket; +import java.time.ZonedDateTime; import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -11,6 +12,7 @@ import com.google.gson.JsonElement; +import io.openems.common.OpenemsConstants; import io.openems.common.exceptions.OpenemsError; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; @@ -24,17 +26,25 @@ import io.openems.common.jsonrpc.request.DeleteComponentConfigRequest; import io.openems.common.jsonrpc.request.EdgeRpcRequest; import io.openems.common.jsonrpc.request.GetEdgeConfigRequest; +import io.openems.common.jsonrpc.request.GetEdgeRequest; +import io.openems.common.jsonrpc.request.GetEdgesRequest; import io.openems.common.jsonrpc.request.LogoutRequest; import io.openems.common.jsonrpc.request.QueryHistoricTimeseriesDataRequest; +import io.openems.common.jsonrpc.request.QueryHistoricTimeseriesEnergyPerPeriodRequest; import io.openems.common.jsonrpc.request.QueryHistoricTimeseriesEnergyRequest; import io.openems.common.jsonrpc.request.QueryHistoricTimeseriesExportXlxsRequest; import io.openems.common.jsonrpc.request.SetChannelValueRequest; import io.openems.common.jsonrpc.request.SubscribeChannelsRequest; +import io.openems.common.jsonrpc.request.SubscribeEdgesRequest; import io.openems.common.jsonrpc.request.SubscribeSystemLogRequest; import io.openems.common.jsonrpc.request.UpdateComponentConfigRequest; import io.openems.common.jsonrpc.response.AuthenticateResponse; import io.openems.common.jsonrpc.response.EdgeRpcResponse; +import io.openems.common.jsonrpc.response.GetEdgeResponse; +import io.openems.common.jsonrpc.response.GetEdgesResponse; +import io.openems.common.jsonrpc.response.GetEdgesResponse.EdgeMetadata; import io.openems.common.jsonrpc.response.QueryHistoricTimeseriesDataResponse; +import io.openems.common.jsonrpc.response.QueryHistoricTimeseriesEnergyPerPeriodResponse; import io.openems.common.jsonrpc.response.QueryHistoricTimeseriesEnergyResponse; import io.openems.common.session.Language; import io.openems.common.session.Role; @@ -78,6 +88,15 @@ public CompletableFuture run(WebSocket ws, Jso case EdgeRpcRequest.METHOD: return this.handleEdgeRpcRequest(wsData, user, EdgeRpcRequest.from(request)); + case GetEdgesRequest.METHOD: + return this.handleGetEdgesRequest(user, GetEdgesRequest.from(request)); + + case GetEdgeRequest.METHOD: + return this.handleGetEdgeRequest(user, GetEdgeRequest.from(request)); + + case SubscribeEdgesRequest.METHOD: + return this.handleSubscribeEdgesReqeust(user, SubscribeEdgesRequest.from(request)); + default: this.parent.logWarn(this.log, "Unhandled Request: " + request); throw OpenemsError.JSONRPC_UNHANDLED_METHOD.exception(request.getMethod()); @@ -132,6 +151,11 @@ private CompletableFuture handleEdgeRpcRequest(WsData wsData, U resultFuture = this.handleQueryHistoricEnergyRequest(QueryHistoricTimeseriesEnergyRequest.from(request)); break; + case QueryHistoricTimeseriesEnergyPerPeriodRequest.METHOD: + resultFuture = this.handleQueryHistoricEnergyPerPeriodRequest( + QueryHistoricTimeseriesEnergyPerPeriodRequest.from(request)); + break; + case QueryHistoricTimeseriesExportXlxsRequest.METHOD: resultFuture = this.handleQueryHistoricTimeseriesExportXlxsRequest(user, QueryHistoricTimeseriesExportXlxsRequest.from(request)); @@ -291,6 +315,23 @@ private CompletableFuture handleQueryHistoricEnergyReque return CompletableFuture.completedFuture(new QueryHistoricTimeseriesEnergyResponse(request.getId(), data)); } + /** + * Handles a {@link QueryHistoricTimeseriesEnergyPerPeriodRequest}. + * + * @param request the {@link QueryHistoricTimeseriesEnergyPerPeriodRequest} + * @return the Future JSON-RPC Response + * @throws OpenemsNamedException on error + */ + private CompletableFuture handleQueryHistoricEnergyPerPeriodRequest( + QueryHistoricTimeseriesEnergyPerPeriodRequest request) throws OpenemsNamedException { + var data = this.parent.getTimedata().queryHistoricEnergyPerPeriod(// + null, /* ignore Edge-ID */ + request.getFromDate(), request.getToDate(), request.getChannels(), request.getResolution()); + + return CompletableFuture + .completedFuture(new QueryHistoricTimeseriesEnergyPerPeriodResponse(request.getId(), data)); + } + /** * Handles a {@link QueryHistoricTimeseriesExportXlxsRequest}. * @@ -455,4 +496,52 @@ private CompletableFuture handleSubscribeSystemLogReques return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(request.getId())); } + /** + * Handles a {@link GetEdgesRequest}. + * + * @param user the {@link User} + * @param request the {@link GetEdgesRequest} + * @return the {@link GetEdgesResponse} Response Future + * @throws OpenemsNamedException on error + */ + private CompletableFuture handleGetEdgesRequest(User user, GetEdgesRequest request) { + return CompletableFuture.completedFuture(// + new GetEdgesResponse(request.getId(), Utils.getEdgeMetadata(user.getGlobalRole()))); + } + + /** + * Handles a {@link GetEdgeRequest}. + * + * @param user the {@link User} + * @param request the {@link GetEdgeRequest} + * @return the {@link GetEdgeResponse} Response Future + */ + private CompletableFuture handleGetEdgeRequest(User user, GetEdgeRequest request) { + return CompletableFuture.completedFuture(// + new GetEdgeResponse(request.id, // + new EdgeMetadata(// + WebsocketApi.EDGE_ID, // + WebsocketApi.EDGE_COMMENT, // + WebsocketApi.EDGE_PRODUCT_TYPE, // + OpenemsConstants.VERSION, // + user.getGlobalRole(), // + true, // + ZonedDateTime.now() // + ) // + ) // + ); + } + + /** + * Handles a {@link SubscribeEdgesRequest}. + * + * @param user the {@link User} + * @param request the {@link SubscribeEdgesRequest} + * @return the Response Future + */ + private CompletableFuture handleSubscribeEdgesReqeust(User user, + SubscribeEdgesRequest request) { + return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(request.getId())); + } + } diff --git a/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/Utils.java b/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/Utils.java index f6c9b51b0d5..1378fc9b5b9 100644 --- a/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/Utils.java +++ b/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/Utils.java @@ -6,10 +6,11 @@ import com.google.common.collect.Lists; import io.openems.common.OpenemsConstants; -import io.openems.common.jsonrpc.response.AuthenticateResponse.EdgeMetadata; +import io.openems.common.jsonrpc.response.GetEdgesResponse.EdgeMetadata; import io.openems.common.session.Role; public class Utils { + /** * Gets the EdgeMetadata for one Edge. * @@ -27,4 +28,5 @@ public static List getEdgeMetadata(Role role) { ZonedDateTime.now() // now )); } + } diff --git a/io.openems.edge.evcs.dezony/generated/buildfiles b/io.openems.edge.evcs.dezony/generated/buildfiles new file mode 100644 index 00000000000..796b599e33d --- /dev/null +++ b/io.openems.edge.evcs.dezony/generated/buildfiles @@ -0,0 +1 @@ +C:/Users/stefan.feilmeier/fems/develop/io.openems.edge.evcs.dezony/generated/io.openems.edge.evcs.dezony.jar diff --git a/ui/angular.json b/ui/angular.json index 2a9b23a3891..5d950ca4654 100644 --- a/ui/angular.json +++ b/ui/angular.json @@ -46,7 +46,8 @@ "extractLicenses": true, "optimization": true, "outputHashing": "all", - "sourceMap": false + "sourceMap": false, + "serviceWorker": true }, "openems": { "assets": [ diff --git a/ui/package-lock.json b/ui/package-lock.json index 50b7450d8a9..c5945d3fe17 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -4615,12 +4615,12 @@ } }, "node_modules/adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", "dev": true, "engines": { - "node": ">=0.3.0" + "node": ">=6.0" } }, "node_modules/agent-base": { @@ -14832,11 +14832,12 @@ } }, "node_modules/webdriver-manager": { - "version": "12.1.8", + "version": "12.1.9", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", + "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", "dev": true, - "license": "MIT", "dependencies": { - "adm-zip": "^0.4.9", + "adm-zip": "^0.5.2", "chalk": "^1.1.1", "del": "^2.2.0", "glob": "^7.0.3", @@ -18652,9 +18653,9 @@ } }, "adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", "dev": true }, "agent-base": { @@ -25959,10 +25960,12 @@ } }, "webdriver-manager": { - "version": "12.1.8", + "version": "12.1.9", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", + "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", "dev": true, "requires": { - "adm-zip": "^0.4.9", + "adm-zip": "^0.5.2", "chalk": "^1.1.1", "del": "^2.2.0", "glob": "^7.0.3", diff --git a/ui/package.json b/ui/package.json index 933576338c8..c1b5d782ed2 100644 --- a/ui/package.json +++ b/ui/package.json @@ -70,4 +70,4 @@ "lint": "ng lint", "test": "ng test" } -} \ No newline at end of file +} diff --git a/ui/src/app/app-routing.module.ts b/ui/src/app/app-routing.module.ts index 6b120bc2671..5c1efaa91e4 100644 --- a/ui/src/app/app-routing.module.ts +++ b/ui/src/app/app-routing.module.ts @@ -38,54 +38,68 @@ import { SystemLogComponent as EdgeSettingsSystemLogComponent } from './edge/set import { SystemUpdateComponent as EdgeSettingsSystemUpdateComponent } from './edge/settings/systemupdate/systemupdate.component'; import { IndexComponent } from './index/index.component'; import { UserComponent } from './user/user.component'; +import { EdgeComponent } from './edge/edge.component'; +import { HistoryParentComponent } from './edge/history/historyparent.component'; +import { ChangelogViewComponent } from './changelog/view/view'; const routes: Routes = [ { path: '', redirectTo: 'index', pathMatch: 'full' }, { path: 'index', component: IndexComponent }, { path: 'user', component: UserComponent }, + { path: 'changelog', component: ChangelogViewComponent }, // Edge Pages - { path: 'device/:edgeId', redirectTo: 'device/:edgeId/live', pathMatch: 'full' }, - { path: 'device/:edgeId/live', component: EdgeLiveComponent }, - { path: 'device/:edgeId/history', component: EdgeHistoryComponent }, + { + path: 'device/:edgeId', component: EdgeComponent, children: [ + { path: '', redirectTo: 'live', pathMatch: 'full' }, + { path: 'live', component: EdgeLiveComponent }, + { + path: 'history', component: HistoryParentComponent, children: [ + { path: '', component: EdgeHistoryComponent }, + // History Chart Pages + { path: ':componentId/asymmetricpeakshavingchart', component: AsymmetricPeakshavingChartOverviewComponent }, + { path: ':componentId/channelthresholdchart', component: ChannelthresholdChartOverviewComponent }, + { path: ':componentId/delayedselltogridchart', component: DelayedSellToGridChartOverviewComponent }, + { path: ':componentId/fixdigitaloutputchart', component: FixDigitalOutputChartOverviewComponent }, + { path: ':componentId/gridOptimizedChargeChart', component: GridOptimizedChargeChartOverviewComponent }, + { path: ':componentId/heatingelementchart', component: HeatingelementChartOverviewComponent }, + { path: ':componentId/heatpumpchart', component: HeatPumpChartOverviewComponent }, + { path: ':componentId/singlethresholdchart', component: SinglethresholdChartOverviewComponent }, + { path: ':componentId/symmetricpeakshavingchart', component: SymmetricPeakshavingChartOverviewComponent }, + { path: ':componentId/timeslotpeakshavingchart', component: TimeslotPeakshavingChartOverviewComponent }, + { path: ':componentId/timeOfUseTariffDischargeChart', component: TimeOfUseTariffDischargeChartOverviewComponent }, + { path: 'autarchychart', component: AutarchyChartOverviewComponent }, + { path: 'consumptionchart', component: ConsumptionChartOverviewComponent }, + { path: 'gridchart', component: GridChartOverviewComponent }, + { path: 'productionchart', component: ProductionChartOverviewComponent }, + { path: 'selfconsumptionchart', component: SelfconsumptionChartOverviewComponent }, + { path: 'storagechart', component: StorageChartOverviewComponent }, + ] + }, - // History Chart Pages - { path: 'device/:edgeId/history/:componentId/asymmetricpeakshavingchart', component: AsymmetricPeakshavingChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/channelthresholdchart', component: ChannelthresholdChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/delayedselltogridchart', component: DelayedSellToGridChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/fixdigitaloutputchart', component: FixDigitalOutputChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/gridOptimizedChargeChart', component: GridOptimizedChargeChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/heatingelementchart', component: HeatingelementChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/heatpumpchart', component: HeatPumpChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/singlethresholdchart', component: SinglethresholdChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/symmetricpeakshavingchart', component: SymmetricPeakshavingChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/timeslotpeakshavingchart', component: TimeslotPeakshavingChartOverviewComponent }, - { path: 'device/:edgeId/history/:componentId/timeOfUseTariffDischargeChart', component: TimeOfUseTariffDischargeChartOverviewComponent }, - { path: 'device/:edgeId/history/autarchychart', component: AutarchyChartOverviewComponent }, - { path: 'device/:edgeId/history/consumptionchart', component: ConsumptionChartOverviewComponent }, - { path: 'device/:edgeId/history/gridchart', component: GridChartOverviewComponent }, - { path: 'device/:edgeId/history/productionchart', component: ProductionChartOverviewComponent }, - { path: 'device/:edgeId/history/selfconsumptionchart', component: SelfconsumptionChartOverviewComponent }, - { path: 'device/:edgeId/history/storagechart', component: StorageChartOverviewComponent }, + { path: 'settings', component: EdgeSettingsComponent }, + { path: 'settings/channels', component: EdgeSettingsChannelsComponent }, + { path: 'settings/component.install', component: EdgeSettingsComponentInstallIndexComponentComponent }, + { path: 'settings/component.install/:factoryId', component: EdgeSettingsComponentInstallComponentComponent }, + { path: 'settings/component.update', component: EdgeSettingsComponentUpdateIndexComponentComponent }, + { path: 'settings/component.update/:componentId', component: EdgeSettingsComponentUpdateComponentComponent }, + { path: 'settings/network', component: EdgeSettingsNetworkComponent }, + { path: 'settings/profile', component: EdgeSettingsProfileComponent }, + { path: 'settings/profile/:componentId', component: AliasUpdateComponent }, + { path: 'settings/systemexecute', component: EdgeSettingsSystemExecuteComponent }, + { path: 'settings/systemlog', component: EdgeSettingsSystemLogComponent }, + { path: 'settings/systemupdate', component: EdgeSettingsSystemUpdateComponent }, + { path: 'settings/app', component: EdgeSettingsAppIndex }, + { path: 'settings/app/install/:appId', component: EdgeSettingsAppInstall }, + { path: 'settings/app/update/:appId', component: EdgeSettingsAppUpdate }, + { path: 'settings/app/single/:appId', component: EdgeSettingsAppSingle }, + { path: 'settings/alerting', component: EdgeSettingsAlerting }, + ] + }, - { path: 'device/:edgeId/settings', component: EdgeSettingsComponent }, - { path: 'device/:edgeId/settings/channels', component: EdgeSettingsChannelsComponent }, - { path: 'device/:edgeId/settings/component.install', component: EdgeSettingsComponentInstallIndexComponentComponent }, - { path: 'device/:edgeId/settings/component.install/:factoryId', component: EdgeSettingsComponentInstallComponentComponent }, - { path: 'device/:edgeId/settings/component.update', component: EdgeSettingsComponentUpdateIndexComponentComponent }, - { path: 'device/:edgeId/settings/component.update/:componentId', component: EdgeSettingsComponentUpdateComponentComponent }, - { path: 'device/:edgeId/settings/network', component: EdgeSettingsNetworkComponent }, - { path: 'device/:edgeId/settings/profile', component: EdgeSettingsProfileComponent }, - { path: 'device/:edgeId/settings/profile/:componentId', component: AliasUpdateComponent }, - { path: 'device/:edgeId/settings/systemexecute', component: EdgeSettingsSystemExecuteComponent }, - { path: 'device/:edgeId/settings/systemlog', component: EdgeSettingsSystemLogComponent }, - { path: 'device/:edgeId/settings/systemupdate', component: EdgeSettingsSystemUpdateComponent }, - { path: 'device/:edgeId/settings/app', component: EdgeSettingsAppIndex }, - { path: 'device/:edgeId/settings/app/install/:appId', component: EdgeSettingsAppInstall }, - { path: 'device/:edgeId/settings/app/update/:appId', component: EdgeSettingsAppUpdate }, - { path: 'device/:edgeId/settings/app/single/:appId', component: EdgeSettingsAppSingle }, - { path: 'device/:edgeId/settings/alerting', component: EdgeSettingsAlerting }, + + { path: 'demo', component: IndexComponent } ]; export const appRoutingProviders: any[] = [ diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts index bcc48605244..471bff62184 100644 --- a/ui/src/app/app.component.ts +++ b/ui/src/app/app.component.ts @@ -1,11 +1,14 @@ import { HttpClient } from '@angular/common/http'; -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { ApplicationRef, Component, Injectable, OnDestroy, OnInit } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { Router } from '@angular/router'; +import { SwUpdate } from '@angular/service-worker'; import { MenuController, ModalController, Platform, ToastController } from '@ionic/angular'; -import { Subject, timer } from 'rxjs'; -import { retry, switchMap, takeUntil } from 'rxjs/operators'; +import { concat, interval, Subject, timer } from 'rxjs'; +import { first, retry, switchMap, takeUntil } from 'rxjs/operators'; + import { environment } from '../environments'; +import { CheckForUpdateService } from './appupdateservice'; import { Service, Websocket } from './shared/shared'; import { Language } from './shared/type/language'; @@ -29,9 +32,11 @@ export class AppComponent implements OnInit, OnDestroy { public service: Service, public toastController: ToastController, public websocket: Websocket, - private titleService: Title + private titleService: Title, + checkForUpdateService: CheckForUpdateService ) { service.setLang(Language.getByKey(localStorage.LANGUAGE) ?? Language.getByBrowserLang(navigator.language)); + checkForUpdateService.init(); } ngOnInit() { diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts index b083e2cbb53..9e12fea13ba 100644 --- a/ui/src/app/app.module.ts +++ b/ui/src/app/app.module.ts @@ -1,17 +1,22 @@ import { registerLocaleData } from '@angular/common'; import { HttpClientModule } from '@angular/common/http'; import localDE from '@angular/common/locales/de'; -import { LOCALE_ID, NgModule } from '@angular/core'; +import { ErrorHandler, LOCALE_ID, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { RouteReuseStrategy } from '@angular/router'; +import { ServiceWorkerModule } from '@angular/service-worker'; import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; import { FORMLY_CONFIG } from '@ngx-formly/core'; import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; import { AngularMyDatePickerModule } from 'angular-mydatepicker'; import { CookieService } from 'ngx-cookie-service'; +import { environment } from 'src/environments'; + import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; +import { CheckForUpdateService } from './appupdateservice'; +import { ChangelogModule } from './changelog/changelog.module'; import { EdgeModule } from './edge/edge.module'; import { SettingsModule as EdgeSettingsModule } from './edge/settings/settings.module'; import { SystemLogComponent } from './edge/settings/systemlog/systemlog.component'; @@ -19,6 +24,8 @@ import { IndexModule } from './index/index.module'; import { RegistrationModule } from './registration/registration.module'; import { ChartOptionsPopoverComponent } from './shared/chartoptions/popover/popover.component'; import { PickDatePopoverComponent } from './shared/pickdate/popover/popover.component'; +import { MyErrorHandler } from './shared/service/myerrorhandler'; +import { Pagination } from './shared/service/pagination'; import { SharedModule } from './shared/shared.module'; import { StatusSingleComponent } from './shared/status/single/status.component'; import { registerTranslateExtension } from './shared/translate.extension'; @@ -42,6 +49,7 @@ import { UserModule } from './user/user.module'; AppRoutingModule, BrowserAnimationsModule, BrowserModule, + ChangelogModule, EdgeModule, EdgeSettingsModule, IndexModule, @@ -50,15 +58,18 @@ import { UserModule } from './user/user.module'; SharedModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: MyTranslateLoader } }), UserModule, - RegistrationModule + RegistrationModule, + ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) ], providers: [ { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, CookieService, - // { provide: ErrorHandler, useExisting: Service }, + { provide: ErrorHandler, useClass: MyErrorHandler }, { provide: LOCALE_ID, useValue: Language.DEFAULT.key }, // Use factory for formly. This allows us to use translations in validationMessages. { provide: FORMLY_CONFIG, multi: true, useFactory: registerTranslateExtension, deps: [TranslateService] }, + Pagination, + CheckForUpdateService ], bootstrap: [AppComponent], }) diff --git a/ui/src/app/appupdateservice.ts b/ui/src/app/appupdateservice.ts new file mode 100644 index 00000000000..d743003cb84 --- /dev/null +++ b/ui/src/app/appupdateservice.ts @@ -0,0 +1,51 @@ +import { Injectable } from "@angular/core"; +import { SwUpdate } from "@angular/service-worker"; + +import { Service } from "./shared/shared"; + +@Injectable({ + providedIn: 'root', +}) +export class CheckForUpdateService { + + constructor(private update: SwUpdate, + private service: Service + ) { } + + init() { + let userId: string; + this.service.metadata.subscribe(entry => { + userId = entry?.user?.id ?? null; + }); + + setInterval(async () => { + const updateFound = await this.update.checkForUpdate(); + console.log(updateFound ? 'A new version is available.' : 'Already on the latest version.'); + + if (updateFound) { + window.location.reload() + } + }, 10000) + } +} +// Will be used in Future +@Injectable() +export class LogUpdateService { + + constructor(updates: SwUpdate) { + updates.versionUpdates.subscribe(evt => { + switch (evt.type) { + case 'VERSION_DETECTED': + console.log(`Downloading new app version: ${evt.version.hash}`); + break; + case 'VERSION_READY': + console.log(`Current app version: ${evt.currentVersion.hash}`); + console.log(`New app version ready for use: ${evt.latestVersion.hash}`); + break; + case 'VERSION_INSTALLATION_FAILED': + console.log(`Failed to install app version '${evt.version.hash}': ${evt.error}`); + break; + } + }); + } +} \ No newline at end of file diff --git a/ui/src/app/changelog/changelog.module.ts b/ui/src/app/changelog/changelog.module.ts new file mode 100644 index 00000000000..b5195439ffe --- /dev/null +++ b/ui/src/app/changelog/changelog.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { SharedModule } from './../shared/shared.module'; +import { ChangelogComponent } from './view/component/changelog.component'; +import { ChangelogViewComponent } from './view/view'; + +@NgModule({ + imports: [ + SharedModule + ], + declarations: [ + ChangelogComponent, + ChangelogViewComponent + ], + exports: [ + ChangelogComponent, + ChangelogViewComponent + ] +}) +export class ChangelogModule { } diff --git a/ui/src/app/changelog/view/component/changelog.component.html b/ui/src/app/changelog/view/component/changelog.component.html new file mode 100644 index 00000000000..6ca45e9aa89 --- /dev/null +++ b/ui/src/app/changelog/view/component/changelog.component.html @@ -0,0 +1,54 @@ + + + + + + + + Menu.changelog + + + + + + Version {{ changelog.version }} + + + +
        + + + + +
      • + + (Dieser Eintrag ist nur sichtbar für '{{ + numberToRole(change['roleIsAtLeast']) + }}') +
      • +
        +
        + + +
      • +
        +
        +
      +
      +
      +
      +
      + + + + Alle anzeigen + + + +
      +
      +
      +
      +
      \ No newline at end of file diff --git a/ui/src/app/changelog/view/component/changelog.component.ts b/ui/src/app/changelog/view/component/changelog.component.ts new file mode 100644 index 00000000000..3b842df183f --- /dev/null +++ b/ui/src/app/changelog/view/component/changelog.component.ts @@ -0,0 +1,46 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { environment } from 'src/environments'; +import { Service } from '../../../shared/shared'; +import { Role } from '../../../shared/type/role'; +import { Changelog, Library, OpenemsComponent, Product } from './changelog.constants'; + +@Component({ + selector: 'changelog', + templateUrl: './changelog.component.html' +}) +export class ChangelogComponent implements OnInit { + + public environment = environment; + + protected slice: number = 10; + protected showAll: boolean = false; + constructor( + public translate: TranslateService, + public service: Service, + private route: ActivatedRoute, + ) { } + + ngOnInit() { + this.service.setCurrentComponent({ languageKey: 'Menu.changelog' }, this.route); + } + + public readonly roleIsAtLeast = Role.isAtLeast; + public numberToRole(role: number): string { + return Role[role].toLowerCase(); + } + + public readonly changelogs: { + version: string, + changes: Array + }[] = [ + { + version: 'x.y.z', + changes: [ + Changelog.link("OpenEMS Releases", 'https://github.com/OpenEMS/openems/releases') + ] + } + ]; + +} \ No newline at end of file diff --git a/ui/src/app/changelog/view/component/changelog.constants.ts b/ui/src/app/changelog/view/component/changelog.constants.ts new file mode 100644 index 00000000000..19cf59867f7 --- /dev/null +++ b/ui/src/app/changelog/view/component/changelog.constants.ts @@ -0,0 +1,92 @@ +import { Role } from "src/app/shared/type/role"; +import { environment } from "src/environments"; + +export class Changelog { + + public static product(...products: Product[]) { + return products.map(product => Changelog.link(product.name, product.url)).join(", ") + '. '; + } + + public static openems(version: string) { + return 'Update auf OpenEMS Version ' + version + '. Mehr Details auf ' + Changelog.link('Github', 'https://github.com/OpenEMS/openems/releases/tag/' + version); + } + + public static openemsComponent(openemsComponent: OpenemsComponent, change: string) { + return { roleIsAtLeast: Role.ADMIN, change: Changelog.link(openemsComponent.name, openemsComponent.url) + ": " + change }; + } + + public static library(...libraries: Library[]) { + return 'Aktualisierung externer Programmbibliotheken: ' + libraries.map(library => library.name).join(", "); + } + + public static link(title: string, url: string) { + return '
      ' + title + ''; + } +} + +export class Product { + public static readonly OPENEMS_EDGE = new Product('OpenEMS Edge', 'https://github.com/OpenEMS/openems'); + public static readonly OPENEMS_UI = new Product('OpenEMS Edge', 'https://github.com/OpenEMS/openems'); + public static readonly OPENEMS_BACKEND = new Product('OpenEMS Edge', 'https://github.com/OpenEMS/openems'); + + // private to disallow creating other instances of this type + private constructor(public readonly name: string, public readonly url: any) { + } +} + +export class OpenemsComponent { + // private to disallow creating other instances of this type + private constructor(public readonly name: string, public readonly url: any) { + } +} + +export class Library { + // Java + public static readonly APACHE_FELIX_FILEINSTALL = new Library('Apache Felix File Install', 'org.apache.felix..fileinstall'); + public static readonly APACHE_FELIX_FRAMEWORK = new Library('Apache Felix Framework', 'org.apache.felix.framework'); + public static readonly APACHE_FELIX_HTTP_JETTY = new Library('Apache Felix HTTP Jetty', 'org.apache.felix.http.jetty'); + public static readonly APACHE_FELIX_INVENTORY = new Library('Apache Felix Inventory', 'org.apache.felix.inventory'); + public static readonly APACHE_FELIX_METATYPE = new Library('Apache Felix MetaType', 'org.apache.felix.metatype'); + public static readonly APACHE_FELIX_SCR = new Library('Apache Felix SCR', 'org.apache.felix.scr'); + public static readonly APACHE_FELIX_WEBCONSOLE = new Library('Apache Felix Webconsole', 'org.apache.felix.webconsole'); + public static readonly APACHE_FELIX_CONFIGADMIN = new Library('Apache Felix Configuration Admin', 'org.apache.felix.configadmin'); + public static readonly CHARGETIME_OCPP = new Library('Open Charge Alliance Java OCPP', 'eu.chargetime.ocpp'); // https://github.com/ChargeTimeEU/Java-OCA-OCPP + public static readonly ECLIPSE_OSGI = new Library('Eclipse OSGi', 'org.eclipse.osgi'); + public static readonly FASTEXCEL = new Library('fastexcel', 'fastexcel'); + public static readonly GRADLE = new Library('Gradle', 'gradle'); + public static readonly GUAVA = new Library('Guava', 'com.google.guava'); + public static readonly GSON = new Library('GSON', 'com.google.gson'); + public static readonly HIKARI_CP = new Library('HikariCP', 'hikaricp'); + public static readonly INFLUXDB = new Library('influxdb-java', 'influxdb-java'); + public static readonly JNA = new Library('JNA', 'net.java.dev.jna'); + public static readonly JAVA_WEBSOCKET = new Library('Java-WebSocket', 'org.java-websocket'); + public static readonly RETROFIT = new Library('Retrofit', 'com.squareup.retrofit'); + public static readonly MOSHI = new Library('Moshi', 'com.squareup.moshi'); + public static readonly MSGPACK = new Library('MsgPack', 'org.msgpack'); + public static readonly PAX_LOGGING = new Library('PAX Logging', 'org.ops4j.pax.logging'); + public static readonly OSGI_UTIL_FUNCTION = new Library('org.osgi.util.function', 'org.osgi.util.function'); + public static readonly OSGI_UTIL_PROMISE = new Library('org.osgi.util.promise', 'org.osgi.util.promise'); + public static readonly OSGI_SERVICE_JDBC = new Library('org.osgi.service.jdbc', 'org.osgi.service.jdbc'); + public static readonly POSTGRESQL = new Library('Postgresql', 'org.postgresql'); + public static readonly SLF4J = new Library('SLF4j', 'org.slf4j'); + public static readonly RRD4J = new Library('RRD4j', 'org.rrd4j'); + public static readonly OKHTTP = new Library('OkHttp', 'com.squareup.okhttp3'); + public static readonly OKIO = new Library('Okio', 'com.squareup.okio'); + + // UI + public static readonly ANGULAR = new Library('Angular', 'angular'); + public static readonly D3 = new Library('d3', 'd3'); + public static readonly DATE_FNS = new Library('date-fns', 'date-fns'); // https://date-fns.org/ + public static readonly IONIC = new Library('Ionic', 'ionic'); + public static readonly MYDATEPICKER = new Library('MyDatePicker', 'mydatepicker'); + public static readonly NG2_CHARTS = new Library('ng2-charts', 'ng2-charts'); + public static readonly NGX_COOKIE_SERVICE = new Library('ngx-cookie-service', 'ngx-cookie-service'); + public static readonly NGX_FORMLY = new Library('ngx-formly', 'ngx-formly'); + public static readonly NGX_SPINNER = new Library('ngx-spinner', 'ngx-spinner'); + public static readonly RXJS = new Library('RxJs', 'rxjs'); + public static readonly UUID = new Library('UUID', 'uuid'); + + // private to disallow creating other instances of this type + private constructor(public readonly name: string, public readonly url: string) { + } +} \ No newline at end of file diff --git a/ui/src/app/changelog/view/view.html b/ui/src/app/changelog/view/view.html new file mode 100644 index 00000000000..ee8a40dc029 --- /dev/null +++ b/ui/src/app/changelog/view/view.html @@ -0,0 +1,4 @@ +
      + + + \ No newline at end of file diff --git a/ui/src/app/changelog/view/view.ts b/ui/src/app/changelog/view/view.ts new file mode 100644 index 00000000000..0f7ca161a3e --- /dev/null +++ b/ui/src/app/changelog/view/view.ts @@ -0,0 +1,7 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: 'changelogViewComponent', + templateUrl: './view.html' +}) +export class ChangelogViewComponent { } \ No newline at end of file diff --git a/ui/src/app/edge/edge.component.ts b/ui/src/app/edge/edge.component.ts new file mode 100644 index 00000000000..e39ca65ddf6 --- /dev/null +++ b/ui/src/app/edge/edge.component.ts @@ -0,0 +1,53 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { SubscribeEdgesRequest } from "src/app/shared/jsonrpc/request/subscribeEdgesRequest"; +import { ChannelAddress, Edge, Service, Websocket } from "src/app/shared/shared"; + +/*** This component is needed as a routing parent and acts as a transit station without being displayed.*/ +@Component({ + selector: "edge", + template: ` + + + `, +}) +export class EdgeComponent implements OnInit, OnDestroy { + + private edge: Edge | null = null; + + constructor( + private router: Router, + private activatedRoute: ActivatedRoute, + private service: Service, + private websocket: Websocket + ) { } + + public ngOnInit(): void { + this.activatedRoute.params.subscribe((params) => { + + // Set CurrentEdge in Metadata + const edgeId = params['edgeId']; + this.service.updateCurrentEdge(edgeId).then((edge) => { + this.edge = edge; + this.service.websocket.sendRequest(new SubscribeEdgesRequest({ edges: [edgeId] })) + .then(() => { + + // Subscribe on these channels for the state in HeaderComponent + edge.subscribeChannels(this.websocket, '', [ + new ChannelAddress('_sum', 'State'), + ]); + }) + }).catch(() => { + this.router.navigate(['index']); + }); + }) + } + + public ngOnDestroy(): void { + if (!this.edge) { + return; + } + this.edge.unsubscribeChannels(this.websocket, ''); + } + +} \ No newline at end of file diff --git a/ui/src/app/edge/edge.module.ts b/ui/src/app/edge/edge.module.ts index 54997603cfd..36fb58af320 100644 --- a/ui/src/app/edge/edge.module.ts +++ b/ui/src/app/edge/edge.module.ts @@ -2,12 +2,19 @@ import { HistoryModule } from './history/history.module'; import { LiveModule } from './live/live.module'; import { NgModule } from '@angular/core'; import { SharedModule } from './../shared/shared.module'; +import { EdgeComponent } from './edge.component'; @NgModule({ + declarations: [ + EdgeComponent + ], imports: [ HistoryModule, LiveModule, SharedModule, + ], + exports: [ + EdgeComponent ] }) export class EdgeModule { } diff --git a/ui/src/app/edge/history/abstracthistorychart.html b/ui/src/app/edge/history/abstracthistorychart.html index 283cab6cd3b..5c6153c4e43 100644 --- a/ui/src/app/edge/history/abstracthistorychart.html +++ b/ui/src/app/edge/history/abstracthistorychart.html @@ -1,3 +1,5 @@ + +
      diff --git a/ui/src/app/edge/history/abstracthistorychart.ts b/ui/src/app/edge/history/abstracthistorychart.ts index c568f8e3527..10a5acd3966 100644 --- a/ui/src/app/edge/history/abstracthistorychart.ts +++ b/ui/src/app/edge/history/abstracthistorychart.ts @@ -2,11 +2,12 @@ import { Data } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { ChartDataSets } from 'chart.js'; import { differenceInDays, differenceInMonths } from 'date-fns'; +import { JsonrpcResponseError } from 'src/app/shared/jsonrpc/base'; +import { QueryHistoricTimeseriesDataRequest } from "src/app/shared/jsonrpc/request/queryHistoricTimeseriesDataRequest"; import { QueryHistoricTimeseriesEnergyPerPeriodRequest } from 'src/app/shared/jsonrpc/request/queryHistoricTimeseriesEnergyPerPeriodRequest'; +import { QueryHistoricTimeseriesDataResponse } from "src/app/shared/jsonrpc/response/queryHistoricTimeseriesDataResponse"; import { QueryHistoricTimeseriesEnergyPerPeriodResponse } from 'src/app/shared/jsonrpc/response/queryHistoricTimeseriesEnergyPerPeriodResponse'; -import { QueryHistoricTimeseriesDataRequest } from "../../shared/jsonrpc/request/queryHistoricTimeseriesDataRequest"; -import { QueryHistoricTimeseriesDataResponse } from "../../shared/jsonrpc/response/queryHistoricTimeseriesDataResponse"; -import { ChannelAddress, Edge, EdgeConfig, Service, Utils } from "../../shared/shared"; +import { ChannelAddress, Edge, EdgeConfig, Service, Utils } from "src/app/shared/shared"; import { calculateResolution, ChartOptions, DEFAULT_TIME_CHART_OPTIONS, EMPTY_DATASET, Resolution, TooltipItem } from './shared'; // NOTE: Auto-refresh of widgets is currently disabled to reduce server load @@ -14,6 +15,7 @@ export abstract class AbstractHistoryChart { public loading: boolean = true; protected edge: Edge | null = null; + protected errorResponse: JsonrpcResponseError | null = null; //observable is used to fetch new chart data every 10 minutes // private refreshChartData = interval(600000); @@ -73,6 +75,8 @@ export abstract class AbstractHistoryChart { // Take custom resolution if passed let resolution = res ?? calculateResolution(this.service, fromDate, toDate).resolution; + this.errorResponse = null; + let result: Promise = new Promise((resolve, reject) => { this.service.getCurrentEdge().then(edge => { this.service.getConfig().then(config => { @@ -82,9 +86,12 @@ export abstract class AbstractHistoryChart { let request = new QueryHistoricTimeseriesDataRequest(fromDate, toDate, channelAddresses, resolution); edge.sendRequest(this.service.websocket, request).then(response => { resolve(response as QueryHistoricTimeseriesDataResponse); - }).catch((error) => resolve(new QueryHistoricTimeseriesDataResponse(error.id, { - timestamps: [null], data: { null: null } - }))); + }).catch(error => { + this.errorResponse = error; + resolve(new QueryHistoricTimeseriesDataResponse(error.id, { + timestamps: [null], data: { null: null } + })) + }); }); }) }) @@ -112,6 +119,8 @@ export abstract class AbstractHistoryChart { // TODO should be removed, edge delivers too much data let resolution = calculateResolution(this.service, fromDate, toDate).resolution; + this.errorResponse = null; + let response: Promise = new Promise((resolve, reject) => { this.service.getCurrentEdge().then(edge => { this.service.getConfig().then(config => { @@ -119,9 +128,12 @@ export abstract class AbstractHistoryChart { resolve(response as QueryHistoricTimeseriesEnergyPerPeriodResponse ?? new QueryHistoricTimeseriesEnergyPerPeriodResponse(response.id, { timestamps: [null], data: { null: null } })) - }).catch(() => resolve(new QueryHistoricTimeseriesDataResponse("0", { - timestamps: [null], data: { null: null } - }))); + }).catch((response) => { + this.errorResponse = response; + resolve(new QueryHistoricTimeseriesDataResponse("0", { + timestamps: [null], data: { null: null } + })) + }); }); }); }).then((response) => { diff --git a/ui/src/app/edge/history/energy/energy.component.html b/ui/src/app/edge/history/energy/energy.component.html index a416eaf147f..be59df6ccac 100644 --- a/ui/src/app/edge/history/energy/energy.component.html +++ b/ui/src/app/edge/history/energy/energy.component.html @@ -11,6 +11,8 @@ + +
      diff --git a/ui/src/app/edge/history/energy/energy.component.ts b/ui/src/app/edge/history/energy/energy.component.ts index 834c98b19a5..0367b38e25b 100644 --- a/ui/src/app/edge/history/energy/energy.component.ts +++ b/ui/src/app/edge/history/energy/energy.component.ts @@ -1,5 +1,5 @@ import { formatNumber } from '@angular/common'; -import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ModalController, Platform } from '@ionic/angular'; import { TranslateService } from '@ngx-translate/core'; @@ -9,6 +9,7 @@ import { format, isSameDay, isSameMonth, isSameYear } from 'date-fns'; import { saveAs } from 'file-saver-es'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { JsonrpcResponseError } from 'src/app/shared/jsonrpc/base'; import { QueryHistoricTimeseriesExportXlxsRequest } from 'src/app/shared/jsonrpc/request/queryHistoricTimeseriesExportXlxs'; import { Base64PayloadResponse } from 'src/app/shared/jsonrpc/response/base64PayloadResponse'; import { QueryHistoricTimeseriesDataResponse } from 'src/app/shared/jsonrpc/response/queryHistoricTimeseriesDataResponse'; @@ -46,6 +47,7 @@ export class EnergyComponent extends AbstractHistoryChart implements OnInit, OnC public chartType: string = "line"; + @Output() setErrorResponse: EventEmitter = new EventEmitter() @Input() public period: DefaultTypes.HistoryPeriod; ngOnChanges() { @@ -387,10 +389,11 @@ export class EnergyComponent extends AbstractHistoryChart implements OnInit, OnC this.datasets = datasets; this.loading = false; this.stopSpinner(); + this.setErrorResponse.emit(null) }).catch(reason => { console.error(reason); // TODO error message - this.initializeChart(); + this.setErrorResponse.emit(reason) return; }); } diff --git a/ui/src/app/edge/history/history.component.html b/ui/src/app/edge/history/history.component.html index 81ee7dd50ff..43cb3941245 100644 --- a/ui/src/app/edge/history/history.component.html +++ b/ui/src/app/edge/history/history.component.html @@ -1,10 +1,14 @@
      + + + - + @@ -62,8 +66,10 @@ + + + *ngSwitchCase="widget.name === 'Controller.Ess.Time-Of-Use-Tariff.Discharge' || widget.name === 'Controller.Ess.Time-Of-Use-Tariff' ? widget.name : '' "> @@ -90,7 +96,7 @@ - Historic data is not available + Historische Daten sind derzeit lokal nicht verfügbar

      Please setup a Timeseries provider like "Timedata InfluxDB" to record and visualize historic data.

      diff --git a/ui/src/app/edge/history/history.component.ts b/ui/src/app/edge/history/history.component.ts index 3d4eede017a..2571225e225 100644 --- a/ui/src/app/edge/history/history.component.ts +++ b/ui/src/app/edge/history/history.component.ts @@ -1,9 +1,10 @@ -import { ActivatedRoute } from '@angular/router'; import { Component, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { HeaderComponent } from 'src/app/shared/header/header.component'; +import { JsonrpcResponseError } from 'src/app/shared/jsonrpc/base'; import { Edge, EdgeConfig, Service, Widgets } from 'src/app/shared/shared'; import { environment } from 'src/environments'; -import { HeaderComponent } from 'src/app/shared/header/header.component'; -import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'history', @@ -16,6 +17,8 @@ export class HistoryComponent implements OnInit { // is a Timedata service available, i.e. can historic data be queried. public isTimedataAvailable: boolean = true; + protected errorResponse: JsonrpcResponseError | null = null; + // sets the height for a chart. This is recalculated on every window resize. public socChartHeight: string = "250px"; public energyChartHeight: string = "250px"; @@ -38,9 +41,10 @@ export class HistoryComponent implements OnInit { ) { } ngOnInit() { - this.service.setCurrentComponent('', this.route).then(edge => { - this.edge = edge; - }); + this.service.setCurrentComponent('', this.route) + this.service.currentEdge.subscribe((edge) => { + this.edge = edge + }) this.service.getConfig().then(config => { // gather ControllerIds of Channelthreshold Components // for (let controllerId of @@ -59,6 +63,10 @@ export class HistoryComponent implements OnInit { }); } + protected setErrorResponse(errorResponse: JsonrpcResponseError | null) { + this.errorResponse = errorResponse; + } + // checks arrows when ChartPage is closed // double viewchild is used to prevent undefined state of PickDateComponent ionViewDidEnter() { diff --git a/ui/src/app/edge/history/history.module.ts b/ui/src/app/edge/history/history.module.ts index e29ac33108f..131c620bbe9 100644 --- a/ui/src/app/edge/history/history.module.ts +++ b/ui/src/app/edge/history/history.module.ts @@ -1,12 +1,12 @@ import { NgModule } from '@angular/core'; import { SharedModule } from '../../shared/shared.module'; -import { Autarchy } from './common/autarchy/Autarchy'; import { ChannelthresholdChartOverviewComponent } from './channelthreshold/channelthresholdchartoverview/channelthresholdchartoverview.component'; import { ChannelthresholdSingleChartComponent } from './channelthreshold/singlechart.component'; import { ChannelthresholdTotalChartComponent } from './channelthreshold/totalchart.component'; import { ChannelthresholdWidgetComponent } from './channelthreshold/widget.component'; import { ChpSocChartComponent } from './chpsoc/chart.component'; import { ChpSocWidgetComponent } from './chpsoc/widget.component'; +import { Autarchy } from './common/autarchy/Autarchy'; import { ConsumptionChartOverviewComponent } from './consumption/consumptionchartoverview/consumptionchartoverview.component'; import { ConsumptionEvcsChartComponent } from './consumption/evcschart.component'; import { ConsumptionMeterChartComponent } from './consumption/meterchart.component'; @@ -37,6 +37,7 @@ import { HeatPumpChartComponent } from './heatpump/chart.component'; import { HeatPumpChartOverviewComponent } from './heatpump/heatpumpchartoverview/heatpumpchartoverview.component'; import { HeatpumpWidgetComponent } from './heatpump/widget.component'; import { HistoryComponent } from './history.component'; +import { HistoryParentComponent } from './historyparent.component'; import { AsymmetricPeakshavingChartOverviewComponent } from './peakshaving/asymmetric/asymmetricpeakshavingchartoverview/asymmetricpeakshavingchartoverview.component'; import { AsymmetricPeakshavingChartComponent } from './peakshaving/asymmetric/chart.component'; import { AsymmetricPeakshavingWidgetComponent } from './peakshaving/asymmetric/widget.component'; @@ -149,6 +150,7 @@ import { TimeOfUseTariffDischargeWidgetComponent } from './timeofusetariffdischa TimeslotPeakshavingChartComponent, TimeslotPeakshavingChartOverviewComponent, TimeslotPeakshavingWidgetComponent, + HistoryParentComponent, ] }) export class HistoryModule { } diff --git a/ui/src/app/edge/history/historyparent.component.ts b/ui/src/app/edge/history/historyparent.component.ts new file mode 100644 index 00000000000..a7b2c7ea2f7 --- /dev/null +++ b/ui/src/app/edge/history/historyparent.component.ts @@ -0,0 +1,13 @@ +import { Component } from "@angular/core"; + +/*** This component is needed as a routing parent and acts as a transit station without being displayed.*/ +@Component({ + selector: "edge", + template: ` + + + `, +}) +export class HistoryParentComponent { + +} \ No newline at end of file diff --git a/ui/src/app/edge/history/timeofusetariffdischarge/chart.component.ts b/ui/src/app/edge/history/timeofusetariffdischarge/chart.component.ts index 6b98a599ace..afe66e80744 100644 --- a/ui/src/app/edge/history/timeofusetariffdischarge/chart.component.ts +++ b/ui/src/app/edge/history/timeofusetariffdischarge/chart.component.ts @@ -17,6 +17,7 @@ export class TimeOfUseTariffDischargeChartComponent extends AbstractHistoryChart @Input() public period: DefaultTypes.HistoryPeriod; @Input() public componentId: string; + public component: EdgeConfig.Component = null; ngOnChanges() { this.updateChart(); @@ -33,6 +34,9 @@ export class TimeOfUseTariffDischargeChartComponent extends AbstractHistoryChart ngOnInit() { this.startSpinner(); this.service.setCurrentComponent('', this.route); + this.service.getConfig().then(config => { + this.component = config.getComponent(this.componentId); + }) } ngOnDestroy() { @@ -60,55 +64,49 @@ export class TimeOfUseTariffDischargeChartComponent extends AbstractHistoryChart // convert datasets let datasets = []; let quarterlyPrices = this.componentId + '/QuarterlyPrices'; - let TimeOfUseTariffState = this.componentId + '/StateMachine'; + let timeOfUseTariffState = this.componentId + '/StateMachine'; // let predictedSocWithoutLogic = this.componentId + '/PredictedSocWithoutLogic'; - if (TimeOfUseTariffState in result.data && quarterlyPrices in result.data) { - - // Get only the 15 minute value - let quarterlyPricesStandbyModeData = []; - let quarterlyPricesNightData = []; - let quarterlyPricesDelayedDischargeData = []; - // let predictedSocWithoutLogicData = []; + if (timeOfUseTariffState in result.data && quarterlyPrices in result.data) { //Size of the data - let size = result.data[TimeOfUseTariffState].length; + let size = result.data[timeOfUseTariffState].length; - for (let i = 0; i < size; i++) { - let quarterlyPrice = this.formatPrice(result.data[quarterlyPrices][i]); - let state = result.data[TimeOfUseTariffState][i]; + // Get only the 15 minute value + let quarterlyPricesStandbyModeData = Array(size).fill(null); + let quarterlyPricesNightData = Array(size).fill(null); + let quarterlyPricesDelayedDischargeData = Array(size).fill(null); + let quarterlyPricesChargedData = Array(size).fill(null); + // let predictedSocWithoutLogicData = Array(size).fill(null); - if (state == null) { - quarterlyPricesDelayedDischargeData.push(null); - quarterlyPricesNightData.push(null); - quarterlyPricesStandbyModeData.push(null); - } else { + for (let index = 0; index < size; index++) { + let quarterlyPrice = this.formatPrice(result.data[quarterlyPrices][index]); + let state = result.data[timeOfUseTariffState][index]; + + if (state !== null) { switch (state) { case 0: // delayed - quarterlyPricesDelayedDischargeData.push(quarterlyPrice); - quarterlyPricesNightData.push(null); - quarterlyPricesStandbyModeData.push(null); + quarterlyPricesDelayedDischargeData[index] = quarterlyPrice; break; case 1: // allowsDischarge - quarterlyPricesDelayedDischargeData.push(null); - quarterlyPricesNightData.push(quarterlyPrice) - quarterlyPricesStandbyModeData.push(null); + quarterlyPricesNightData[index] = quarterlyPrice; break; case -1: // notStarted case 2: // standby - quarterlyPricesDelayedDischargeData.push(null); - quarterlyPricesNightData.push(null); - quarterlyPricesStandbyModeData.push(quarterlyPrice); + quarterlyPricesStandbyModeData[index] = quarterlyPrice; + break; + case 3: + // charged + quarterlyPricesChargedData[index] = quarterlyPrice; break; } } } - // Set dataset for no limit datasets.push({ type: 'bar', @@ -149,6 +147,22 @@ export class TimeOfUseTariffDischargeChartComponent extends AbstractHistoryChart borderColor: 'rgba(0,0,200,0.9)', }) + // Show charge data only for the new controller. + if (this.component.factoryId === 'Controller.Ess.Time-Of-Use-Tariff') { + // Set dataset for Quarterly Prices being charged. + datasets.push({ + type: 'bar', + label: this.translate.instant('Edge.Index.Widgets.TimeOfUseTariff.State.CHARGING'), + data: quarterlyPricesChargedData, + order: 3, + }); + this.colors.push({ + // Sky blue + backgroundColor: 'rgba(0, 204, 204,0.5)', + borderColor: 'rgba(0, 204, 204,0.7)', + }) + } + // Predicted SoC is not shown for now, because it is not inteligent enough with the simple prediction // if (predictedSocWithoutLogic in result.data) { // for (let i = 0; i < 96; i++) { @@ -219,13 +233,13 @@ export class TimeOfUseTariffDischargeChartComponent extends AbstractHistoryChart } /** - * Converts a value in €/MWh to €/kWh. + * Converts a value in €/MWh to €Ct./kWh. * * @param price the price value * @returns the converted price */ private formatPrice(price: number): number { - if (price == null || price == NaN) { + if (price == null || Number.isNaN(price)) { return null; } else if (price == 0) { return 0; @@ -237,14 +251,20 @@ export class TimeOfUseTariffDischargeChartComponent extends AbstractHistoryChart protected getChannelAddresses(edge: Edge, config: EdgeConfig): Promise { return new Promise((resolve) => { - resolve( - [ - new ChannelAddress(this.componentId, 'Delayed'), - new ChannelAddress(this.componentId, 'QuarterlyPrices'), - new ChannelAddress(this.componentId, 'StateMachine'), - new ChannelAddress('_sum', 'EssSoc'), - // new ChannelAddress(this.componentId, 'PredictedSocWithoutLogic'), - ]); + let channels: ChannelAddress[] = [ + new ChannelAddress(this.componentId, 'Delayed'), + new ChannelAddress(this.componentId, 'QuarterlyPrices'), + new ChannelAddress(this.componentId, 'StateMachine'), + new ChannelAddress('_sum', 'EssSoc'), + // new ChannelAddress(this.componentId, 'PredictedSocWithoutLogic'), + ]; + + // Channel only in the new controller. + if (this.component.factoryId === 'Controller.Ess.Time-Of-Use-Tariff') { + channels.push(new ChannelAddress(this.componentId, 'Charged')) + } + + resolve(channels); }); } @@ -252,6 +272,9 @@ export class TimeOfUseTariffDischargeChartComponent extends AbstractHistoryChart let options = this.createDefaultChartOptions(); let translate = this.translate; + // Scale prices y-axis between min-/max-values, not from zero + options.scales.yAxes[0].ticks.beginAtZero = false; + // Adds second y-axis to chart options.scales.yAxes.push({ id: 'yAxis2', diff --git a/ui/src/app/edge/history/timeofusetariffdischarge/widget.component.html b/ui/src/app/edge/history/timeofusetariffdischarge/widget.component.html index ae0a7ec5d14..177185cba68 100644 --- a/ui/src/app/edge/history/timeofusetariffdischarge/widget.component.html +++ b/ui/src/app/edge/history/timeofusetariffdischarge/widget.component.html @@ -4,15 +4,30 @@ {{ component.alias }} - - - - - - -
      - Edge.Index.Widgets.TimeOfUseTariff.delayedDischarge - {{ activeTimeOverPeriod | formatSecondsToDuration }} -
      -
      + + + + + + + +
      + Edge.Index.Widgets.TimeOfUseTariff.CHARGED + {{ chargedActiveTimeOverPeriod | formatSecondsToDuration }} +
      +
      +
      + + + + + + + +
      + Edge.Index.Widgets.TimeOfUseTariff.delayedDischarge + {{ delayedActiveTimeOverPeriod | formatSecondsToDuration }} +
      +
      +
      \ No newline at end of file diff --git a/ui/src/app/edge/history/timeofusetariffdischarge/widget.component.ts b/ui/src/app/edge/history/timeofusetariffdischarge/widget.component.ts index 9ebe1366d1d..353c38a992d 100644 --- a/ui/src/app/edge/history/timeofusetariffdischarge/widget.component.ts +++ b/ui/src/app/edge/history/timeofusetariffdischarge/widget.component.ts @@ -15,7 +15,8 @@ export class TimeOfUseTariffDischargeWidgetComponent extends AbstractHistoryWidg private static readonly SELECTOR = "timeOfUseTariffDischargeWidget"; - public activeTimeOverPeriod: number = null; + public delayedActiveTimeOverPeriod: number = null; + public chargedActiveTimeOverPeriod: number = null; public edge: Edge = null; public component: EdgeConfig.Component = null; @@ -51,7 +52,10 @@ export class TimeOfUseTariffDischargeWidgetComponent extends AbstractHistoryWidg this.service.queryEnergy(this.period.from, this.period.to, channels).then(response => { let result = response.result; if (this.componentId + '/DelayedTime' in result.data) { - this.activeTimeOverPeriod = result.data[this.componentId + '/DelayedTime']; + this.delayedActiveTimeOverPeriod = result.data[this.componentId + '/DelayedTime']; + } + if (this.componentId + '/ChargedTime' in result.data) { + this.chargedActiveTimeOverPeriod = result.data[this.componentId + '/ChargedTime']; } }) }); @@ -61,7 +65,9 @@ export class TimeOfUseTariffDischargeWidgetComponent extends AbstractHistoryWidg protected getChannelAddresses(edge: Edge, config: EdgeConfig): Promise { return new Promise((resolve) => { - resolve([new ChannelAddress(this.componentId, 'DelayedTime')]); + resolve([ + new ChannelAddress(this.componentId, 'DelayedTime'), + new ChannelAddress(this.componentId, 'ChargedTime')]); }); } } \ No newline at end of file diff --git a/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariffDischarge/modal/modal.html b/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariffDischarge/modal/modal.html index 8f4a15ae959..8c57cb39578 100644 --- a/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariffDischarge/modal/modal.html +++ b/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariffDischarge/modal/modal.html @@ -27,7 +27,7 @@
      - + diff --git a/ui/src/app/edge/live/common/storage/modal/modal.component.html b/ui/src/app/edge/live/common/storage/modal/modal.component.html index 19ca975e322..c81ae11bd7f 100644 --- a/ui/src/app/edge/live/common/storage/modal/modal.component.html +++ b/ui/src/app/edge/live/common/storage/modal/modal.component.html @@ -11,8 +11,9 @@ - -
      + + + @@ -98,56 +99,200 @@ - - - - - - + + +
      - Edge.Index.EmergencyReserve.emergencyReserve - - {{ formGroup.value[component.id]?.reserveSoc | unitvalue:'%' }} - + + + + + + + + - - -
      + Edge.Index.EmergencyReserve.emergencyReserve + + {{formGroup.value[component.id]?.['emergencyReserveController']?.reserveSoc| + unitvalue:'%' }} + - - - -
      + + + + + +
      + + + + + +
      + + + + + + Edge.Index.EmergencyReserve.InfoForEmergencyReserveSlider + + + +
      - - - - - -
      - - - - - - Edge.Index.EmergencyReserve.InfoForEmergencyReserveSlider - - - -
      - - - - - {{ 5 | unitvalue:'%' }} - - - {{ 100 | unitvalue:'%' }} - - + + + + + {{ 5 | unitvalue:'%' }} + + + {{ 100 | unitvalue:'%' }} + + + + +
      + + + + + + + + + + + + +
      + Edge.Index.RETROFITTING.OPTIMAL + + + +
      + + + + + + + Edge.Index.RETROFITTING.INSTANT_START + + + Edge.Index.RETROFITTING.PLANNED_EXPANSION + + + + + + + + +
      + + + + + + Edge.Index.RETROFITTING.INFORMATION_FOR_INSTANT_START + + + +
      + + + + + + + +
      + + Edge.Index.RETROFITTING.ON_DATE_AT_TIME + + + + + + Edge.Index.RETROFITTING.SELECT_A_DATE + + + + + + + + + +
      + + + + + +
      + + + + + + Edge.Index.RETROFITTING.INFORMATION_FOR_PlANNED_EXPANSION + + + Edge.Index.RETROFITTING.INFORMATION_FOR_PlANNED_EXPANSION_INVALID_TARGET_DATE + + + +
      +
      +
      +
      +
      + +
      - @@ -335,25 +480,264 @@ + + + + + + + + + + +
      + Edge.Index.EmergencyReserve.emergencyReserve + + {{formGroup.value[component.id]?.['emergencyReserveController']?.reserveSoc| + unitvalue:'%' }} + + + + + + + +
      + + + + + + + +
      + + + + + + Edge.Index.EmergencyReserve.InfoForEmergencyReserveSlider + + + +
      + + + + + + {{ 5 | unitvalue:'%' }} + + + {{ 100 | unitvalue:'%' }} + + + +
      +
      + + + + + + + + + + + +
      + Edge.Index.RETROFITTING.OPTIMAL + + + +
      + + + + + + + Edge.Index.RETROFITTING.INSTANT_START + + + Edge.Index.RETROFITTING.PLANNED_EXPANSION + + + + + + + + +
      + + + + + + Edge.Index.RETROFITTING.INFORMATION_FOR_INSTANT_START + + + +
      + + + + + + + +
      + + Edge.Index.RETROFITTING.ON_DATE_AT_TIME + + + + + + Edge.Index.RETROFITTING.SELECT_A_DATE + + + + + + + + + +
      + + + + + +
      + + + + + + Edge.Index.RETROFITTING.INFORMATION_FOR_PlANNED_EXPANSION + + + Edge.Index.RETROFITTING.INFORMATION_FOR_PlANNED_EXPANSION_INVALID_TARGET_DATE + + + +
      +
      +
      +
      + + +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      {{ component.alias }}
      General.chargePower + {{ (value > 0 ? value : null) | unitvalue:'W' }} +
      General.dischargePower + {{ (value <= 0 ? (value * -1) : null | unitvalue:'W') }}
      + + + + + - -
      Edge.Index.EmergencyReserve.emergencyReserve - {{ formGroup.value[component.id]?.reserveSoc | unitvalue:'%' }} + + {{formGroup.value[component.id]?.['emergencyReserveController']?.reserveSoc| + unitvalue:'%' }} + - - + + + +
      -
      @@ -370,8 +754,11 @@
      + + - + {{ 5 | unitvalue:'%' }} @@ -382,95 +769,163 @@ -
      -
      -
      - - + + - - - - - - - +
      - - - - - - - - - - - + + + + + - - -
      {{ component.alias }}
      General.chargePower - {{ (value > 0 ? value : null) | unitvalue:'W' }} -
      General.dischargePower - {{ (value <= 0 ? (value * -1) : null | unitvalue:'W') }} + Edge.Index.RETROFITTING.OPTIMAL + + + +
      + + + + + + + + Edge.Index.RETROFITTING.INSTANT_START + + + Edge.Index.RETROFITTING.PLANNED_EXPANSION + + - - - - - - - - - - -
      - Edge.Index.EmergencyReserve.emergencyReserve - - {{ formGroup.value[component.id]?.reserveSoc | unitvalue:'%' }} - + + + + + +
      + + + + + + Edge.Index.RETROFITTING.INFORMATION_FOR_INSTANT_START + + + +
      - - - -
      + + -
      - - - - -
      - - - - - - Edge.Index.EmergencyReserve.InfoForEmergencyReserveSlider - - - -
      + + + + Edge.Index.RETROFITTING.ON_DATE_AT_TIME + + + + + + Edge.Index.RETROFITTING.SELECT_A_DATE + + - - - - - {{ 5 | unitvalue:'%' }} - - - {{ 100 | unitvalue:'%' }} - - + + + + + + + + + + + + + + +
      + + + + + + Edge.Index.RETROFITTING.INFORMATION_FOR_PlANNED_EXPANSION + + + Edge.Index.RETROFITTING.INFORMATION_FOR_PlANNED_EXPANSION_INVALID_TARGET_DATE + + + +
      +
      +
      +
      + + +
      -
      + + + + + +
      + + + Edge.Index.RETROFITTING.UPDATE_TO_NEW_VERSION + + ? + + +
      +
      diff --git a/ui/src/app/edge/live/common/storage/modal/modal.component.ts b/ui/src/app/edge/live/common/storage/modal/modal.component.ts index 240654525a2..ec63f0183b7 100644 --- a/ui/src/app/edge/live/common/storage/modal/modal.component.ts +++ b/ui/src/app/edge/live/common/storage/modal/modal.component.ts @@ -1,15 +1,16 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { ModalController } from '@ionic/angular'; import { TranslateService } from '@ngx-translate/core'; -import { first } from 'rxjs/operators'; -import { Edge, EdgeConfig, Service, Utils, Websocket } from 'src/app/shared/shared'; +import { isBefore } from 'date-fns'; +import { ChannelAddress, Edge, EdgeConfig, Service, Utils, Websocket } from 'src/app/shared/shared'; +import { Role } from 'src/app/shared/type/role'; @Component({ selector: 'storage-modal', templateUrl: './modal.component.html', }) -export class StorageModalComponent implements OnInit { +export class StorageModalComponent implements OnInit, OnDestroy { // TODO after refactoring of Model: subscribe to EssActivePowerL1/L2/L3 here instead of Flat Widget @@ -22,7 +23,10 @@ export class StorageModalComponent implements OnInit { // reference to the Utils method to access via html public isLastElement = Utils.isLastElement; - public formGroup: FormGroup; + public formGroup: FormGroup = new FormGroup({}); + protected isAtLeastInstaller: boolean; + protected isTargetTimeInValid: Map = new Map(); + protected controllerIsRequiredEdgeVersion: boolean = false; constructor( public service: Service, @@ -34,62 +38,169 @@ export class StorageModalComponent implements OnInit { ngOnInit() { - let emergencyReserveComponents = this.config - .getComponentsImplementingNature('io.openems.edge.controller.ess.emergencycapacityreserve.EmergencyCapacityReserve') - .filter(component => component.isEnabled) + // Future Work: Remove when all fems are at least at this version + this.controllerIsRequiredEdgeVersion = this.edge.isVersionAtLeast('2023.2.5') - // Reduce emergencyComponents to have essId as key for controller - .reduce((result, component) => { - return { - ...result, - [component.properties['ess.id']]: component - } - }, {}); + this.isAtLeastInstaller = this.edge.roleIsAtLeast(Role.INSTALLER); + let emergencyReserveCtrl = this.config.getComponentsImplementingNature('io.openems.edge.controller.ess.emergencycapacityreserve.EmergencyCapacityReserve') + let prepareBatteryExtensionCtrl = this.config.getComponentsByFactory("Controller.Ess.PrepareBatteryExtension") + let components = [...prepareBatteryExtensionCtrl, ...emergencyReserveCtrl].filter(component => component.isEnabled).reduce((result, component) => { + let essId = component.properties['ess.id']; + if (result[essId] == null) { + result[essId] = [] + } + result[essId].push(component) + return result; + }, {}); + + let channelAddresses: ChannelAddress[] = []; + for (let essId in prepareBatteryExtensionCtrl) { + let controller = prepareBatteryExtensionCtrl[essId]; + channelAddresses.push( + new ChannelAddress(controller.id, "_PropertyIsRunning"), + new ChannelAddress(controller.id, "_PropertyTargetTime"), + new ChannelAddress(controller.id, "_PropertyTargetTimeSpecified"), + new ChannelAddress(controller.id, "_PropertyTargetSoc"), + new ChannelAddress(controller.id, "_PropertyTargetTimeBuffer"), + new ChannelAddress(controller.id, "ExpectedStartEpochSeconds") + ) + } + this.edge.subscribeChannels(this.websocket, "storage", channelAddresses); - this.formGroup = new FormGroup({}); this.edge.currentData - .pipe(first()) .subscribe(currentData => { - for (let essId in emergencyReserveComponents) { - let controller = emergencyReserveComponents[essId]; - let reserveSoc = currentData.channel[controller.id + "/_PropertyReserveSoc"] ?? 20 /* default Reserve-Soc */; - let isReserveSocEnabled = currentData.channel[controller.id + "/_PropertyIsReserveSocEnabled"] == 1; - this.formGroup.addControl(essId, this.formBuilder.group({ - controllerId: new FormControl(controller.id), - isReserveSocEnabled: new FormControl(isReserveSocEnabled), - reserveSoc: new FormControl(reserveSoc), - })); + + let controls: FormGroup = new FormGroup({}); + for (let essId of Object.keys(components)) { + let controllers = components[essId] + + let controllerFrmGrp: FormGroup = new FormGroup({}); + for (let controller of (controllers as EdgeConfig.Component[])) { + + if (controller.factoryId == 'Controller.Ess.EmergencyCapacityReserve') { + let reserveSoc = currentData.channel[controller.id + "/_PropertyReserveSoc"] ?? 20 /* default Reserve-Soc */; + let isReserveSocEnabled = currentData.channel[controller.id + "/_PropertyIsReserveSocEnabled"] == 1; + + controllerFrmGrp.addControl('emergencyReserveController', + this.formBuilder.group({ + controllerId: new FormControl(controller['id']), + isReserveSocEnabled: new FormControl(isReserveSocEnabled), + reserveSoc: new FormControl(reserveSoc), + }) + ) + } else if (controller.factoryId == 'Controller.Ess.PrepareBatteryExtension') { + + let isRunning = currentData.channel[controller.id + "/_PropertyIsRunning"] == 1 + + // Because of ionic segment buttons only accepting a string value, i needed to convert it + let targetTimeSpecified = (currentData.channel[controller.id + "/_PropertyTargetTimeSpecified"] == 1).toString();; + let targetTime = currentData.channel[controller.id + "/_PropertyTargetTime"] + let targetSoc = currentData.channel[controller.id + "/_PropertyTargetSoc"] + let targetTimeBuffer = currentData.channel[controller.id + "/_PropertyTargetTimeBuffer"] + let epochSeconds = currentData.channel[controller.id + "/ExpectedStartEpochSeconds"]; + + let expectedStartOfPreparation = new Date(0) + expectedStartOfPreparation.setUTCSeconds(epochSeconds ?? 0) + + // If targetTime not set, not equals 0 or targetTime is no valid time, + // then set targetTime to null + if (!targetTime || targetTime == 0 || isNaN(Date.parse(targetTime))) { + targetTime = null; + } + + // Channel "ExpectedStartEpochSeconds" is not set + if ((epochSeconds == null + || epochSeconds == 0)) { + this.isTargetTimeInValid.set(essId, true); + } else if + + // If expected expectedStartOfpreparation is after targetTime + // Guarantee, that the TargetSoc should be reached after the preparation to reach that Soc started + (isBefore(new Date(targetTime), expectedStartOfPreparation) + || isBefore(new Date(targetTime), new Date())) { + this.isTargetTimeInValid.set(essId, true); + } else { + this.isTargetTimeInValid.set(essId, false); + } + + controllerFrmGrp.addControl('prepareBatteryExtensionController', + this.formBuilder.group({ + controllerId: new FormControl(controller.id), + isRunning: new FormControl(isRunning), + targetTime: new FormControl(targetTime), + targetTimeSpecified: new FormControl(targetTimeSpecified), + targetSoc: new FormControl(targetSoc), + targetTimeBuffer: new FormControl(targetTimeBuffer), + expectedStartOfPreparation: new FormControl(expectedStartOfPreparation) + }) + ) + } + } + controls.addControl(essId, controllerFrmGrp) } - }); + + if (!this.formGroup.dirty) { + this.formGroup = controls; + } + }) } applyChanges() { if (this.edge == null) { return; } + + let updateArray: Map>> = new Map(); for (let essId in this.formGroup.controls) { - let essGroup = this.formGroup.controls[essId]; + let essGroups = this.formGroup.controls[essId]; + + let emergencyReserveController = (essGroups.get('emergencyReserveController') as FormGroup)?.controls ?? {}; + for (let essGroup of Object.keys(emergencyReserveController)) { + if (emergencyReserveController[essGroup].dirty) { + if (updateArray.get(emergencyReserveController['controllerId'].value)) { + updateArray.get(emergencyReserveController['controllerId'].value).push(new Map().set(essGroup, emergencyReserveController[essGroup].value)) + } else { + updateArray.set(emergencyReserveController['controllerId'].value, [new Map().set(essGroup, emergencyReserveController[essGroup].value)]); + } + } + + } + let prepareBatteryExtensionController = (essGroups.get('prepareBatteryExtensionController') as FormGroup)?.controls ?? {}; + for (let essGroup of Object.keys(prepareBatteryExtensionController)) { + if (prepareBatteryExtensionController[essGroup].dirty) { - // Check if essGroup didn't change - if (essGroup.pristine) { - continue; + // For simplicity, split targetTimeSpecified in 2 for template formControlName + if (updateArray.get(prepareBatteryExtensionController['controllerId'].value)) { + updateArray.get(prepareBatteryExtensionController['controllerId'].value).push(new Map().set(essGroup, prepareBatteryExtensionController[essGroup].value)) + } else { + updateArray.set(prepareBatteryExtensionController['controllerId'].value, [new Map().set(essGroup, prepareBatteryExtensionController[essGroup].value)]); + } + } } + } + + for (let controllerId of updateArray.keys()) { + let controllers = updateArray.get(controllerId) + let properties: { name: string, value: any }[] = []; + controllers.forEach((element) => { + let name = element.keys().next().value + let value = element.values().next().value + properties.push({ + name: name, + value: value + }) + }) - this.edge.updateComponentConfig(this.websocket, - essGroup.value['controllerId'], - [{ - name: 'isReserveSocEnabled', - value: essGroup.value['isReserveSocEnabled'] - }, - { - name: 'reserveSoc', - value: essGroup.value['reserveSoc'] - }]).then(() => { - this.service.toast(this.translate.instant('General.changeAccepted'), 'success'); - this.formGroup.markAsPristine(); - }).catch(reason => { - this.service.toast(this.translate.instant('General.changeFailed') + '\n' + reason, 'danger'); - }); + this.edge.updateComponentConfig(this.websocket, controllerId, properties).then(() => { + this.service.toast(this.translate.instant('General.changeAccepted'), 'success'); + this.formGroup.markAsPristine(); + }).catch(reason => { + this.service.toast(this.translate.instant('General.changeFailed') + '\n' + reason, 'danger'); + }); } } + + ngOnDestroy() { + this.edge.unsubscribeChannels(this.websocket, "storage") + } } diff --git a/ui/src/app/edge/live/common/storage/storage.component.html b/ui/src/app/edge/live/common/storage/storage.component.html index f4b1cedc39f..2797d9a7d68 100644 --- a/ui/src/app/edge/live/common/storage/storage.component.html +++ b/ui/src/app/edge/live/common/storage/storage.component.html @@ -49,6 +49,9 @@ + + diff --git a/ui/src/app/edge/live/common/storage/storage.component.ts b/ui/src/app/edge/live/common/storage/storage.component.ts index 6572590c45d..de5b5bda5e6 100644 --- a/ui/src/app/edge/live/common/storage/storage.component.ts +++ b/ui/src/app/edge/live/common/storage/storage.component.ts @@ -1,8 +1,10 @@ import { formatNumber } from '@angular/common'; import { Component } from '@angular/core'; +import { AbstractFlatWidget } from 'src/app/shared/genericComponents/flat/abstract-flat-widget'; import { CurrentData } from "src/app/shared/shared"; +import { Role } from 'src/app/shared/type/role'; + import { ChannelAddress, EdgeConfig, Utils } from '../../../../shared/shared'; -import { AbstractFlatWidget } from 'src/app/shared/genericComponents/flat/abstract-flat-widget'; import { StorageModalComponent } from './modal/modal.component'; @Component({ @@ -18,9 +20,14 @@ export class StorageComponent extends AbstractFlatWidget { public emergencyReserveComponents: { [essId: string]: EdgeConfig.Component } = {}; public currentSoc: number[] = []; public isEmergencyReserveEnabled: boolean[] = []; + private prepareBatteryExtensionCtrl: { [key: string]: EdgeConfig.Component } + protected possibleBatteryExtensionMessage: Map = new Map(); + protected isAtLeastInstaller: boolean = false; protected getChannelAddresses() { + this.isAtLeastInstaller = this.edge.roleIsAtLeast(Role.INSTALLER) + let channelAddresses: ChannelAddress[] = [ new ChannelAddress('_sum', 'EssSoc'), @@ -30,6 +37,25 @@ export class StorageComponent extends AbstractFlatWidget { new ChannelAddress('_sum', 'EssActivePowerL3'), ]; + this.prepareBatteryExtensionCtrl = this.config.getComponentsByFactory("Controller.Ess.PrepareBatteryExtension") + .filter(component => component.isEnabled) + .reduce((result, component) => { + return { + ...result, + [component.properties['ess.id']]: component + } + }, {}); + + for (let essId in this.prepareBatteryExtensionCtrl) { + let controller = this.prepareBatteryExtensionCtrl[essId]; + channelAddresses.push( + new ChannelAddress(controller.id, "CtrlIsBlockingEss"), + new ChannelAddress(controller.id, "CtrlIsChargingEss"), + new ChannelAddress(controller.id, "CtrlIsDischargingEss"), + new ChannelAddress(controller.id, "_PropertyIsRunning"), + ) + } + // Get emergencyReserves this.emergencyReserveComponents = this.config .getComponentsImplementingNature('io.openems.edge.controller.ess.emergencycapacityreserve.EmergencyCapacityReserve') @@ -91,8 +117,40 @@ export class StorageComponent extends AbstractFlatWidget { return channelAddresses } + private getBatteryCapacityExtensionStatus(isRunning: boolean, essIsBlocking: number, essIsCharging: number, essIsDischarging: number): { color: string, text: string } { + if (!isRunning) { + return null; + } + + if (essIsBlocking != null && essIsBlocking == 1) { + // If ess reached targetSoc + return { color: 'green', text: this.translate.instant('Edge.Index.RETROFITTING.REACHED_TARGET_SOC') }; + + } else if ((essIsCharging != null && essIsCharging == 1) || (essIsDischarging != null && essIsDischarging == 1)) { + + // If Ess is charging to or discharging to the targetSoc + return { color: 'orange', text: this.translate.instant('Edge.Index.RETROFITTING.PREPARING') } + } else { + return null; + } + } + protected onCurrentData(currentData: CurrentData) { + for (let essId in this.prepareBatteryExtensionCtrl) { + let controller = this.prepareBatteryExtensionCtrl[essId]; + + + this.possibleBatteryExtensionMessage.set( + essId, + this.getBatteryCapacityExtensionStatus( + currentData.allComponents[controller.id + '/_PropertyIsRunning'] == 1, + currentData.allComponents[controller.id + '/CtrlIsBlockingEss'], + currentData.allComponents[controller.id + '/CtrlIsChargingEss'], + currentData.allComponents[controller.id + '/CtrlIsDischargingEss'], + )) + } + // Check total State_of_Charge for dynamical icon in widget-header let soc = currentData.allComponents['_sum/EssSoc']; this.storageItem = "assets/img/" + Utils.getStorageSocImage(soc); diff --git a/ui/src/app/edge/live/info/info.component.ts b/ui/src/app/edge/live/info/info.component.ts index 2166f9e61ed..209badc2cb5 100644 --- a/ui/src/app/edge/live/info/info.component.ts +++ b/ui/src/app/edge/live/info/info.component.ts @@ -4,6 +4,4 @@ import { Component } from '@angular/core'; selector: 'info', templateUrl: './info.component.html' }) -export class InfoComponent { - -} +export class InfoComponent { } diff --git a/ui/src/app/edge/live/live.component.html b/ui/src/app/edge/live/live.component.html index cbd5cc91fd2..ebd74f38195 100644 --- a/ui/src/app/edge/live/live.component.html +++ b/ui/src/app/edge/live/live.component.html @@ -117,8 +117,11 @@ - + + + diff --git a/ui/src/app/edge/live/live.component.ts b/ui/src/app/edge/live/live.component.ts index da98c481e41..c3d08867f19 100644 --- a/ui/src/app/edge/live/live.component.ts +++ b/ui/src/app/edge/live/live.component.ts @@ -1,38 +1,39 @@ -import { Component } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { SubscribeEdgesRequest } from 'src/app/shared/jsonrpc/request/subscribeEdgesRequest'; -import { Edge, EdgeConfig, Service, Utils, Widgets } from 'src/app/shared/shared'; -import { environment } from 'src/environments'; +import { Subject } from 'rxjs'; +import { Edge, EdgeConfig, Service, Utils, Websocket, Widgets } from 'src/app/shared/shared'; @Component({ selector: 'live', templateUrl: './live.component.html' }) -export class LiveComponent { +export class LiveComponent implements OnInit, OnDestroy { public edge: Edge = null public config: EdgeConfig = null; public widgets: Widgets = null; + private stopOnDestroy: Subject = new Subject(); constructor( private route: ActivatedRoute, public service: Service, protected utils: Utils, - ) { - } - - ionViewWillEnter() { - this.service.setCurrentComponent('', this.route).then(edge => { + protected websocket: Websocket + ) { } - if (environment.backend == 'OpenEMS Backend' && edge.isOnline) { - this.service.websocket.sendRequest(new SubscribeEdgesRequest({ edges: [edge.id] })) - .catch(error => console.warn(error)) - } - this.edge = edge; - }); + public ngOnInit() { + this.service.setCurrentComponent('', this.route) + this.service.currentEdge.subscribe((edge) => { + this.edge = edge + }) this.service.getConfig().then(config => { this.config = config; this.widgets = config.widgets; - }) + }); + } + + public ngOnDestroy() { + this.stopOnDestroy.next(); + this.stopOnDestroy.complete(); } -} +} \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/app.module.ts b/ui/src/app/edge/settings/app/app.module.ts index b72f7540869..6c5f69ef7aa 100644 --- a/ui/src/app/edge/settings/app/app.module.ts +++ b/ui/src/app/edge/settings/app/app.module.ts @@ -4,16 +4,47 @@ import { InstallAppComponent } from './install.component'; import { IndexComponent } from './index.component'; import { SingleAppComponent } from './single.component'; import { UpdateAppComponent } from './update.component'; +import { KeyModalComponent } from './keypopup/modal.component'; +import { FormControl, ValidationErrors } from '@angular/forms'; +import { FormlyModule, FORMLY_CONFIG } from '@ngx-formly/core'; +import { TranslateExtension } from 'src/app/shared/translate.extension'; +import { TranslateService } from '@ngx-translate/core'; + +export function KeyValidator(control: FormControl): ValidationErrors { + return /^(.{4}-){3}.{4}$/.test(control.value) ? null : { 'key': true }; +} + +export function registerTranslateExtension(translate: TranslateService) { + return { + validationMessages: [ + { + name: 'key', + message() { + return translate.stream('Edge.Config.App.Key.invalidPattern'); + }, + }, + ] + }; +} @NgModule({ imports: [ SharedModule, + FormlyModule.forRoot({ + validators: [ + { name: 'key', validation: KeyValidator } + ], + validationMessages: [ + { name: 'key', message: "The key doesnt match the pattern!" } + ] + }) ], declarations: [ IndexComponent, InstallAppComponent, SingleAppComponent, UpdateAppComponent, + KeyModalComponent, ], exports: [ IndexComponent, @@ -21,5 +52,9 @@ import { UpdateAppComponent } from './update.component'; SingleAppComponent, UpdateAppComponent, ], + providers: [ + // Use factory for formly. This allows us to use translations in validationMessages. + { provide: FORMLY_CONFIG, multi: true, useFactory: registerTranslateExtension, deps: [TranslateService] }, + ], }) export class AppModule { } diff --git a/ui/src/app/edge/settings/app/index.component.html b/ui/src/app/edge/settings/app/index.component.html index a2dddfee24d..607d35c8b3e 100644 --- a/ui/src/app/edge/settings/app/index.component.html +++ b/ui/src/app/edge/settings/app/index.component.html @@ -1,17 +1,42 @@ - - + + {{ app.name }} - -
      - + +
      +
      + +
      + + + + + + +

      Edge.Config.App.notAvailable

      +
      +
      + +
      + +
      +
      + +
      + +
      +
      +
      +
      +
      +

      Technischer Name: {{ app.appId }}
      @@ -21,18 +46,6 @@
      Cardinality: {{ app.cardinality }}

      -
      -
      - Edge.Config.App.errorCompatible
      - - {{ message - }}
      -
      -
      - Edge.Config.App.errorInstallable
      - - {{ message - }}
      -
      -
      @@ -60,7 +73,7 @@ - + @@ -72,13 +85,44 @@ + + + + + + Edge.Config.App.Key.useKey + + + + + + + + Edge.Config.App.Key.registerKey + + + + + + + + + + + + {{ bundle.length }} + + + +
      - + this.key === null // only show installed apps when the user is not currently selecting an app from a key + }; + public availableApps: AppList = { + name: 'Edge.Config.App.available', appCategories: [] + , shouldBeShown: () => true // always show available apps + }; + public incompatibleApps: AppList = { + name: 'Edge.Config.App.incompatible', appCategories: [] + , shouldBeShown: () => this.edge.roleIsAtLeast(Role.ADMIN) // only show incompatible apps for admins + }; public appLists: AppList[] = [this.installedApps, this.availableApps, this.incompatibleApps]; public categories: { val: GetApps.Category, isChecked: boolean }[] = []; + protected key: Key | null = null + protected selectedBundle: number | null = null + // check if update is available protected isUpdateAvailable: boolean = false; + protected canEnterKey: boolean | undefined + + private stopOnDestroy: Subject = new Subject(); + public constructor( private route: ActivatedRoute, private service: Service, private websocket: Websocket, private translate: TranslateService, + private router: Router, + private modalController: ModalController ) { } - private ionViewWillEnter() { - // gets always called when entering the page + public ngOnInit() { this.init() } private init() { this.service.startSpinner(this.spinnerId); + this.key = null; + this.selectedBundle = null; this.appLists.forEach(element => { element.appCategories = [] }); - this.service.setCurrentComponent(environment.edgeShortName + " Apps", this.route).then(edge => { + this.service.setCurrentComponent(environment.edgeShortName + ' Apps', this.route).then(edge => { this.edge = edge; + + this.service.metadata + .pipe(takeUntil(this.stopOnDestroy)) + .subscribe(entry => { + this.canEnterKey = canEnterKey(edge, entry.user); + }); edge.sendRequest(this.websocket, new ComponentJsonApiRequest({ - componentId: "_appManager", + componentId: '_appManager', payload: new GetApps.Request() })).then(response => { this.service.stopSpinner(this.spinnerId); - this.apps = (response as GetApps.Response).result.apps; // init categories @@ -77,13 +109,13 @@ export class IndexComponent { this.categories.push({ val: category, isChecked: true }) } }); - }) + }); - this.updateSelection(null) + this.updateSelection(null); }).catch(reason => { console.error(reason.error); - this.service.toast("Error while receiving available apps: " + reason.error.message, 'danger'); + this.service.toast('Error while receiving available apps: ' + reason.error.message, 'danger'); }); const systemUpdate = new ExecuteSystemUpdate(edge, this.websocket); @@ -96,26 +128,36 @@ export class IndexComponent { }); } + public ngOnDestroy(): void { + this.stopOnDestroy.next(); + this.stopOnDestroy.complete(); + } + /** * Updates the selected categories. * @param event the event of a click on a 'ion-fab-list' to stop it from closing */ protected updateSelection(event: PointerEvent) { if (event != null) { - event.stopPropagation() + event.stopPropagation(); } - this.installedApps.appCategories = [] - this.availableApps.appCategories = [] + this.installedApps.appCategories = []; + this.availableApps.appCategories = []; var sortedApps = [] this.apps.forEach(a => { - a.categorys.every(category => { + a.categorys.forEach(category => { + if (this.selectedBundle >= 0 && this.key) { + if (!this.key.bundles[this.selectedBundle].some((app) => app.appId === a.appId)) { + return false; + } + } var cat = this.categories.find(c => c.val.name === category.name) - if (cat.isChecked) { - sortedApps.push(a) - return false + if (!cat.isChecked) { + return false; } - return true + sortedApps.push(a); + return true; }) }) @@ -135,38 +177,100 @@ export class IndexComponent { }) } - private pushIntoCategory(app: GetApps.App, list: AppList) { + private pushIntoCategory(app: GetApps.App, list: AppList): void { app.categorys.forEach(category => { var catList = list.appCategories.find(l => l.category.name === category.name) - if (catList == undefined) { - catList = { category: category, apps: [] } - list.appCategories.push(catList) + if (catList === undefined) { + catList = { category: category, apps: [] }; + list.appCategories.push(catList); } - catList.apps.push(app) + catList.apps.push(app); }) } - protected showCategories(app: AppList) { + protected showCategories(app: AppList): boolean { return this.sum(app) > IndexComponent.MAX_APPS_IN_LIST } - protected isEmpty(app: AppList) { + protected isEmpty(app: AppList): boolean { return this.sum(app) === 0 } - private sum(app: AppList) { - let sum = 0 - app.appCategories.forEach(element => { - sum += element.apps.length + private sum(app: AppList): number { + return app.appCategories.reduce((p, c) => p + c.apps.length, 0) + } + + /** + * Opens a popup to select a key. + */ + protected async redeemKey(): Promise { + const modal = await this.modalController.create({ + component: KeyModalComponent, + componentProps: { + edge: this.edge, + behaviour: KeyValidationBehaviour.SELECT, + knownApps: this.apps + }, + cssClass: 'auto-height' }); - return sum + modal.onDidDismiss().then(data => { + if (!data.data) { + this.key = null; + this.updateSelection(null); + return; // no key selected + } + this.key = data.data.key + if (!this.key.bundles) { + // load bundles + this.edge.sendRequest(this.websocket, new AppCenter.Request({ + payload: new AppCenterGetPossibleApps.Request({ + key: this.key.keyId + }) + })).then(response => { + const result = (response as AppCenterGetPossibleApps.Response).result; + this.key.bundles = result.bundles; + this.selectedBundle = 0; + this.updateSelection(null); + }) + } else { + this.selectedBundle = 0; + this.updateSelection(null); + } + }) + return await modal.present(); + } + + protected onAppClicked(app: GetApps.App): void { + if (this.key != null) { + this.router.navigate(['device/' + (this.edge.id) + '/settings/app/single/' + app.appId] + , { queryParams: { name: app.name }, state: { app: app, appKey: this.key.keyId } }); + } else { + this.router.navigate(['device/' + (this.edge.id) + '/settings/app/single/' + app.appId], { queryParams: { name: app.name }, state: app }); + } + } + + /** + * Opens a popup to register a key. + */ + protected async registerKey(): Promise { + const modal = await this.modalController.create({ + component: KeyModalComponent, + componentProps: { + edge: this.edge, + behaviour: KeyValidationBehaviour.REGISTER, + }, + cssClass: 'auto-height' + }); + + return await modal.present(); } } interface AppList { name: string, - appCategories: AppListByCategorie[]; + appCategories: AppListByCategorie[], + shouldBeShown: () => boolean; } interface AppListByCategorie { diff --git a/ui/src/app/edge/settings/app/install.component.html b/ui/src/app/edge/settings/app/install.component.html index 3508efec352..92b8960b12f 100644 --- a/ui/src/app/edge/settings/app/install.component.html +++ b/ui/src/app/edge/settings/app/install.component.html @@ -1,5 +1,6 @@
      + @@ -16,12 +17,14 @@ Edge.Config.App.createApp +
      +
      + -
      \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/install.component.ts b/ui/src/app/edge/settings/app/install.component.ts index c8ad95dbc7e..55ec1381b81 100644 --- a/ui/src/app/edge/settings/app/install.component.ts +++ b/ui/src/app/edge/settings/app/install.component.ts @@ -1,107 +1,224 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; +import { ModalController } from '@ionic/angular'; import { FormlyFieldConfig } from '@ngx-formly/core'; +import { TranslateService } from '@ngx-translate/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { JsonrpcRequest } from 'src/app/shared/jsonrpc/base'; import { ComponentJsonApiRequest } from 'src/app/shared/jsonrpc/request/componentJsonApiRequest'; import { Edge, Service, Utils, Websocket } from '../../../shared/shared'; import { AddAppInstance } from './jsonrpc/addAppInstance'; import { GetAppAssistant } from './jsonrpc/getAppAssistant'; +import { AppCenter } from './keypopup/appCenter'; +import { AppCenterInstallAppWithSuppliedKeyRequest } from './keypopup/appCenterInstallAppWithSuppliedKey'; +import { AppCenterIsAppFree } from './keypopup/appCenterIsAppFree'; +import { KeyModalComponent, KeyValidationBehaviour } from './keypopup/modal.component'; +import { hasPredefinedKey } from './permissions'; @Component({ selector: InstallAppComponent.SELECTOR, templateUrl: './install.component.html' }) -export class InstallAppComponent implements OnInit { +export class InstallAppComponent implements OnInit, OnDestroy { - private static readonly SELECTOR = "appInstall"; + private static readonly SELECTOR = 'app-install'; public readonly spinnerId: string = InstallAppComponent.SELECTOR; + private stopOnDestroy: Subject = new Subject() + protected form: FormGroup | null = null; protected fields: FormlyFieldConfig[] = null; protected model: any | null = null; + private key: string | null = null; private appId: string | null = null; protected appName: string | null = null; private edge: Edge | null = null; protected isInstalling: boolean = false; + private hasPredefinedKey: boolean = false; + private isAppFree: boolean = false; + public constructor( private route: ActivatedRoute, protected utils: Utils, private websocket: Websocket, private service: Service, + private modalController: ModalController, + private router: Router, + private translate: TranslateService, ) { } public ngOnInit() { this.service.startSpinner(this.spinnerId); - let appId = this.route.snapshot.params["appId"]; + const state = history?.state; + if (state && 'appKey' in state) { + this.key = state['appKey']; + } + let appId = this.route.snapshot.params['appId']; let appName = this.route.snapshot.queryParams['name']; this.appId = appId; this.service.setCurrentComponent(appName, this.route).then(edge => { this.edge = edge + + this.edge.sendRequest(this.websocket, + new AppCenter.Request({ + payload: new AppCenterIsAppFree.Request({ + appId: this.appId + }) + }) + ).then(response => { + const result = (response as AppCenterIsAppFree.Response).result; + this.isAppFree = result.isAppFree; + }).catch(() => { + this.isAppFree = false; + }); + + this.service.metadata + .pipe(takeUntil(this.stopOnDestroy)) + .subscribe(entry => { + this.hasPredefinedKey = hasPredefinedKey(edge, entry.user); + }); edge.sendRequest(this.websocket, new ComponentJsonApiRequest({ - componentId: "_appManager", + componentId: '_appManager', payload: new GetAppAssistant.Request({ appId: appId }) })).then(response => { - let appAssistant = GetAppAssistant.postprocess((response as GetAppAssistant.Response).result); - // insert alias field into appAssistent fields - let aliasField = { key: "ALIAS", type: "input", templateOptions: { label: "Alias" }, defaultValue: appAssistant.alias }; - appAssistant.fields.splice(0, 0, aliasField) this.fields = appAssistant.fields; this.appName = appAssistant.name; this.model = {}; this.form = new FormGroup({}); - this.service.stopSpinner(this.spinnerId); - }) - .catch(reason => { + }).catch(reason => { console.error(reason.error); this.service.toast("Error while receiving App Assistant for [" + appId + "]: " + reason.error.message, 'danger'); + }).finally(() => { + this.service.stopSpinner(this.spinnerId); }); }); } + public ngOnDestroy(): void { + this.stopOnDestroy.next(); + this.stopOnDestroy.complete(); + } + + /** + * Submit for installing a app. + */ protected submit() { - // remove alias field from properties - let alias = this.form.value["ALIAS"] - const clonedFields = {}; - for (let item in this.form.value) { - if (item != "ALIAS") { - clonedFields[item] = this.form.value[item] + this.obtainKey().then(key => { + this.service.startSpinnerTransparentBackground(this.appId); + // remove alias field from properties + let alias = this.form.value['ALIAS']; + const clonedFields = {}; + for (let item in this.form.value) { + if (item !== 'ALIAS') { + clonedFields[item] = this.form.value[item]; + } } - } - this.isInstalling = true - this.edge.sendRequest(this.websocket, - new ComponentJsonApiRequest({ - componentId: "_appManager", + + let request: JsonrpcRequest = new ComponentJsonApiRequest({ + componentId: '_appManager', payload: new AddAppInstance.Request({ appId: this.appId, alias: alias, - properties: clonedFields + properties: clonedFields, + ...(key && { key: key }) }) - })).then(response => { - let result = (response as AddAppInstance.Response).result + }); + // if key not set send request with supplied key + if (!key) { + request = new AppCenter.Request({ + payload: new AppCenterInstallAppWithSuppliedKeyRequest.Request({ + installRequest: request + }) + }); + } + + this.isInstalling = true + this.edge.sendRequest(this.websocket, request).then(response => { + let result = (response as AddAppInstance.Response).result; if (result.instance) { - result.instanceId = result.instance.instanceId - this.model = result.instance.properties + result.instanceId = result.instance.instanceId; + this.model = result.instance.properties; } if (result.warnings && result.warnings.length > 0) { - this.service.toast(result.warnings.join(";"), 'warning') + this.service.toast(result.warnings.join(';'), 'warning'); } else { - this.service.toast("Successfully installed App", 'success'); + this.service.toast(this.translate.instant('Edge.Config.App.successInstall'), 'success') } this.form.markAsPristine(); + this.router.navigate(['device/' + (this.edge.id) + '/settings/app/']); }).catch(reason => { - this.service.toast("Error installing App:" + reason.error.message, 'danger'); + this.service.toast(this.translate.instant('Edge.Config.App.failInstall', { error: reason.error.message }), 'danger') }).finally(() => { this.isInstalling = false + this.service.stopSpinner(this.appId); }); + }).catch(() => { + // can not get key => dont install + }) + } + + /** + * Gets the key to install the current app with. + * + * @returns the key or null if the predefined key gets used + */ + private obtainKey(): Promise { + return new Promise((resolve, reject) => { + if (this.key) { + resolve(this.key); + return; + } + if (this.hasPredefinedKey) { + resolve(null); + return; + } + if (this.isAppFree) { + resolve(null); + return; + } + this.presentModal() + .then(resolve) + .catch(reject) + }); } + // popup for key + private async presentModal(): Promise { + const modal = await this.modalController.create({ + component: KeyModalComponent, + componentProps: { + edge: this.edge, + appId: this.appId, + behaviour: KeyValidationBehaviour.SELECT, + appName: this.appName + }, + cssClass: 'auto-height' + }); + + const selectKeyPromise = new Promise((resolve, reject) => { + modal.onDidDismiss().then(event => { + if (!event.data) { + reject(); + return; // no key selected + } + resolve(event.data.key["keyId"]); + }) + }); + + await modal.present(); + return selectKeyPromise; + } + + } diff --git a/ui/src/app/edge/settings/app/jsonrpc/addAppInstance.ts b/ui/src/app/edge/settings/app/jsonrpc/addAppInstance.ts index 74cef3fd4f6..f1f0d5a03f4 100644 --- a/ui/src/app/edge/settings/app/jsonrpc/addAppInstance.ts +++ b/ui/src/app/edge/settings/app/jsonrpc/addAppInstance.ts @@ -41,6 +41,7 @@ export namespace AddAppInstance { public constructor( public readonly params: { + key?: string, // only for newer versions appId: string, alias: string, properties: {} diff --git a/ui/src/app/edge/settings/app/jsonrpc/getAppAssistant.ts b/ui/src/app/edge/settings/app/jsonrpc/getAppAssistant.ts index 23a2c861932..193263b24f5 100644 --- a/ui/src/app/edge/settings/app/jsonrpc/getAppAssistant.ts +++ b/ui/src/app/edge/settings/app/jsonrpc/getAppAssistant.ts @@ -63,12 +63,49 @@ export namespace GetAppAssistant { export function postprocess(appAssistant: AppAssistant): AppAssistant { let fields = appAssistant.fields; + + let hasAliasField = false; for (let field of fields) { - // 'defaultValue' false for checkboxes - if (field.type === 'checkbox' && !('defaultValue' in field)) { - field['defaultValue'] = false; + if (eachFieldRecursive(field)) { + hasAliasField = true; } } + if (!hasAliasField) { + // insert alias field into appAssistent fields + let aliasField = { key: 'ALIAS', type: 'input', templateOptions: { label: 'Alias' }, defaultValue: appAssistant.alias }; + appAssistant.fields.splice(0, 0, aliasField); + } return appAssistant; } + + /** + * Iterates over the given field an all child fields. + * + * @param field the current field to iterate thrue + * @returns true if any field has 'ALIAS' as their key + */ + function eachFieldRecursive(field: FormlyFieldConfig) { + // 'defaultValue' false for checkboxes + if (field.type === 'checkbox' && !('defaultValue' in field)) { + field['defaultValue'] = false; + } + // this is needed to still show the input as the default style defined by us + if (field.wrappers?.includes('formly-wrapper-default-of-cases')) { + field.wrappers?.push('form-field') + } + + let childHasAlias = false; + if (field.fieldGroup) { + for (let f of field.fieldGroup) { + if (eachFieldRecursive(f)) { + childHasAlias = true; + } + } + } + if (field.key == 'ALIAS') { + return true; + } + return childHasAlias; + } + } \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/keypopup/app.ts b/ui/src/app/edge/settings/app/keypopup/app.ts new file mode 100644 index 00000000000..8aaa9a97d18 --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/app.ts @@ -0,0 +1,7 @@ +/** + * Represents a app from the backend (not edge). + */ +export type App = { + id: number, + appId: string +} \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/keypopup/appCenter.ts b/ui/src/app/edge/settings/app/keypopup/appCenter.ts new file mode 100644 index 00000000000..736872a9dcd --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/appCenter.ts @@ -0,0 +1,43 @@ +import { JsonrpcRequest } from "src/app/shared/jsonrpc/base"; + + +/** + * Wrapper for Requests specific to AppCenter. + * + *

      + * Request: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "appCenter",
      + *   "params": {
      + *     "payload": {} // the specific request to the AppCenter
      + *   }
      + * }
      + * 
      + * + *

      + * Response: + * + *

      + * The response base on the request in the payload.
      + * 
      + */ +export namespace AppCenter { + + export const METHOD: string = "appCenter"; + + export class Request extends JsonrpcRequest { + + public constructor( + public readonly params: { + payload: JsonrpcRequest + } + ) { + super(AppCenter.METHOD, params); + } + } + +} diff --git a/ui/src/app/edge/settings/app/keypopup/appCenterAddRegisterKeyHistory.ts b/ui/src/app/edge/settings/app/keypopup/appCenterAddRegisterKeyHistory.ts new file mode 100644 index 00000000000..69cf182e739 --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/appCenterAddRegisterKeyHistory.ts @@ -0,0 +1,52 @@ +import { JsonrpcRequest } from "src/app/shared/jsonrpc/base"; + + +/** + * Registeres a Key to the current edge and the given app. + * + *

      + * Note: This Request needs to be wrapped in a appCenter Request. + * + *

      + * Request: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "addRegisterKeyHistory",
      + *   "params": {
      + *     "key": string,
      + *     "appId": string
      + *   }
      + * }
      + * 
      + * + *

      + * Response: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {}
      + * }
      + * 
      + */ +export namespace AppCenterAddRegisterKeyHistory { + + export const METHOD: string = "addRegisterKeyHistory"; + + export class Request extends JsonrpcRequest { + + public constructor( + public readonly params: { + key: string, + appId: string, + } + ) { + super(METHOD, params); + } + } + +} diff --git a/ui/src/app/edge/settings/app/keypopup/appCenterGetPossibleApps.ts b/ui/src/app/edge/settings/app/keypopup/appCenterGetPossibleApps.ts new file mode 100644 index 00000000000..78925d20d40 --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/appCenterGetPossibleApps.ts @@ -0,0 +1,65 @@ +import { JsonrpcRequest, JsonrpcResponseSuccess } from "src/app/shared/jsonrpc/base"; +import { App } from "./app"; + + +/** + * Gets the Apps that can be installed with the given key. + * + *

      + * Note: This Request needs to be wrapped in a appCenter Request. + * + *

      + * Request: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getPossibleApps",
      + *   "params": {
      + *     "key": string
      + *   }
      + * }
      + * 
      + * + *

      + * Response: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *      bundles: (App[])[]
      + *   }
      + * }
      + * 
      + */ +export namespace AppCenterGetPossibleApps { + + export const METHOD: string = "getPossibleApps"; + + export class Request extends JsonrpcRequest { + + public constructor( + public readonly params: { + key: string + } + ) { + super(METHOD, params); + } + } + + export class Response extends JsonrpcResponseSuccess { + + public constructor( + public readonly id: string, + public readonly result: { + bundles: (App[])[] + } + ) { + super(id, result); + } + } + +} \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/keypopup/appCenterGetRegisteredKeys.ts b/ui/src/app/edge/settings/app/keypopup/appCenterGetRegisteredKeys.ts new file mode 100644 index 00000000000..c90c6e4ed57 --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/appCenterGetRegisteredKeys.ts @@ -0,0 +1,65 @@ +import { JsonrpcRequest, JsonrpcResponseSuccess } from "src/app/shared/jsonrpc/base"; +import { Key } from "./key"; + + +/** + * Gets the registered keys to the current edge and if provided to the given app. + * + *

      + * Note: This Request needs to be wrapped in a appCenter Request. + * + *

      + * Request: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getRegisteredKeys",
      + *   "params": {
      + *     "appId": string
      + *   }
      + * }
      + * 
      + * + *

      + * Response: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      +        keys: Key[]
      + *   }
      + * }
      + * 
      + */ +export namespace AppCenterGetRegisteredKeys { + + export const METHOD: string = "getRegisteredKeys"; + + export class Request extends JsonrpcRequest { + + public constructor( + public readonly params: { + appId?: string, + } + ) { + super(METHOD, params); + } + } + + export class Response extends JsonrpcResponseSuccess { + + public constructor( + public readonly id: string, + public readonly result: { + keys: Key[] + } + ) { + super(id, result); + } + } + +} \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/keypopup/appCenterInstallAppWithSuppliedKey.ts b/ui/src/app/edge/settings/app/keypopup/appCenterInstallAppWithSuppliedKey.ts new file mode 100644 index 00000000000..8d136c0f529 --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/appCenterInstallAppWithSuppliedKey.ts @@ -0,0 +1,46 @@ +import { JsonrpcRequest, JsonrpcResponseSuccess } from "src/app/shared/jsonrpc/base"; +import { ComponentJsonApiRequest } from "src/app/shared/jsonrpc/request/componentJsonApiRequest"; +import { AddAppInstance } from "../jsonrpc/addAppInstance"; +import { App } from "./app"; + + +/** + * Gets if a key can be redeemed. + * + *

      + * Note: This Request needs to be wrapped in a appCenter Request. + * + *

      + * Request: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "isKeyApplicable",
      + *   "params": {
      + *     "key": string,
      + *     "appId": string
      + *   }
      + * }
      + * 
      + * + *

      + * Response: AddAppInstance#Response + */ +export namespace AppCenterInstallAppWithSuppliedKeyRequest { + + export const METHOD: string = "installAppWithSuppliedKey"; + + export class Request extends JsonrpcRequest { + + public constructor( + public readonly params: { + installRequest: JsonrpcRequest + } + ) { + super(METHOD, params); + } + } + +} diff --git a/ui/src/app/edge/settings/app/keypopup/appCenterIsAppFree.ts b/ui/src/app/edge/settings/app/keypopup/appCenterIsAppFree.ts new file mode 100644 index 00000000000..c82ad94ebc1 --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/appCenterIsAppFree.ts @@ -0,0 +1,65 @@ +import { JsonrpcRequest, JsonrpcResponseSuccess } from "src/app/shared/jsonrpc/base"; +import { App } from "./app"; + + +/** + * Gets if the key is free. + * + *

      + * Note: This Request needs to be wrapped in a appCenter Request. + * + *

      + * Request: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "isAppFree",
      + *   "params": {
      + *     "appId": string
      + *   }
      + * }
      + * 
      + * + *

      + * Response: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *      isAppFree: boolean
      + *   }
      + * }
      + * 
      + */ +export namespace AppCenterIsAppFree { + + export const METHOD: string = "isAppFree"; + + export class Request extends JsonrpcRequest { + + public constructor( + public readonly params: { + appId: string, + } + ) { + super(METHOD, params); + } + } + + export class Response extends JsonrpcResponseSuccess { + + public constructor( + public readonly id: string, + public readonly result: { + isAppFree: boolean + } + ) { + super(id, result); + } + } + +} diff --git a/ui/src/app/edge/settings/app/keypopup/appCenterIsKeyApplicable.ts b/ui/src/app/edge/settings/app/keypopup/appCenterIsKeyApplicable.ts new file mode 100644 index 00000000000..debb2a6788f --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/appCenterIsKeyApplicable.ts @@ -0,0 +1,91 @@ +import { JsonrpcRequest, JsonrpcResponseSuccess } from "src/app/shared/jsonrpc/base"; +import { App } from "./app"; + + +/** + * Gets if a key can be redeemed. + * + *

      + * Note: This Request needs to be wrapped in a appCenter Request. + * + *

      + * Request: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "isKeyApplicable",
      + *   "params": {
      + *     "key": string,
      + *     "appId": string
      + *   }
      + * }
      + * 
      + * + *

      + * Response: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *      isKeyApplicable: boolean,
      + *      additionalInfo: {
      + *          keyId: string,
      + *          bundles: (App[])[],
      + *          registrations: {
      + *              edgeId: string,
      + *              appId?: string
      + *          }[],
      + *          usages: {
      + *              appId: string,
      + *              installedInstances: number,
      + *          }[]
      + *      }
      + *   }
      + * }
      + * 
      + */ +export namespace AppCenterIsKeyApplicable { + + export const METHOD: string = "isKeyApplicable"; + + export class Request extends JsonrpcRequest { + + public constructor( + public readonly params: { + key: string, + appId: string, + } + ) { + super(METHOD, params); + } + } + + export class Response extends JsonrpcResponseSuccess { + + public constructor( + public readonly id: string, + public readonly result: { + isKeyApplicable: boolean, + additionalInfo: { + keyId: string, + bundles: (App[])[], + registrations: { + edgeId: string, + appId?: string + }[], + usages: { + appId: string, + installedInstances: number + }[] + } + } + ) { + super(id, result); + } + } + +} diff --git a/ui/src/app/edge/settings/app/keypopup/key.ts b/ui/src/app/edge/settings/app/keypopup/key.ts new file mode 100644 index 00000000000..686c464636a --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/key.ts @@ -0,0 +1,6 @@ +import { App } from "./app" + +export type Key = { + keyId: string + bundles?: (App[])[] +} diff --git a/ui/src/app/edge/settings/app/keypopup/modal.component.html b/ui/src/app/edge/settings/app/keypopup/modal.component.html new file mode 100644 index 00000000000..5086a5dd202 --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/modal.component.html @@ -0,0 +1,53 @@ + + + Edge.Config.App.Key.useKey + Edge.Config.App.Key.registerKey + + + + + + + + +
      + + + + + Edge.Config.App.Key.enterKey + + + + + + + + + + + + + General.cancel + + + + + Edge.Config.App.Key.validateKey + + + + Edge.Config.App.Key.registerKey + + Edge.Config.App.Key.useKey + + Edge.Config.App.Key.useKey + + + + + + +
      \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/keypopup/modal.component.ts b/ui/src/app/edge/settings/app/keypopup/modal.component.ts new file mode 100644 index 00000000000..30fa0b4184f --- /dev/null +++ b/ui/src/app/edge/settings/app/keypopup/modal.component.ts @@ -0,0 +1,417 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { Router } from '@angular/router'; +import { ModalController } from '@ionic/angular'; +import { FormlyFieldConfig } from '@ngx-formly/core'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { Edge, Service, Websocket } from 'src/app/shared/shared'; +import { environment } from 'src/environments'; +import { GetApps } from '../jsonrpc/getApps'; +import { AppCenter } from './appCenter'; +import { AppCenterAddRegisterKeyHistory } from './appCenterAddRegisterKeyHistory'; +import { AppCenterGetRegisteredKeys } from './appCenterGetRegisteredKeys'; +import { AppCenterIsKeyApplicable } from './appCenterIsKeyApplicable'; +import { Key } from './key'; + +@Component({ + selector: KeyModalComponent.SELECTOR, + templateUrl: './modal.component.html', +}) +export class KeyModalComponent implements OnInit { + + @Input() public edge: Edge; + @Input() public appId: string | null = null; + @Input() public appName: string | null = null; + @Input() public behaviour: KeyValidationBehaviour; + + @Input() public knownApps: GetApps.App[] | null = null; + + private static readonly SELECTOR = 'key-modal'; + public readonly spinnerId: string = KeyModalComponent.SELECTOR; + + private lastValidKey: AppCenterIsKeyApplicable.Response | null = null; + private registeredKeys: Key[] = [] + + protected form: FormGroup; + protected fields: FormlyFieldConfig[] + protected model; + + constructor( + private service: Service, + protected modalCtrl: ModalController, + private router: Router, + private websocket: Websocket, + private translate: TranslateService + ) { } + + + public ngOnInit(): void { + this.form = new FormGroup({}); + this.model = { + 'useRegisteredKeys': false, + 'registeredKey': '', + 'key': '', + }; + + if (this.behaviour === KeyValidationBehaviour.REGISTER) { + this.fields = this.getFields(); + return; + } + this.service.startSpinner(this.spinnerId); + this.edge.sendRequest(this.websocket, new AppCenter.Request({ + payload: new AppCenterGetRegisteredKeys.Request({ + ...(this.appId && { appId: this.appId }) + }) + })).then(response => { + const result = (response as AppCenterGetRegisteredKeys.Response).result; + this.registeredKeys = result.keys; + this.fields = this.getFields(); + if (this.registeredKeys.length > 0) { + this.model['useRegisteredKeys'] = true; + this.model['registeredKey'] = this.registeredKeys[0].keyId; + } + const selectRegisteredKey = this.fields.find(f => f.key === 'registeredKey'); + this.registeredKeys.forEach(key => { + const desc = this.getDescription(key); + (selectRegisteredKey.props.options as any[]).push({ + value: key.keyId, + label: key.keyId, + description: desc + }); + }); + }).catch(reason => { + this.fields = this.getFields(); + this.service.toast(this.translate.instant('Edge.Config.App.Key.failedLoadingRegisterKey'), 'danger'); + }).finally(() => { + this.service.stopSpinner(this.spinnerId); + }); + } + + private getDescription(key: Key): string | null { + if (!this.knownApps) { + return null; + } + const bundles = key.bundles + if (!bundles) { + return null; + } + if (!bundles.some(bundle => bundle.length != 0)) { + return null; + } + + const appPrefix = environment.edgeShortName + ' App'; + // map to multiple description fields + const descriptionFields = []; + for (const bundle of bundles) { + let isCategorySet = false; + // if multiple apps are in bundle find category which has all the apps + // and set the category name as the description + for (const [catName, apps] of Object.entries(this.getAppsByCategory())) { + if (apps.every(app => { + for (const appFromBundle of bundle) { + if (appFromBundle.appId === app.appId) { + return true; + } + } + return false; + })) { + const category = apps[0].categorys.find(c => c.name === catName); + descriptionFields.push(category.readableName); + isCategorySet = true; + } + } + if (isCategorySet) { + continue; + } + // if apps are not directly of a category, list them + for (const appOfBundle of bundle) { + const app = this.knownApps.find(app => app.appId === appOfBundle.appId); + descriptionFields.push(app.name); + } + } + return descriptionFields.length === 0 ? null : descriptionFields.map(e => appPrefix + ' ' + e).join(", "); + } + + private getAppsByCategory(): { [key: string]: GetApps.App[]; } { + const map: { [key: string]: GetApps.App[]; } = {} + for (const app of this.knownApps) { + for (const category of app.categorys) { + let appList: GetApps.App[] + if (map[category.name]) { + appList = map[category.name] + } else { + appList = [] + map[category.name] = appList + } + appList.push(app) + } + } + return map; + } + + /** + * Gets the input fields. + * + * @returns the input fields + */ + private getFields(): FormlyFieldConfig[] { + const fields: FormlyFieldConfig[] = []; + fields.push({ + key: 'useRegisteredKeys', + type: 'checkbox', + props: { + label: this.translate.instant('Edge.Config.App.Key.useRegisteredKey') + }, + hide: this.registeredKeys.length === 0, + }); + + fields.push({ + key: 'registeredKey', + type: 'select', + props: { + label: this.translate.instant('Edge.Config.App.Key.registeredKey'), + required: true, + options: [] + }, + expressions: { + hide: () => this.registeredKeys.length === 0, + 'props.disabled': field => !field.model.useRegisteredKeys + }, + wrappers: ['formly-select-extended-wrapper'] + }); + + fields.push({ + key: 'key', + type: 'input', + props: { + label: this.translate.instant('Edge.Config.App.Key.key'), + required: true, + placeholder: 'XXXX-XXXX-XXXX-XXXX' + }, + expressions: { + 'templateOptions.disabled': field => field.model.useRegisteredKeys + }, + validators: { + validation: ['key'], + }, + hooks: { + onInit: (field) => { + field.formControl.valueChanges.subscribe((next) => { + const nextInput = KeyModalComponent.transformInput(next) + if (!nextInput) { + return; + } + field.formControl.setValue(nextInput) + }); + } + } + }); + return fields; + } + + /** + * Transformes the input so that the input matches the pattern 'XXXX-XXXX-XXXX-XXXX'. + * + * Prevents the user from typing in an invalid key. + * Gets automatically called when the user types something in. + * + * @param value the value to transform + * @returns the transformed value or null if there was no change to the given value + */ + private static transformInput(value: string): string { + // remove spaces + let trimmed = value.replace(/\s+/g, ''); + + // trimm max length of input + if (trimmed.length > 19) { + trimmed = trimmed.substring(0, 19); + } + + // remove last dash + let hasDashAsLastChar = trimmed.substring(trimmed.length - 1, trimmed.length) == "-" + trimmed = trimmed.replace(/-/g, ''); + + let numbers = []; + + // push single parts into array + numbers.push(trimmed.substring(0, 4)); + if (trimmed.substring(4, 8) !== '') numbers.push(trimmed.substring(4, 8)); + if (trimmed.substring(8, 12) != '') numbers.push(trimmed.substring(8, 12)); + if (trimmed.substring(12, 16) != '') numbers.push(trimmed.substring(12, 16)); + + // join parts so it matches 'XXXX-XXXX-XXXX-XXXX' + let modifiedValue = numbers.join('-'); + // readd last + if (hasDashAsLastChar) { + modifiedValue += '-'; + } + + // if there was no change to the original value return null + if (modifiedValue === value) { + return null; + } + return modifiedValue; + } + + + /** + * Depending on the behaviour: + * + * KeyValidationBehaviour.NAVIGATE: + * navigates to the install page of the app and passes the key + * + * KeyValidationBehaviour.REGISTER: + * registers the entered key for the passed app + * + * KeyValidationBehaviour.SELECT: + * if a valid key gets selected it gets returned + */ + protected onClickCreateApp(): void { + switch (this.behaviour) { + case KeyValidationBehaviour.NAVIGATE: + this.service.startSpinner(this.spinnerId); + this.modalCtrl.dismiss({ 'key': this.getSelectedKey() }); + // navigate to App install view and pass valid key + this.router.navigate(['device/' + (this.edge.id) + '/settings/app/install/' + this.appId] + , { queryParams: { name: this.appName }, state: { appKey: this.getRawAppKey() } }); + this.service.stopSpinner(this.spinnerId); + break; + case KeyValidationBehaviour.REGISTER: + this.service.startSpinner(this.spinnerId); + // only register key for this app + this.registerKey().then(() => { + this.modalCtrl.dismiss({ 'key': this.getSelectedKey() }); + this.service.toast(this.translate.instant('Edge.Config.App.Key.successRegisterKey'), 'success'); + }).catch(() => { + this.service.toast(this.translate.instant('Edge.Config.App.Key.failedRegisterKey'), 'danger'); + }).finally(() => { + this.service.stopSpinner(this.spinnerId); + }); + break; + case KeyValidationBehaviour.SELECT: + this.modalCtrl.dismiss({ key: this.getSelectedKey() }); + } + } + + private registerKey(): Promise { + return new Promise((resolve, reject) => { + // key already registered + if (this.lastValidKey?.result.additionalInfo.keyId === this.getRawAppKey() + && this.lastValidKey.result.additionalInfo.registrations.some(registration => { + return registration.edgeId === this.edge.id && registration.appId === this.appId; + })) { + resolve() + return; + } + // only register key for this app + this.edge.sendRequest(this.websocket, new AppCenter.Request({ + payload: new AppCenterAddRegisterKeyHistory.Request({ + key: this.getRawAppKey(), + ...(this.appId && { appId: this.appId }), + }) + })).then(() => { + resolve(); + }).catch(reason => { + reject(reason); + }) + }); + } + + /** + * Gets the selected key. + * + * @returns the selected key + */ + private getSelectedKey() { + if (this.model['useRegisteredKeys']) { + return this.registeredKeys.find(k => k.keyId === this.getRawAppKey()) + } else { + return { keyId: this.getRawAppKey() } + } + } + + /** + * Validates the currently entered key. + */ + protected validateKey(): void { + if (this.form.invalid) { + return + } + const appKey = this.getRawAppKey(); + const request = new AppCenter.Request({ + payload: new AppCenterIsKeyApplicable.Request({ key: appKey, appId: this.appId }) + }); + + this.service.startSpinner(this.spinnerId); + this.edge.sendRequest(this.websocket, request) + .then((response) => { + const result = (response as AppCenterIsKeyApplicable.Response).result; + if (result.isKeyApplicable) { + this.lastValidKey = (response as AppCenterIsKeyApplicable.Response); + + if (result.additionalInfo.registrations.length !== 0 + && this.behaviour === KeyValidationBehaviour.REGISTER) { + const differentEdge = result.additionalInfo.registrations.some(registration => { + return registration.edgeId !== this.edge.id; + }); + if (differentEdge) { + this.service.toast(this.translate.instant('Edge.Config.App.Key.alreadyRegisteredDifferentSystem'), 'warning'); + return; + } + const sameApp = result.additionalInfo.registrations.some(registration => { + return registration.appId === this.appId && registration.edgeId === this.edge.id; + }); + if (!sameApp) { + this.service.toast(this.translate.instant('Edge.Config.App.Key.alreadyRegisteredDifferentApp'), 'warning'); + return; + } + } + + this.service.toast(this.translate.instant('Edge.Config.App.Key.valid'), 'success'); + } else { + this.service.toast(this.translate.instant('Edge.Config.App.Key.invalid'), 'danger'); + } + }).catch(reason => { + // this may happen if the key is not stored in the database + this.service.toast(this.translate.instant('Edge.Config.App.Key.invalid'), 'danger'); + if (environment.debugMode) { + console.log('Failed to validate Key', reason); + } + }).finally(() => { + this.service.stopSpinner(this.spinnerId); + }); + } + + /** + * Gets the currently entered key. + * + * @returns the entered key + */ + private getRawAppKey(): string { + if (this.model['useRegisteredKeys']) { + return this.model['registeredKey'] + } else { + return this.model['key'] + } + } + + /** + * Determines if the current selected key is valid. + * + * @returns true if the current selected key is valid + */ + protected isKeyValid(): boolean { + if (this.model['useRegisteredKeys']) { + return true + } + return this.lastValidKey !== null && this.getRawAppKey() === this.lastValidKey.result.additionalInfo.keyId; + }; + +} + +export enum KeyValidationBehaviour { + REGISTER = 0, + NAVIGATE = 1, + SELECT = 2, +} \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/permissions.ts b/ui/src/app/edge/settings/app/permissions.ts new file mode 100644 index 00000000000..ff66242eee3 --- /dev/null +++ b/ui/src/app/edge/settings/app/permissions.ts @@ -0,0 +1,35 @@ +import { User } from "src/app/shared/jsonrpc/shared"; +import { Edge } from "src/app/shared/shared"; +import { Role } from "src/app/shared/type/role"; + +const keyTestUsers: string[] = [ +] + +function isTestUser(user: User): boolean { + return keyTestUsers.some((id) => { + return user.id === id + }); +} + +export function canSeeAppCenter(edge: Edge): boolean { + return edge.roleIsAtLeast(Role.ADMIN) + && edge.isVersionAtLeast('2022.1.0'); +} + +export function canEnterKey(edge: Edge, user: User): boolean { + if (isTestUser(user)) { + return true; + } + return false +} + +export function hasPredefinedKey(edge: Edge, user: User): boolean { + if (isTestUser(user)) { + return false; + } + return edge.roleIsAtLeast(Role.ADMIN); +} + +export function hasKeyModel(edge: Edge): boolean { + return edge.isVersionAtLeast('2023.1.2') +} \ No newline at end of file diff --git a/ui/src/app/edge/settings/app/single.component.html b/ui/src/app/edge/settings/app/single.component.html index 590f18f4d05..e56481b3340 100644 --- a/ui/src/app/edge/settings/app/single.component.html +++ b/ui/src/app/edge/settings/app/single.component.html @@ -17,34 +17,26 @@
      -
      + +
      Edge.Config.App.buyApp
      +
      + + Edge.Config.App.Key.registerKey +
      Edge.Config.App.modifyApp
      -
      - - Edge.Config.App.createApp - +
      + Edge.Config.App.createApp
      -
      -
      - Edge.Config.App.errorCompatible
      - - {{ message - }}
      -
      -
      - Edge.Config.App.errorInstallable
      - - {{ message - }}
      -
      -
      diff --git a/ui/src/app/edge/settings/app/single.component.ts b/ui/src/app/edge/settings/app/single.component.ts index 86e9f488ecd..801ac457e47 100644 --- a/ui/src/app/edge/settings/app/single.component.ts +++ b/ui/src/app/edge/settings/app/single.component.ts @@ -1,87 +1,177 @@ -import { Component, HostListener, OnInit } from '@angular/core'; +import { Component, HostListener, OnDestroy, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { DomSanitizer } from '@angular/platform-browser'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; +import { ModalController } from '@ionic/angular'; +import { Subject } from 'rxjs'; +import { filter, takeUntil } from 'rxjs/operators'; import { ComponentJsonApiRequest } from 'src/app/shared/jsonrpc/request/componentJsonApiRequest'; import { Edge, Service, Utils, Websocket } from '../../../shared/shared'; import { GetApp } from './jsonrpc/getApp'; import { GetAppDescriptor } from './jsonrpc/getAppDescriptor'; import { GetApps } from './jsonrpc/getApps'; +import { AppCenter } from './keypopup/appCenter'; +import { AppCenterGetPossibleApps } from './keypopup/appCenterGetPossibleApps'; +import { AppCenterIsAppFree } from './keypopup/appCenterIsAppFree'; +import { KeyModalComponent, KeyValidationBehaviour } from './keypopup/modal.component'; +import { canEnterKey, hasKeyModel, hasPredefinedKey } from './permissions'; @Component({ selector: SingleAppComponent.SELECTOR, templateUrl: './single.component.html' }) -export class SingleAppComponent implements OnInit { +export class SingleAppComponent implements OnInit, OnDestroy { - private static readonly SELECTOR = "appSingle"; + private static readonly SELECTOR = 'app-single'; public readonly spinnerId: string = SingleAppComponent.SELECTOR; public form: FormGroup | null = null; public model: any | null = null; private appId: string | null = null; + private appName: string | null = null; private app: GetApps.App | null = null; private descriptor: GetAppDescriptor.AppDescriptor | null = null; private isXL: boolean = true; // for stopping spinner when all responses are recieved - private readonly requestCount: number = 2; - private recievedResponse: number = 0; + private readonly requestCount: number = 3; + private receivedResponse: number = 0; private edge: Edge | null = null; + private key: string | null = null; + + protected canEnterKey: boolean | undefined + protected hasPredefinedKey: boolean | undefined + + private stopOnDestroy: Subject = new Subject() + protected keyForFreeApps: string + protected isFreeApp: boolean = false + protected isPreInstalledApp: boolean = false + public constructor( private route: ActivatedRoute, + private router: Router, protected utils: Utils, private websocket: Websocket, private service: Service, - private sanitizer: DomSanitizer + private sanitizer: DomSanitizer, + protected modalController: ModalController ) { } public ngOnInit() { this.service.startSpinner(this.spinnerId); this.updateIsXL(); - this.appId = this.route.snapshot.params["appId"]; - let appName = this.route.snapshot.queryParams['name']; + + this.appId = this.route.snapshot.params['appId']; + this.appName = this.route.snapshot.queryParams['name']; let appId = this.appId; - this.service.setCurrentComponent(appName, this.route).then(edge => { + this.service.setCurrentComponent(this.appName, this.route).then(edge => { this.edge = edge; + this.edge.sendRequest(this.websocket, + new AppCenter.Request({ + payload: new AppCenterIsAppFree.Request({ + appId: this.appId + }) + }) + ).then(response => { + const result = (response as AppCenterIsAppFree.Response).result; + this.isFreeApp = result.isAppFree; + }).catch(() => { + this.isFreeApp = false; + }); + + // update if the app is free depending of the configured key in the edge config + if (hasKeyModel(this.edge)) { + this.edge.getConfig(this.websocket).pipe( + filter(config => config !== null), + takeUntil(this.stopOnDestroy) + ).subscribe(next => { + let appManager = next.getComponent("_appManager") + let newKeyForFreeApps = appManager.properties["keyForFreeApps"] + if (!newKeyForFreeApps) { + // no key in config + this.increaseReceivedResponse(); + } + if (this.keyForFreeApps === newKeyForFreeApps) { + return; + } + this.keyForFreeApps = newKeyForFreeApps + // update free apps + this.edge.sendRequest(this.websocket, new AppCenter.Request({ + payload: new AppCenterGetPossibleApps.Request({ + key: this.keyForFreeApps + }) + })).then(response => { + const result = (response as AppCenterGetPossibleApps.Response).result; + this.isPreInstalledApp = result.bundles.some(bundle => { + return bundle.some(app => { + return app.appId == this.appId + }) + }) + }).finally(() => { + this.increaseReceivedResponse(); + }) + }) + } else { + this.isPreInstalledApp = false; + this.increaseReceivedResponse(); + } + + this.service.metadata + .pipe(takeUntil(this.stopOnDestroy)) + .subscribe(entry => { + this.canEnterKey = canEnterKey(edge, entry.user); + this.hasPredefinedKey = hasPredefinedKey(edge, entry.user); + }); + // set appname, image ... - if ('appId' in history.state) { - this.setApp(history.state) + const state = history?.state + if (state && 'app' in history.state) { + if ('app' in history.state) { + this.setApp(history.state['app']) + } + if ('appKey' in history.state) { + this.key = history.state['appKey'] + } } else { edge.sendRequest(this.websocket, new ComponentJsonApiRequest({ - componentId: "_appManager", + componentId: '_appManager', payload: new GetApp.Request({ appId: appId }) })).then(response => { let app = (response as GetApp.Response).result.app; this.setApp(app) }).catch(reason => { console.error(reason.error); - this.service.toast("Error while receiving App[" + appId + "]: " + reason.error.message, 'danger'); + this.service.toast('Error while receiving App[' + appId + ']: ' + reason.error.message, 'danger'); }); } // set app descriptor edge.sendRequest(this.websocket, new ComponentJsonApiRequest({ - componentId: "_appManager", + componentId: '_appManager', payload: new GetAppDescriptor.Request({ appId: appId }) })).then(response => { let descriptor = (response as GetAppDescriptor.Response).result; this.descriptor = GetAppDescriptor.postprocess(descriptor, this.sanitizer); }).catch(reason => { console.error(reason.error); - this.service.toast("Error while receiving AppDescriptor for App[" + appId + "]: " + reason.error.message, 'danger'); + this.service.toast('Error while receiving AppDescriptor for App[' + appId + ']: ' + reason.error.message, 'danger'); }).finally(() => { - this.increaseRecievedResponse(); + this.increaseReceivedResponse(); }); }); } + public ngOnDestroy(): void { + this.stopOnDestroy.next(); + this.stopOnDestroy.complete(); + } + @HostListener('window:resize', ['$event']) private onResize(event) { this.updateIsXL(); @@ -101,15 +191,52 @@ export class SingleAppComponent implements OnInit { private setApp(app: GetApps.App) { this.app = app; this.form = new FormGroup({}); - this.increaseRecievedResponse(); + this.increaseReceivedResponse(); } - private increaseRecievedResponse() { - this.recievedResponse++; - if (this.recievedResponse == this.requestCount) { - this.recievedResponse = 0; + private increaseReceivedResponse() { + this.receivedResponse++; + if (this.receivedResponse == this.requestCount) { + this.receivedResponse = 0; this.service.stopSpinner(this.spinnerId); } } -} \ No newline at end of file + // popup for key + private async presentModal(appId: string, behaviour: KeyValidationBehaviour) { + const modal = await this.modalController.create({ + component: KeyModalComponent, + componentProps: { + edge: this.edge, + appId: appId, + behaviour: behaviour, + appName: this.appName + }, + cssClass: 'auto-height' + }); + return await modal.present(); + } + + protected installApp(appId: string) { + if (this.key != null) { + let key = this.key + // if key already set navigate directly to installation view + this.router.navigate(['device/' + (this.edge.id) + '/settings/app/install/' + this.appId] + , { queryParams: { name: this.appName }, state: { appKey: key } }); + return; + } + // if the version is not high enough and the edge doesnt support installing apps via keys directly navigate to installation + if (!hasKeyModel(this.edge) || this.hasPredefinedKey || this.isFreeApp) { + this.router.navigate(['device/' + (this.edge.id) + '/settings/app/install/' + this.appId] + , { queryParams: { name: this.appName } }); + return; + } + // show modal to let the user enter a key + this.presentModal(appId, KeyValidationBehaviour.NAVIGATE) + } + + protected registerKey(appId: string) { + this.presentModal(appId, KeyValidationBehaviour.REGISTER) + } + +} diff --git a/ui/src/app/edge/settings/app/update.component.html b/ui/src/app/edge/settings/app/update.component.html index 1a722b5ce2c..ab1982ac6ef 100644 --- a/ui/src/app/edge/settings/app/update.component.html +++ b/ui/src/app/edge/settings/app/update.component.html @@ -1,26 +1,29 @@
      - +
      - {{ appName }} + {{ appName }} Edge.Config.App.updateApp - + Edge.Config.App.deleteApp +
      +
      +
      diff --git a/ui/src/app/edge/settings/app/update.component.ts b/ui/src/app/edge/settings/app/update.component.ts index 767a2d0aa45..8daceda0e2a 100644 --- a/ui/src/app/edge/settings/app/update.component.ts +++ b/ui/src/app/edge/settings/app/update.component.ts @@ -1,7 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { FormlyFieldConfig } from '@ngx-formly/core'; +import { TranslateService } from '@ngx-translate/core'; import { ComponentJsonApiRequest } from 'src/app/shared/jsonrpc/request/componentJsonApiRequest'; import { Edge, Service, Utils, Websocket } from '../../../shared/shared'; import { DeleteAppInstance } from './jsonrpc/deleteAppInstance'; @@ -13,7 +14,7 @@ interface MyInstance { instanceId: string, // uuid form: FormGroup, isDeleting: boolean, - isUpdateting: boolean, + isUpdating: boolean, fields: FormlyFieldConfig[] properties: {}, } @@ -24,7 +25,7 @@ interface MyInstance { }) export class UpdateAppComponent implements OnInit { - private static readonly SELECTOR = "appUpdate"; + private static readonly SELECTOR = 'app-update'; public readonly spinnerId: string = UpdateAppComponent.SELECTOR; protected instances: MyInstance[] = []; @@ -39,6 +40,8 @@ export class UpdateAppComponent implements OnInit { protected utils: Utils, private websocket: Websocket, private service: Service, + private router: Router, + private translate: TranslateService, ) { } @@ -50,14 +53,14 @@ export class UpdateAppComponent implements OnInit { this.edge = edge; edge.sendRequest(this.websocket, new ComponentJsonApiRequest({ - componentId: "_appManager", + componentId: '_appManager', payload: new GetAppInstances.Request({ appId: appId }) })).then(response => { let recInstances = (response as GetAppInstances.Response).result.instances; edge.sendRequest(this.websocket, new ComponentJsonApiRequest({ - componentId: "_appManager", + componentId: '_appManager', payload: new GetAppAssistant.Request({ appId: appId }) })).then(response2 => { let appAssistant = GetAppAssistant.postprocess((response2 as GetAppAssistant.Response).result); @@ -68,14 +71,11 @@ export class UpdateAppComponent implements OnInit { this.forms.push(form) const clonedFields = []; appAssistant.fields.forEach(val => clonedFields.push(Object.assign({}, val))); - // insert alias field into fields - let aliasField = { key: "ALIAS", type: "input", templateOptions: { label: "Alias" }, defaultValue: instance.alias }; - clonedFields.splice(0, 0, aliasField) this.instances.push({ instanceId: instance.instanceId, form: form, isDeleting: false, - isUpdateting: false, + isUpdating: false, fields: clonedFields, properties: instance.properties, }) @@ -85,67 +85,72 @@ export class UpdateAppComponent implements OnInit { }).catch(reason => { console.error(reason.error); - this.service.toast("Error while receiving App Assistant for [" + appId + "]: " + reason.error.message, 'danger'); + this.service.toast('Error while receiving App Assistant for [' + appId + ']: ' + reason.error.message, 'danger'); }); }).catch(reason => { console.error(reason.error); - this.service.toast("Error while receiving App-Instances for [" + appId + "]: " + reason.error.message, 'danger'); + this.service.toast('Error while receiving App-Instances for [' + appId + ']: ' + reason.error.message, 'danger'); }); }); } protected submit(instance: MyInstance) { - instance.isUpdateting = true + this.service.startSpinnerTransparentBackground(instance.instanceId); + instance.isUpdating = true // remove alias field from properties - let alias = instance.form.value["ALIAS"] + let alias = instance.form.value['ALIAS'] const clonedFields = {}; for (let item in instance.form.value) { - if (item != "ALIAS") { + if (item != 'ALIAS') { clonedFields[item] = instance.form.value[item] } } instance.form.markAsPristine(); this.edge.sendRequest(this.websocket, new ComponentJsonApiRequest({ - componentId: "_appManager", + componentId: '_appManager', payload: new UpdateAppInstance.Request({ instanceId: instance.instanceId, alias: alias, properties: clonedFields }) })).then(response => { - var res = (response as UpdateAppInstance.Response); + const result = (response as UpdateAppInstance.Response).result; - if (res.result.warnings && res.result.warnings.length > 0) { - this.service.toast(res.result.warnings.join(";"), 'warning'); + if (result.warnings && result.warnings.length > 0) { + this.service.toast(result.warnings.join(';'), 'warning'); } else { - this.service.toast("Successfully updated App", 'success'); + this.service.toast(this.translate.instant('Edge.Config.App.successUpdate'), 'success'); } - instance.properties = res.result.instance.properties - instance.properties["ALIAS"] = res.result.instance.alias - instance.isUpdateting = false + instance.properties = result.instance.properties; + instance.properties['ALIAS'] = result.instance.alias; }).catch(reason => { - this.service.toast("Error updating App:" + reason.error.message, 'danger'); - instance.isUpdateting = false + this.service.toast(this.translate.instant('Edge.Config.App.failUpdate', { error: reason.error.message }), 'danger'); + }).finally(() => { + instance.isUpdating = false + this.service.stopSpinner(instance.instanceId); }); } protected delete(instance: MyInstance) { + this.service.startSpinnerTransparentBackground(instance.instanceId); instance.isDeleting = true this.edge.sendRequest(this.websocket, new ComponentJsonApiRequest({ - componentId: "_appManager", + componentId: '_appManager', payload: new DeleteAppInstance.Request({ instanceId: instance.instanceId }) })).then(response => { - this.instances.splice(this.instances.indexOf(instance), 1) - this.service.toast("Successfully deleted App", 'success'); + this.instances.splice(this.instances.indexOf(instance), 1); + this.service.toast(this.translate.instant('Edge.Config.App.successDelete'), 'success'); + this.router.navigate(['device/' + (this.edge.id) + '/settings/app/']); }).catch(reason => { - this.service.toast("Error deleting App:" + reason.error.message, 'danger'); + this.service.toast(this.translate.instant('Edge.Config.App.failDelete', { error: reason.error.message }), 'danger'); }).finally(() => { instance.isDeleting = false + this.service.stopSpinner(instance.instanceId); }) } -} \ No newline at end of file +} diff --git a/ui/src/app/edge/settings/component/update/index.component.ts b/ui/src/app/edge/settings/component/update/index.component.ts index fd62ccaa2bd..514155944b2 100644 --- a/ui/src/app/edge/settings/component/update/index.component.ts +++ b/ui/src/app/edge/settings/component/update/index.component.ts @@ -1,8 +1,7 @@ +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { CategorizedComponents } from 'src/app/shared/edge/edgeconfig'; -import { Component } from '@angular/core'; -import { Service, Utils, EdgeConfig } from '../../../../shared/shared'; -import { TranslateService } from '@ngx-translate/core'; +import { EdgeConfig, Service, Utils } from '../../../../shared/shared'; interface MyCategorizedComponents extends CategorizedComponents { isNatureClicked?: Boolean, @@ -13,7 +12,7 @@ interface MyCategorizedComponents extends CategorizedComponents { selector: IndexComponent.SELECTOR, templateUrl: './index.component.html' }) -export class IndexComponent { +export class IndexComponent implements OnInit { private static readonly SELECTOR = "indexComponentUpdate"; @@ -24,12 +23,11 @@ export class IndexComponent { constructor( private route: ActivatedRoute, - private service: Service, - private translate: TranslateService + private service: Service ) { } - ionViewWillEnter() { + public ngOnInit() { this.service.setCurrentComponent({ languageKey: 'Edge.Config.Index.adjustComponents' }, this.route); this.service.getConfig().then(config => { this.config = config; diff --git a/ui/src/app/edge/settings/profile/profile.component.ts b/ui/src/app/edge/settings/profile/profile.component.ts index 0a9abb64a07..b54e51c4e5c 100644 --- a/ui/src/app/edge/settings/profile/profile.component.ts +++ b/ui/src/app/edge/settings/profile/profile.component.ts @@ -1,6 +1,6 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { PopoverController } from '@ionic/angular'; +import { PopoverController, ViewWillEnter } from '@ionic/angular'; import { TranslateService } from '@ngx-translate/core'; import { CategorizedComponents } from 'src/app/shared/edge/edgeconfig'; import { JsonrpcResponseError } from 'src/app/shared/jsonrpc/base'; @@ -15,7 +15,7 @@ import { GetModbusProtocolExportXlsxRequest } from './modbusapi/getModbusProtoco selector: ProfileComponent.SELECTOR, templateUrl: './profile.component.html' }) -export class ProfileComponent { +export class ProfileComponent implements OnInit { private static readonly SELECTOR = "profile"; @@ -34,7 +34,7 @@ export class ProfileComponent { private translate: TranslateService, ) { } - ionViewWillEnter() { + public ngOnInit() { this.service.setCurrentComponent({ languageKey: 'Edge.Config.Index.systemProfile' }, this.route).then(edge => { this.edge = edge; this.service.getConfig().then(config => { diff --git a/ui/src/app/edge/settings/settings.component.html b/ui/src/app/edge/settings/settings.component.html index aa0367f0ca6..613c0ecc6f3 100644 --- a/ui/src/app/edge/settings/settings.component.html +++ b/ui/src/app/edge/settings/settings.component.html @@ -118,7 +118,7 @@
      - + diff --git a/ui/src/app/edge/settings/settings.component.ts b/ui/src/app/edge/settings/settings.component.ts index 215b6ecc586..dbf745a231e 100644 --- a/ui/src/app/edge/settings/settings.component.ts +++ b/ui/src/app/edge/settings/settings.component.ts @@ -1,18 +1,21 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ProductType } from 'src/app/shared/type/widget'; import { environment } from 'src/environments'; import { Edge, Service, Utils } from '../../shared/shared'; +import { canSeeAppCenter } from './app/permissions'; @Component({ selector: 'settings', templateUrl: './settings.component.html' }) -export class SettingsComponent { +export class SettingsComponent implements OnInit { public edge: Edge = null; public environment = environment; + public canSeeAppCenter: boolean | undefined + constructor( private route: ActivatedRoute, protected utils: Utils, @@ -20,9 +23,10 @@ export class SettingsComponent { ) { } - ionViewWillEnter() { + public ngOnInit() { this.service.setCurrentComponent({ languageKey: 'Menu.edgeSettings' }, this.route).then(edge => { this.edge = edge + this.canSeeAppCenter = canSeeAppCenter(this.edge) }); } } diff --git a/ui/src/app/edge/settings/settings.module.ts b/ui/src/app/edge/settings/settings.module.ts index 461fbfefbdd..4604342a290 100644 --- a/ui/src/app/edge/settings/settings.module.ts +++ b/ui/src/app/edge/settings/settings.module.ts @@ -1,4 +1,5 @@ import { NgModule } from '@angular/core'; +import { ChangelogModule } from 'src/app/changelog/changelog.module'; import { SharedModule } from './../../shared/shared.module'; import { AlertingComponent } from './alerting/alerting.component'; import { AppModule } from './app/app.module'; @@ -19,6 +20,7 @@ import { SystemUpdateComponent } from './systemupdate/systemupdate.component'; imports: [ AppModule, SharedModule, + ChangelogModule ], declarations: [ AliasUpdateComponent, diff --git a/ui/src/app/edge/settings/systemupdate/systemupdate.component.html b/ui/src/app/edge/settings/systemupdate/systemupdate.component.html index 5479acbc508..53947cd4a75 100644 --- a/ui/src/app/edge/settings/systemupdate/systemupdate.component.html +++ b/ui/src/app/edge/settings/systemupdate/systemupdate.component.html @@ -9,7 +9,7 @@ - System Update + Systemupdate für {{ edge.id }} diff --git a/ui/src/app/index/index.component.html b/ui/src/app/index/index.component.html index 285a08b9397..f3b09856b14 100644 --- a/ui/src/app/index/index.component.html +++ b/ui/src/app/index/index.component.html @@ -112,7 +112,8 @@ - + @@ -120,37 +121,37 @@ - - - - -

      {{ edge.comment }}

      -

      - Index.deviceOffline - - Index.OFFLINE_SINCE - {{edge.lastmessage | date:'dd.MM.yyyy HH:mm'}} - -

      -
      - - -

      ID: {{ edge.id }}

      + + + + + +

      {{ edge.comment }}

      +

      + Index.deviceOffline + + Index.OFFLINE_SINCE + {{edge.lastmessage | date:'dd.MM.yyyy HH:mm'}} + +

      +
      + + +

      ID: {{ edge.id }}

      +

      + Index.type {{ edge.producttype }} +

      +

      - Index.type {{ edge.producttype }} + Index.loggedInAs {{ edge.getRoleString() }}.

      -
      -

      - Index.loggedInAs {{ edge.getRoleString() }}. -

      -
      - -
      - - - + + +
      + + + diff --git a/ui/src/app/index/index.component.ts b/ui/src/app/index/index.component.ts index 2e6d0f7963b..51cc7335775 100644 --- a/ui/src/app/index/index.component.ts +++ b/ui/src/app/index/index.component.ts @@ -1,9 +1,11 @@ -import { Component } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; +import { InfiniteScrollCustomEvent } from '@ionic/angular'; import { Subject } from 'rxjs'; -import { filter, takeUntil } from 'rxjs/operators'; +import { filter, take } from 'rxjs/operators'; import { environment } from 'src/environments'; + import { AuthenticateWithPasswordRequest } from '../shared/jsonrpc/request/authenticateWithPasswordRequest'; import { Edge, Service, Utils, Websocket } from '../shared/shared'; import { Role } from '../shared/type/role'; @@ -12,9 +14,7 @@ import { Role } from '../shared/type/role'; selector: 'index', templateUrl: './index.component.html' }) -export class IndexComponent { - - private static readonly EDGE_ID_REGEXP = new RegExp('\\d+'); +export class IndexComponent implements OnInit, OnDestroy { public environment = environment; @@ -30,12 +30,22 @@ export class IndexComponent { public loggedInUserCanInstall: boolean = false; public form: FormGroup; - public filter: string = ''; public filteredEdges: Edge[] = []; - protected formIsDisabled: boolean = false; + private stopOnDestroy: Subject = new Subject(); - public slice: number = 20; + private page = 0; + private query: string | null = null; + + /** Limits edges in pagination response */ + private readonly limit: number = 20; + /** True, if all available edges for this user had been retrieved */ + private limitReached: boolean = false; + + protected formIsDisabled: boolean = false; + protected onlyOneEdgeAvailable: boolean = false; + protected spinnerId: string = 'index'; + protected loading: boolean = false; constructor( public service: Service, @@ -43,61 +53,50 @@ export class IndexComponent { public utils: Utils, private router: Router, private route: ActivatedRoute, - ) { - service.metadata - .pipe( - takeUntil(this.stopOnDestroy), - filter(metadata => metadata != null) - ) - .subscribe(metadata => { - let edgeIds = Object.keys(metadata.edges); - this.noEdges = edgeIds.length === 0; - this.loggedInUserCanInstall = Role.isAtLeast(metadata.user.globalRole, "installer"); - - // Forward directly to device page, if - // - Direct local access to Edge - // - No installer (i.e. guest or owner) and access to only one Edge - if (environment.backend == 'OpenEMS Edge' || (!this.loggedInUserCanInstall && edgeIds.length == 1)) { - let edge = metadata.edges[edgeIds[0]]; - if (edge.isOnline) { - this.router.navigate(['/device', edge.id]); - } - } + ) { } - this.updateFilteredEdges(); - }) + ngOnInit() { + this.page = 0; + this.filteredEdges = []; + this.limitReached = false; + this.service.metadata.pipe(filter(metadata => !!metadata), take(1)).subscribe(() => { + this.init() + }) } - updateFilteredEdges() { - let filter = this.filter.toLowerCase(); - let allEdges = this.service.metadata.value?.edges ?? {}; - this.filteredEdges = Object.keys(allEdges) - .filter(edgeId => { - let edge = allEdges[edgeId]; - if (/* name */ edge.id.toLowerCase().includes(filter) - || /* comment */ edge.comment.toLowerCase().includes(filter) - || /* producttype */ edge.producttype.toLowerCase().includes(filter)) { - return true; - } - return false; - }) - .sort((edge1, edge2) => { - // first: try to compare the number, e.g. 'edge5' < 'edge100' - let e1match = edge1.match(IndexComponent.EDGE_ID_REGEXP) - if (e1match != null) { - let e2match = edge2.match(IndexComponent.EDGE_ID_REGEXP) - if (e2match != null) { - let e1 = Number(e1match[0]); - let e2 = Number(e2match[0]); - if (!isNaN(e1) && !isNaN(e2)) { - return e1 - e2; - } - } + async ionViewWillEnter() { + + // Execute Login-Request if url path matches 'demo' + if (this.route.snapshot.routeConfig.path == 'demo') { + + // Wait for Websocket + await new Promise((resolve) => setTimeout(() => { + if (this.websocket.status == 'waiting for credentials') { + resolve(this.websocket.login(new AuthenticateWithPasswordRequest({ username: 'admin', password: 'admin' }))) } - // second: apply 'natural sort' - return edge1.localeCompare(edge2); - }) - .map(edgeId => allEdges[edgeId]); + }, 2000)).then(() => { this.service.setCurrentComponent('', this.route) }); + } else { + this.service.setCurrentComponent('', this.route); + } + } + + /** + * Search on change, triggered by searchbar input-event. + * + * @param event from template passed event + */ + protected searchOnChange(event) { + this.filteredEdges = []; + this.page = 0; + this.limitReached = false; + + const query = event.target.value.toLowerCase(); + this.query = query; + + this.loadNextPage().then((edges) => { + this.filteredEdges = edges + this.page++; + }) } /** @@ -106,21 +105,89 @@ export class IndexComponent { * @param param data provided in login form */ public doLogin(param: { username?: string, password: string }) { + + this.limitReached = false; + + // Prevent that user submits via keyevent 'enter' multiple times + if (this.formIsDisabled) { + return + } + this.formIsDisabled = true; - this.websocket.login(new AuthenticateWithPasswordRequest(param)).then(() => { - this.formIsDisabled = false; + this.websocket.login(new AuthenticateWithPasswordRequest(param)) + .finally(() => { + + // Unclean + this.ngOnInit(); + this.formIsDisabled = false + }); + } + + private init() { + this.loadNextPage().then((edges) => { + this.service.metadata + .pipe( + filter(metadata => !!metadata), + take(1) + ) + .subscribe(metadata => { + + let edgeIds = Object.keys(metadata.edges); + this.onlyOneEdgeAvailable = edgeIds.length <= 1; + this.noEdges = edgeIds.length === 0; + this.loggedInUserCanInstall = Role.isAtLeast(metadata.user.globalRole, "installer"); + + // Forward directly to device page, if + // - Direct local access to Edge + // - No installer (i.e. guest or owner) and access to only one Edge + if (environment.backend == 'OpenEMS Edge' || (!this.loggedInUserCanInstall && edgeIds.length == 1)) { + let edge = metadata.edges[edgeIds[0]]; + this.router.navigate(['/device', edge.id]); + return + } + this.filteredEdges = edges; + }) }) } - doInfinite(infiniteScroll) { + /** + * Updates available edges on scroll-event + * + * @param infiniteScroll the InfiniteScrollCustomEvent + */ + doInfinite(infiniteScroll: InfiniteScrollCustomEvent) { setTimeout(() => { - this.slice += 5; - infiniteScroll.target.complete(); + this.page++; + this.loadNextPage().then((edges) => { + this.filteredEdges.push(...edges); + infiniteScroll.target.complete(); + }).catch(() => { + infiniteScroll.target.complete(); + }) }, 200); } - onDestroy() { + ngOnDestroy() { this.stopOnDestroy.next(); this.stopOnDestroy.complete(); } + + loadNextPage(): Promise { + + this.loading = true; + return new Promise((resolve, reject) => { + if (this.limitReached) { + resolve([]) + return + } + this.service.getEdges(this.page, this.query, this.limit) + .then((edges) => { + this.limitReached = edges.length < this.limit; + resolve(edges) + }).catch((err) => { + reject(err) + }) + }).finally(() => + this.loading = false) + } } \ No newline at end of file diff --git a/ui/src/app/shared/formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper.html b/ui/src/app/shared/formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper.html new file mode 100644 index 00000000000..a590984e1f7 --- /dev/null +++ b/ui/src/app/shared/formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper.html @@ -0,0 +1,17 @@ + + + + + + {{props.label}} {{secondLabel}} + + + + + + + + + + \ No newline at end of file diff --git a/ui/src/app/shared/formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper.ts b/ui/src/app/shared/formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper.ts new file mode 100644 index 00000000000..9708b8b8003 --- /dev/null +++ b/ui/src/app/shared/formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper.ts @@ -0,0 +1,27 @@ +import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core'; +import { FieldWrapper } from '@ngx-formly/core'; + +@Component({ + selector: 'form-field-checkbox-hyperlink', + templateUrl: './form-field-checkbox-hyperlink.wrapper.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class FormlyCheckBoxHyperlinkWrapperComponent extends FieldWrapper implements OnInit { + + protected secondLabel: string; + + public ngOnInit() { + // If the default value is not set in beginning. + if (!this.formControl.value) { + this.formControl.setValue(this.field.props.defaultValue); + } + + // Since its a custom wrapper, we are seperating label with checkbox. + // mentioning required to true does not generate (*) to the label, so we are hard coding it. + if (this.field.props.required) { + this.secondLabel = this.field.props.description + '*'; + } else { + this.secondLabel = this.field.props.description + } + } +} \ No newline at end of file diff --git a/ui/src/app/shared/formly/form-field-default-cases.wrapper.ts b/ui/src/app/shared/formly/form-field-default-cases.wrapper.ts new file mode 100644 index 00000000000..241127e16e1 --- /dev/null +++ b/ui/src/app/shared/formly/form-field-default-cases.wrapper.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from '@angular/core'; +import { FieldWrapper } from '@ngx-formly/core'; + +@Component({ + selector: 'formly-wrapper-default-of-cases', + template: `` +}) +export class FormlyWrapperDefaultValueWithCasesComponent extends FieldWrapper implements OnInit { + + ngOnInit() { + this.props.defaultValueOptions?.forEach((item: FieldDefaultCases) => { + this.form.get(item["field"]).valueChanges.subscribe((value) => { + this.onChange(item, value); + }); + let value = this.model[item.field] + if (value) { + this.onChange(item, value); + } + }) + } + + private onChange(item: FieldDefaultCases, value: any) { + const foundCase = item.cases.find(element => element.case == value); + if (!foundCase) { + return; + } + this.formControl.setValue(foundCase.defaultValue); + } + +} + +type FieldDefaultCases = { field: string, cases: [{ case: any, defaultValue: any }] } \ No newline at end of file diff --git a/ui/src/app/shared/formly/formly-select-field-modal.component.html b/ui/src/app/shared/formly/formly-select-field-modal.component.html new file mode 100644 index 00000000000..77488ad7fbd --- /dev/null +++ b/ui/src/app/shared/formly/formly-select-field-modal.component.html @@ -0,0 +1,54 @@ + + + {{ title }} + + + + + + + + +
      + + + + + + + + + + {{ option.label }} + + +
      + {{ option.description }} +
      +
      +
      +
      +
      +
      +
      +
      + + + + + + + General.cancel + + + + + General.ok + + + + + + +
      +
      \ No newline at end of file diff --git a/ui/src/app/shared/formly/formly-select-field-modal.component.ts b/ui/src/app/shared/formly/formly-select-field-modal.component.ts new file mode 100644 index 00000000000..7c12e61e3af --- /dev/null +++ b/ui/src/app/shared/formly/formly-select-field-modal.component.ts @@ -0,0 +1,29 @@ +import { Component, Input, OnInit } from "@angular/core"; +import { ModalController } from "@ionic/angular"; + +@Component({ + selector: 'formly-select-modal', + templateUrl: './formly-select-field-modal.component.html', +}) +export class FormlySelectFieldModalComponent implements OnInit { + + @Input() public title: string + @Input() public options: { label: string, value: string, description?: string }[]; + + @Input() public initialSelectedValue: string | null = null + + protected selectedValue: string | null = null; + + constructor( + protected modalCtrl: ModalController + ) { } + + public ngOnInit(): void { + this.selectedValue = this.initialSelectedValue; + } + + protected onSelected() { + this.modalCtrl.dismiss({ selectedValue: this.selectedValue }); + } + +} \ No newline at end of file diff --git a/ui/src/app/shared/formly/formly-select-field.extended.html b/ui/src/app/shared/formly/formly-select-field.extended.html new file mode 100644 index 00000000000..1409c0b07f6 --- /dev/null +++ b/ui/src/app/shared/formly/formly-select-field.extended.html @@ -0,0 +1,11 @@ + + + {{to.label}} + * +
      {{ to.description }}
      +
      + + {{ formControl.value }} + + +
      \ No newline at end of file diff --git a/ui/src/app/shared/formly/formly-select-field.extended.ts b/ui/src/app/shared/formly/formly-select-field.extended.ts new file mode 100644 index 00000000000..6a0a6847931 --- /dev/null +++ b/ui/src/app/shared/formly/formly-select-field.extended.ts @@ -0,0 +1,52 @@ +import { ChangeDetectorRef, Component } from "@angular/core"; +import { ModalController } from "@ionic/angular"; +import { FieldWrapper } from "@ngx-formly/core"; +import { FormlySelectFieldModalComponent } from "./formly-select-field-modal.component"; + +@Component({ + selector: 'formly-select-extended-wrapper', + templateUrl: './formly-select-field.extended.html', +}) +export class FormlySelectFieldExtendedWrapperComponent extends FieldWrapper { + + // this wrapper is used to display a select which has more + // detailed information about an item when selecting them + constructor( + private modalController: ModalController + ) { + super(); + + } + + protected onSelectItem() { + this.openModal(); + } + + /** + * Opens the model to select the option. + */ + private async openModal() { + const modal = await this.modalController.create({ + component: FormlySelectFieldModalComponent, + componentProps: { + title: this.props.label, + options: this.props.options, + initialSelectedValue: this.formControl.value + }, + cssClass: ['auto-height', 'full-width'] + }); + modal.onDidDismiss().then(event => { + if (!event.data) { + // nothing selected + return; + } + const selectedValue = event.data.selectedValue + if (!selectedValue) { + return; + } + this.formControl.setValue(selectedValue) + }); + return await modal.present(); + } + +} diff --git a/ui/src/app/shared/formly/formly-select-field.wrapper.html b/ui/src/app/shared/formly/formly-select-field.wrapper.html deleted file mode 100644 index 34354be6b18..00000000000 --- a/ui/src/app/shared/formly/formly-select-field.wrapper.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - {{to.label}} - * -
      {{ to.description }}
      -
      - - - {{option.label}} - - -
      -
      -
      -
      \ No newline at end of file diff --git a/ui/src/app/shared/formly/formly-select-field.wrapper.ts b/ui/src/app/shared/formly/formly-select-field.wrapper.ts deleted file mode 100644 index f24b4d79b4a..00000000000 --- a/ui/src/app/shared/formly/formly-select-field.wrapper.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Component } from "@angular/core"; -import { FieldWrapper } from "@ngx-formly/core"; - -@Component({ - selector: 'formly-select-field-wrapper', - templateUrl: './formly-select-field.wrapper.html', -}) -export class FormlySelectFieldWrapperComponent extends FieldWrapper { } \ No newline at end of file diff --git a/ui/src/app/shared/formly/panel-wrapper.component.ts b/ui/src/app/shared/formly/panel-wrapper.component.ts new file mode 100644 index 00000000000..e9a32f5cc04 --- /dev/null +++ b/ui/src/app/shared/formly/panel-wrapper.component.ts @@ -0,0 +1,20 @@ +import { Component, ViewChild, ViewContainerRef } from "@angular/core"; +import { FieldWrapper } from "@ngx-formly/core"; + +@Component({ + selector: 'formly-wrapper-panel', + template: ` + + + + + {{ to.label }} + + + + + + `, +}) +export class PanelWrapperComponent extends FieldWrapper { +} \ No newline at end of file diff --git a/ui/src/app/shared/genericComponents/chart/abstracthistorychart.html b/ui/src/app/shared/genericComponents/chart/abstracthistorychart.html index df44a88921b..32bdd72e8fc 100644 --- a/ui/src/app/shared/genericComponents/chart/abstracthistorychart.html +++ b/ui/src/app/shared/genericComponents/chart/abstracthistorychart.html @@ -1,3 +1,5 @@ + + diff --git a/ui/src/app/shared/genericComponents/chart/abstracthistorychart.ts b/ui/src/app/shared/genericComponents/chart/abstracthistorychart.ts index a9041f91032..2816b7f0595 100644 --- a/ui/src/app/shared/genericComponents/chart/abstracthistorychart.ts +++ b/ui/src/app/shared/genericComponents/chart/abstracthistorychart.ts @@ -7,6 +7,7 @@ import { ChartDataSets, ChartLegendLabelItem } from 'chart.js'; import { QueryHistoricTimeseriesEnergyPerPeriodResponse } from 'src/app/shared/jsonrpc/response/queryHistoricTimeseriesEnergyPerPeriodResponse'; import { DefaultTypes } from 'src/app/shared/service/defaulttypes'; import { calculateResolution, ChannelFilter, ChartData, ChartOptions, DEFAULT_TIME_CHART_OPTIONS, EMPTY_DATASET, isLabelVisible, setLabelVisible, TooltipItem, Unit } from '../../../edge/history/shared'; +import { JsonrpcResponseError } from '../../jsonrpc/base'; import { QueryHistoricTimeseriesDataRequest } from '../../jsonrpc/request/queryHistoricTimeseriesDataRequest'; import { QueryHistoricTimeseriesEnergyPerPeriodRequest } from '../../jsonrpc/request/queryHistoricTimeseriesEnergyPerPeriodRequest'; import { QueryHistoricTimeseriesDataResponse } from '../../jsonrpc/response/queryHistoricTimeseriesDataResponse'; @@ -32,6 +33,8 @@ export abstract class AbstractHistoryChart implements OnInit, OnChanges { public chartObject: ChartData = this.getChartData(); public chartType: 'line' | 'bar' = 'line'; + protected errorResponse: JsonrpcResponseError | null = null; + constructor( public service: Service, public cdRef: ChangeDetectorRef, @@ -200,10 +203,16 @@ export abstract class AbstractHistoryChart implements OnInit, OnChanges { if (Object.keys(result).length != 0) { resolve(response as QueryHistoricTimeseriesDataResponse); } else { + this.errorResponse = new JsonrpcResponseError(request.id, { code: 1, message: "Empty Result" }); resolve(new QueryHistoricTimeseriesDataResponse(response.id, { timestamps: [null], data: { null: null } })); } + }).catch((response) => { + this.errorResponse = response; + resolve(new QueryHistoricTimeseriesDataResponse("0", { + timestamps: [null], data: { null: null } + })) }); }) }) @@ -211,7 +220,6 @@ export abstract class AbstractHistoryChart implements OnInit, OnChanges { // Check if channelAddresses are empty if (Utils.isDataEmpty(response)) { - // load defaultchart this.service.stopSpinner(this.spinnerId) this.initializeChart() @@ -246,14 +254,18 @@ export abstract class AbstractHistoryChart implements OnInit, OnChanges { timestamps: [null], data: { null: null } })); } - }) + }).catch((response) => { + this.errorResponse = response; + resolve(new QueryHistoricTimeseriesDataResponse("0", { + timestamps: [null], data: { null: null } + })) + }); }) }); }).then((response) => { // Check if channelAddresses are empty if (Utils.isDataEmpty(response)) { - // load defaultchart this.service.stopSpinner(this.spinnerId) this.initializeChart() diff --git a/ui/src/app/shared/genericComponents/chart/chart.html b/ui/src/app/shared/genericComponents/chart/chart.html index 8a95f14bee7..726c404277c 100644 --- a/ui/src/app/shared/genericComponents/chart/chart.html +++ b/ui/src/app/shared/genericComponents/chart/chart.html @@ -8,7 +8,7 @@ - + diff --git a/ui/src/app/shared/genericComponents/flat/flat-widget-percentagebar/flat-widget-percentagebar.html b/ui/src/app/shared/genericComponents/flat/flat-widget-percentagebar/flat-widget-percentagebar.html index 8c5bb50478f..2c180a5e934 100644 --- a/ui/src/app/shared/genericComponents/flat/flat-widget-percentagebar/flat-widget-percentagebar.html +++ b/ui/src/app/shared/genericComponents/flat/flat-widget-percentagebar/flat-widget-percentagebar.html @@ -1,5 +1,5 @@ - + event).urlAfterRedirects); }) - - // subscribe for single status component - this.service.currentEdge.pipe(takeUntil(this.ngUnsubscribe)).subscribe(edge => { - if (edge != null) { - edge.subscribeChannels(this.websocket, '', [ - new ChannelAddress('_sum', 'State'), - ]); - } - }) } // used to prevent 'Expression has changed after it was checked' error @@ -69,7 +62,7 @@ export class HeaderComponent implements OnInit, OnDestroy, AfterViewChecked { let urlArray = url.split('/'); let file = urlArray.pop(); - if (file == 'user' || file == 'settings' || urlArray.length > 3) { + if (file == 'user' || file == 'settings' || file == 'changelog' || urlArray.length > 3) { // disable side-menu; show back-button instead this.enableSideMenu = false; } else { @@ -91,6 +84,11 @@ export class HeaderComponent implements OnInit, OnDestroy, AfterViewChecked { this.backUrl = '/device/' + currentEdge.id + "/live" return; } + if (url === '/changelog' && currentEdge != null) { + // TODO this does not work if Changelog was opened from /user + this.backUrl = '/device/' + currentEdge.id + "/settings/profile" + return; + } let urlArray = url.split('/'); let backUrl: string | boolean = '/'; @@ -156,7 +154,7 @@ export class HeaderComponent implements OnInit, OnDestroy, AfterViewChecked { this.cdRef.detectChanges(); } if (event.detail.value == "IndexHistory") { - this.router.navigateByUrl("/device/" + this.service.currentEdge.value.id + "/history", { replaceUrl: true }); + this.router.navigate(['../history'], { relativeTo: this.route }); this.cdRef.detectChanges(); } } diff --git a/ui/src/app/shared/history-data-error.component.ts b/ui/src/app/shared/history-data-error.component.ts new file mode 100644 index 00000000000..e94cef5725d --- /dev/null +++ b/ui/src/app/shared/history-data-error.component.ts @@ -0,0 +1,37 @@ +import { Component, Input } from "@angular/core"; +import { JsonrpcResponseError } from "src/app/shared/jsonrpc/base"; + +@Component({ + selector: 'oe-history-data-error', + template: ` + + + + + Edge.Index.Energymonitor.ERROR_TEMPORARY + + +` +}) +export class HistoryDataErrorComponent { + + protected type: ErrorType; + + @Input() + set response(response: JsonrpcResponseError | null) { + this.type = toType(response); + } +} + +type ErrorType = 'TEMPORARY' | 'TOO_LONG' | null; + +function toType(response: JsonrpcResponseError | null): ErrorType { + let message = response?.error?.message; + if (message === undefined) { + return null; + } + switch (message) { + default: + return 'TEMPORARY'; + } +} diff --git a/ui/src/app/shared/jsonrpc/request/sendLogMessage.ts b/ui/src/app/shared/jsonrpc/notification/logMessageNotification.ts similarity index 58% rename from ui/src/app/shared/jsonrpc/request/sendLogMessage.ts rename to ui/src/app/shared/jsonrpc/notification/logMessageNotification.ts index 1a824289f98..ef49b88358b 100644 --- a/ui/src/app/shared/jsonrpc/request/sendLogMessage.ts +++ b/ui/src/app/shared/jsonrpc/notification/logMessageNotification.ts @@ -1,12 +1,12 @@ import { Level } from "../../service/logger"; -import { JsonrpcRequest } from "../base"; +import { JsonrpcNotification } from "../base"; /** *
        * {
        *  "jsonrpc": "2.0",
        *  "id": UUID,
      - *  "method": "sendLogMessage"
      + *  "method": "logMessage"
        *  "params": {
        *      "level": Level,
        *      "msg": string
      @@ -14,9 +14,9 @@ import { JsonrpcRequest } from "../base";
        * }
        * 
      */ -export class SendLogMessage extends JsonrpcRequest { +export class LogMessageNotification extends JsonrpcNotification { - static METHOD: string = "sendLogMessage"; + static METHOD: string = "logMessage"; public constructor( public readonly params: { @@ -24,7 +24,7 @@ export class SendLogMessage extends JsonrpcRequest { msg: string } ) { - super(SendLogMessage.METHOD, params); + super(LogMessageNotification.METHOD, params); } } \ No newline at end of file diff --git a/ui/src/app/shared/jsonrpc/request/getEdgeRequest.ts b/ui/src/app/shared/jsonrpc/request/getEdgeRequest.ts new file mode 100644 index 00000000000..ecf7f91ad15 --- /dev/null +++ b/ui/src/app/shared/jsonrpc/request/getEdgeRequest.ts @@ -0,0 +1,32 @@ +import { JsonrpcRequest } from "../base"; + +/** + * Represents a JSON-RPC Request to get a Edge. + * + *

      + * This is used by UI to get an Edge. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getEdge",
      + *   "params": {
      + *    "edgeId": string
      + *   }
      + * }
      + * 
      + */ +export class GetEdgeRequest extends JsonrpcRequest { + + static METHOD: string = "getEdge"; + + public constructor( + public readonly params: { + edgeId: string + } + ) { + super(GetEdgeRequest.METHOD, params); + } + +} \ No newline at end of file diff --git a/ui/src/app/shared/jsonrpc/request/getEdgesRequest.ts b/ui/src/app/shared/jsonrpc/request/getEdgesRequest.ts new file mode 100644 index 00000000000..56641104e96 --- /dev/null +++ b/ui/src/app/shared/jsonrpc/request/getEdgesRequest.ts @@ -0,0 +1,36 @@ +import { JsonrpcRequest } from "../base"; + +/** + * Represents a JSON-RPC Request to get Edges. + * + *

      + * This is used by UI to get Edges for the overview. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getEdges",
      + *   "params": {
      + *      "page": number,
      + *      "query?": string,
      + *      "limit?": number
      + *   }
      + * }
      + * 
      + */ +export class GetEdgesRequest extends JsonrpcRequest { + + static METHOD: string = "getEdges"; + + public constructor( + public readonly params: { + page: number, + query?: string, + limit?: number + } + ) { + super(GetEdgesRequest.METHOD, params); + } + +} \ No newline at end of file diff --git a/ui/src/app/shared/jsonrpc/request/submitSetupProtocolRequest.ts b/ui/src/app/shared/jsonrpc/request/submitSetupProtocolRequest.ts index 72ca6249bab..e94128b579f 100644 --- a/ui/src/app/shared/jsonrpc/request/submitSetupProtocolRequest.ts +++ b/ui/src/app/shared/jsonrpc/request/submitSetupProtocolRequest.ts @@ -4,7 +4,7 @@ import { Utils } from "../../shared"; import { JsonrpcRequest } from "../base"; export type SetupProtocol = { - edge: { + fems: { id: string }, installer: { @@ -63,7 +63,7 @@ export type SetupProtocol = { * "method": "submitSetupProtocol", * "params": { * protocol: { - * edge: { + * fems: { * id: string * }, * customer: { diff --git a/ui/src/app/shared/jsonrpc/response/getEdgeResponse.ts b/ui/src/app/shared/jsonrpc/response/getEdgeResponse.ts new file mode 100644 index 00000000000..817a0b9d498 --- /dev/null +++ b/ui/src/app/shared/jsonrpc/response/getEdgeResponse.ts @@ -0,0 +1,28 @@ +import { Edge } from "../../edge/edge"; +import { JsonrpcResponseSuccess } from "../base"; + + +/** + * Wraps a JSON-RPC Response for a GetEdgeRequest. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": UUID,
      + *   "result": {
      + *     "edge": Edge
      + *   }
      + * }
      + * 
      + */ +export class GetEdgeResponse extends JsonrpcResponseSuccess { + + public constructor( + public readonly id: string, + public readonly result: { + edge: Edge + } + ) { + super(id, result); + } +} \ No newline at end of file diff --git a/ui/src/app/shared/jsonrpc/response/getEdgesResponse.ts b/ui/src/app/shared/jsonrpc/response/getEdgesResponse.ts new file mode 100644 index 00000000000..7c52bb6d1fa --- /dev/null +++ b/ui/src/app/shared/jsonrpc/response/getEdgesResponse.ts @@ -0,0 +1,28 @@ +import { Edge } from "../../edge/edge"; +import { JsonrpcResponseSuccess } from "../base"; + + +/** + * Wraps a JSON-RPC Response for a GetEdgesRequest. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": UUID,
      + *   "result": {
      + *      "edges": Edge[]
      + *    }
      + * }
      + * 
      + */ +export class GetEdgesResponse extends JsonrpcResponseSuccess { + + public constructor( + public readonly id: string, + public readonly result: { + edges: Edge[] + } + ) { + super(id, result); + } +} \ No newline at end of file diff --git a/ui/src/app/shared/service/logger.ts b/ui/src/app/shared/service/logger.ts index de789bfadf9..ea8acb9224f 100644 --- a/ui/src/app/shared/service/logger.ts +++ b/ui/src/app/shared/service/logger.ts @@ -1,5 +1,6 @@ import { Injectable } from "@angular/core"; -import { SendLogMessage } from "../jsonrpc/request/sendLogMessage"; +import { environment } from "src/environments"; +import { LogMessageNotification } from "../jsonrpc/notification/logMessageNotification"; import { Service } from "./service"; /** @@ -23,8 +24,11 @@ export class Logger { * @param level the log level * @param msg the message to be logged */ - private log(level: Level, msg: string) { - this.service.websocket.sendRequest(new SendLogMessage({ level, msg })).catch(err => console.log(err)); + private sendLogMessageNotification(level: Level, msg: string) { + + if (environment.production == true) { + this.service.websocket.sendNotification(new LogMessageNotification({ level: level, msg: msg })); + } } /** @@ -33,7 +37,7 @@ export class Logger { * @param msg the message to be logged */ public debug(msg: string) { - this.log(Level.DEBUG, msg); + this.sendLogMessageNotification(Level.DEBUG, msg); } /** @@ -42,7 +46,7 @@ export class Logger { * @param msg the message to be logged */ public info(msg: string) { - this.log(Level.INFO, msg); + this.sendLogMessageNotification(Level.INFO, msg); } /** @@ -51,7 +55,7 @@ export class Logger { * @param msg the message to be logged */ public warn(msg: string) { - this.log(Level.WARNING, msg); + this.sendLogMessageNotification(Level.WARNING, msg); } /** @@ -60,7 +64,7 @@ export class Logger { * @param msg the message to be logged */ public error(msg: string) { - this.log(Level.ERROR, msg); + this.sendLogMessageNotification(Level.ERROR, msg); } } \ No newline at end of file diff --git a/ui/src/app/shared/service/myerrorhandler.ts b/ui/src/app/shared/service/myerrorhandler.ts new file mode 100644 index 00000000000..54016063de5 --- /dev/null +++ b/ui/src/app/shared/service/myerrorhandler.ts @@ -0,0 +1,27 @@ +import { ErrorHandler, Injectable, Injector } from "@angular/core"; + +import { Logger } from "./logger"; + +@Injectable() +export class MyErrorHandler implements ErrorHandler { + constructor( + private injector: Injector + ) { } + + handleError(error: any) { + let logger = this.injector.get(Logger); + console.error(error); + if (error.message) { + let json = { + error: { + message: error.message + }, + metadata: { + browser: navigator.userAgent + } + } + + logger.error(JSON.stringify(json)); + } + } +} \ No newline at end of file diff --git a/ui/src/app/shared/service/pagination.ts b/ui/src/app/shared/service/pagination.ts new file mode 100644 index 00000000000..11636f793b3 --- /dev/null +++ b/ui/src/app/shared/service/pagination.ts @@ -0,0 +1,37 @@ +import { Directive } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { filter } from 'rxjs/operators'; + +import { GetEdgeConfigRequest } from '../jsonrpc/request/getEdgeConfigRequest'; +import { SubscribeEdgesRequest } from '../jsonrpc/request/subscribeEdgesRequest'; +import { ChannelAddress, Edge } from '../shared'; +import { Service } from './service'; + +@Directive() +export class Pagination { + + private edge: Edge | null = null; + + constructor( + public service: Service, + private router: Router, + ) { } + + getAndSubscribeEdge(edge: Edge): Promise { + return new Promise((resolve) => { + + this.service.updateCurrentEdge(edge.id).then((edge) => { + this.edge = edge; + this.service.websocket.sendRequest(new SubscribeEdgesRequest({ edges: [edge.id] })) + }).then(() => { + this.edge.subscribeChannels(this.service.websocket, '', [ + new ChannelAddress('_sum', 'State'), + ]); + }) + .finally(resolve) + .catch(() => { + this.router.navigate(['index']); + }); + }) + } +} \ No newline at end of file diff --git a/ui/src/app/shared/service/service.ts b/ui/src/app/shared/service/service.ts index 19fbff39fdc..22e1c635823 100644 --- a/ui/src/app/shared/service/service.ts +++ b/ui/src/app/shared/service/service.ts @@ -3,17 +3,22 @@ import { ActivatedRoute, Router } from '@angular/router'; import { ModalController, ToastController } from '@ionic/angular'; import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; import { NgxSpinnerService } from 'ngx-spinner'; -import { BehaviorSubject, Subject, Subscription } from 'rxjs'; -import { filter, first, map, take } from 'rxjs/operators'; +import { BehaviorSubject, Subject } from 'rxjs'; +import { filter, first, take } from 'rxjs/operators'; import { environment } from 'src/environments'; import { Edge } from '../edge/edge'; import { EdgeConfig } from '../edge/edgeconfig'; import { JsonrpcResponseError } from '../jsonrpc/base'; +import { GetEdgeRequest } from '../jsonrpc/request/getEdgeRequest'; +import { GetEdgesRequest } from '../jsonrpc/request/getEdgesRequest'; import { QueryHistoricTimeseriesEnergyRequest } from '../jsonrpc/request/queryHistoricTimeseriesEnergyRequest'; +import { GetEdgeResponse } from '../jsonrpc/response/getEdgeResponse'; +import { GetEdgesResponse } from '../jsonrpc/response/getEdgesResponse'; import { QueryHistoricTimeseriesEnergyResponse } from '../jsonrpc/response/queryHistoricTimeseriesEnergyResponse'; import { User } from '../jsonrpc/shared'; import { ChannelAddress } from '../shared'; import { Language } from '../type/language'; +import { Role } from '../type/role'; import { AbstractService } from './abstractservice'; import { DefaultTypes } from './defaulttypes'; import { Websocket } from './websocket'; @@ -115,7 +120,7 @@ export class Service extends AbstractService { } public setCurrentComponent(currentPageTitle: string | { languageKey: string }, activatedRoute: ActivatedRoute): Promise { - return new Promise((resolve) => { + return new Promise((resolve, reject) => { // Set the currentPageTitle only once per ActivatedRoute if (this.currentActivatedRoute != activatedRoute) { if (typeof currentPageTitle === 'string') { @@ -135,66 +140,23 @@ export class Service extends AbstractService { } this.currentActivatedRoute = activatedRoute; - // Get Edge-ID. If not existing -> resolve null - let route = activatedRoute.snapshot; - let edgeId = route.params["edgeId"]; - if (edgeId == null) { - // allow modal components to get edge id - if (route.url.length == 0) { - this.getCurrentEdge().then(edge => { - resolve(edge); - }) - } else { - resolve(null); - } - } - - let subscription: Subscription = null; - let onError = () => { - if (subscription != null) { - subscription.unsubscribe(); - } - setCurrentEdge.apply(null); - // redirect to index - this.router.navigate(['/index']); - } - - let timeout = setTimeout(() => { - console.error("Timeout while setting current edge"); - // onError(); - }, Service.TIMEOUT); - - let setCurrentEdge = (edge: Edge) => { - clearTimeout(timeout); - if (edge != this.currentEdge.value) { - if (edge != null) { - edge.markAsCurrentEdge(this.websocket); - } - this.currentEdge.next(edge); - } + this.getCurrentEdge().then(edge => { resolve(edge); - } - - subscription = this.metadata - .pipe( - filter(metadata => metadata != null && edgeId in metadata.edges), - first(), - map(metadata => metadata.edges[edgeId]) - ) - .subscribe(edge => { - setCurrentEdge(edge); - }, error => { - console.error("Error while setting current edge: ", error); - onError(); - }) + }).catch(reject) }); } public getCurrentEdge(): Promise { - return this.currentEdge.pipe( - filter(edge => edge != null), - first() - ).toPromise(); + // TODO maybe timeout + return new Promise((resolve) => { + this.currentEdge.pipe( + filter(edge => edge != null), + first(), + ).toPromise().then(resolve); + if (this.currentEdge.value) { + resolve(this.currentEdge.value) + } + }) } public getConfig(): Promise { @@ -304,6 +266,85 @@ export class Service extends AbstractService { return response; } + /** + * Gets the page for the given number. + * + * @param page the page number + * @param query the query to restrict the edgeId + * @param limit the number of edges to be retrieved + * @returns a Promise + */ + public getEdges(page: number, query?: string, limit?: number): Promise { + return new Promise((resolve, reject) => { + this.websocket.sendSafeRequest( + new GetEdgesRequest({ + page: page, + ...(query && query != "" && { query: query }), + ...(limit && { limit: limit }) + })).then((response) => { + + const result = (response as GetEdgesResponse).result; + + // TODO change edges-map to array or other way around + let value = this.metadata.value; + let mappedResult = []; + for (let edge of result.edges) { + let mappedEdge = new Edge( + edge.id, + edge.comment, + edge.producttype, + ("version" in edge) ? edge["version"] : "0.0.0", + Role.getRole(edge.role.toString()), + edge.isOnline, + edge.lastmessage + ); + value.edges[edge.id] = mappedEdge + mappedResult.push(mappedEdge) + } + + this.metadata.next(value) + resolve(mappedResult) + }).catch((err) => { + reject(err) + }) + }) + } + + /** + * Updates the currentEdge in metadata + * + * @param edgeId the edgeId + * @returns a empty Promise + */ + public updateCurrentEdge(edgeId: string): Promise { + return new Promise((resolve, reject) => { + const existingEdge = this.metadata.value?.edges[edgeId]; + if (existingEdge) { + this.currentEdge.next(existingEdge) + resolve(existingEdge); + return; + } + this.websocket.sendSafeRequest(new GetEdgeRequest({ edgeId: edgeId })).then((response) => { + let edgeData = (response as GetEdgeResponse).result.edge + let value = this.metadata.value; + const currentEdge = new Edge( + edgeData.id, + edgeData.comment, + edgeData.producttype, + ("version" in edgeData) ? edgeData["version"] : "0.0.0", + Role.getRole(edgeData.role.toString()), + edgeData.isOnline, + edgeData.lastmessage + ); + + this.currentEdge.next(currentEdge) + value.edges[edgeData.id] = currentEdge + this.metadata.next(value) + resolve(currentEdge) + }).catch(reject) + }) + } + private queryEnergyQueue: { fromDate: Date, toDate: Date, channels: ChannelAddress[], promises: { resolve, reject }[] }[] = []; diff --git a/ui/src/app/shared/service/utils.ts b/ui/src/app/shared/service/utils.ts index 940b75db834..556d71175eb 100644 --- a/ui/src/app/shared/service/utils.ts +++ b/ui/src/app/shared/service/utils.ts @@ -393,6 +393,8 @@ export class Utils { return translate.instant('Edge.Index.Widgets.TimeOfUseTariff.State.allowsDischarge'); case 2: return translate.instant('Edge.Index.Widgets.TimeOfUseTariff.State.standby'); + case 3: + return translate.instant('Edge.Index.Widgets.TimeOfUseTariff.State.charging'); } } } diff --git a/ui/src/app/shared/service/websocket.ts b/ui/src/app/shared/service/websocket.ts index cdbf30e2fce..09e699ee0b0 100644 --- a/ui/src/app/shared/service/websocket.ts +++ b/ui/src/app/shared/service/websocket.ts @@ -5,7 +5,7 @@ import { CookieService } from 'ngx-cookie-service'; import { delay, retryWhen } from 'rxjs/operators'; import { webSocket, WebSocketSubject } from 'rxjs/webSocket'; import { environment } from "src/environments"; -import { Edge } from '../edge/edge'; + import { JsonrpcMessage, JsonrpcNotification, JsonrpcRequest, JsonrpcResponse, JsonrpcResponseError, JsonrpcResponseSuccess } from '../jsonrpc/base'; import { CurrentDataNotification } from '../jsonrpc/notification/currentDataNotification'; import { EdgeConfigNotification } from '../jsonrpc/notification/edgeConfigNotification'; @@ -18,7 +18,7 @@ import { LogoutRequest } from '../jsonrpc/request/logoutRequest'; import { RegisterUserRequest } from '../jsonrpc/request/registerUserRequest'; import { AuthenticateResponse } from '../jsonrpc/response/authenticateResponse'; import { Language } from '../type/language'; -import { Role } from '../type/role'; +import { Pagination } from './pagination'; import { Service } from './service'; import { WebsocketInterface } from './websocketInterface'; import { WsData } from './wsdata'; @@ -29,7 +29,9 @@ export class Websocket implements WebsocketInterface { private readonly wsdata = new WsData(); private socket: WebSocketSubject; - public status: 'initial' // before first connection attempt + + public status: + 'initial' // before first connection attempt | 'connecting' // trying to connect to backend | 'authenticating' // sent authentication request; waiting for response | 'waiting for credentials' // login is required. Waiting for credentials input @@ -42,6 +44,7 @@ export class Websocket implements WebsocketInterface { private translate: TranslateService, private cookieService: CookieService, private router: Router, + private pagination: Pagination ) { service.websocket = this; @@ -66,8 +69,8 @@ export class Websocket implements WebsocketInterface { } /* - * Open Websocket connection + define onOpen/onClose callbacks. - */ + * Open Websocket connection + define onOpen/onClose callbacks. + */ this.socket = webSocket({ url: environment.url, openObserver: { @@ -79,8 +82,9 @@ export class Websocket implements WebsocketInterface { let token = this.cookieService.get('token'); if (token) { // Login with Session Token - this.login(new AuthenticateWithTokenRequest({ token: token })); + this.login(new AuthenticateWithTokenRequest({ token: token })) this.status = 'authenticating'; + } else { // No Token -> directly ask for Login credentials this.status = 'waiting for credentials'; @@ -152,37 +156,30 @@ export class Websocket implements WebsocketInterface { public login(request: AuthenticateWithPasswordRequest | AuthenticateWithTokenRequest): Promise { return new Promise((resolve) => { this.sendRequest(request).then(r => { - let response = (r as AuthenticateResponse).result; + let authenticateResponse = (r as AuthenticateResponse).result; - let language = Language.getByKey(response.user.language.toLocaleLowerCase()); + let language = Language.getByKey(authenticateResponse.user.language.toLocaleLowerCase()); localStorage.LANGUAGE = language.key; this.service.setLang(language); this.status = 'online'; // received login token -> save in cookie - this.cookieService.set('token', response.token, { expires: 365, path: '/', sameSite: 'Strict' }); + this.cookieService.set('token', authenticateResponse.token, { expires: 365, path: '/', sameSite: 'Strict' }); // Metadata this.service.metadata.next({ - user: response.user, - edges: response.edges.reduce((map, edge) => { - map[edge.id] = new Edge( - edge.id, - edge.comment, - edge.producttype, - ("version" in edge) ? edge["version"] : "0.0.0", - Role.getRole(edge.role), - edge.isOnline, - edge.lastmessage - ); - return map; - }, {}) + user: authenticateResponse.user, + edges: {} }); // Resubscribe Channels this.service.getCurrentEdge().then(edge => { - if (edge != null) { - edge.subscribeChannelsOnReconnect(this); - } + + this.pagination.getAndSubscribeEdge(edge).then(() => { + edge.subscribeChannelsSuccessful = true; + if (edge != null) { + edge.subscribeChannelsOnReconnect(this); + } + }) }); resolve() }).catch(reason => { @@ -194,7 +191,7 @@ export class Websocket implements WebsocketInterface { private checkErrorCode(reason: JsonrpcResponseError) { - // TODO create global Errorhandler + // TODO create global Errorhandler for any type of error switch (reason.error.code) { case 1003: this.service.toast(this.translate.instant('Login.authenticationFailed'), 'danger'); @@ -275,6 +272,27 @@ export class Websocket implements WebsocketInterface { } } + /** + * Waits until Websocket is 'online' and then + * sends a safe JSON-RPC Request to a Websocket and promises a callback. + * + * @param request the JSON-RPC Request + */ + public sendSafeRequest(request: JsonrpcRequest): Promise { + return new Promise((resolve, reject) => { + let interval = setInterval(() => { + + // TODO: Status should be Observable, furthermore status should be like state-machine + if (this.status == 'online') { + clearInterval(interval) + this.sendRequest(request) + .then((response) => resolve(response)) + .catch((err) => reject(err)) + } + }, 500) + }) + } + /** * Sends a JSON-RPC notification to a Websocket. * diff --git a/ui/src/app/shared/shared.module.ts b/ui/src/app/shared/shared.module.ts index 7db73e64d5e..c0691a13aec 100644 --- a/ui/src/app/shared/shared.module.ts +++ b/ui/src/app/shared/shared.module.ts @@ -13,13 +13,18 @@ import { appRoutingProviders } from './../app-routing.module'; import { ChartOptionsComponent } from './chartoptions/chartoptions.component'; import { DirectiveModule } from './directive/directive'; import { MeterModule } from './edge/meter/meter.module'; +import { FormlyCheckBoxHyperlinkWrapperComponent } from './formly/form-field-checkbox-hyperlink/form-field-checkbox-hyperlink.wrapper'; +import { FormlyWrapperDefaultValueWithCasesComponent } from './formly/form-field-default-cases.wrapper'; import { FormlyWrapperFormFieldComponent } from './formly/form-field.wrapper'; -import { FormlySelectFieldWrapperComponent } from './formly/formly-select-field.wrapper'; +import { FormlySelectFieldModalComponent } from './formly/formly-select-field-modal.component'; +import { FormlySelectFieldExtendedWrapperComponent } from './formly/formly-select-field.extended'; import { InputTypeComponent } from './formly/input'; import { FormlyInputSerialNumberWrapperComponent as FormlyWrapperInputSerialNumber } from './formly/input-serial-number-wrapper'; +import { PanelWrapperComponent } from './formly/panel-wrapper.component'; import { RepeatTypeComponent } from './formly/repeat'; import { Generic_ComponentsModule } from './genericComponents/genericComponents'; import { HeaderComponent } from './header/header.component'; +import { HistoryDataErrorComponent } from './history-data-error.component'; import { PercentageBarComponent } from './percentagebar/percentagebar.component'; import { PipeModule } from './pipe/pipe'; import { Logger } from './service/logger'; @@ -61,7 +66,10 @@ export function SubnetmaskValidatorMessage(err, field: FormlyFieldConfig) { wrappers: [ { name: 'form-field', component: FormlyWrapperFormFieldComponent }, { name: "input-serial-number", component: FormlyWrapperInputSerialNumber }, - { name: 'formly-select-field-wrapper', component: FormlySelectFieldWrapperComponent } + { name: 'formly-select-extended-wrapper', component: FormlySelectFieldExtendedWrapperComponent }, + { name: 'form-field-checkbox-hyperlink', component: FormlyCheckBoxHyperlinkWrapperComponent }, + { name: 'formly-wrapper-default-of-cases', component: FormlyWrapperDefaultValueWithCasesComponent }, + { name: 'panel', component: PanelWrapperComponent } ], types: [ { name: 'input', component: InputTypeComponent }, @@ -77,19 +85,25 @@ export function SubnetmaskValidatorMessage(err, field: FormlyFieldConfig) { ], }), PipeModule, - Generic_ComponentsModule + Generic_ComponentsModule, + TranslateModule ], declarations: [ // components ChartOptionsComponent, HeaderComponent, + HistoryDataErrorComponent, PercentageBarComponent, // formly InputTypeComponent, FormlyWrapperFormFieldComponent, RepeatTypeComponent, FormlyWrapperInputSerialNumber, - FormlySelectFieldWrapperComponent + FormlySelectFieldExtendedWrapperComponent, + FormlySelectFieldModalComponent, + FormlyCheckBoxHyperlinkWrapperComponent, + FormlyWrapperDefaultValueWithCasesComponent, + PanelWrapperComponent ], exports: [ // modules @@ -111,6 +125,7 @@ export function SubnetmaskValidatorMessage(err, field: FormlyFieldConfig) { // components ChartOptionsComponent, HeaderComponent, + HistoryDataErrorComponent, PercentageBarComponent, ], providers: [ diff --git a/ui/src/app/user/user.component.html b/ui/src/app/user/user.component.html index 0611f2439c9..8f4aa6426e7 100644 --- a/ui/src/app/user/user.component.html +++ b/ui/src/app/user/user.component.html @@ -105,8 +105,7 @@

      About.build

      diff --git a/ui/src/app/user/user.component.ts b/ui/src/app/user/user.component.ts index 25279ad0532..3080313402a 100644 --- a/ui/src/app/user/user.component.ts +++ b/ui/src/app/user/user.component.ts @@ -40,8 +40,7 @@ export class UserComponent implements OnInit { public service: Service, private route: ActivatedRoute, private websocket: Websocket, - ) { - } + ) { } ngOnInit() { // Set currentLanguage to diff --git a/ui/src/assets/i18n/cz.json b/ui/src/assets/i18n/cz.json index 0d49c1b1832..95305a748b7 100644 --- a/ui/src/assets/i18n/cz.json +++ b/ui/src/assets/i18n/cz.json @@ -88,15 +88,14 @@ "save": "Save" }, "Menu": { - "aboutUI": "About OpenEMS", "accessLevel": "Úroveň přístupu", - "edgeSettings": "OpenEMS PÅ™edvolby", + "edgeSettings": "PÅ™edvolby", "generalSettings": "Obecné Nastavení", "index": "PÅ™ehled", "logout": "Odhlásit", "menu": "Menu", "name": "Název", - "overview": "OpenEMS PÅ™ehled", + "overview": "VÅ¡echny systémy", "settings": "nastavení", "user": "Uživatel", "changelog": "Changelog" @@ -120,43 +119,6 @@ "authenticationFailed": "Ověření se nezdaÅ™ilo", "user": "Uživatel" }, - "Register": { - "title": "VytvoÅ™ení uživatelského úÄtu", - "segment": { - "user": "Uživatel", - "installer": "Instalatér" - }, - "Form": { - "user": { - "acceptPrivacyPolicy": "VytvoÅ™ením úÄtu FENECON prohlaÅ¡uji, že jsem si pÅ™eÄetl/a Zásady ochrany osobních údajů a Podmínky používání a souhlasím s nimi.*" - }, - "installer": { - "acceptPrivacyPolicy": "VytvoÅ™ením úÄtu FENECON prohlaÅ¡uji, že jsem si pÅ™eÄetl/a Zásady ochrany osobních údajů a Podmínky používání a souhlasím s nimi.*" - }, - "contactDetails": "Kontaktní údaje", - "companyName": "název spoleÄnosti", - "firstname": "jméno", - "lastname": " Příjmení", - "street": "Ulice", - "zip": "Ulice", - "city": "MÄ›sto", - "country": "MÄ›sto", - "phone": "Telefonní Äíslo", - "email": "E-Mail", - "password": "Heslo", - "confirmPassword": "Potvrzení hesla", - "isElectrician": "Potvrzuji, že moje spoleÄnost je zapsána v registru instalátorů, a jsem tedy oprávnÄ›n pÅ™ipojit a uvést do provozu systém ukládání dat.", - "acceptPrivacyPolicy": "VytvoÅ™ením úÄtu instalátoru FENECON prohlaÅ¡uji, že jsem si pÅ™eÄetl(a) a souhlasím se Zásadami ochrany osobních údajů a Podmínkami použití spoleÄnosti FENECON.*", - "acceptAgb": "Potvrzuji AGB.*", - "subscribeNewsletter": "Chci se pÅ™ihlásit k odbÄ›ru newsletteru FENECON a dostávat vÅ¡echny novinky z FENECON." - }, - "button": "VytvoÅ™it", - "errors": { - "requiredFields": "Vyplňte prosím vÅ¡echna pole", - "passwordNotEqual": "Hesla nejsou stejná" - }, - "success": "Úspěšná registrace" - }, "Edge": { "Index": { "EmergencyReserve": { @@ -172,8 +134,7 @@ "storage": "ÚložiÅ¡tÄ›", "storageCharge": "baterie nakládání", "storageDischarge": "baterie výtok", - "title": "Monitoring energetických toků", - "excelExportWarning": "Zobrazení a export dat za delší Äasové období je v souÄasné dobÄ› možné pouze v omezené míře. Zkuste to prosím pozdÄ›ji." + "title": "Monitoring energetických toků" }, "Widgets": { "autarchyInfo": "Autarky oznaÄuje procento aktuální energie, kterou lze pokrýt vybitím z výroby a skladování.", @@ -501,16 +462,16 @@ "error": "Chyba pÅ™i naÄítání nastavení" }, "interval": { - "hour": "hodina", - "hours": "hodiny", - "minute": "minuta", - "minutes": "minuty", - "day": "den", - "days": "dny" + "hour": "Hodina", + "hours": "Hodiny", + "minute": "Minuta", + "minutes": "Minuty", + "day": "Den", + "days": "Dny" } }, "App": { - "header": "Správce aplikací je v souÄasné dobÄ› v první testovací verzi. Pokud se nezobrazují vÅ¡echny aplikace, je možné, že bude tÅ™eba aktualizovat verzi OpenEMS.", + "header": "Správce aplikací je v souÄasné dobÄ› v první testovací verzi.", "installed": "Nainstalováno", "available": "Dostupné na", "incompatible": "Nekompatibilní", @@ -518,7 +479,8 @@ "modifyApp": "upravit aplikaci", "createApp": "vytvoÅ™it aplikaci", "deleteApp": "odstranit aplikaci", - "updateApp": "aktualizace aplikace" + "updateApp": "aktualizace aplikace", + "notAvailable": "Není k dispozici" } }, "Service": { @@ -549,8 +511,7 @@ "faq": "ÄŒasto kladené otázky (FAQ)", "language": "Zvolte jazyk:", "openEMS": "Více o OpenEMS", - "patchnotes": "ZmÄ›ny v monitorování tohoto sestavení", - "ui": "Uživatelské rozhraní pro OpenEMS" + "patchnotes": "ZmÄ›ny v monitorování tohoto sestavení" }, "Notifications": { "authenticationFailed": "Žádné pÅ™ipojení: Ověření uživatele selhalo.", @@ -559,4 +520,4 @@ "loggedIn": "PÅ™ihlášení probÄ›hlo úspěšnÄ›.", "loggedInAs": "Uživatel pÅ™ihlášen jako {{ value }}." } -} +} \ No newline at end of file diff --git a/ui/src/assets/i18n/de.json b/ui/src/assets/i18n/de.json index 5141b2890a8..37b24349bfd 100644 --- a/ui/src/assets/i18n/de.json +++ b/ui/src/assets/i18n/de.json @@ -1,14 +1,12 @@ { "About": { "build": "Dieser Build", - "contact": "Für Rückfragen und Anregungen zum System, wenden Sie sich bitte an unser Team unter {{ value }}.", "currentDevelopments": "Aktuelle Entwicklungen", "developed": "Diese Benutzeroberfläche wird als Open-Source-Software entwickelt.", "faq": "Häufig gestellte Fragen (FAQ)", "language": "Sprache wählen:", "openEMS": "Mehr zu OpenEMS", - "patchnotes": "Änderungen im Monitoring zu diesem Build", - "ui": "Benutzeroberfläche für OpenEMS" + "patchnotes": "Änderungen im Monitoring zu diesem Build" }, "Edge": { "Index": { @@ -26,7 +24,7 @@ "storageCharge": "Speicher-Beladung", "storageDischarge": "Speicher-Entladung", "title": "Energiemonitor", - "excelExportWarning": "Die Anzeige und der Export von Daten über einen längeren Zeitraum ist derzeit nur eingeschränkt möglich. Bitte versuchen Sie es später noch einmal." + "ERROR_TEMPORARY": "Fehler beim Abruf der Daten. Bitte versuchen Sie es später noch einmal." }, "Widgets": { "autarchyInfo": "Die Autarkie gibt an zu wie viel Prozent die aktuell genutzte Leistung durch Erzeugung und Speicherentladung gedeckt wird.", @@ -236,10 +234,26 @@ "notStarted": "Noch nicht gestartet", "delayed": "Verzögert", "allowsDischarge": "Freigegeben", - "standby": "Standby" - } + "standby": "Standby", + "CHARGING": "Aufladen" + }, + "CHARGED": "Aufgeladen" } - } + }, + "RETROFITTING": { + "UPDATE_TO_NEW_VERSION": "Um die Kapazitätserweiterung nutzen zu können, ist ein Update auf die neueste Version erforderlich.", + "OPTIMAL": "Kapazitätserweiterung", + "INFORMATION_FOR_INSTANT_START": "Die Batterie wird mit maximaler Leistung beladen, beziehungsweise entladen um schnellstmöglichst {{targetSoc}}\u00a0% Ladezustand für eine Erweiterung zu erreichen. Dabei kann es zu Netzbezug oder Netzeinspeisung kommen. Dieser Ladezustand wird für {{targetTimeBuffer}}\u00a0Minuten gehalten, danach oder nach erfolgter Kapazitätserweiterung kehrt das Speichersystem in den regulären Betriebszustand zurück.", + "SELECT_A_DATE": "Wählen Sie bitte ein Datum aus", + "ON_DATE_AT_TIME": "am {{date}} um {{time}}", + "INSTANT_START": "Sofortstart", + "PLANNED_EXPANSION": "Geplante Erweiterung", + "INFORMATION_FOR_PlANNED_EXPANSION": "Die Batterie wird voraussichtlich ab {{targetTime}}\u00a0Uhr am {{targetDate}} beladen/entladen um zur geplanten Erweiterung {{targetSoc}}\u00a0% Ladezustand zu erreichen. Dabei kann es zu Netzbezug oder Netzeinspeisung kommen. Dieser Ladezustand wird für {{targetTimeBuffer}}\u00a0Minuten gehalten, danach oder nach erfolgter Kapazitätserweiterung kehrt das Speichersystem in den regulären Betriebszustand zurück.", + "PREPARING": "Kapazitätserweiterung wird vorbereitet", + "REACHED_TARGET_SOC": "Bereit zur Kapazitätserweiterung", + "INFORMATION_FOR_PlANNED_EXPANSION_INVALID_TARGET_DATE": "Die Batterie wird voraussichtlich beladen/entladen um zur geplanten Erweiterung {{targetSoc}}\u00a0% zu erreichen." + }, + "SYSTEMUPDATE": "Systemupdate" }, "History": { "beginDate": "Startdatum wählen", @@ -350,7 +364,7 @@ "hour": "Stunde", "hours": "Stunden", "minute": "Minute", - "minutes": "minuten", + "minutes": "Minuten", "day": "Tag", "days": "Tage" } @@ -361,13 +375,37 @@ "installed": "Installiert", "available": "Verfügbar", "incompatible": "Inkompatibel", - "buyApp": "App kaufen", + "buyApp": "Lizenzschlüssel kaufen", "modifyApp": "App bearbeiten", "createApp": "App installieren", "deleteApp": "App entfernen", "updateApp": "App aktualisieren", "errorInstallable": "Installierungs fehler", - "errorCompatible": "Kompatibilitäts fehler" + "errorCompatible": "Kompatibilitäts fehler", + "notAvailable": "Nicht verfügbar", + "Key": { + "enterKey": "Geben Sie hier den Lizenzschlüssel ein, den Sie mit der Bestellung der App erhalten haben", + "useRegisteredKey": "Bereits registrierten Lizenzschlüssel einlösen?", + "registeredKey": "Registrierte Lizenzschlüssel", + "key": "Lizenzschlüssel", + "validateKey": "Lizenzschlüssel validieren", + "useKey": "Lizenzschlüssel einlösen", + "registerKey": "Lizenzschlüssel registrieren", + "alreadyRegisteredDifferentSystem": "Lizenzschlüssel wurde bereits auf einem anderen System registriert! Wenn Sie fortfahren, wird die andere Registrierung entfernt.", + "failedLoadingRegisterKey": "Bereits registrierte Schlüssel konnten nicht abgerufen werden", + "successRegisterKey": "Schlüssel wurde erfolgreich registriert", + "failedRegisterKey": "Registrierung des Schlüssels fehlgeschlagen", + "alreadyRegisteredDifferentApp": "Key wurde bereits für eine App auf diesem System registriert! \nWenn Sie fortfahren, wird die andere Registrierung entfernt.", + "valid": "Lizenzschlüssel ist gültig", + "invalid": "Lizenzschlüssel ist ungültig", + "invalidPattern": "Eingabe ist ungültig" + }, + "successInstall": "App erfolgreich installiert", + "failInstall": "Installation der App fehlgeschlagen: {{error}}", + "successUpdate": "App erfolgreich aktualisiert", + "failUpdate": "Fehler während der Aktualisierung: {{error}}", + "successDelete": "App erfolgreich entfernt", + "failDelete": "Entfernen der App fehlgeschlagen: {{error}}" } }, "Service": { @@ -390,7 +428,7 @@ "advancedMode": "erweiterte Ansicht", "submit": "Anwenden" }, - "title": "OpenEMS" + "title": "{{ edgeShortName }}" }, "General": { "active": "Aktiv", @@ -565,7 +603,9 @@ "COMMUNICATION_WITH_METER": "Kommunikation mit den Zählern", "WAGO_BRIDGE": "Wago Bridge", "FIELD_BUS_COUPLER": "Feldbuskoppler", - "CONTROL_GRID_POINT": "Ansteuerung der Netztrennstelle" + "CONTROL_GRID_POINT": "Ansteuerung der Netztrennstelle", + "BATTERY_INTERFACE": "Schnittstelle Batterie", + "WEIDMUELLER_BRIDGE": "Weidmueller Bridge" }, "CONFIGURATION_LINE_SIDE_METER_FUSE": { "FIXED_VALUE_DESCRIPTION": "Mit welcher Stromstärke ist der Zähler abgesichert?", @@ -573,7 +613,8 @@ "OTHER": "Sonstige", "TITLE_COMMERCIAL": "Vorsicherung Netzanschlusspunkt / Zählervorsicherung", "TITLE_HOME": "Vorsicherung Hausanschlusszähler", - "VALUE": "Wert [A]" + "VALUE": "Wert [A]", + "METER_LABEL": "Netzanschlusspunkt Zählertyp" }, "CONFIGURATION_SUMMARY": { "BATTERY_LOCATION": "Standort", @@ -583,7 +624,7 @@ "DEVICE_ACTIVE_CHECKED": "Batterie und Wechselrichter eingeschaltet", "EDGE_NUMBER": "{{ edgeShortName }} Nummer", "GENERAL": "Allgemein", - "GTC_ACCEPT": "AGB akzeptieren", + "GTC_ACCEPT": "AGB", "INSTALLER": "Installateur", "INVERTER": "Wechselrichter", "NEXT_CLICKED_DESCRIPTION": "Wenn Sie jetzt 'weiter' klicken, wird das Speichersystem konfiguriert. Stellen Sie sicher, dass die Batterie und der Wechselrichter während des gesamten Konfigurationsvorgangs eingeschaltet sind.", @@ -591,10 +632,11 @@ "SUMMARY": "Zusammenfassung", "TIME_OF_INSTALLATION": "Zeitpunkt der Installation", "VALUE_AC": "Wert AC", - "WARRANTY_TERMS": "Garantiebedingungen akzeptieren", + "WARRANTY_TERMS": "Garantiebedingungen", "PEAK_SHAVING": "Lastspitzenkappung", "APPS": "Apps", - "HECKERT": "Ihre gewählte kostenlose App" + "HECKERT": "Ihre gewählte kostenlose App", + "ACCEPT": "akzeptieren" }, "CONFIGURATION_SYSTEM": { "OPEN_INSTRUCTIONS": "Anleitung öffnen", @@ -678,7 +720,8 @@ "MARKED_AS": " MPPT {{number}} (beschriftet mit \"PV{{ number}}\")", "METER_TYPE_WITH_LABEL": "Zählertyp {{ label }}{{ number }}", "METER_TYPE": "Zählertyp", - "MODBUS_DESCRIPTION": "Der Zähler muss mit den folgenden Parametern konfiguriert werden: Kommunikationsgeschwindigkeit (bAud) \"9600\", Kommunikationsparität (PrtY) \"n\", Kommunikations-Stopbit (StoP) \"1\"", + "MODBUS_SOCOMEC_DESCRIPTION": "Der Zähler muss mit den folgenden Parametern konfiguriert werden: Kommunikationsgeschwindigkeit (baud) \"9600\", Kommunikationsparität (PrtY) \"n\", Kommunikations-Stopbit (StoP) \"1\"", + "MODBUS_KDK_DESCRIPTION": "Der Zähler muss mit den folgenden Parametern konfiguriert werden: Kommunikationsgeschwindigkeit (baud) \"9600\", Kommunikationsparität (PrtY) \"e\", Kommunikations-Stopbit (StoP) \"1\"", "MODBUS_WITH_LABEL": "Modbus Kommunikationsadresse {{ label }}{{ number }}", "MODBUS": "Modbus Kommunikationsadresse", "MODULE_TYPE_DESCRIPTION": "z. B. Hersteller und Leistung", @@ -695,9 +738,10 @@ "SHADE_MANAGEMENT_DESCRIPTION": "Nur wenn Optimierer verbaut sind, muss das Schattenmanagement deaktiviert werden", "TITLE_ADDITIONAL_AC": "AC-Erzeuger", "TITLE_PV": "DC-PV Installation (Wechselrichtereingänge)", - "VALID_DATA": "Geben Sie gültige Daten ein um zu Speichern.", + "VALID_DATA": "Geben Sie gültige Daten ein, um zu speichern.", "TITLE_DC": "DC-PV-Installation", - "AC_NOT_CREATED": "AC zähler nicht erstellt!" + "AC_NOT_CREATED": "AC zähler nicht erstellt!", + "METER_SELECTION_WARNING": "Bitte wählen Sie den Zähler aus, indem Sie den Erzeuger hinzufügen." }, "PROTOCOL_SERIAL_NUMBERS": { "BATTERY_MODULE": "Batteriemodul ", @@ -720,7 +764,15 @@ "SYSTEM_SETUP": "Voreinstellungen", "BATTERY_STRING": "Batterie String {{ stringNumber }}", "EMS_BOX_HOME": "EMS Box ({{edgeShortName }} Box)", - "EMS_BOX_HECKERT": "EMS Box" + "EMS_BOX_HECKERT": "EMS Box", + "NUMBER_OF_STRINGS": "Anzahl Strings", + "MINIMUM_AND_MAXIMUM_STRINGS": "Minimum Strings: {{ min }} und Maximum: {{ max }}", + "NUMBER_OF_MODULES_PER_STRINGS": "Anzahl Module pro String", + "MODULES_PER_STRINGS_DESCRIPTION": "Modules pro String für Commercial-50 system: {{ number }}", + "EMS_BOX_COMMERCIAL": "{{ edgeShortname }} Anschlussbox", + "MINIMUM_AND_MAXIMUM_MODULES_PER_STRINGS": "Minimum modules pro String: {{ min }} und Maximum: {{ max }}", + "EMS_BOX_CONNECTION_BOX_COMMERCIAL30": "{{ edgeShortName }} Anschlussbox", + "EMS_BOX_GRID_CONNECTION_POINT_COMMERCIAL30": "{{ edgeShortName }} Netztrennstelle" }, "PROTOCOL_SYSTEM": { "FIRSTNAME": "Vorname Kontaktperson", @@ -735,6 +787,24 @@ }, "VALUE_WITH_LABEL": "Wert {{ label }}{{ number }} {{ symbol }}", "ALIAS_WITH_LABEL": "Alias {{label}}{{number}}", + "CONFIGURATION_FEATURES_STORAGE_SYSTEM": { + "BALANCING": "Eigenverbrauchsoptimierung", + "PEAK_SHAVING_SYMMETRIC": "Lastspitzenkappung", + "PEAK_SHAVING_ASYMMETRIC": "Phasengenaue Lastspitzenkappung", + "FEATURE_DESCRIPTION": "Die entsprechende App muss vorhanden sein", + "HEADER": "Angaben zum Einsatz des Speichers", + "PEAK_SHAVING_SYMMETRIC_HEADER": "Einstellungen Lastspitzenkappung", + "PEAK_SHAVING_ASYMMETRIC_HEADER": "Einstellungen Phasen Genaue Lastspitzenkappung" + }, + "CONFIGURATION_PEAK_SHAVING": { + "DISCHARGE_ABOVE_VALUE": "Beladung unter - Wert [W]", + "CHARGE_BELOW_VALUE": "Beladung unter - Wert [W]", + "DISCHARGE_ABOVE_DESCRIPTION": "liegt die Netzbezugsleistung oberhalb von diesem Wert, wird die Batterie entladen.", + "CHARGE_BELOW_DESCRIPTION": "liegt die Netzbezugsleistung unterhalb von diesem Wert, wird die Batterie wieder beladen.\nDieser Wert darf max. dem Wert \"Entladung über\" entsprechen.", + "DESCRIPTION": "Eingetragene Leistungswerte beziehen sich auf einzelne Phasen. Es wird auf die jeweils am stärksten belastete Phase ausgeregelt.", + "DISCHARGE_ABOVE_LABEL": "Entladung über", + "CHARGE_BELOW_LABEL": "Beladung unter" + }, "CLICK_RECOMMENDATION": "Bitte klicken Sie unten auf den \"Hinzufügen\"-Button wenn sie ein {{ edgeShortName }} in Betrieb nehmen wollen." }, "Login": { @@ -747,7 +817,6 @@ "REQUEST_TIMEOUT": "Zeitüberschreitung der Anforderung. Versuche es später noch einmal." }, "Menu": { - "aboutUI": "Ãœber OpenEMS", "accessLevel": "Zugriffslevel", "edgeSettings": "Einstellungen", "generalSettings": "Allgemeine Einstellungen", @@ -776,7 +845,7 @@ }, "SETTINGS": { "SYSTEM_UPDATE": { - "INSTALLED_VERSION": "Installierte version:", + "INSTALLED_VERSION": "Installierte Version:", "LATEST_VERISON": "Das System ist auf dem aktuellsten Softwarestand", "NEW_VERSION_INSTALLING": "Neueste version installieren", "NEW_VERSION": "Neueste version:", diff --git a/ui/src/assets/i18n/en.json b/ui/src/assets/i18n/en.json index 52b53414659..49a98ef0e25 100644 --- a/ui/src/assets/i18n/en.json +++ b/ui/src/assets/i18n/en.json @@ -1,14 +1,12 @@ { "About": { "build": "This build", - "contact": "Please contact our team for further information or suggestions about the system at {{ value }}.", "currentDevelopments": "Current developments", "developed": "This user interface is developed as open-source software.", "faq": "Frequently asked questions (FAQ)", "language": "Select language:", "openEMS": "More about OpenEMS", - "patchnotes": "Changes in the monitoring for this build", - "ui": "User interface for OpenEMS" + "patchnotes": "Changes in the monitoring for this build" }, "Edge": { "Index": { @@ -26,8 +24,7 @@ "storageCharge": "Storage-Charge", "storageDischarge": "Storage-Discharge", "title": "Energymonitor", - "excelExportWarning": "The display and export of data over a longer period of time is currently only possible to a limited extent. The function is expected to be usable again at the start of 2023.", - "displayWarning": "The display of data over a longer period of time is currently only possible to a limited extent. \nThe feature is expected to be available again in early 2023." + "ERROR_TEMPORARY": "Error while fetching data. Please try again later." }, "Widgets": { "autarchyInfo": "Autarky indicates the percentage of current power that can be covered by generation and storage discharge.", @@ -238,10 +235,26 @@ "notStarted": "Controller has not yet started", "delayed": "Delayed", "allowsDischarge": "Allows Discharge", - "standby": "Standby" - } + "standby": "Standby", + "CHARGING": "Charging" + }, + "CHARGED": "Charged" } - } + }, + "RETROFITTING": { + "OPTIMAL": "Capacity expansion", + "ON_DATE_AT_TIME": "on {{date}} at {{time}}", + "INSTANT_START": "Instant start", + "PLANNED_EXPANSION": "Planned Expansion", + "INFORMATION_FOR_PlANNED_EXPANSION": "The battery is expected to be charged/discharged from {{targetTime}} on {{targetDate}} to reach reach {{targetSoc}}\u00a0% state of charge for the planned expansion. In the process there may be grid consumption or grid feed-in. This state of charge is maintained for {{targetTimeBuffer}}\u00a0minutes, after which or after the capacity expansion, the storage system returns to the regular operating state.", + "INFORMATION_FOR_INSTANT_START": "The battery is charged or discharged at maximum power in order to reach a state of charge of {{targetSoc}}\u00a0% as quickly as possible for an expansion. This can result in grid consumption or grid feed-in. This state of charge is maintained for {{targetTimeBuffer}}\u00a0minutes, after which, or after the capacity has been expanded, the storage system returns to its regular operating state.", + "PREPARING": "Prepare for Capacity Extension", + "REACHED_TARGET_SOC": "Ready for Capacity Extension", + "INFORMATION_FOR_PlANNED_EXPANSION_INVALID_TARGET_DATE": "The battery is expected to be charged/discharged to reach {{targetSoc}}\u00a0% state of charge for the planned expansion.", + "SELECT_A_DATE": "Please select a date", + "UPDATE_TO_NEW_VERSION": "Update to the newest version to be able to use the battery retrofitting feature." + }, + "SYSTEMUPDATE": "System update" }, "History": { "beginDate": "Select Begin Date", @@ -350,27 +363,51 @@ "error": "Error loading the settings" }, "interval": { - "hour": "hour", - "hours": "hours", - "minute": "minute", - "minutes": "minutes", - "day": "day", - "days": "days" + "hour": "Hour", + "hours": "Hours", + "minute": "Minute", + "minutes": "Minutes", + "day": "Day", + "days": "Days" } }, "App": { "header": "The App Manager is currently in a first test version.", - "updateAvailable": "There is a new {{ edgeShortName }} version is available! Please update the {{ edgeShortName }} so that all new {{ edgeShortName }} Apps are displayed in the App Center.", + "updateAvailable": "There is a new {{ edgeShortName }} version available! Please update the {{ edgeShortName }} so that all new {{ edgeShortName }} Apps are displayed in the App Center.", "installed": "Installed", "available": "Available", "incompatible": "Incompatible", - "buyApp": "Buy app", + "buyApp": "Buy licence key", "modifyApp": "Modify app", "createApp": "Install app", "deleteApp": "Delete app", "updateApp": "Update app", - "errorInstallable": "installation errors", - "errorCompatible": "Compatibility errors" + "errorInstallable": "Installation errors", + "errorCompatible": "Compatibility errors", + "notAvailable": "Not available", + "Key": { + "enterKey": "Enter the license key you received when you ordered the app here", + "useRegisteredKey": "Redeem already registered licence key?", + "registeredKey": "Registered licence keys", + "successRegisterKey": "successfully registered Key", + "failedRegisterKey": "failed registering Key", + "failedLoadingRegisterKey": "failed to get already registered Keys", + "key": "licence key", + "validateKey": "validate licence key", + "useKey": "redeem licence key", + "registerKey": "register licence key", + "valid": "licence key is valid", + "invalid": "licence key is invalid", + "alreadyRegisteredDifferentSystem": "Key already got registered on a different System! If you continue the other registration will get removed.", + "alreadyRegisteredDifferentApp": "Key already got registered for an app on this System! If you continue the other registration will get removed.", + "invalidPattern": "Input is invalid" + }, + "successInstall": "Successfully installed App", + "failInstall": "Error installing App '{{error}}'", + "successUpdate": "Successfully updated App", + "failUpdate": "Error updating App '{{error}}'", + "successDelete": "Successfully deleted App", + "failDelete": "Error deleting App '{{error}}'" } }, "Service": { @@ -393,7 +430,7 @@ "advancedMode": "Advanced Mode", "submit": "Submit" }, - "title": "OpenEMS" + "title": "{{ edgeShortName }}" }, "General": { "active": "Active", @@ -565,7 +602,9 @@ "COMMUNICATION_WITH_METER": "Communication with the Meter", "WAGO_BRIDGE": "Wago Bridge", "FIELD_BUS_COUPLER": "Fieldbus coupler", - "CONTROL_GRID_POINT": "Control of the grid disconnection point" + "CONTROL_GRID_POINT": "Control of the grid disconnection point", + "BATTERY_INTERFACE": "Battery interface", + "WEIDMUELLER_BRIDGE": "Weidmueller Bridge" }, "CONFIGURATION_LINE_SIDE_METER_FUSE": { "FIXED_VALUE_DESCRIPTION": "What is the current value on the circuit breaker?", @@ -573,7 +612,8 @@ "OTHER": "Other", "TITLE_COMMERCIAL": "Circuit breaker at the grid connection point / Counter circuit breaker", "TITLE_HOME": "Circuit breaker at the grid connection point", - "VALUE": "Value [A]" + "VALUE": "Value [A]", + "METER_LABEL": "Grid connection point meter type" }, "CONFIGURATION_SUMMARY": { "BATTERY_LOCATION": "BESS Location", @@ -583,7 +623,7 @@ "DEVICE_ACTIVE_CHECKED": "Battery and Inverter swicthed ON", "EDGE_NUMBER": "{{ edgeShortName }} Number", "GENERAL": "General", - "GTC_ACCEPT": "GTC acceptation", + "GTC_ACCEPT": "GTC", "INSTALLER": "Installer", "INVERTER": "Inverter", "NEXT_CLICKED_DESCRIPTION": "By clicking on the 'next' button, the storage system will be configured. Make sure the battery and inverter are powered on throughout the configuration process.", @@ -591,10 +631,11 @@ "SUMMARY": "Summary", "TIME_OF_INSTALLATION": "Time of the installation", "VALUE_AC": "Value AC", - "WARRANTY_TERMS": "Warranty terms acceptation", + "WARRANTY_TERMS": "Warranty terms", "PEAK_SHAVING": "Peak shaving", "APPS": "Apps", - "HECKERT": "Your chosen free app" + "HECKERT": "Your chosen free app", + "ACCEPT": "acceptation" }, "CONFIGURATION_SYSTEM": { "OPEN_INSTRUCTIONS": "Open instructions", @@ -678,7 +719,8 @@ "MARKED_AS": " MPPT {{number}} (marked as \"PV{{ number}}\")", "METER_TYPE_WITH_LABEL": "Type of the sensor {{ label }}{{ number }}", "METER_TYPE": "Type of the sensor", - "MODBUS_DESCRIPTION": "The sensor has to be configured with the following settings: Communication speed (baud) \"9600\", Communication parity(pasrtY) \"n\", Communication Stopbit (StoP) \"1\"", + "MODBUS_SOCOMEC_DESCRIPTION": "The sensor has to be configured with the following settings: Communication speed (baud) \"9600\", Communication parity (partY) \"n\", Communication Stopbit (StoP) \"1\"", + "MODBUS_KDK_DESCRIPTION": "The sensor has to be configured with the following settings: Communication speed (baud) \"9600\", Communication parity (partY) \"e\", Communication Stopbit (StoP) \"1\"", "MODBUS_WITH_LABEL": "Modbus {{ label }}{{ number }}", "MODBUS": "Modbus", "MODULE_TYPE_DESCRIPTION": "e.g. Manufuturer and Power", @@ -697,7 +739,8 @@ "TITLE_PV": "DC-PV installation (Inverter inputs)", "VALID_DATA": "Enter valid data to save.", "TITLE_DC": "DC-PV-Installation", - "AC_NOT_CREATED": "AC Meter not created!" + "AC_NOT_CREATED": "AC Meter not created!", + "METER_SELECTION_WARNING": "Please select the meter by adding generator." }, "PROTOCOL_SERIAL_NUMBERS": { "BATTERY_MODULE": "Battery module ", @@ -720,7 +763,15 @@ "SYSTEM_SETUP": "System setup", "BATTERY_STRING": "Battery String {{ stringNumber }}", "EMS_BOX_HOME": "EMS Box ({{edgeShortName }} Box)", - "EMS_BOX_HECKERT": "EMS Box" + "EMS_BOX_HECKERT": "EMS Box", + "MINIMUM_AND_MAXIMUM_STRINGS": "Minimum Strings: {{ min }} and Maximum: {{ max }}", + "NUMBER_OF_STRINGS": "Number of Strings", + "NUMBER_OF_MODULES_PER_STRINGS": "Number of Modules per String", + "MODULES_PER_STRINGS_DESCRIPTION": "Modules per String for Commercial-50 system: {{ number }}", + "EMS_BOX_COMMERCIAL": "{{ edgeShortname }} Connection Box", + "MINIMUM_AND_MAXIMUM_MODULES_PER_STRINGS": "Minimum modules per string: {{ min }} and Maximum: {{ max }}", + "EMS_BOX_CONNECTION_BOX_COMMERCIAL30": "{{ edgeShortName }} Connection Box", + "EMS_BOX_GRID_CONNECTION_POINT_COMMERCIAL30": "{{ edgeShortName }} Grid connection point" }, "PROTOCOL_SYSTEM": { "FIRSTNAME": "First name of the contact person", @@ -735,6 +786,24 @@ }, "VALUE_WITH_LABEL": "Value {{ label }}{{ number }} {{ symbol }}", "ALIAS_WITH_LABEL": "Alias {{label}}{{number}}", + "CONFIGURATION_FEATURES_STORAGE_SYSTEM": { + "BALANCING": "Self-Consumption optmization", + "PEAK_SHAVING_SYMMETRIC": "Peak shaving", + "PEAK_SHAVING_ASYMMETRIC": "Phase Accurate Peak shaving", + "FEATURE_DESCRIPTION": "The corresponding App must be available", + "HEADER": "Information on the use of the Storage system", + "PEAK_SHAVING_SYMMETRIC_HEADER": "Peak load shaving settings", + "PEAK_SHAVING_ASYMMETRIC_HEADER": "Phases Accurate peak shaving settings" + }, + "CONFIGURATION_PEAK_SHAVING": { + "DISCHARGE_ABOVE_VALUE": "Discharging above - Value [W]", + "CHARGE_BELOW_VALUE": "Charging below - Value [W]", + "DISCHARGE_ABOVE_DESCRIPTION": "If the grid power is above this value, the battery will be discharged.", + "CHARGE_BELOW_DESCRIPTION": "if the grid power is below this value, the battery is charged again.\nThis value must not exceed the \"Discharge over\" value.", + "DESCRIPTION": "Entered power values refer to individual phases. It is adjusted to the most heavily loaded phase.", + "DISCHARGE_ABOVE_LABEL": "Discharge above", + "CHARGE_BELOW_LABEL": "Charge below" + }, "CLICK_RECOMMENDATION": "Please click on the \"Add\" button below if you want to commission a {{ edgeShortName }}." }, "Login": { @@ -748,9 +817,8 @@ "REQUEST_TIMEOUT": "Request timed out. Try again later." }, "Menu": { - "aboutUI": "About OpenEMS", "accessLevel": "Access Level", - "edgeSettings": "OpenEMS Settings", + "edgeSettings": "Settings", "generalSettings": "General Settings", "index": "Index", "logout": "Sign Out", @@ -769,44 +837,6 @@ "loggedIn": "Logged in.", "loggedInAs": "Logged in as '{{ value }}'." }, - "Register": { - "title": "Create user account", - "segment": { - "user": "User", - "installer": "Installer" - }, - "Form": { - "user": { - "acceptPrivacyPolicy": "By creating a FENECON account, I declare that I have read and agree to the FENECON Privacy Policy and Terms of Use.*" - }, - "installer": { - "acceptPrivacyPolicy": "By creating a FENECON installer account, I declare that I have read and agree to the FENECON Privacy Policy and Terms of Use.*" - }, - "contactDetails": "Contact Details", - "companyName": "Company name", - "firstname": "First name", - "lastname": "Last name", - "street": "Street", - "zip": "Postal code", - "city": "City", - "country": "Country", - "phone": "Phone number", - "email": "E-Mail", - "password": "Password", - "confirmPassword": "Confirm password", - "isElectrician": "I confirm that my company is registered in the installer register and i am therefore authorised to connect and commission a storage system.", - "acceptPrivacyPolicy": "By creating a FENECON installer account, I declare that I have read and agree to the FENECON Privacy Policy and Terms of Use.*", - "acceptAgb": "I confirm the AGB.*", - "subscribeNewsletter": "I would like to subscribe to the FENECON newsletter to receive all the latest news from FENECON.", - "company": "Company" - }, - "button": "Create", - "errors": { - "requiredFields": "Please fill in all fields", - "passwordNotEqual": "Passwords are not equal" - }, - "success": "Registration successful" - }, "Role": { "guest": "Guest", "owner": "Owner", diff --git a/ui/src/assets/i18n/es.json b/ui/src/assets/i18n/es.json index e68e9ea1c92..304f9c45a53 100644 --- a/ui/src/assets/i18n/es.json +++ b/ui/src/assets/i18n/es.json @@ -86,15 +86,14 @@ "save": "Ahorrar" }, "Menu": { - "aboutUI": "Sobre OpenEMS", "accessLevel": "Nivel de acceso", - "edgeSettings": "Configuración OpenEMS", + "edgeSettings": "Configuración", "generalSettings": "Configuración general", "index": "Visión general", "logout": "Desuscribirse", "menu": "Menú", "name": "Nombre", - "overview": "estudio OpenEMS", + "overview": "Todos los sistemas", "settings": "Ajustes", "user": "Usuario", "changelog": "Changelog", @@ -119,43 +118,6 @@ "authenticationFailed": "Fallo de autentificación", "user": "Usuario" }, - "Register": { - "title": "Crear una cuenta de usuario", - "segment": { - "user": "Usuario", - "installer": "Instalador" - }, - "Form": { - "user": { - "acceptPrivacyPolicy": "Al crear una cuenta de FENECON, declaro que he leído y acepto la Política de Privacidad y las Condiciones de Uso de FENECON.*" - }, - "installer": { - "acceptPrivacyPolicy": "Al crear una cuenta de instalador de FENECON, declaro que he leído y acepto la Política de privacidad y las Condiciones de uso de FENECON.*" - }, - "contactDetails": "Datos de contacto", - "companyName": "Nombre de la empresa", - "firstname": "Nombre", - "lastname": "Apellido", - "street": "Calle | número de casa", - "zip": "Código postal", - "city": "Ciudad", - "country": "País", - "phone": "Número de teléfono", - "email": "Correo electrónico", - "password": "Contraseña", - "confirmPassword": "Confirmar contraseña", - "isElectrician": "Confirmo que mi empresa está inscrita en el registro de instaladores y, por tanto, estoy autorizado a conectar y poner en marcha un sistema de almacenamiento.", - "acceptPrivacyPolicy": "Al crear una cuenta de instalador de FENECON, declaro que he leído y acepto la Política de privacidad y las condiciones de uso de FENECON.*", - "acceptAgb": "Confirmo el AGB.*", - "subscribeNewsletter": "Me gustaría suscribirme al boletín de FENECON para recibir todas las novedades de FENECON." - }, - "button": "Crear", - "errors": { - "requiredFields": "Por favor, rellene todos los campos", - "passwordNotEqual": "Las contraseñas no son iguales" - }, - "success": "Registro realizado con éxito" - }, "Edge": { "Index": { "EmergencyReserve": { @@ -171,8 +133,7 @@ "storage": "Memoria", "storageCharge": "Carga del almacenaje", "storageDischarge": "Descarga de memoria", - "title": "Monitor de energía", - "excelExportWarning": "La visualización y exportación de datos durante un periodo de tiempo más largo sólo es posible actualmente de forma limitada. Por favor, inténtelo más tarde." + "title": "Monitor de energía" }, "Widgets": { "autarchyInfo": "La autarquía indica el porcentaje de energía actual que puede cubrirse mediante la descarga de generación y almacenamiento.", @@ -499,12 +460,12 @@ "error": "Error al cargar la configuración" }, "interval": { - "hours": "horas", - "minute": "minuto", - "minutes": "minutos", - "day": "día", - "days": "días", - "hour": "hora" + "hours": "Horas", + "minute": "Minuto", + "minutes": "Minutos", + "day": "Día", + "days": "Días", + "hour": "Hora" } }, "App": { @@ -519,7 +480,8 @@ "deleteApp": "Eliminar la aplicación", "updateApp": "Actualizar la aplicación", "errorInstallable": "Errores de instalación", - "errorCompatible": "Errores de compatibilidad" + "errorCompatible": "Errores de compatibilidad", + "notAvailable": "No disponible" } }, "Service": { @@ -544,14 +506,12 @@ }, "About": { "build": "Esta compilación", - "contact": "Para preguntas y sugerencias sobre el sistema, por favor contacte a nuestro OpenEMS-Team en {{value}}.", "currentDevelopments": "Desarrollos actuales", "developed": "Esta interfaz de usario es desarrollada por FENECON como software de código abierto.", "faq": "Preguntas frecuentes (FAQ)", "language": "Seleccionar idioma:", "openEMS": "Acerca de OpenEMS", - "patchnotes": "Cambios en la supervisión de esta compilación", - "ui": "Interfaz de usario para OpenEMS" + "patchnotes": "Cambios en la supervisión de esta compilación" }, "Notifications": { "authenticationFailed": "Sin conexión: error de autenticación.", @@ -560,4 +520,4 @@ "loggedIn": "Registrado.", "loggedInAs": "Conectado como usuario \"{{ value }}\"." } -} +} \ No newline at end of file diff --git a/ui/src/assets/i18n/fr.json b/ui/src/assets/i18n/fr.json index b8b291bd5b1..385e2375e29 100644 --- a/ui/src/assets/i18n/fr.json +++ b/ui/src/assets/i18n/fr.json @@ -88,15 +88,14 @@ "save": "sauvegarder" }, "Menu": { - "aboutUI": "à propos de OpenEMS UI", "accessLevel": "Niveau d'accès", - "edgeSettings": "Réglages de OpenEMS", + "edgeSettings": "Réglages", "generalSettings": "Réglages généraux", "index": "Index", "logout": "Déconnexion", "menu": "Menu", "name": "Nom", - "overview": "Apperçu OpenEMS ", + "overview": "Tous les systèmes", "profile": "Utilisateur", "settings": "Réglages", "changelog": "Changelog", @@ -121,43 +120,6 @@ "authenticationFailed": "Échec de l'authentification", "user": "Utilisateur" }, - "Register": { - "title": "Créer un compte utilisateur", - "segment": { - "user": "Utilisateur", - "installer": "Installateur" - }, - "Form": { - "user": { - "acceptPrivacyPolicy": "En créant un compte FENECON, je déclare avoir lu et accepté la Politique de confidentialité et les conditions d'utilisation de FENECON*." - }, - "installer": { - "acceptPrivacyPolicy": "En créant un compte installateur FENECON, je déclare avoir lu et accepté la Politique de confidentialité et les conditions d'utilisation de FENECON.*" - }, - "contactDetails": "Coordonnées", - "companyName": "Nom de la société", - "firstname": "Prénom", - "lastname": "Nom de famille", - "street": "Rue | Numéro de maison", - "zip": "Code postal", - "city": "Ville", - "country": "Pays", - "phone": "Numéro de téléphone", - "email": "Courrier électronique.", - "password": "Mot de passe.", - "confirmPassword": "Confirmer le mot de passe.", - "isElectrician": "Je confirme que mon entreprise est inscrite dans le registre des installateurs et que je suis donc autorisé à raccorder et à mettre en service un système de stockage.", - "acceptPrivacyPolicy": "En créant un compte installateur FENECON, je déclare avoir lu et accepté la Politique de confidentialité et les conditions d'utilisation de FENECON.*", - "acceptAgb": "Je confirme le AGB.*", - "subscribeNewsletter": "Je souhaite m'inscrire à la newsletter de la FENECON pour recevoir toutes les dernières nouvelles de la FENECON." - }, - "button": "Créer", - "errors": { - "requiredFields": "Veuillez remplir tous les champs", - "passwordNotEqual": "Les mots de passe ne sont pas égaux." - }, - "success": "Inscription réussie" - }, "Edge": { "Index": { "EmergencyReserve": { @@ -173,8 +135,7 @@ "storage": "Stockage", "storageCharge": "Stockage-Charge", "storageDischarge": "Stockage-Décharge", - "title": "Moniteur d'énergie", - "excelExportWarning": "L`affichage et l`exportation de données sur une longue période sont actuellement limités. Veuillez réessayer ultérieurement." + "title": "Moniteur d'énergie" }, "Energytable": { "title": "Tableau énergétique", @@ -500,12 +461,12 @@ "error": "Erreur lors du chargement des paramètres" }, "interval": { - "hours": "heures", - "minute": "minute", - "minutes": "minutes", - "day": "journée", - "days": "journées", - "hour": "heure" + "hours": "Heures", + "minute": "Minute", + "minutes": "Minutes", + "day": "Journée", + "days": "Journées", + "hour": "Heure" } }, "App": { @@ -520,7 +481,8 @@ "deleteApp": "Supprimer l'application", "updateApp": "Mise à jour de l'application", "errorInstallable": "Erreurs d'installation", - "errorCompatible": "Erreurs de compatibilité" + "errorCompatible": "Erreurs de compatibilité", + "notAvailable": "Pas disponible" } }, "Service": { @@ -545,12 +507,10 @@ }, "About": { "build": "This build", - "contact": "Veuillez contacter notre équipe pour plus d'informations ou suggestions sur le système à l'adresse{{ value }}.", "currentDevelopments": "Développement actuels", "developed": "Cet interface utilisateur est développé en tant que logiciel libre.", "language": "Sélectionnez la langue:", - "openEMS": "Plus au sujet d'OpenEMS", - "ui": "interface utilisateur pour OpenEMS" + "openEMS": "Plus au sujet d'OpenEMS" }, "Notifications": { "authenticationFailed": "Pas de connexion, échec d'authentification .", @@ -559,4 +519,4 @@ "loggedIn": "Enregistré.", "loggedInAs": "Enregistré sous as '{{ value }}'." } -} +} \ No newline at end of file diff --git a/ui/src/assets/i18n/nl.json b/ui/src/assets/i18n/nl.json index fb2dcdd8f57..355ad850f06 100644 --- a/ui/src/assets/i18n/nl.json +++ b/ui/src/assets/i18n/nl.json @@ -83,15 +83,14 @@ "save": "Opslaan" }, "Menu": { - "aboutUI": "Over FEMS", "accessLevel": "Toegangsniveau", - "edgeSettings": "FEMS instellingen", + "edgeSettings": "instellingen", "generalSettings": "Algemene instellingen", "index": "Overzicht", "logout": "Uitloggen", "menu": "Menu", "name": "Naam", - "overview": "FEMS overzicht", + "overview": "Alle systemen", "settings": "Instellingen", "user": "Gebruiker", "changelog": "Changelog", @@ -116,43 +115,6 @@ "authenticationFailed": "Authenticatie mislukt", "user": "Gebruiker" }, - "Register": { - "title": "Gebruikersaccount aanmaken", - "segment": { - "user": "Gebruiker", - "installer": "Installateur" - }, - "Form": { - "user": { - "acceptPrivacyPolicy": "Door een FENECON account aan te maken, verklaar ik dat ik de FENECON Privacybeleid en Gebruiksvoorwaarden heb gelezen en ermee akkoord ga.*" - }, - "installer": { - "acceptPrivacyPolicy": "Door een FENECON installateursaccount aan te maken verklaar ik dat ik het FENECON Privacybeleid en de Gebruiksvoorwaarden heb gelezen en ermee akkoord ga.*" - }, - "contactDetails": "Contactgegevens", - "companyName": "Bedrijfsnaam", - "firstname": "Voornaam", - "lastname": "Achternaam", - "street": "Straat | huisnummer", - "zip": "Postcode", - "city": "Stad", - "country": "Land", - "phone": "Telefoonnummer", - "email": "E-Mail - adres", - "password": "Wachtwoord", - "confirmPassword": "Bevestig wachtwoord", - "isElectrician": "Ik bevestig dat mijn bedrijf is ingeschreven in het installateursregister en dat ik daarmee bevoegd ben om een opslagsysteem aan te sluiten en in bedrijf te stellen.*", - "acceptPrivacyPolicy": "Door een FENECON installateursaccount aan te maken, verklaar ik dat ik hetprivacybeleid en de gebruiksvoorwaarden van FENECON heb gelezen en ermee akkoord ga.*", - "acceptAgb": "Ik bevestig de AGB.*", - "subscribeNewsletter": "Ik wil me graag abonneren op de FENECON nieuwsbrief om al het laatste nieuws van FENECON te ontvangen." - }, - "button": "Maken", - "errors": { - "requiredFields": "Gelieve alle velden in te vullen" - }, - "passwordNotEqual": "Wachtwoorden zijn niet gelijk", - "success": "Registratie succesvol" - }, "Edge": { "Index": { "EmergencyReserve": { @@ -166,8 +128,7 @@ "productionMeter": "Productiemeter", "reactivePower": "Blind vermogen", "storage": "Batterij", - "title": "Energiemonitor", - "excelExportWarning": "De weergave en uitvoer van gegevens over een langere periode is momenteel slechts in beperkte mate mogelijk. Probeer het later nog eens." + "title": "Energiemonitor" }, "Widgets": { "autarchyInfo": "Autarky geeft het percentage huidig ​​vermogen aan dat kan worden gedekt door opwekking en ontlading van de opslag.", @@ -495,12 +456,12 @@ "error": "Fout bij het laden van de instellingen" }, "interval": { - "hours": "uur", - "minute": "minuut", - "minutes": "minuten", - "day": "dag", - "days": "dagen", - "hour": "uur" + "hours": "Uur", + "minute": "Minuut", + "minutes": "Minuten", + "day": "Dag", + "days": "Dagen", + "hour": "Uur" } }, "App": { @@ -515,7 +476,8 @@ "deleteApp": "App verwijderen", "updateApp": "App bijwerken", "errorInstallable": "Installatiefouten", - "errorCompatible": "Compatibiliteitsfouten" + "errorCompatible": "Compatibiliteitsfouten", + "notAvailable": "Niet beschikbaar" } }, "Service": { @@ -540,14 +502,12 @@ }, "About": { "build": "Versie", - "contact": "Voor meer informatie of suggesties over het systeem, neem contact op met het team via {{value}}.", "currentDevelopments": "Huidige ontwikkelingen", "developed": "Deze gebruikersinterface is ontwikkeld als open-source-software.", "faq": "Veel Gestelde Vragen (FAQ)", "language": "Selecteer taal:", "openEMS": "Meer over OpenEMS", - "patchnotes": "Veranderingen in de monitoring voor deze build", - "ui": "Gebruikersinterface voor FEMS" + "patchnotes": "Veranderingen in de monitoring voor deze build" }, "Notifications": { "authenticationFailed": "Geen verbinding.Autorisatie mislukt.", @@ -556,4 +516,4 @@ "loggedIn": "Aangemeld.", "loggedInAs": "Aangemeld als gebruiker {{ value }}." } -} +} \ No newline at end of file diff --git a/ui/src/global.scss b/ui/src/global.scss index 1f96b663397..56b3426db5c 100644 --- a/ui/src/global.scss +++ b/ui/src/global.scss @@ -31,7 +31,6 @@ formly-wrapper-ion-form-field, formly-input-serial-number, -formly-select-field-wrapper, formly-field-ion-radio { ion-label { line-height: 1.2; @@ -60,6 +59,12 @@ formly-field-ion-radio { } } +// Removes the ripple effect while using the custom box. +.custom-checkbox { + --ripple-color: transparent; + --background-hover: transparent; +} + .margin-top { ion-item { @@ -278,4 +283,36 @@ formly-input-section { ion-toggle { --background-checked: var(--ion-color-primary-tint); } + + ion-spinner { + transform: scale(1.5); + left: 25%; + width: 50%; + color: var(--ion-color-primary); + } +} + +// auto height for modals +ion-modal.auto-height { + &.bottom { + align-items: flex-end; + } + + --height: auto; + + .ion-page { + position: relative; + display: block; + contain: content; + + .inner-content { + max-height: 80vh; + overflow: auto; + padding: 10px; + } + } +} + +ion-modal.full-width { + --width: 100%; } \ No newline at end of file diff --git a/ui/src/test.ts b/ui/src/test.ts index 50193eb0f28..b3cf9ae58b7 100644 --- a/ui/src/test.ts +++ b/ui/src/test.ts @@ -1,25 +1,21 @@ +// TO NOT AUTOFORMAT THIS FILE AS IT WILL BREAK CI BUILD WITH FOLLOWING ERROR: +// Error: zone-testing.js is needed for the fakeAsync() test helper but could not be found. +// Please make sure that your environment includes zone.js/testing +// (See https://stackoverflow.com/a/68797535/4137113) + +// This file is a copy of https://github.com/angular/angular/blob/main/aio/src/test.ts + // This file is required by karma.conf.js and loads recursively all the .spec and framework files -import 'zone.js/dist/zone-testing'; +import 'zone.js/testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; -declare const require: { - context(path: string, deep?: boolean, filter?: RegExp): { - keys(): string[]; - (id: string): T; - }; -}; - // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, - platformBrowserDynamicTesting() -); -// Then we find all the tests. -const context = require.context('./', true, /\.spec\.ts$/); -// And load the modules. -context.keys().map(context); + platformBrowserDynamicTesting(), +); \ No newline at end of file diff --git a/ui/src/themes/openems/scss/variables.scss b/ui/src/themes/openems/scss/variables.scss index 1a01388df4d..ff688b12e78 100644 --- a/ui/src/themes/openems/scss/variables.scss +++ b/ui/src/themes/openems/scss/variables.scss @@ -26,7 +26,7 @@ $font-family: var(--ion-font-family); --ion-color-secondary-tint: #f2cc9e; /** tertiary **/ - --ion-color-tertiary: #e1d5c4; + --ion-color-tertiary: #f4f4f4; --ion-color-tertiary-rgb: 225, 213, 196; --ion-color-tertiary-contrast: #000000; --ion-color-tertiary-contrast-rgb: 0, 0, 0; diff --git a/ui/tsconfig.json b/ui/tsconfig.json index 6cb571f3373..c8430f590ca 100644 --- a/ui/tsconfig.json +++ b/ui/tsconfig.json @@ -10,14 +10,15 @@ "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, - "target": "es2015", + "target": "ES2022", "module": "es2020", "lib": [ "es2018", "dom" ], "resolveJsonModule": true, - "esModuleInterop": true + "esModuleInterop": true, + "useDefineForClassFields": false, }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, From f750fa5bda7a1ab86c2d86ab5cfa9de2f93cb2d1 Mon Sep 17 00:00:00 2001 From: Stefan Feilmeier Date: Fri, 24 Mar 2023 13:14:07 +0100 Subject: [PATCH 16/23] Update to Java 17 (#1685) Java 17 is the latest LTS (Long Term Support) release of Java. See discussion in OpenEMS Community: https://community.openems.io/t/switch-to-java-17/1326 --- .github/workflows/build.yml | 4 ++-- .gitpod.Dockerfile | 2 +- cnf/build.bnd | 4 ++-- doc/modules/ROOT/pages/contribute/coding-guidelines.adoc | 2 +- doc/modules/ROOT/pages/gettingstarted.adoc | 8 ++++---- io.openems.backend.alerting/.classpath | 2 +- io.openems.backend.application/.classpath | 2 +- io.openems.backend.application/BackendApp.bndrun | 2 +- io.openems.backend.b2brest/.classpath | 2 +- io.openems.backend.b2bwebsocket/.classpath | 2 +- io.openems.backend.common/.classpath | 2 +- io.openems.backend.core/.classpath | 2 +- io.openems.backend.edgewebsocket/.classpath | 2 +- io.openems.backend.metadata.dummy/.classpath | 2 +- io.openems.backend.metadata.file/.classpath | 2 +- io.openems.backend.metadata.odoo/.classpath | 2 +- io.openems.backend.timedata.dummy/.classpath | 2 +- io.openems.backend.timedata.influx/.classpath | 2 +- io.openems.backend.timedata.timescaledb/.classpath | 2 +- io.openems.backend.uiwebsocket/.classpath | 2 +- io.openems.common/.classpath | 2 +- io.openems.edge.application/.classpath | 2 +- io.openems.edge.application/EdgeApp.bndrun | 2 +- io.openems.edge.battery.api/.classpath | 2 +- io.openems.edge.battery.bmw/.classpath | 2 +- io.openems.edge.battery.bydcommercial/.classpath | 2 +- io.openems.edge.battery.fenecon.commercial/.classpath | 2 +- io.openems.edge.battery.fenecon.home/.classpath | 2 +- io.openems.edge.battery.soltaro/.classpath | 2 +- io.openems.edge.batteryinverter.api/.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.batteryinverter.refu88k/.classpath | 2 +- io.openems.edge.batteryinverter.sinexcel/.classpath | 2 +- io.openems.edge.batteryinverter.sunspec/.classpath | 2 +- io.openems.edge.bosch.bpts5hybrid/.classpath | 2 +- io.openems.edge.bridge.mbus/.classpath | 2 +- io.openems.edge.bridge.modbus/.classpath | 2 +- io.openems.edge.bridge.onewire/.classpath | 2 +- io.openems.edge.common/.classpath | 2 +- io.openems.edge.controller.api.backend/.classpath | 2 +- io.openems.edge.controller.api.common/.classpath | 2 +- io.openems.edge.controller.api.modbus/.classpath | 2 +- io.openems.edge.controller.api.mqtt/.classpath | 2 +- io.openems.edge.controller.api.rest/.classpath | 2 +- io.openems.edge.controller.api.websocket/.classpath | 2 +- io.openems.edge.controller.api/.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.controller.channelthreshold/.classpath | 2 +- io.openems.edge.controller.chp.soc/.classpath | 2 +- io.openems.edge.controller.debug.detailedlog/.classpath | 2 +- io.openems.edge.controller.debug.log/.classpath | 2 +- io.openems.edge.controller.ess.acisland/.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.controller.ess.cycle/.classpath | 2 +- io.openems.edge.controller.ess.delaycharge/.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.controller.ess.fixactivepower/.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.controller.ess.linearpowerband/.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.controller.ess.selltogridlimit/.classpath | 2 +- io.openems.edge.controller.ess.standby/.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.controller.evcs.fixactivepower/.classpath | 2 +- io.openems.edge.controller.evcs/.classpath | 2 +- io.openems.edge.controller.generic.jsonlogic/.classpath | 2 +- io.openems.edge.controller.highloadtimeslot/.classpath | 2 +- io.openems.edge.controller.io.alarm/.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.controller.io.fixdigitaloutput/.classpath | 2 +- io.openems.edge.controller.io.heatingelement/.classpath | 2 +- io.openems.edge.controller.io.heatpump.sgready/.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.controller.symmetric.balancing/.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.core/.classpath | 2 +- io.openems.edge.edge2edge/.classpath | 2 +- io.openems.edge.ess.adstec.storaxe/.classpath | 2 +- io.openems.edge.ess.api/.classpath | 2 +- io.openems.edge.ess.byd.container/.classpath | 2 +- io.openems.edge.ess.cluster/.classpath | 2 +- io.openems.edge.ess.core/.classpath | 2 +- io.openems.edge.ess.fenecon.commercial40/.classpath | 2 +- io.openems.edge.ess.generic/.classpath | 2 +- io.openems.edge.ess.mr.gridcon/.classpath | 2 +- io.openems.edge.ess.sma/.classpath | 2 +- io.openems.edge.evcs.alpitronic.hypercharger/.classpath | 2 +- io.openems.edge.evcs.api/.classpath | 2 +- io.openems.edge.evcs.cluster/.classpath | 2 +- io.openems.edge.evcs.core/.classpath | 2 +- io.openems.edge.evcs.dezony/generated/buildfiles | 1 - io.openems.edge.evcs.goe.chargerhome/.classpath | 2 +- io.openems.edge.evcs.hardybarth/.classpath | 2 +- io.openems.edge.evcs.keba.kecontact/.classpath | 2 +- io.openems.edge.evcs.ocpp.abl/.classpath | 2 +- io.openems.edge.evcs.ocpp.common/.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.evcs.ocpp.server/.classpath | 2 +- io.openems.edge.evcs.webasto.next/.classpath | 2 +- io.openems.edge.evcs.webasto.unite/.classpath | 2 +- io.openems.edge.fenecon.dess/.classpath | 2 +- io.openems.edge.fenecon.mini/.classpath | 2 +- io.openems.edge.fenecon.pro/.classpath | 2 +- io.openems.edge.goodwe/.classpath | 2 +- io.openems.edge.io.api/.classpath | 2 +- io.openems.edge.io.kmtronic/.classpath | 2 +- io.openems.edge.io.offgridswitch/.classpath | 2 +- io.openems.edge.io.revpi/.classpath | 2 +- io.openems.edge.io.shelly/.classpath | 2 +- io.openems.edge.io.wago/.classpath | 2 +- io.openems.edge.io.weidmueller/.classpath | 2 +- io.openems.edge.kaco.blueplanet.hybrid10/.classpath | 2 +- io.openems.edge.katek.edcom/.classpath | 2 +- io.openems.edge.kostal.piko/.classpath | 2 +- io.openems.edge.meter.abb/.classpath | 2 +- io.openems.edge.meter.api/.classpath | 2 +- io.openems.edge.meter.artemes.am2/.classpath | 2 +- io.openems.edge.meter.bcontrol.em300/.classpath | 2 +- io.openems.edge.meter.bgetech/.classpath | 2 +- io.openems.edge.meter.carlo.gavazzi.em300/.classpath | 2 +- io.openems.edge.meter.discovergy/.classpath | 2 +- io.openems.edge.meter.janitza/.classpath | 2 +- io.openems.edge.meter.kdk/.classpath | 2 +- io.openems.edge.meter.microcare.sdm630/.classpath | 2 +- io.openems.edge.meter.plexlog/.classpath | 2 +- io.openems.edge.meter.pqplus/.classpath | 2 +- .../.classpath | 2 +- io.openems.edge.meter.siemens/.classpath | 2 +- io.openems.edge.meter.sma.shm20/.classpath | 2 +- io.openems.edge.meter.socomec/.classpath | 2 +- io.openems.edge.meter.sunspec/.classpath | 2 +- io.openems.edge.meter.virtual/.classpath | 2 +- io.openems.edge.meter.weidmueller/.classpath | 2 +- io.openems.edge.meter.ziehl/.classpath | 2 +- io.openems.edge.onewire.thermometer/.classpath | 2 +- io.openems.edge.predictor.api/.classpath | 2 +- io.openems.edge.predictor.persistencemodel/.classpath | 2 +- io.openems.edge.predictor.similardaymodel/.classpath | 2 +- io.openems.edge.pvinverter.api/.classpath | 2 +- io.openems.edge.pvinverter.cluster/.classpath | 2 +- io.openems.edge.pvinverter.fronius/.classpath | 2 +- io.openems.edge.pvinverter.kaco.blueplanet/.classpath | 2 +- io.openems.edge.pvinverter.kostal/.classpath | 2 +- io.openems.edge.pvinverter.sma/.classpath | 2 +- io.openems.edge.pvinverter.solarlog/.classpath | 2 +- io.openems.edge.pvinverter.sunspec/.classpath | 2 +- io.openems.edge.scheduler.allalphabetically/.classpath | 2 +- io.openems.edge.scheduler.api/.classpath | 2 +- io.openems.edge.scheduler.daily/.classpath | 2 +- io.openems.edge.scheduler.fixedorder/.classpath | 2 +- io.openems.edge.simulator/.classpath | 2 +- io.openems.edge.solaredge/.classpath | 2 +- io.openems.edge.tesla.powerwall2/.classpath | 2 +- io.openems.edge.thermometer.api/.classpath | 2 +- io.openems.edge.timedata.api/.classpath | 2 +- io.openems.edge.timedata.influxdb/.classpath | 2 +- io.openems.edge.timedata.rrd4j/.classpath | 2 +- io.openems.edge.timeofusetariff.api/.classpath | 2 +- io.openems.edge.timeofusetariff.awattar/.classpath | 2 +- io.openems.edge.timeofusetariff.corrently/.classpath | 2 +- io.openems.edge.timeofusetariff.tibber/.classpath | 2 +- io.openems.shared.influxdb/.classpath | 2 +- io.openems.wrapper/.classpath | 2 +- tools/docker/openems-backend/Dockerfile | 4 ++-- tools/prepare-commit.sh | 2 +- 179 files changed, 184 insertions(+), 185 deletions(-) delete mode 100644 io.openems.edge.evcs.dezony/generated/buildfiles diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ec3249aa87..61f3784d0e6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,11 +6,11 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Setup Java 11 + - name: Setup Java 17 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '11' + java-version: '17' java-package: jdk - name: Setup Cache for Java/Gradle diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index ae22ac510ec..7cbb6ac5295 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -1,7 +1,7 @@ FROM gitpod/workspace-postgres RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh \ - && sdk install java 11.0.13-tem" + && sdk install java 17.0.6-tem" # disable angular analytics ENV NG_CLI_ANALYTICS=false diff --git a/cnf/build.bnd b/cnf/build.bnd index 71586cd322d..76ce7586ca7 100644 --- a/cnf/build.bnd +++ b/cnf/build.bnd @@ -74,5 +74,5 @@ testpath: \ Edge_Timedata;member=${filter;${p};io\.openems\.edge\.timedata\..*},\ Edge_TimeOfUseTariff;member=${filter;${p};io\.openems\.edge\.timeofusetariff\..*},\ -javac.source: 11 -javac.target: 11 +javac.source: 17 +javac.target: 17 diff --git a/doc/modules/ROOT/pages/contribute/coding-guidelines.adoc b/doc/modules/ROOT/pages/contribute/coding-guidelines.adoc index 44aa2ac54aa..86f373381c9 100644 --- a/doc/modules/ROOT/pages/contribute/coding-guidelines.adoc +++ b/doc/modules/ROOT/pages/contribute/coding-guidelines.adoc @@ -26,7 +26,7 @@ * Use precise naming for methods/functions * Use narrow scopes for variables; avoid class variables * Split code in Interface, Implementation(..Impl) and Config files -* Use modern Java 11 syntax (e.g. 'var' keyword, streams, etc.) +* Use modern Java 17 syntax (e.g. 'var' keyword, streams, etc.) * Add readme.adoc to a new bundle * Review data in bnd.bnd file * Format all files via Eclipse Autoformat, organize Imports, apply Checkstyle suggestions (see below) diff --git a/doc/modules/ROOT/pages/gettingstarted.adoc b/doc/modules/ROOT/pages/gettingstarted.adoc index 697961fcab7..edac3eb0565 100644 --- a/doc/modules/ROOT/pages/gettingstarted.adoc +++ b/doc/modules/ROOT/pages/gettingstarted.adoc @@ -42,7 +42,7 @@ NOTE: OpenEMS uses the **git** version control system via the popular GitHub pla NOTE: Eclipse IDE is the recommended development environment for newcomers to OpenEMS. If you are more familiar with IntelliJ IDEA, feel free to use it. Follow xref:intellij.adoc[this guide]. . Prepare Eclipse IDE -.. Download Java Development Kit (JDK) 11 and install it. We recommend the https://adoptium.net/?variant=openjdk11&jvmVariant=hotspot[OpenJDK Temurin builds by the Adoptium project] +.. Download Java Development Kit (JDK) 17 and install it. We recommend the https://adoptium.net/de/temurin/releases/?version=17[OpenJDK Temurin builds by the Adoptium project] .. Download https://www.eclipse.org[Eclipse for Java icon:external-link[]], install and start it .. On first start you will get asked to create a workspace. Select your source code directory (`C:\Users\your.user\git\openems` in our example) and press btn:[Launch]. @@ -54,15 +54,15 @@ image::eclipse-workspace.png[Creating a workspace in Eclipse IDE] + Menu: btn:[Help] → btn:[Eclipse Marketplace...] → btn:[Find:] → enter btn:[Bndtools] → press btn:[Install] -.. Configure Eclipse IDE to use JDK 11. +.. Configure Eclipse IDE to use JDK 17. + - In the Menu select btn:[Windows] → btn:[Preferences] - Select btn:[Java] - btn:[Installed JREs] in the navigation tree - Press the btn:[Add...] button - Keep btn:[Standard VM] selected and press btn:[Next >] -- Press the btn:[Directory...] button and select the folder of the installed JDK (e.g. `C:\Program Files\Eclipse Adoptium\jdk-11.0.13.8-hotspot`) +- Press the btn:[Directory...] button and select the folder of the installed JDK (e.g. `C:\Program Files\Eclipse Adoptium\jdk-17.0.6.10-hotspot`) - Press the btn:[Finish] button -- Back in the Preferences window, tick the newly added JDK 11 and press btn:[Apply and Close] +- Back in the Preferences window, tick the newly added JDK 17 and press btn:[Apply and Close] + .Creating a workspace in Eclipse IDE image::eclipse-select-jdk.png[Set the Java Development Kit in Eclipse IDE] diff --git a/io.openems.backend.alerting/.classpath b/io.openems.backend.alerting/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.alerting/.classpath +++ b/io.openems.backend.alerting/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.application/.classpath b/io.openems.backend.application/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.application/.classpath +++ b/io.openems.backend.application/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.application/BackendApp.bndrun b/io.openems.backend.application/BackendApp.bndrun index f1dee20aea7..f6fe613c2bd 100644 --- a/io.openems.backend.application/BackendApp.bndrun +++ b/io.openems.backend.application/BackendApp.bndrun @@ -1,5 +1,5 @@ -runfw: org.apache.felix.framework;version='[7.0.5,7.0.5]' --runee: JavaSE-11 +-runee: JavaSE-17 -runprovidedcapabilities: ${native_capability} -resolve.effective: active diff --git a/io.openems.backend.b2brest/.classpath b/io.openems.backend.b2brest/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.b2brest/.classpath +++ b/io.openems.backend.b2brest/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.b2bwebsocket/.classpath b/io.openems.backend.b2bwebsocket/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.b2bwebsocket/.classpath +++ b/io.openems.backend.b2bwebsocket/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.common/.classpath b/io.openems.backend.common/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.common/.classpath +++ b/io.openems.backend.common/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.core/.classpath b/io.openems.backend.core/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.core/.classpath +++ b/io.openems.backend.core/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.edgewebsocket/.classpath b/io.openems.backend.edgewebsocket/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.edgewebsocket/.classpath +++ b/io.openems.backend.edgewebsocket/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.metadata.dummy/.classpath b/io.openems.backend.metadata.dummy/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.metadata.dummy/.classpath +++ b/io.openems.backend.metadata.dummy/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.metadata.file/.classpath b/io.openems.backend.metadata.file/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.metadata.file/.classpath +++ b/io.openems.backend.metadata.file/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.metadata.odoo/.classpath b/io.openems.backend.metadata.odoo/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.metadata.odoo/.classpath +++ b/io.openems.backend.metadata.odoo/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.timedata.dummy/.classpath b/io.openems.backend.timedata.dummy/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.timedata.dummy/.classpath +++ b/io.openems.backend.timedata.dummy/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.timedata.influx/.classpath b/io.openems.backend.timedata.influx/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.timedata.influx/.classpath +++ b/io.openems.backend.timedata.influx/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.timedata.timescaledb/.classpath b/io.openems.backend.timedata.timescaledb/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.timedata.timescaledb/.classpath +++ b/io.openems.backend.timedata.timescaledb/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.backend.uiwebsocket/.classpath b/io.openems.backend.uiwebsocket/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.backend.uiwebsocket/.classpath +++ b/io.openems.backend.uiwebsocket/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.common/.classpath b/io.openems.common/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.common/.classpath +++ b/io.openems.common/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.application/.classpath b/io.openems.edge.application/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.application/.classpath +++ b/io.openems.edge.application/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index 685bab5550c..8cf883fc0cd 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -1,5 +1,5 @@ -runfw: org.apache.felix.framework;version='[7.0.5,7.0.5]' --runee: JavaSE-11 +-runee: JavaSE-17 -runprovidedcapabilities: ${native_capability} -resolve.effective: active diff --git a/io.openems.edge.battery.api/.classpath b/io.openems.edge.battery.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.battery.api/.classpath +++ b/io.openems.edge.battery.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.battery.bmw/.classpath b/io.openems.edge.battery.bmw/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.battery.bmw/.classpath +++ b/io.openems.edge.battery.bmw/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.battery.bydcommercial/.classpath b/io.openems.edge.battery.bydcommercial/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.battery.bydcommercial/.classpath +++ b/io.openems.edge.battery.bydcommercial/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.battery.fenecon.commercial/.classpath b/io.openems.edge.battery.fenecon.commercial/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.battery.fenecon.commercial/.classpath +++ b/io.openems.edge.battery.fenecon.commercial/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.battery.fenecon.home/.classpath b/io.openems.edge.battery.fenecon.home/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.battery.fenecon.home/.classpath +++ b/io.openems.edge.battery.fenecon.home/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.battery.soltaro/.classpath b/io.openems.edge.battery.soltaro/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.battery.soltaro/.classpath +++ b/io.openems.edge.battery.soltaro/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.batteryinverter.api/.classpath b/io.openems.edge.batteryinverter.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.batteryinverter.api/.classpath +++ b/io.openems.edge.batteryinverter.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/.classpath b/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/.classpath +++ b/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.batteryinverter.refu88k/.classpath b/io.openems.edge.batteryinverter.refu88k/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.batteryinverter.refu88k/.classpath +++ b/io.openems.edge.batteryinverter.refu88k/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.batteryinverter.sinexcel/.classpath b/io.openems.edge.batteryinverter.sinexcel/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.batteryinverter.sinexcel/.classpath +++ b/io.openems.edge.batteryinverter.sinexcel/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.batteryinverter.sunspec/.classpath b/io.openems.edge.batteryinverter.sunspec/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.batteryinverter.sunspec/.classpath +++ b/io.openems.edge.batteryinverter.sunspec/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.bosch.bpts5hybrid/.classpath b/io.openems.edge.bosch.bpts5hybrid/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.bosch.bpts5hybrid/.classpath +++ b/io.openems.edge.bosch.bpts5hybrid/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.bridge.mbus/.classpath b/io.openems.edge.bridge.mbus/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.bridge.mbus/.classpath +++ b/io.openems.edge.bridge.mbus/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.bridge.modbus/.classpath b/io.openems.edge.bridge.modbus/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.bridge.modbus/.classpath +++ b/io.openems.edge.bridge.modbus/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.bridge.onewire/.classpath b/io.openems.edge.bridge.onewire/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.bridge.onewire/.classpath +++ b/io.openems.edge.bridge.onewire/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.common/.classpath b/io.openems.edge.common/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.common/.classpath +++ b/io.openems.edge.common/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.api.backend/.classpath b/io.openems.edge.controller.api.backend/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.api.backend/.classpath +++ b/io.openems.edge.controller.api.backend/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.api.common/.classpath b/io.openems.edge.controller.api.common/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.api.common/.classpath +++ b/io.openems.edge.controller.api.common/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.api.modbus/.classpath b/io.openems.edge.controller.api.modbus/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.api.modbus/.classpath +++ b/io.openems.edge.controller.api.modbus/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.api.mqtt/.classpath b/io.openems.edge.controller.api.mqtt/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.api.mqtt/.classpath +++ b/io.openems.edge.controller.api.mqtt/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.api.rest/.classpath b/io.openems.edge.controller.api.rest/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.api.rest/.classpath +++ b/io.openems.edge.controller.api.rest/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.api.websocket/.classpath b/io.openems.edge.controller.api.websocket/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.api.websocket/.classpath +++ b/io.openems.edge.controller.api.websocket/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.api/.classpath b/io.openems.edge.controller.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.api/.classpath +++ b/io.openems.edge.controller.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.asymmetric.balancingcosphi/.classpath b/io.openems.edge.controller.asymmetric.balancingcosphi/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.asymmetric.balancingcosphi/.classpath +++ b/io.openems.edge.controller.asymmetric.balancingcosphi/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.asymmetric.fixactivepower/.classpath b/io.openems.edge.controller.asymmetric.fixactivepower/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.asymmetric.fixactivepower/.classpath +++ b/io.openems.edge.controller.asymmetric.fixactivepower/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.asymmetric.fixreactivepower/.classpath b/io.openems.edge.controller.asymmetric.fixreactivepower/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.asymmetric.fixreactivepower/.classpath +++ b/io.openems.edge.controller.asymmetric.fixreactivepower/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.asymmetric.peakshaving/.classpath b/io.openems.edge.controller.asymmetric.peakshaving/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.asymmetric.peakshaving/.classpath +++ b/io.openems.edge.controller.asymmetric.peakshaving/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.asymmetric.phaserectification/.classpath b/io.openems.edge.controller.asymmetric.phaserectification/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.asymmetric.phaserectification/.classpath +++ b/io.openems.edge.controller.asymmetric.phaserectification/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.channelthreshold/.classpath b/io.openems.edge.controller.channelthreshold/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.channelthreshold/.classpath +++ b/io.openems.edge.controller.channelthreshold/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.chp.soc/.classpath b/io.openems.edge.controller.chp.soc/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.chp.soc/.classpath +++ b/io.openems.edge.controller.chp.soc/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.debug.detailedlog/.classpath b/io.openems.edge.controller.debug.detailedlog/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.debug.detailedlog/.classpath +++ b/io.openems.edge.controller.debug.detailedlog/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.debug.log/.classpath b/io.openems.edge.controller.debug.log/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.debug.log/.classpath +++ b/io.openems.edge.controller.debug.log/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.acisland/.classpath b/io.openems.edge.controller.ess.acisland/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.acisland/.classpath +++ b/io.openems.edge.controller.ess.acisland/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.activepowervoltagecharacteristic/.classpath b/io.openems.edge.controller.ess.activepowervoltagecharacteristic/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.activepowervoltagecharacteristic/.classpath +++ b/io.openems.edge.controller.ess.activepowervoltagecharacteristic/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.cycle/.classpath b/io.openems.edge.controller.ess.cycle/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.cycle/.classpath +++ b/io.openems.edge.controller.ess.cycle/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.delaycharge/.classpath b/io.openems.edge.controller.ess.delaycharge/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.delaycharge/.classpath +++ b/io.openems.edge.controller.ess.delaycharge/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.delayedselltogrid/.classpath b/io.openems.edge.controller.ess.delayedselltogrid/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.delayedselltogrid/.classpath +++ b/io.openems.edge.controller.ess.delayedselltogrid/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.emergencycapacityreserve/.classpath b/io.openems.edge.controller.ess.emergencycapacityreserve/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.emergencycapacityreserve/.classpath +++ b/io.openems.edge.controller.ess.emergencycapacityreserve/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.fixactivepower/.classpath b/io.openems.edge.controller.ess.fixactivepower/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.fixactivepower/.classpath +++ b/io.openems.edge.controller.ess.fixactivepower/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.gridoptimizedcharge/.classpath b/io.openems.edge.controller.ess.gridoptimizedcharge/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.gridoptimizedcharge/.classpath +++ b/io.openems.edge.controller.ess.gridoptimizedcharge/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.hybrid.surplusfeedtogrid/.classpath b/io.openems.edge.controller.ess.hybrid.surplusfeedtogrid/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.hybrid.surplusfeedtogrid/.classpath +++ b/io.openems.edge.controller.ess.hybrid.surplusfeedtogrid/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.limittotaldischarge/.classpath b/io.openems.edge.controller.ess.limittotaldischarge/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.limittotaldischarge/.classpath +++ b/io.openems.edge.controller.ess.limittotaldischarge/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.linearpowerband/.classpath b/io.openems.edge.controller.ess.linearpowerband/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.linearpowerband/.classpath +++ b/io.openems.edge.controller.ess.linearpowerband/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.mindischargeperiod/.classpath b/io.openems.edge.controller.ess.mindischargeperiod/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.mindischargeperiod/.classpath +++ b/io.openems.edge.controller.ess.mindischargeperiod/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.reactivepowervoltagecharacteristic/.classpath b/io.openems.edge.controller.ess.reactivepowervoltagecharacteristic/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.reactivepowervoltagecharacteristic/.classpath +++ b/io.openems.edge.controller.ess.reactivepowervoltagecharacteristic/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.selltogridlimit/.classpath b/io.openems.edge.controller.ess.selltogridlimit/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.selltogridlimit/.classpath +++ b/io.openems.edge.controller.ess.selltogridlimit/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.standby/.classpath b/io.openems.edge.controller.ess.standby/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.standby/.classpath +++ b/io.openems.edge.controller.ess.standby/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.ess.timeofusetariff.discharge/.classpath b/io.openems.edge.controller.ess.timeofusetariff.discharge/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.ess.timeofusetariff.discharge/.classpath +++ b/io.openems.edge.controller.ess.timeofusetariff.discharge/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.evcs.fixactivepower/.classpath b/io.openems.edge.controller.evcs.fixactivepower/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.evcs.fixactivepower/.classpath +++ b/io.openems.edge.controller.evcs.fixactivepower/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.evcs/.classpath b/io.openems.edge.controller.evcs/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.evcs/.classpath +++ b/io.openems.edge.controller.evcs/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.generic.jsonlogic/.classpath b/io.openems.edge.controller.generic.jsonlogic/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.generic.jsonlogic/.classpath +++ b/io.openems.edge.controller.generic.jsonlogic/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.highloadtimeslot/.classpath b/io.openems.edge.controller.highloadtimeslot/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.highloadtimeslot/.classpath +++ b/io.openems.edge.controller.highloadtimeslot/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.io.alarm/.classpath b/io.openems.edge.controller.io.alarm/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.io.alarm/.classpath +++ b/io.openems.edge.controller.io.alarm/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.io.channelsinglethreshold/.classpath b/io.openems.edge.controller.io.channelsinglethreshold/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.io.channelsinglethreshold/.classpath +++ b/io.openems.edge.controller.io.channelsinglethreshold/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.io.fixdigitaloutput/.classpath b/io.openems.edge.controller.io.fixdigitaloutput/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.io.fixdigitaloutput/.classpath +++ b/io.openems.edge.controller.io.fixdigitaloutput/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.io.heatingelement/.classpath b/io.openems.edge.controller.io.heatingelement/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.io.heatingelement/.classpath +++ b/io.openems.edge.controller.io.heatingelement/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.io.heatpump.sgready/.classpath b/io.openems.edge.controller.io.heatpump.sgready/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.io.heatpump.sgready/.classpath +++ b/io.openems.edge.controller.io.heatpump.sgready/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.pvinverter.fixpowerlimit/.classpath b/io.openems.edge.controller.pvinverter.fixpowerlimit/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.pvinverter.fixpowerlimit/.classpath +++ b/io.openems.edge.controller.pvinverter.fixpowerlimit/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.pvinverter.selltogridlimit/.classpath b/io.openems.edge.controller.pvinverter.selltogridlimit/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.pvinverter.selltogridlimit/.classpath +++ b/io.openems.edge.controller.pvinverter.selltogridlimit/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.symmetric.balancing/.classpath b/io.openems.edge.controller.symmetric.balancing/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.symmetric.balancing/.classpath +++ b/io.openems.edge.controller.symmetric.balancing/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.symmetric.balancingschedule/.classpath b/io.openems.edge.controller.symmetric.balancingschedule/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.symmetric.balancingschedule/.classpath +++ b/io.openems.edge.controller.symmetric.balancingschedule/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.symmetric.fixreactivepower/.classpath b/io.openems.edge.controller.symmetric.fixreactivepower/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.symmetric.fixreactivepower/.classpath +++ b/io.openems.edge.controller.symmetric.fixreactivepower/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.symmetric.limitactivepower/.classpath b/io.openems.edge.controller.symmetric.limitactivepower/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.symmetric.limitactivepower/.classpath +++ b/io.openems.edge.controller.symmetric.limitactivepower/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.symmetric.peakshaving/.classpath b/io.openems.edge.controller.symmetric.peakshaving/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.symmetric.peakshaving/.classpath +++ b/io.openems.edge.controller.symmetric.peakshaving/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.symmetric.randompower/.classpath b/io.openems.edge.controller.symmetric.randompower/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.symmetric.randompower/.classpath +++ b/io.openems.edge.controller.symmetric.randompower/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.controller.symmetric.timeslotpeakshaving/.classpath b/io.openems.edge.controller.symmetric.timeslotpeakshaving/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.controller.symmetric.timeslotpeakshaving/.classpath +++ b/io.openems.edge.controller.symmetric.timeslotpeakshaving/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.core/.classpath b/io.openems.edge.core/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.core/.classpath +++ b/io.openems.edge.core/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.edge2edge/.classpath b/io.openems.edge.edge2edge/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.edge2edge/.classpath +++ b/io.openems.edge.edge2edge/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.adstec.storaxe/.classpath b/io.openems.edge.ess.adstec.storaxe/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.adstec.storaxe/.classpath +++ b/io.openems.edge.ess.adstec.storaxe/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.api/.classpath b/io.openems.edge.ess.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.api/.classpath +++ b/io.openems.edge.ess.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.byd.container/.classpath b/io.openems.edge.ess.byd.container/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.byd.container/.classpath +++ b/io.openems.edge.ess.byd.container/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.cluster/.classpath b/io.openems.edge.ess.cluster/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.cluster/.classpath +++ b/io.openems.edge.ess.cluster/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.core/.classpath b/io.openems.edge.ess.core/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.core/.classpath +++ b/io.openems.edge.ess.core/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.fenecon.commercial40/.classpath b/io.openems.edge.ess.fenecon.commercial40/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.fenecon.commercial40/.classpath +++ b/io.openems.edge.ess.fenecon.commercial40/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.generic/.classpath b/io.openems.edge.ess.generic/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.generic/.classpath +++ b/io.openems.edge.ess.generic/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.mr.gridcon/.classpath b/io.openems.edge.ess.mr.gridcon/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.mr.gridcon/.classpath +++ b/io.openems.edge.ess.mr.gridcon/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.ess.sma/.classpath b/io.openems.edge.ess.sma/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.ess.sma/.classpath +++ b/io.openems.edge.ess.sma/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.alpitronic.hypercharger/.classpath b/io.openems.edge.evcs.alpitronic.hypercharger/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.alpitronic.hypercharger/.classpath +++ b/io.openems.edge.evcs.alpitronic.hypercharger/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.api/.classpath b/io.openems.edge.evcs.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.api/.classpath +++ b/io.openems.edge.evcs.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.cluster/.classpath b/io.openems.edge.evcs.cluster/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.cluster/.classpath +++ b/io.openems.edge.evcs.cluster/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.core/.classpath b/io.openems.edge.evcs.core/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.core/.classpath +++ b/io.openems.edge.evcs.core/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.dezony/generated/buildfiles b/io.openems.edge.evcs.dezony/generated/buildfiles deleted file mode 100644 index 796b599e33d..00000000000 --- a/io.openems.edge.evcs.dezony/generated/buildfiles +++ /dev/null @@ -1 +0,0 @@ -C:/Users/stefan.feilmeier/fems/develop/io.openems.edge.evcs.dezony/generated/io.openems.edge.evcs.dezony.jar diff --git a/io.openems.edge.evcs.goe.chargerhome/.classpath b/io.openems.edge.evcs.goe.chargerhome/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.goe.chargerhome/.classpath +++ b/io.openems.edge.evcs.goe.chargerhome/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.hardybarth/.classpath b/io.openems.edge.evcs.hardybarth/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.hardybarth/.classpath +++ b/io.openems.edge.evcs.hardybarth/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.keba.kecontact/.classpath b/io.openems.edge.evcs.keba.kecontact/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.keba.kecontact/.classpath +++ b/io.openems.edge.evcs.keba.kecontact/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.ocpp.abl/.classpath b/io.openems.edge.evcs.ocpp.abl/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.ocpp.abl/.classpath +++ b/io.openems.edge.evcs.ocpp.abl/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.ocpp.common/.classpath b/io.openems.edge.evcs.ocpp.common/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.ocpp.common/.classpath +++ b/io.openems.edge.evcs.ocpp.common/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.ocpp.ies.keywatt.singleccs/.classpath b/io.openems.edge.evcs.ocpp.ies.keywatt.singleccs/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.ocpp.ies.keywatt.singleccs/.classpath +++ b/io.openems.edge.evcs.ocpp.ies.keywatt.singleccs/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.ocpp.server/.classpath b/io.openems.edge.evcs.ocpp.server/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.ocpp.server/.classpath +++ b/io.openems.edge.evcs.ocpp.server/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.webasto.next/.classpath b/io.openems.edge.evcs.webasto.next/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.webasto.next/.classpath +++ b/io.openems.edge.evcs.webasto.next/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.evcs.webasto.unite/.classpath b/io.openems.edge.evcs.webasto.unite/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.evcs.webasto.unite/.classpath +++ b/io.openems.edge.evcs.webasto.unite/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.fenecon.dess/.classpath b/io.openems.edge.fenecon.dess/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.fenecon.dess/.classpath +++ b/io.openems.edge.fenecon.dess/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.fenecon.mini/.classpath b/io.openems.edge.fenecon.mini/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.fenecon.mini/.classpath +++ b/io.openems.edge.fenecon.mini/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.fenecon.pro/.classpath b/io.openems.edge.fenecon.pro/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.fenecon.pro/.classpath +++ b/io.openems.edge.fenecon.pro/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.goodwe/.classpath b/io.openems.edge.goodwe/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.goodwe/.classpath +++ b/io.openems.edge.goodwe/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.io.api/.classpath b/io.openems.edge.io.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.io.api/.classpath +++ b/io.openems.edge.io.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.io.kmtronic/.classpath b/io.openems.edge.io.kmtronic/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.io.kmtronic/.classpath +++ b/io.openems.edge.io.kmtronic/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.io.offgridswitch/.classpath b/io.openems.edge.io.offgridswitch/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.io.offgridswitch/.classpath +++ b/io.openems.edge.io.offgridswitch/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.io.revpi/.classpath b/io.openems.edge.io.revpi/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.io.revpi/.classpath +++ b/io.openems.edge.io.revpi/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.io.shelly/.classpath b/io.openems.edge.io.shelly/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.io.shelly/.classpath +++ b/io.openems.edge.io.shelly/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.io.wago/.classpath b/io.openems.edge.io.wago/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.io.wago/.classpath +++ b/io.openems.edge.io.wago/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.io.weidmueller/.classpath b/io.openems.edge.io.weidmueller/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.io.weidmueller/.classpath +++ b/io.openems.edge.io.weidmueller/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.kaco.blueplanet.hybrid10/.classpath b/io.openems.edge.kaco.blueplanet.hybrid10/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.kaco.blueplanet.hybrid10/.classpath +++ b/io.openems.edge.kaco.blueplanet.hybrid10/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.katek.edcom/.classpath b/io.openems.edge.katek.edcom/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.katek.edcom/.classpath +++ b/io.openems.edge.katek.edcom/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.kostal.piko/.classpath b/io.openems.edge.kostal.piko/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.kostal.piko/.classpath +++ b/io.openems.edge.kostal.piko/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.abb/.classpath b/io.openems.edge.meter.abb/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.abb/.classpath +++ b/io.openems.edge.meter.abb/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.api/.classpath b/io.openems.edge.meter.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.api/.classpath +++ b/io.openems.edge.meter.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.artemes.am2/.classpath b/io.openems.edge.meter.artemes.am2/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.artemes.am2/.classpath +++ b/io.openems.edge.meter.artemes.am2/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.bcontrol.em300/.classpath b/io.openems.edge.meter.bcontrol.em300/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.bcontrol.em300/.classpath +++ b/io.openems.edge.meter.bcontrol.em300/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.bgetech/.classpath b/io.openems.edge.meter.bgetech/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.bgetech/.classpath +++ b/io.openems.edge.meter.bgetech/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.carlo.gavazzi.em300/.classpath b/io.openems.edge.meter.carlo.gavazzi.em300/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.carlo.gavazzi.em300/.classpath +++ b/io.openems.edge.meter.carlo.gavazzi.em300/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.discovergy/.classpath b/io.openems.edge.meter.discovergy/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.discovergy/.classpath +++ b/io.openems.edge.meter.discovergy/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.janitza/.classpath b/io.openems.edge.meter.janitza/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.janitza/.classpath +++ b/io.openems.edge.meter.janitza/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.kdk/.classpath b/io.openems.edge.meter.kdk/.classpath index 43d68895d03..bbfbdbe40e7 100755 --- a/io.openems.edge.meter.kdk/.classpath +++ b/io.openems.edge.meter.kdk/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.microcare.sdm630/.classpath b/io.openems.edge.meter.microcare.sdm630/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.microcare.sdm630/.classpath +++ b/io.openems.edge.meter.microcare.sdm630/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.plexlog/.classpath b/io.openems.edge.meter.plexlog/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.plexlog/.classpath +++ b/io.openems.edge.meter.plexlog/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.pqplus/.classpath b/io.openems.edge.meter.pqplus/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.pqplus/.classpath +++ b/io.openems.edge.meter.pqplus/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.schneider.acti9.smartlink/.classpath b/io.openems.edge.meter.schneider.acti9.smartlink/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.schneider.acti9.smartlink/.classpath +++ b/io.openems.edge.meter.schneider.acti9.smartlink/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.siemens/.classpath b/io.openems.edge.meter.siemens/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.siemens/.classpath +++ b/io.openems.edge.meter.siemens/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.sma.shm20/.classpath b/io.openems.edge.meter.sma.shm20/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.sma.shm20/.classpath +++ b/io.openems.edge.meter.sma.shm20/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.socomec/.classpath b/io.openems.edge.meter.socomec/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.socomec/.classpath +++ b/io.openems.edge.meter.socomec/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.sunspec/.classpath b/io.openems.edge.meter.sunspec/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.sunspec/.classpath +++ b/io.openems.edge.meter.sunspec/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.virtual/.classpath b/io.openems.edge.meter.virtual/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.virtual/.classpath +++ b/io.openems.edge.meter.virtual/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.weidmueller/.classpath b/io.openems.edge.meter.weidmueller/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.weidmueller/.classpath +++ b/io.openems.edge.meter.weidmueller/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.meter.ziehl/.classpath b/io.openems.edge.meter.ziehl/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.meter.ziehl/.classpath +++ b/io.openems.edge.meter.ziehl/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.onewire.thermometer/.classpath b/io.openems.edge.onewire.thermometer/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.onewire.thermometer/.classpath +++ b/io.openems.edge.onewire.thermometer/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.predictor.api/.classpath b/io.openems.edge.predictor.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.predictor.api/.classpath +++ b/io.openems.edge.predictor.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.predictor.persistencemodel/.classpath b/io.openems.edge.predictor.persistencemodel/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.predictor.persistencemodel/.classpath +++ b/io.openems.edge.predictor.persistencemodel/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.predictor.similardaymodel/.classpath b/io.openems.edge.predictor.similardaymodel/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.predictor.similardaymodel/.classpath +++ b/io.openems.edge.predictor.similardaymodel/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.pvinverter.api/.classpath b/io.openems.edge.pvinverter.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.pvinverter.api/.classpath +++ b/io.openems.edge.pvinverter.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.pvinverter.cluster/.classpath b/io.openems.edge.pvinverter.cluster/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.pvinverter.cluster/.classpath +++ b/io.openems.edge.pvinverter.cluster/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.pvinverter.fronius/.classpath b/io.openems.edge.pvinverter.fronius/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.pvinverter.fronius/.classpath +++ b/io.openems.edge.pvinverter.fronius/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.pvinverter.kaco.blueplanet/.classpath b/io.openems.edge.pvinverter.kaco.blueplanet/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.pvinverter.kaco.blueplanet/.classpath +++ b/io.openems.edge.pvinverter.kaco.blueplanet/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.pvinverter.kostal/.classpath b/io.openems.edge.pvinverter.kostal/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.pvinverter.kostal/.classpath +++ b/io.openems.edge.pvinverter.kostal/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.pvinverter.sma/.classpath b/io.openems.edge.pvinverter.sma/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.pvinverter.sma/.classpath +++ b/io.openems.edge.pvinverter.sma/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.pvinverter.solarlog/.classpath b/io.openems.edge.pvinverter.solarlog/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.pvinverter.solarlog/.classpath +++ b/io.openems.edge.pvinverter.solarlog/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.pvinverter.sunspec/.classpath b/io.openems.edge.pvinverter.sunspec/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.pvinverter.sunspec/.classpath +++ b/io.openems.edge.pvinverter.sunspec/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.scheduler.allalphabetically/.classpath b/io.openems.edge.scheduler.allalphabetically/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.scheduler.allalphabetically/.classpath +++ b/io.openems.edge.scheduler.allalphabetically/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.scheduler.api/.classpath b/io.openems.edge.scheduler.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.scheduler.api/.classpath +++ b/io.openems.edge.scheduler.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.scheduler.daily/.classpath b/io.openems.edge.scheduler.daily/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.scheduler.daily/.classpath +++ b/io.openems.edge.scheduler.daily/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.scheduler.fixedorder/.classpath b/io.openems.edge.scheduler.fixedorder/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.scheduler.fixedorder/.classpath +++ b/io.openems.edge.scheduler.fixedorder/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.simulator/.classpath b/io.openems.edge.simulator/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.simulator/.classpath +++ b/io.openems.edge.simulator/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.solaredge/.classpath b/io.openems.edge.solaredge/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.solaredge/.classpath +++ b/io.openems.edge.solaredge/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.tesla.powerwall2/.classpath b/io.openems.edge.tesla.powerwall2/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.tesla.powerwall2/.classpath +++ b/io.openems.edge.tesla.powerwall2/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.thermometer.api/.classpath b/io.openems.edge.thermometer.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.thermometer.api/.classpath +++ b/io.openems.edge.thermometer.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.timedata.api/.classpath b/io.openems.edge.timedata.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.timedata.api/.classpath +++ b/io.openems.edge.timedata.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.timedata.influxdb/.classpath b/io.openems.edge.timedata.influxdb/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.timedata.influxdb/.classpath +++ b/io.openems.edge.timedata.influxdb/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.timedata.rrd4j/.classpath b/io.openems.edge.timedata.rrd4j/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.timedata.rrd4j/.classpath +++ b/io.openems.edge.timedata.rrd4j/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.timeofusetariff.api/.classpath b/io.openems.edge.timeofusetariff.api/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.timeofusetariff.api/.classpath +++ b/io.openems.edge.timeofusetariff.api/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.timeofusetariff.awattar/.classpath b/io.openems.edge.timeofusetariff.awattar/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.timeofusetariff.awattar/.classpath +++ b/io.openems.edge.timeofusetariff.awattar/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.timeofusetariff.corrently/.classpath b/io.openems.edge.timeofusetariff.corrently/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.timeofusetariff.corrently/.classpath +++ b/io.openems.edge.timeofusetariff.corrently/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.edge.timeofusetariff.tibber/.classpath b/io.openems.edge.timeofusetariff.tibber/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.edge.timeofusetariff.tibber/.classpath +++ b/io.openems.edge.timeofusetariff.tibber/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.shared.influxdb/.classpath b/io.openems.shared.influxdb/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.shared.influxdb/.classpath +++ b/io.openems.shared.influxdb/.classpath @@ -1,7 +1,7 @@ - + diff --git a/io.openems.wrapper/.classpath b/io.openems.wrapper/.classpath index 43d68895d03..bbfbdbe40e7 100644 --- a/io.openems.wrapper/.classpath +++ b/io.openems.wrapper/.classpath @@ -1,7 +1,7 @@ - + diff --git a/tools/docker/openems-backend/Dockerfile b/tools/docker/openems-backend/Dockerfile index 9082e360ae8..d7f9c989b47 100644 --- a/tools/docker/openems-backend/Dockerfile +++ b/tools/docker/openems-backend/Dockerfile @@ -9,8 +9,8 @@ RUN apt-get install -y --no-install-recommends software-properties-common curl RUN curl -sL https://repos.influxdata.com/influxdb.key | apt-key add - RUN add-apt-repository -y ppa:openjdk-r/ppa RUN apt-get update -RUN apt-get install -y openjdk-11-jdk -RUN apt-get install -y openjdk-11-jre +RUN apt-get install -y openjdk-17-jdk +RUN apt-get install -y openjdk-17-jre RUN apt-get install -y influxdb RUN update-alternatives --config java RUN update-alternatives --config javac diff --git a/tools/prepare-commit.sh b/tools/prepare-commit.sh index a2f456c4488..b761df5c793 100755 --- a/tools/prepare-commit.sh +++ b/tools/prepare-commit.sh @@ -78,7 +78,7 @@ EOT - + From f27e8b8c03877cf9ec15cf77de2c0bf3c8367f32 Mon Sep 17 00:00:00 2001 From: Stefan Feilmeier Date: Sun, 26 Mar 2023 21:07:09 +0200 Subject: [PATCH 17/23] Fix OpenEMS Docs & Warnings for Java 17 (#2119) --- .github/workflows/docs.yml | 7 + .../onewire/adapter/MulticastListener.java | 1 + .../dalsemi/onewire/adapter/NetAdapter.java | 1861 ----------------- .../common/linecharacteristic/PolyLine.java | 3 +- 4 files changed, 9 insertions(+), 1863 deletions(-) delete mode 100644 io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/NetAdapter.java diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index fae339d5e21..162af43755d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -10,6 +10,13 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Setup Java 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + java-package: jdk + - name: Setup Cache for Java/Gradle uses: actions/cache@v3 with: diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/MulticastListener.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/MulticastListener.java index b70d0efafbb..73965b9d85c 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/MulticastListener.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/MulticastListener.java @@ -71,6 +71,7 @@ public class MulticastListener implements Runnable { * @param expectedMessage the message to look for * @param returnMessage the message to reply with */ + @SuppressWarnings("deprecation") public MulticastListener(int multicastPort, String multicastGroup, byte[] expectedMessage, byte[] returnMessage) throws IOException, UnknownHostException { this.expectedMessage = expectedMessage; diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/NetAdapter.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/NetAdapter.java deleted file mode 100644 index bb2c8181c43..00000000000 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/NetAdapter.java +++ /dev/null @@ -1,1861 +0,0 @@ -// CHECKSTYLE:OFF -/*--------------------------------------------------------------------------- - * Copyright (C) 2002 Maxim Integrated Products, All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL MAXIM INTEGRATED PRODUCTS BE LIABLE FOR ANY CLAIM, DAMAGES - * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of Maxim Integrated Products - * shall not be used except as stated in the Maxim Integrated Products - * Branding Policy. - *--------------------------------------------------------------------------- - */ - -package com.dalsemi.onewire.adapter; - -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.InetAddress; -import java.net.MulticastSocket; -import java.net.Socket; -import java.util.Enumeration; -import java.util.Vector; - -import com.dalsemi.onewire.OneWireAccessProvider; -import com.dalsemi.onewire.OneWireException; -import com.dalsemi.onewire.utils.CRC16; -import com.dalsemi.onewire.utils.Convert; - -/** - *

      - * NetAdapter is a network-based DSPortAdapter. It allows for the use of an - * actual DSPortAdapter which isn't on the local machine, but rather is - * connected to another device which is reachable via a TCP/IP network - * connection. - *

      - * - *

      - * The syntax for the selectPort(String) command is the hostname of - * the computer which hosts the actual DSPortAdapter and the TCP/IP port that - * the host is listening on. If the port number is not specified, a default - * value of 6161 is used. Here are a few examples to illustrate the syntax: - *

        - *
      • my.host.com:6060
      • - *
      • 180.0.2.46:6262
      • - *
      • my.host.com
      • - *
      • 180.0.2.46
      • - *
      - *

      - * - * - * - *

      - * In the onewire.properties file, you can add a host to your list of valid - * hosts by making a NetAdapter.host with an integer to distinguish the hosts. - * There is no limit on the number of hosts which can appear in this list, but - * the first one must be numbered '0'. These hosts will then be returned in the - * list of valid 'ports' from the selectPortNames() method. Note - * that there do not have to be any servers returned from - * selectPortNames() for the NetAdapter to be able to connect to - * them (so it isn't necessary to add these entries for it to function), but - * applications which allow a user to automatically select an appropriate - * adapter and a port from a given list will not function properly without it. - * For example: - *

        - *
      • NetAdapter.host0=my.host.com:6060
      • - *
      • NetAdapter.host1=180.0.2.46:6262
      • - *
      • NetAdapter.host2=my.host.com
      • - *
      • NetAdapter.host3=180.0.2.46
      • - *
      - *

      - * - *

      - * The multicast socket technique allows you to automatically discover hosts on - * your subnet which are listening for multicast packets. By default, the - * multicast discovery of NetAdapter hosts is disabled. When enabled, the - * NetAdapter creates a multicast socket and looks for servers every time you - * call selectPortNames(). This will add a 1 second delay (due to - * the socket timeout) on calling the method. If you'd like to enable this - * feature, add the following line to your onewire.properties file: - *

        - *
      • NetAdapter.MulticastEnabled=true
      • - *
      - * The port used and the multicast group used for multicast sockets can also be - * changed. The group however, must fall within a valid range. For more - * information about multicast sockets in Java, see the Java tutorial on - * networking at - * http://java.sun.com/docs/books/tutorial/. Change the defaults in the - * onewire.properties file with the following entries: - *
        - *
      • NetAdapter.MulticastGroup=228.5.6.7
      • - *
      • NetAdapter.MulticastPort=6163
      • - *
      - *

      - * - *

      - * Once the NetAdapter is connected with a host, a version check is performed - * followed by a simple authentication step. The authentication is dependent - * upon a secret shared between the NetAdapter and the host. Both will use a - * default value, that each will agree with if you don't provide a secret of - * your own. To set the secret, add the following line to your - * onewire.properties file: - *

        - *
      • NetAdapter.secret="This is my custom secret"
      • - *
      - * Optionally, the secret can be specified on a per-host basis by simply adding - * the secret after the port number followed by a colon. If no port number is - * specified, a double-colon is required. Here are examples: - *
        - *
      • my.host.com:6060:my custom secret
      • - *
      • 180.0.2.46:6262:another custom secret
      • - *
      • my.host.com::the custom secret without port number
      • - *
      • 180.0.2.46::another example of a custom secret
      • - *
      - *

      - * - *

      - * All of the above mentioned properties can be set on the command-line as well - * as being set in the onewire.properties file. To set the properties on the - * command-line, use the -D option: java -DNetAdapter.Secret="custom secret" - * myApplication - *

      - * - *

      - * The following is a list of all parameters that can be set for the NetAdapter, - * followed by default values where applicable.
      - *

        - *
      • NetAdapter.secret=Adapter Secret Default
      • - *
      • NetAdapter.secret[0-MaxInt]=[no default]
      • - *
      • NetAdapter.host[0-MaxInt]=[no default]
      • - *
      • NetAdapter.MulticastEnabled=false
      • - *
      • NetAdapter.MulticastGroup=228.5.6.7
      • - *
      • NetAdapter.MulticastPort=6163
      • - *
      - *

      - * - *

      - * If you wanted added security on the communication channel, an SSL socket (or - * similar custom socket implementation) can be used by circumventing the - * standard DSPortAdapter's selectPort(String) and using the - * NetAdapter-specific selectPort(Socket). For example: - * - *

      - * NetAdapter na = new NetAdapter();
      - *
      - * Socket secureSocket = // insert fancy secure socket implementation here
      - *
      - * na.selectPort(secureSocket);
      - *
      - * 
      - * 

      - * - *

      - * For information on setting up the host component, see the JavaDocs for the - * NetAdapterHost - * - * @see NetAdapterHost - * - * @author SH - * @version 1.00, 9 Jan 2002 - */ -public class NetAdapter extends DSPortAdapter implements NetAdapterConstants { - /** Error message when neither RET_SUCCESS or RET_FAILURE are returned */ - protected static final String UNSPECIFIED_ERROR = "An unspecified error occurred."; - /** Error message when I/O failure occurs */ - protected static final String COMM_FAILED = "IO Error: "; - - /** constant for no exclusive lock */ - protected static final Integer NOT_OWNED = Integer.valueOf(0); - /** Keeps hash of current thread for exclusive lock */ - protected Integer currentThreadHash = NOT_OWNED; - - /** instance for current connection, defaults to EMPTY */ - protected Connection conn = EMPTY_CONNECTION; - - /** portName For Reconnecting to Host */ - protected String portNameForReconnect = null; - - /** secret for authentication with the server */ - protected byte[] netAdapterSecret = null; - - /** if true, the user used a custom secret */ - protected boolean useCustomSecret = false; - - // ------- - // ------- Multicast variables - // ------- - - /** indicates whether or not mulicast is enabled */ - protected Boolean multicastEnabled = null; - - /** The multicast group to use for NetAdapter Datagram packets */ - protected String multicastGroup = null; - - /** The port to use for NetAdapter Datagram packets */ - protected int datagramPort = -1; - - /** - * Creates an instance of NetAdapter that isn't connected. Must call - * selectPort(String); or selectPort(Socket); - */ - public NetAdapter() { - try { - this.resetSecret(); - } catch (Throwable t) { - this.setSecret(DEFAULT_SECRET); - } - } - - /** - * Sets the shared secret for authenticating this NetAdapter with a - * NetAdapterHost. - * - * @param secret the new secret for authenticating this client. - */ - public void setSecret(String secret) { - if (secret != null) { - this.netAdapterSecret = secret.getBytes(); - } else { - this.resetSecret(); - } - } - - /** - * Resets the secret to be the default stored in the onewire.properties file (if - * there is one), or the default as defined by NetAdapterConstants. - */ - public void resetSecret() { - var secret = OneWireAccessProvider.getProperty("NetAdapter.Secret"); - if (secret != null) { - this.netAdapterSecret = secret.getBytes(); - } else { - this.netAdapterSecret = DEFAULT_SECRET.getBytes(); - } - } - - /** - * Checks return value from input stream. Reads one byte. If that byte is not - * equal to RET_SUCCESS, then it tries to create an appropriate error message. - * If it is RET_FAILURE, it reads a string representing the error message. If it - * is neither, it wraps an error message indicating that an unspecified error - * occurred and attempts a reconnect. - */ - private void checkReturnValue(Connection conn) throws IOException, OneWireException, OneWireIOException { - var retVal = conn.input.readByte(); - if (retVal != RET_SUCCESS) { - // an error occurred - String errorMsg; - if (retVal == RET_FAILURE) { - // should be a standard error message after RET_FAILURE - errorMsg = conn.input.readUTF(); - } else { - // didn't even get RET_FAILURE - errorMsg = UNSPECIFIED_ERROR; - - // that probably means we have a major communication error. - // better to disconnect and reconnect. - this.freePort(); - this.selectPort(this.portNameForReconnect); - } - - throw new OneWireIOException(errorMsg); - } - } - - /** - * Sends a ping to the host, just to keep the connection alive. Although it - * currently is not implemented on the standard NetAdapterHost, this command is - * used as a signal to the NetAdapterSim to simulate some amount of time that - * has run. - */ - public void pingHost() throws OneWireException, OneWireIOException { - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_PINGCONNECTION); - this.conn.output.flush(); - - this.checkReturnValue(this.conn); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - // -------- - // -------- Methods - // -------- - - /** - * Detects adapter presence on the selected port. - * - * @return true if the adapter is confirmed to be connected to the - * selected port, false if the adapter is not connected. - * - * @throws OneWireIOException - * @throws OneWireException - */ - @Override - public boolean adapterDetected() throws OneWireIOException, OneWireException { - synchronized (this.conn) { - return this.conn != EMPTY_CONNECTION && this.conn.sock != null; - } - } - - /** - * Retrieves the name of the port adapter as a string. The 'Adapter' is a device - * that connects to a 'port' that allows one to communicate with an iButton or - * other 1-Wire device. As example of this is 'DS9097U'. - * - * @return String representation of the port adapter. - */ - @Override - public String getAdapterName() { - return "NetAdapter"; - } - - /** - * Retrieves a description of the port required by this port adapter. An example - * of a 'Port' would 'serial communication port'. - * - * @return String description of the port type required. - */ - @Override - public String getPortTypeDescription() { - return "Network 'Hostname:Port'"; - } - - /** - * Retrieves a version string for this class. - * - * @return version string - */ - @Override - public String getClassVersion() { - return "" + versionUID; - } - - // -------- - // -------- Port Selection - // -------- - - /** - * Retrieves a list of the platform appropriate port names for this adapter. A - * port must be selected with the method 'selectPort' before any other - * communication methods can be used. Using a communication method before - * 'selectPort' will result in a OneWireException exception. - * - * @return Enumeration of type String that contains - * the port names - */ - @Override - public Enumeration getPortNames() { - var v = new Vector(); - - // figure out if multicast is enabled - if (this.multicastEnabled == null) { - String enabled = null; - try { - enabled = OneWireAccessProvider.getProperty("NetAdapter.MulticastEnabled"); - } catch (Throwable t) { - - } - if (enabled != null) { - this.multicastEnabled = Boolean.valueOf(enabled); - } else { - this.multicastEnabled = Boolean.FALSE; - } - } - - // if multicasting is enabled, we'll look for servers dynamically - // and add them to the list - if (this.multicastEnabled.booleanValue()) { - // figure out what the datagram listen port is - if (this.datagramPort == -1) { - String strPort = null; - try { - strPort = OneWireAccessProvider.getProperty("NetAdapter.MulticastPort"); - } catch (Throwable t) { - - } - if (strPort == null) { - this.datagramPort = DEFAULT_MULTICAST_PORT; - } else { - this.datagramPort = Integer.parseInt(strPort); - } - } - - // figure out what the multicast group is - if (this.multicastGroup == null) { - String group = null; - try { - group = OneWireAccessProvider.getProperty("NetAdapter.MulticastGroup"); - } catch (Throwable t) { - - } - if (group == null) { - this.multicastGroup = DEFAULT_MULTICAST_GROUP; - } else { - this.multicastGroup = group; - } - } - - MulticastSocket socket = null; - InetAddress group = null; - try { - // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// - if (DEBUG) { - System.out.println("DEBUG: Opening multicast on port: " + this.datagramPort); - System.out.println("DEBUG: joining group: " + this.multicastGroup); - } - // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// - - // create the multi-cast socket - socket = new MulticastSocket(this.datagramPort); - // create the group's InetAddress - group = InetAddress.getByName(this.multicastGroup); - // join the group - socket.joinGroup(group); - - // convert the versionUID to a byte[] - var versionBytes = Convert.toByteArray(versionUID); - - // send a packet with the versionUID - var outPacket = new DatagramPacket(versionBytes, 4, group, this.datagramPort); - socket.send(outPacket); - - // set a timeout of 1/2 second for the receive - socket.setSoTimeout(500); - - var receiveBuffer = new byte[32]; - for (;;) { - // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// - if (DEBUG) { - System.out.println("DEBUG: waiting for multicast packet"); - } - // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// - var inPacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); - socket.receive(inPacket); - - var length = inPacket.getLength(); - var data = inPacket.getData(); - // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// - if (DEBUG) { - System.out.println("DEBUG: packet.length=" + length); - System.out.println("DEBUG: expecting=" + 5); - } - // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// - if (length == 5 && data[4] == (byte) 0xFF) { - var listenPort = Convert.toInt(data, 0, 4); - v.addElement(inPacket.getAddress().getHostName() + ":" + listenPort); - } - } - } catch (Exception e) { - /* drain */ - } finally { - try { - socket.leaveGroup(group); - socket.close(); - } catch (Exception e) { - /* drain */ - } - } - } - - // get all servers from the properties file - var server = ""; - try { - for (var i = 0; server != null; i++) { - server = OneWireAccessProvider.getProperty("NetAdapter.host" + i); - if (server != null) { - v.addElement(server); - } - } - } catch (Throwable t) { - - } - - return v.elements(); - } - - /** - * Specifies a platform appropriate port name for this adapter. Note that even - * though the port has been selected, it's ownership may be relinquished if it - * is not currently held in a 'exclusive' block. This class will then try to - * re-acquire the port when needed. If the port cannot be re-acquired when the - * exception PortInUseException will be thrown. - * - * @param portName Address to connect this NetAdapter to, in the form of - * "hostname:port". For example, "shughes.dalsemi.com:6161", - * where 6161 is the port number to connect to. The use of - * NetAdapter.DEFAULT_PORT is recommended. - * - * @return true if the port was acquired, false if the - * port is not available. - * - * @throws OneWireIOException If port does not exist, or unable to communicate - * with port. - * @throws OneWireException If port does not exist - */ - @Override - public boolean selectPort(String portName) throws OneWireIOException, OneWireException { - synchronized (this.conn) { - Socket s = null; - try { - var port = DEFAULT_PORT; - // should be of the format "hostname:port" or hostname - var index = portName.indexOf(':'); - if (index >= 0) { - var index2 = portName.indexOf(':', index + 1); - if (index2 < 0) // no custom secret specified - { - port = Integer.parseInt(portName.substring(index + 1)); - // reset the secret to default - this.resetSecret(); - this.useCustomSecret = false; - } else { - // custom secret is specified - this.setSecret(portName.substring(index2 + 1)); - this.useCustomSecret = true; - if (index < index2 - 1) { - port = Integer.parseInt(portName.substring(index + 1, index2)); - } - } - portName = portName.substring(0, index); - } else { - // reset the secret - this.resetSecret(); - this.useCustomSecret = false; - } - s = new Socket(portName, port); - } catch (IOException ioe) { - throw new OneWireIOException("Can't reach server: " + ioe.getMessage()); - } - - return this.selectPort(s); - } - } - - /** - * New method, unique to NetAdapter. Sets the "port", i.e. the connection to the - * server via an already established socket connection. - * - * @param sock Socket connection to NetAdapterHost - * - * @return true if connection to host was successful - * - * @throws OneWireIOException If port does not exist, or unable to communicate - * with port. - * @throws OneWireException If port does not exist - */ - public boolean selectPort(Socket sock) throws OneWireIOException, OneWireException { - var bSuccess = false; - synchronized (this.conn) { - var tmpConn = new Connection(); - tmpConn.sock = sock; - - try { - tmpConn.input = new DataInputStream(sock.getInputStream()); - if (BUFFERED_OUTPUT) { - tmpConn.output = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream())); - } else { - tmpConn.output = new DataOutputStream(sock.getOutputStream()); - } - - // check host version - var hostVersionUID = tmpConn.input.readInt(); - - if (hostVersionUID == versionUID) { - // tell the server that the versionUID matched - tmpConn.output.writeByte(RET_SUCCESS); - tmpConn.output.flush(); - - // if the versionUID matches, we need to authenticate ourselves - // using the challenge from the server. - var chlg = new byte[8]; - tmpConn.input.read(chlg, 0, 8); - - // compute the crc of the secret and the challenge - var crc = CRC16.compute(this.netAdapterSecret, 0); - crc = CRC16.compute(chlg, crc); - // and send it back to the server - tmpConn.output.writeInt(crc); - tmpConn.output.flush(); - - // check to see if it matched - this.checkReturnValue(tmpConn); - - bSuccess = true; - } else { - tmpConn.output.writeByte(RET_FAILURE); - tmpConn.output.flush(); - tmpConn = null; - } - } catch (IOException e) { - bSuccess = false; - tmpConn = null; - } - - if (bSuccess) { - this.portNameForReconnect = sock.getInetAddress().getHostName() + ":" + sock.getPort(); - this.conn = tmpConn; - } - } - - // invalid response or version number - return bSuccess; - } - - /** - * Frees ownership of the selected port, if it is currently owned, back to the - * system. This should only be called if the recently selected port does not - * have an adapter, or at the end of your application's use of the port. - * - * @throws OneWireException If port does not exist - */ - @Override - public void freePort() throws OneWireException { - try { - synchronized (this.conn) { - this.conn.output.writeByte(CMD_CLOSECONNECTION); - this.conn.output.flush(); - this.conn.sock.close(); - this.conn = EMPTY_CONNECTION; - } - } catch (Exception e) { - throw new OneWireException(COMM_FAILED + e.getMessage()); - } - } - - /** - * Retrieves the name of the selected port as a String. - * - * @return String of selected port - * - * @throws OneWireException if valid port not yet selected - */ - @Override - public String getPortName() throws OneWireException { - synchronized (this.conn) { - if (!this.adapterDetected()) { - return "Not Connected"; - } - if (this.useCustomSecret) { - return this.conn.sock.getInetAddress().getHostName() + ":" + this.conn.sock.getPort() + ":" - + new String(this.netAdapterSecret); - } else { - return this.conn.sock.getInetAddress().getHostName() + ":" + this.conn.sock.getPort(); - } - } - } - - /** - * Returns whether adapter can physically support overdrive mode. - * - * @return true if this port adapter can do OverDrive, - * false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error with the adapter - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean canOverdrive() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_CANOVERDRIVE); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from beginExclusive - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Returns whether the adapter can physically support hyperdrive mode. - * - * @return true if this port adapter can do HyperDrive, - * false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error with the adapter - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean canHyperdrive() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_CANHYPERDRIVE); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from beginExclusive - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Returns whether the adapter can physically support flex speed mode. - * - * @return true if this port adapter can do flex speed, - * false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error with the adapter - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean canFlex() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_CANFLEX); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from beginExclusive - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Returns whether adapter can physically support 12 volt power mode. - * - * @return true if this port adapter can do Program voltage, - * false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error with the adapter - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean canProgram() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_CANPROGRAM); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from beginExclusive - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Returns whether the adapter can physically support strong 5 volt power mode. - * - * @return true if this port adapter can do strong 5 volt mode, - * false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error with the adapter - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean canDeliverPower() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_CANDELIVERPOWER); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from beginExclusive - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Returns whether the adapter can physically support "smart" strong 5 volt - * power mode. "smart" power delivery is the ability to deliver power until it - * is no longer needed. The current drop it detected and power delivery is - * stopped. - * - * @return true if this port adapter can do "smart" strong 5 volt - * mode, false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error with the adapter - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean canDeliverSmartPower() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_CANDELIVERSMARTPOWER); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from beginExclusive - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Returns whether adapter can physically support 0 volt 'break' mode. - * - * @return true if this port adapter can do break, - * false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error with the adapter - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean canBreak() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_CANBREAK); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from beginExclusive - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - // -------- - // -------- Finding iButton/1-Wire device options - // -------- - - /** - * Returns true if the first iButton or 1-Wire device is found on - * the 1-Wire Network. If no devices are found, then false will be - * returned. - * - * @return true if an iButton or 1-Wire device is found. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean findFirstDevice() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send findFirstDevice command - this.conn.output.writeByte(CMD_FINDFIRSTDEVICE); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // return boolean from findFirstDevice - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Returns true if the next iButton or 1-Wire device is found. The - * previous 1-Wire device found is used as a starting point in the search. If no - * more devices are found then false will be returned. - * - * @return true if an iButton or 1-Wire device is found. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean findNextDevice() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send findNextDevice command - this.conn.output.writeByte(CMD_FINDNEXTDEVICE); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // return boolean from findNextDevice - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Copies the 'current' 1-Wire device address being used by the adapter into the - * array. This address is the last iButton or 1-Wire device found in a search - * (findNextDevice()...). This method copies into a user generated array to - * allow the reuse of the buffer. When searching many iButtons on the one wire - * network, this will reduce the memory burn rate. - * - * @param address An array to be filled with the current iButton address. - * @see com.dalsemi.onewire.utils.Address - */ - @Override - public void getAddress(byte[] address) { - try { - synchronized (this.conn) { - // send getAddress command - this.conn.output.writeByte(CMD_GETADDRESS); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // get the address - this.conn.input.read(address, 0, 8); - } - } catch (Exception e) { - /* drain */ } - } - - /** - * Sets the 1-Wire Network search to find only iButtons and 1-Wire devices that - * are in an 'Alarm' state that signals a need for attention. Not all iButton - * types have this feature. Some that do: DS1994, DS1920, DS2407. This selective - * searching can be canceled with the 'setSearchAllDevices()' method. - * - * @see #setNoResetSearch - */ - @Override - public void setSearchOnlyAlarmingDevices() { - try { - synchronized (this.conn) { - // send setSearchOnlyAlarmingDevices command - this.conn.output.writeByte(CMD_SETSEARCHONLYALARMINGDEVICES); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - - /** - * Sets the 1-Wire Network search to not perform a 1-Wire reset before a search. - * This feature is chiefly used with the DS2409 1-Wire coupler. The normal reset - * before each search can be restored with the 'setSearchAllDevices()' method. - */ - @Override - public void setNoResetSearch() { - try { - synchronized (this.conn) { - // send setNoResetSearch command - this.conn.output.writeByte(CMD_SETNORESETSEARCH); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - - /** - * Sets the 1-Wire Network search to find all iButtons and 1-Wire devices - * whether they are in an 'Alarm' state or not and restores the default setting - * of providing a 1-Wire reset command before each search. (see - * setNoResetSearch() method). - * - * @see #setNoResetSearch - */ - @Override - public void setSearchAllDevices() { - try { - synchronized (this.conn) { - // send setSearchAllDevices command - this.conn.output.writeByte(CMD_SETSEARCHALLDEVICES); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - - /** - * Removes any selectivity during a search for iButtons or 1-Wire devices by - * family type. The unique address for each iButton and 1-Wire device contains a - * family descriptor that indicates the capabilities of the device. - * - * @see #targetFamily - * @see #targetFamily(byte[]) - * @see #excludeFamily - * @see #excludeFamily(byte[]) - */ - @Override - public void targetAllFamilies() { - try { - synchronized (this.conn) { - // send targetAllFamilies command - this.conn.output.writeByte(CMD_TARGETALLFAMILIES); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - - /** - * Takes an integer to selectively search for this desired family type. If this - * method is used, then no devices of other families will be found by any of the - * search methods. - * - * @param family the code of the family type to target for searches - * @see com.dalsemi.onewire.utils.Address - * @see #targetAllFamilies - */ - @Override - public void targetFamily(int family) { - try { - synchronized (this.conn) { - // send targetFamily command - this.conn.output.writeByte(CMD_TARGETFAMILY); - this.conn.output.writeInt(1); - this.conn.output.writeByte((byte) family); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - - /** - * Takes an array of bytes to use for selectively searching for acceptable - * family codes. If used, only devices with family codes in this array will be - * found by any of the search methods. - * - * @param family array of the family types to target for searches - * @see com.dalsemi.onewire.utils.Address - * @see #targetAllFamilies - */ - @Override - public void targetFamily(byte family[]) { - try { - synchronized (this.conn) { - // send targetFamily command - this.conn.output.writeByte(CMD_TARGETFAMILY); - this.conn.output.writeInt(family.length); - this.conn.output.write(family, 0, family.length); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - - /** - * Takes an integer family code to avoid when searching for iButtons. or 1-Wire - * devices. If this method is used, then no devices of this family will be found - * by any of the search methods. - * - * @param family the code of the family type NOT to target in searches - * @see com.dalsemi.onewire.utils.Address - * @see #targetAllFamilies - */ - @Override - public void excludeFamily(int family) { - try { - synchronized (this.conn) { - // send excludeFamily command - this.conn.output.writeByte(CMD_EXCLUDEFAMILY); - this.conn.output.writeInt(1); - this.conn.output.writeByte((byte) family); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - - /** - * Takes an array of bytes containing family codes to avoid when finding - * iButtons or 1-Wire devices. If used, then no devices with family codes in - * this array will be found by any of the search methods. - * - * @param family array of family cods NOT to target for searches - * @see com.dalsemi.onewire.utils.Address - * @see #targetAllFamilies - */ - @Override - public void excludeFamily(byte family[]) { - try { - synchronized (this.conn) { - // send excludeFamily command - this.conn.output.writeByte(CMD_EXCLUDEFAMILY); - this.conn.output.writeInt(family.length); - this.conn.output.write(family, 0, family.length); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - - // -------- - // -------- 1-Wire Network Semaphore methods - // -------- - - /** - * Gets exclusive use of the 1-Wire to communicate with an iButton or 1-Wire - * Device. This method should be used for critical sections of code where a - * sequence of commands must not be interrupted by communication of threads with - * other iButtons, and it is permissible to sustain a delay in the special case - * that another thread has already been granted exclusive access and this access - * has not yet been relinquished. - *

      - * - * It can be called through the OneWireContainer class by the end application if - * they want to ensure exclusive use. If it is not called around several methods - * then it will be called inside each method. - * - * @param blocking true if want to block waiting for exclusive - * access to the adapter - * @return true if blocking was false and a exclusive session with - * the adapter was acquired - * - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean beginExclusive(boolean blocking) throws OneWireException { - boolean bGotLocalBlock = false, bGotServerBlock = false; - if (blocking) { - while (!this.beginExclusive()) { - try { - Thread.sleep(50); - } catch (Exception e) { - } - } - - bGotLocalBlock = true; - } else { - bGotLocalBlock = this.beginExclusive(); - } - - try { - synchronized (this.conn) { - // send beginExclusive command - this.conn.output.writeByte(CMD_BEGINEXCLUSIVE); - this.conn.output.writeBoolean(blocking); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from beginExclusive - bGotServerBlock = this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - - // if blocking, I shouldn't get here unless both are true - return bGotLocalBlock && bGotServerBlock; - } - - /** - * Gets exclusive use of the 1-Wire to communicate with an iButton or 1-Wire - * Device. This method should be used for critical sections of code where a - * sequence of commands must not be interrupted by communication of threads with - * other iButtons, and it is permissible to sustain a delay in the special case - * that another thread has already been granted exclusive access and this access - * has not yet been relinquished. This is private and non blocking - *

      - * - * @return true a exclusive session with the adapter was acquired - * - * @throws OneWireException - */ - private boolean beginExclusive() throws OneWireException { - synchronized (this.currentThreadHash) { - if (this.currentThreadHash == NOT_OWNED) { - // not owned so take - this.currentThreadHash = Integer.valueOf(Thread.currentThread().hashCode()); - - // provided debug on standard out - if (DEBUG) { - System.out.println("beginExclusive, now owned by: " + Thread.currentThread().getName()); - } - - return true; - } - if (this.currentThreadHash.intValue() == Thread.currentThread().hashCode()) { - // provided debug on standard out - if (DEBUG) { - System.out.println("beginExclusive, already owned by: " + Thread.currentThread().getName()); - } - - // already own - return true; - } else { - // want port but don't own - return false; - } - } - } - - /** - * Relinquishes exclusive control of the 1-Wire Network. This command - * dynamically marks the end of a critical section and should be used when - * exclusive control is no longer needed. - */ - @Override - public void endExclusive() { - synchronized (this.currentThreadHash) { - // if own then release - if (this.currentThreadHash != NOT_OWNED - && this.currentThreadHash.intValue() == Thread.currentThread().hashCode()) { - if (DEBUG) { - System.out.println("endExclusive, was owned by: " + Thread.currentThread().getName()); - } - - this.currentThreadHash = NOT_OWNED; - try { - synchronized (this.conn) { - // send endExclusive command - this.conn.output.writeByte(CMD_ENDEXCLUSIVE); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (Exception e) { - /* drain */ } - } - } - } - - // -------- - // -------- Primitive 1-Wire Network data methods - // -------- - - /** - * Sends a Reset to the 1-Wire Network. - * - * @return the result of the reset. Potential results are: - *

        - *
      • 0 (RESET_NOPRESENCE) no devices present on the 1-Wire Network. - *
      • 1 (RESET_PRESENCE) normal presence pulse detected on the 1-Wire - * Network indicating there is a device present. - *
      • 2 (RESET_ALARM) alarming presence pulse detected on the 1-Wire - * Network indicating there is a device present and it is in the alarm - * condition. This is only provided by the DS1994/DS2404 devices. - *
      • 3 (RESET_SHORT) inticates 1-Wire appears shorted. This can be - * transient conditions in a 1-Wire Network. Not all adapter types can - * detect this condition. - *
      - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public int reset() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send reset command - this.conn.output.writeByte(CMD_RESET); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from reset - return this.conn.input.readInt(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Sends a bit to the 1-Wire Network. - * - * @param bitValue the bit value to send to the 1-Wire Network. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public void putBit(boolean bitValue) throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send putBit command - this.conn.output.writeByte(CMD_PUTBIT); - // followed by the bit - this.conn.output.writeBoolean(bitValue); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Gets a bit from the 1-Wire Network. - * - * @return the bit value received from the the 1-Wire Network. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean getBit() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send getBit command - this.conn.output.writeByte(CMD_GETBIT); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from getBit - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Sends a byte to the 1-Wire Network. - * - * @param byteValue the byte value to send to the 1-Wire Network. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public void putByte(int byteValue) throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send putByte command - this.conn.output.writeByte(CMD_PUTBYTE); - // followed by the byte - this.conn.output.writeByte(byteValue); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Gets a byte from the 1-Wire Network. - * - * @return the byte value received from the the 1-Wire Network. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public int getByte() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send getByte command - this.conn.output.writeByte(CMD_GETBYTE); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next parameter should be the return from getByte - return this.conn.input.readByte() & 0x0FF; - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Gets a block of data from the 1-Wire Network. - * - * @param len length of data bytes to receive - * - * @return the data received from the 1-Wire Network. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public byte[] getBlock(int len) throws OneWireIOException, OneWireException { - var buffer = new byte[len]; - this.getBlock(buffer, 0, len); - return buffer; - } - - /** - * Gets a block of data from the 1-Wire Network and write it into the provided - * array. - * - * @param arr array in which to write the received bytes - * @param len length of data bytes to receive - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public void getBlock(byte[] arr, int len) throws OneWireIOException, OneWireException { - this.getBlock(arr, 0, len); - } - - /** - * Gets a block of data from the 1-Wire Network and write it into the provided - * array. - * - * @param arr array in which to write the received bytes - * @param off offset into the array to start - * @param len length of data bytes to receive - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public void getBlock(byte[] arr, int off, int len) throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send getBlock command - this.conn.output.writeByte(CMD_GETBLOCK); - // followed by the number of bytes to get - this.conn.output.writeInt(len); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next should be the bytes - this.conn.input.readFully(arr, off, len); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Sends a block of data and returns the data received in the same array. This - * method is used when sending a block that contains reads and writes. The - * 'read' portions of the data block need to be pre-loaded with 0xFF's. It - * starts sending data from the index at offset 'off' for length 'len'. - * - * @param dataBlock array of data to transfer to and from the 1-Wire Network. - * @param off offset into the array of data to start - * @param len length of data to send / receive starting at 'off' - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public void dataBlock(byte[] dataBlock, int off, int len) throws OneWireIOException, OneWireException { - if (DEBUG) { - System.out.println("DataBlock called for " + len + " bytes"); - } - try { - synchronized (this.conn) { - // send dataBlock command - this.conn.output.writeByte(CMD_DATABLOCK); - // followed by the number of bytes to block - this.conn.output.writeInt(len); - // followed by the bytes - this.conn.output.write(dataBlock, off, len); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // next should be the bytes returned - this.conn.input.readFully(dataBlock, off, len); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - if (DEBUG) { - System.out.println(" Done DataBlocking"); - } - } - - // -------- - // -------- 1-Wire Network power methods - // -------- - - /** - * Sets the duration to supply power to the 1-Wire Network. This method takes a - * time parameter that indicates the program pulse length when the method - * startPowerDelivery(). - *

      - * - * Note: to avoid getting an exception, use the canDeliverPower() and - * canDeliverSmartPower() method to check it's availability. - *

      - * - * @param timeFactor - *

        - *
      • 0 (DELIVERY_HALF_SECOND) provide power for 1/2 second. - *
      • 1 (DELIVERY_ONE_SECOND) provide power for 1 second. - *
      • 2 (DELIVERY_TWO_SECONDS) provide power for 2 seconds. - *
      • 3 (DELIVERY_FOUR_SECONDS) provide power for 4 seconds. - *
      • 4 (DELIVERY_SMART_DONE) provide power until the the - * device is no longer drawing significant power. - *
      • 5 (DELIVERY_INFINITE) provide power until the - * setPowerNormal() method is called. - *
      - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public void setPowerDuration(int timeFactor) throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send setPowerDuration command - this.conn.output.writeByte(CMD_SETPOWERDURATION); - // followed by the timeFactor - this.conn.output.writeInt(timeFactor); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Sets the 1-Wire Network voltage to supply power to a 1-Wire device. This - * method takes a time parameter that indicates whether the power delivery - * should be done immediately, or after certain conditions have been met. - *

      - * - * Note: to avoid getting an exception, use the canDeliverPower() and - * canDeliverSmartPower() method to check it's availability. - *

      - * - * @param changeCondition - *

        - *
      • 0 (CONDITION_NOW) operation should occur - * immediately. - *
      • 1 (CONDITION_AFTER_BIT) operation should be - * pending execution immediately after the next bit is - * sent. - *
      • 2 (CONDITION_AFTER_BYTE) operation should be - * pending execution immediately after next byte is sent. - *
      - * - * @return true if the voltage change was successful, - * false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public boolean startPowerDelivery(int changeCondition) throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send startPowerDelivery command - this.conn.output.writeByte(CMD_STARTPOWERDELIVERY); - // followed by the changeCondition - this.conn.output.writeInt(changeCondition); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // and get the return value from startPowerDelivery - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Sets the duration for providing a program pulse on the 1-Wire Network. This - * method takes a time parameter that indicates the program pulse length when - * the method startProgramPulse(). - *

      - * - * Note: to avoid getting an exception, use the canDeliverPower() method to - * check it's availability. - *

      - * - * @param timeFactor - *

        - *
      • 7 (DELIVERY_EPROM) provide program pulse for 480 - * microseconds - *
      • 5 (DELIVERY_INFINITE) provide power until the - * setPowerNormal() method is called. - *
      - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter - */ - @Override - public void setProgramPulseDuration(int timeFactor) throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send setProgramPulseDuration command - this.conn.output.writeByte(CMD_SETPROGRAMPULSEDURATION); - // followed by the timeFactor - this.conn.output.writeInt(timeFactor); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Sets the 1-Wire Network voltage to eprom programming level. This method takes - * a time parameter that indicates whether the power delivery should be done - * immediately, or after certain conditions have been met. - *

      - * - * Note: to avoid getting an exception, use the canProgram() method to check - * it's availability. - *

      - * - * @param changeCondition - *

        - *
      • 0 (CONDITION_NOW) operation should occur - * immediately. - *
      • 1 (CONDITION_AFTER_BIT) operation should be - * pending execution immediately after the next bit is - * sent. - *
      • 2 (CONDITION_AFTER_BYTE) operation should be - * pending execution immediately after next byte is sent. - *
      - * - * @return true if the voltage change was successful, - * false otherwise. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter or the - * adapter does not support this operation - */ - @Override - public boolean startProgramPulse(int changeCondition) throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send startProgramPulse command - this.conn.output.writeByte(CMD_STARTPROGRAMPULSE); - // followed by the changeCondition - this.conn.output.writeInt(changeCondition); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // and get the return value from startPowerDelivery - return this.conn.input.readBoolean(); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Sets the 1-Wire Network voltage to 0 volts. This method is used rob all - * 1-Wire Network devices of parasite power delivery to force them into a hard - * reset. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter or the - * adapter does not support this operation - */ - @Override - public void startBreak() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send startBreak command - this.conn.output.writeByte(CMD_STARTBREAK); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED); - } - } - - /** - * Sets the 1-Wire Network voltage to normal level. This method is used to - * disable 1-Wire conditions created by startPowerDelivery and - * startProgramPulse. This method will automatically be called if a - * communication method is called while an outstanding power command is taking - * place. - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter or the - * adapter does not support this operation - */ - @Override - public void setPowerNormal() throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send startBreak command - this.conn.output.writeByte(CMD_SETPOWERNORMAL); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - // -------- - // -------- 1-Wire Network speed methods - // -------- - - /** - * Sets the new speed of data transfer on the 1-Wire Network. - *

      - * - * @param speed - *

        - *
      • 0 (SPEED_REGULAR) set to normal communication speed - *
      • 1 (SPEED_FLEX) set to flexible communication speed used for - * long lines - *
      • 2 (SPEED_OVERDRIVE) set to normal communication speed to - * overdrive - *
      • 3 (SPEED_HYPERDRIVE) set to normal communication speed to - * hyperdrive - *
      • >3 future speeds - *
      - * - * @throws OneWireIOException on a 1-Wire communication error - * @throws OneWireException on a setup error with the 1-Wire adapter or the - * adapter does not support this operation - */ - @Override - public void setSpeed(int speed) throws OneWireIOException, OneWireException { - try { - synchronized (this.conn) { - // send startBreak command - this.conn.output.writeByte(CMD_SETSPEED); - // followed by the speed - this.conn.output.writeInt(speed); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - } - } catch (IOException ioe) { - throw new OneWireException(COMM_FAILED + ioe.getMessage()); - } - } - - /** - * Returns the current data transfer speed on the 1-Wire Network. - *

      - * - * @return int representing the current 1-Wire speed - *

        - *
      • 0 (SPEED_REGULAR) set to normal communication speed - *
      • 1 (SPEED_FLEX) set to flexible communication speed used for long - * lines - *
      • 2 (SPEED_OVERDRIVE) set to normal communication speed to - * overdrive - *
      • 3 (SPEED_HYPERDRIVE) set to normal communication speed to - * hyperdrive - *
      • >3 future speeds - *
      - */ - @Override - public int getSpeed() { - try { - synchronized (this.conn) { - // send startBreak command - this.conn.output.writeByte(CMD_GETSPEED); - this.conn.output.flush(); - - // check return value for success - this.checkReturnValue(this.conn); - - // and return the return value from getSpeed() - return this.conn.input.readInt(); - } - } catch (Exception e) { - /* drain */ - } - - return -1; - } -} -// CHECKSTYLE:ON diff --git a/io.openems.edge.common/src/io/openems/edge/common/linecharacteristic/PolyLine.java b/io.openems.edge.common/src/io/openems/edge/common/linecharacteristic/PolyLine.java index 15165af95d0..e109887240b 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/linecharacteristic/PolyLine.java +++ b/io.openems.edge.common/src/io/openems/edge/common/linecharacteristic/PolyLine.java @@ -1,6 +1,5 @@ package io.openems.edge.common.linecharacteristic; -import java.security.PolicySpi; import java.util.Map.Entry; import java.util.TreeMap; @@ -214,7 +213,7 @@ public Double getValue(Integer x) { *

      * Use this method to visualize the {@link PolyLine} in a spreadsheet. * - * @param polyLine the {@link PolicySpi} + * @param polyLine the {@link PolyLine} */ public static void printAsCsv(PolyLine polyLine) { System.out.println("x;y"); From 812ea44591b1b2005c98758df77c674cfa2a9867 Mon Sep 17 00:00:00 2001 From: Lukas Rieger <73471197+lukasrgr@users.noreply.github.com> Date: Mon, 27 Mar 2023 10:31:17 +0200 Subject: [PATCH 18/23] UI: add ESLint rule for explicit member accessibility (#2118) NOTE: this produces build warnings which will be addressed in future PRs --- ui/.eslintrc.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ui/.eslintrc.json b/ui/.eslintrc.json index 46cc0290ddc..27df56fcc3c 100644 --- a/ui/.eslintrc.json +++ b/ui/.eslintrc.json @@ -19,6 +19,19 @@ "plugin:@angular-eslint/template/process-inline-templates" ], "rules": { + "@typescript-eslint/explicit-member-accessibility": [ + "warn", + { + "accessibility": "explicit", + "overrides": { + "accessors": "off", + "constructors": "off", + "methods": "off", + "properties": "explicit", + "parameterProperties": "off" + } + } + ], "@angular-eslint/directive-selector": [ "error", { From fc303d209946a30d82b63bdecfdeb0eebfd9035b Mon Sep 17 00:00:00 2001 From: Stefan Feilmeier Date: Mon, 27 Mar 2023 16:50:48 +0200 Subject: [PATCH 19/23] App-Center: FEMS-Backports (#2120) Co-authored-by: Michael Grill <59126309+michaelgrill@users.noreply.github.com> --- .../request/AddAppInstanceRequest.java | 82 ++ ...terAddDeinstallInstanceHistoryRequest.java | 84 ++ ...enterAddInstallInstanceHistoryRequest.java | 89 ++ ...AppCenterAddRegisterKeyHistoryRequest.java | 68 ++ ...pCenterAddUnregisterKeyHistoryRequest.java | 68 ++ .../AppCenterGetInstalledAppsRequest.java | 60 ++ .../AppCenterGetPossibleAppsRequest.java | 68 ++ .../AppCenterGetRegisteredKeysRequest.java | 63 ++ ...enterInstallAppWithSuppliedKeyRequest.java | 64 ++ .../request/AppCenterIsAppFreeRequest.java | 63 ++ .../AppCenterIsKeyApplicableRequest.java | 74 ++ .../jsonrpc/request/AppCenterRequest.java | 68 ++ .../AppCenterGetInstalledAppsResponse.java | 130 +++ .../AppCenterGetPossibleAppsResponse.java | 138 +++ .../AppCenterGetRegisteredKeysResponse.java | 55 ++ .../response/AppCenterIsAppFreeResponse.java | 67 ++ .../AppCenterIsKeyApplicableResponse.java | 214 +++++ .../io/openems/common/utils/EnumUtils.java | 35 + .../io/openems/common/utils/JsonUtils.java | 22 + .../io/openems/common/utils/ServiceUtils.java | 69 ++ .../controller/api/backend/BackendApi.java | 10 +- .../api/backend/BackendApiImpl.java | 21 +- .../controller/api/backend/package-info.java | 3 + io.openems.edge.core/bnd.bnd | 1 + .../edge/app/api/ModbusTcpApiReadOnly.java | 81 +- .../edge/app/api/ModbusTcpApiReadWrite.java | 18 +- .../src/io/openems/edge/app/api/MqttApi.java | 8 +- .../edge/app/api/RestJsonApiReadOnly.java | 71 +- .../edge/app/api/RestJsonApiReadWrite.java | 18 +- .../edge/app/common/props/CommonProps.java | 37 + .../app/common/props/CommunicationProps.java | 56 ++ .../edge/app/enums/OptionsFactory.java | 57 ++ .../src/io/openems/edge/app/enums/Parity.java | 17 + .../src/io/openems/edge/app/enums/Phase.java | 28 + .../openems/edge/app/enums/SafetyCountry.java | 37 + .../edge/app/enums/TranslatableEnum.java | 16 + .../edge/app/ess/PrepareBatteryExtension.java | 184 ++++ .../edge/app/evcs/AbstractEvcsApp.java | 8 +- .../io/openems/edge/app/evcs/EvcsCluster.java | 98 ++- .../openems/edge/app/evcs/HardyBarthEvcs.java | 306 ++++++- .../openems/edge/app/evcs/IesKeywattEvcs.java | 3 +- .../io/openems/edge/app/evcs/KebaEvcs.java | 6 +- .../edge/app/hardware/KMtronic8Channel.java | 8 +- .../edge/app/heat/CombinedHeatAndPower.java | 12 +- .../io/openems/edge/app/heat/HeatPump.java | 16 +- .../openems/edge/app/heat/HeatingElement.java | 40 +- .../app/integratedsystem/FeneconHome.java | 205 +++-- .../app/loadcontrol/ManualRelayControl.java | 8 +- .../app/loadcontrol/ThresholdControl.java | 8 +- .../edge/app/meter/AbstractMeterApp.java | 7 +- .../edge/app/meter/CarloGavazziMeter.java | 6 +- .../openems/edge/app/meter/JanitzaMeter.java | 6 +- .../io/openems/edge/app/meter/KdkMeter.java | 147 ++++ .../openems/edge/app/meter/SocomecMeter.java | 6 +- .../app/pvinverter/AbstractPvInverter.java | 7 +- .../CommonPvInverterConfiguration.java | 115 +++ .../app/pvinverter/FroniusPvInverter.java | 3 +- .../edge/app/pvinverter/KacoPvInverter.java | 3 +- .../edge/app/pvinverter/KostalPvInverter.java | 3 +- .../edge/app/pvinverter/SmaPvInverter.java | 139 ++- .../app/pvinverter/SolarEdgePvInverter.java | 3 +- .../GridOptimizedCharge.java | 32 +- .../SelfConsumptionOptimization.java | 9 +- .../app/timeofusetariff/AwattarHourly.java | 9 +- .../timeofusetariff/StromdaoCorrently.java | 8 +- .../edge/app/timeofusetariff/Tibber.java | 95 +- .../appmanager/AbstractEnumOpenemsApp.java | 80 ++ .../core/appmanager/AbstractOpenemsApp.java | 193 ++--- .../AbstractOpenemsAppWithProps.java | 304 +++++++ .../edge/core/appmanager/AppAssistant.java | 7 +- .../core/appmanager/AppCenterBackendUtil.java | 71 ++ .../appmanager/AppCenterBackendUtilImpl.java | 137 +++ .../openems/edge/core/appmanager/AppDef.java | 814 ++++++++++++++++++ .../core/appmanager/AppInstallWorker.java | 138 ++- .../edge/core/appmanager/AppManager.java | 31 + .../edge/core/appmanager/AppManagerImpl.java | 366 ++++++-- .../edge/core/appmanager/AppManagerUtil.java | 10 + .../core/appmanager/AppManagerUtilImpl.java | 27 +- .../core/appmanager/AppSynchronizeWorker.java | 137 +++ .../edge/core/appmanager/ComponentUtil.java | 20 +- .../core/appmanager/ComponentUtilImpl.java | 27 +- .../openems/edge/core/appmanager/Config.java | 3 + .../core/appmanager/ConfigurationTarget.java | 12 - .../edge/core/appmanager/JsonFormlyUtil.java | 569 ++++++++++-- .../edge/core/appmanager/Nameable.java | 12 + .../openems/edge/core/appmanager/OnlyIf.java | 21 + .../edge/core/appmanager/OpenemsApp.java | 246 ++++-- .../core/appmanager/OpenemsAppCategory.java | 5 + .../core/appmanager/OpenemsAppInstance.java | 4 +- .../appmanager/OpenemsAppPermissions.java | 43 + .../OpenemsAppPropertyDefinition.java | 44 + .../core/appmanager/ResolveDependencies.java | 158 ++++ .../io/openems/edge/core/appmanager/Self.java | 12 + .../edge/core/appmanager/TranslationUtil.java | 6 +- .../io/openems/edge/core/appmanager/Type.java | 123 +++ .../dependency/AppManagerAppHelper.java | 6 +- .../dependency/AppManagerAppHelperImpl.java | 461 ++++++---- .../ComponentAggregateTaskImpl.java | 11 +- .../appmanager/dependency/DependencyUtil.java | 4 +- .../SchedulerAggregateTaskImpl.java | 7 + .../dependency/StaticIpAggregateTaskImpl.java | 4 +- .../appmanager/jsonrpc/AddAppInstance.java | 23 +- .../edge/core/appmanager/jsonrpc/GetApp.java | 82 +- .../appmanager/jsonrpc/GetAppInstances.java | 7 +- .../edge/core/appmanager/jsonrpc/GetApps.java | 55 +- .../appmanager/jsonrpc/UpdateAppInstance.java | 4 +- .../core/appmanager/translation_de.properties | 94 +- .../core/appmanager/translation_en.properties | 144 ++-- .../validator/CheckAppsNotInstalled.java | 6 +- .../validator/CheckCardinality.java | 10 +- .../core/appmanager/validator/CheckHome.java | 6 +- .../core/appmanager/validator/CheckHost.java | 6 +- .../CheckNoComponentInstalledOfFactoryId.java | 6 +- .../appmanager/validator/CheckRelayCount.java | 54 +- .../appmanager/validator/ValidatorImpl.java | 103 +-- .../validator/translation_de.properties | 7 +- .../validator/translation_en.properties | 7 +- .../openems/edge/app/TestADependencyToC.java | 9 +- .../openems/edge/app/TestBDependencyToC.java | 9 +- .../test/io/openems/edge/app/TestC.java | 9 +- .../io/openems/edge/app/TestMultipleIds.java | 114 +++ .../app/api/TestModbusTcpApiReadWrite.java | 26 +- .../edge/app/evcs/TestHardyBarthEvcs.java | 132 +++ .../openems/edge/app/heat/TestHeatPump.java | 41 +- .../app/integratedsystem/TestFeneconHome.java | 61 +- .../edge/app/timeofusetariff/TestTibber.java | 7 +- .../AppManagerAppHelperImplTest.java | 79 +- .../core/appmanager/AppManagerImplTest.java | 61 +- .../core/appmanager/AppManagerTestBundle.java | 108 ++- .../io/openems/edge/core/appmanager/Apps.java | 265 ++++++ .../appmanager/DummyAppCenterBackendUtil.java | 49 ++ .../edge/core/appmanager/MyConfig.java | 19 +- .../appmanager/ResolveDependenciesTest.java | 64 ++ .../appmanager/TestSettingComponentIds.java | 115 +++ .../FixedOrderSchedulerImplTest.java | 3 +- 135 files changed, 8160 insertions(+), 1298 deletions(-) create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AddAppInstanceRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddDeinstallInstanceHistoryRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddInstallInstanceHistoryRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddRegisterKeyHistoryRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddUnregisterKeyHistoryRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetInstalledAppsRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetPossibleAppsRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetRegisteredKeysRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterInstallAppWithSuppliedKeyRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterIsAppFreeRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterIsKeyApplicableRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterRequest.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetInstalledAppsResponse.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetPossibleAppsResponse.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetRegisteredKeysResponse.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterIsAppFreeResponse.java create mode 100644 io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterIsKeyApplicableResponse.java create mode 100644 io.openems.common/src/io/openems/common/utils/ServiceUtils.java create mode 100644 io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/package-info.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/common/props/CommonProps.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/common/props/CommunicationProps.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/enums/OptionsFactory.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/enums/Parity.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/enums/Phase.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/enums/SafetyCountry.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/enums/TranslatableEnum.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/ess/PrepareBatteryExtension.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/meter/KdkMeter.java create mode 100644 io.openems.edge.core/src/io/openems/edge/app/pvinverter/CommonPvInverterConfiguration.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractEnumOpenemsApp.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractOpenemsAppWithProps.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/AppCenterBackendUtil.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/AppCenterBackendUtilImpl.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/AppDef.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/AppSynchronizeWorker.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/Nameable.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/OnlyIf.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppPermissions.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppPropertyDefinition.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/ResolveDependencies.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/Self.java create mode 100644 io.openems.edge.core/src/io/openems/edge/core/appmanager/Type.java create mode 100644 io.openems.edge.core/test/io/openems/edge/app/TestMultipleIds.java create mode 100644 io.openems.edge.core/test/io/openems/edge/app/evcs/TestHardyBarthEvcs.java create mode 100644 io.openems.edge.core/test/io/openems/edge/core/appmanager/Apps.java create mode 100644 io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyAppCenterBackendUtil.java create mode 100644 io.openems.edge.core/test/io/openems/edge/core/appmanager/ResolveDependenciesTest.java create mode 100644 io.openems.edge.core/test/io/openems/edge/core/appmanager/TestSettingComponentIds.java diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AddAppInstanceRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AddAppInstanceRequest.java new file mode 100644 index 00000000000..2904b6042cc --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AddAppInstanceRequest.java @@ -0,0 +1,82 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Adds an OpenemsAppInstance. This is used by Ui to install a app on the edge. + * + *

      + * Request: + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "addAppInstance",
      + *   "params": {
      + *     "appId": string,
      + *     "alias": string,
      + *     "key": string,
      + *     "properties": {}
      + *   }
      + * }
      + * 
      + */ +public class AddAppInstanceRequest extends JsonrpcRequest { + + public static final String METHOD = "addAppInstance"; + + /** + * Parses a generic {@link JsonrpcRequest} to a {@link AddAppInstance}. + * + * @param r the {@link JsonrpcRequest} + * @return the {@link AddAppInstance} Request + * @throws OpenemsNamedException on error + */ + public static AddAppInstanceRequest from(JsonrpcRequest r) throws OpenemsNamedException { + final var p = r.getParams(); + return new AddAppInstanceRequest(r, // + JsonUtils.getAsOptionalString(p, "key").orElse(null), // + JsonUtils.getAsString(p, "appId"), // + JsonUtils.getAsOptionalString(p, "alias").orElse(null), // + JsonUtils.getAsJsonObject(p, "properties") // + ); + } + + public final String key; + + public final String appId; + public final String alias; + public final JsonObject properties; + + private AddAppInstanceRequest(JsonrpcRequest request, String key, String appId, String alias, + JsonObject properties) { + super(request, METHOD); + this.key = key; + this.appId = appId; + this.alias = alias; + this.properties = properties; + } + + public AddAppInstanceRequest(String appId, String key, String alias, JsonObject properties) { + super(METHOD); + this.key = key; + this.appId = appId; + this.alias = alias; + this.properties = properties; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("appId", this.appId) // + .addPropertyIfNotNull("alias", this.alias) // + .addPropertyIfNotNull("key", this.key) // + .add("properties", this.properties) // + .build(); + } +} \ No newline at end of file diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddDeinstallInstanceHistoryRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddDeinstallInstanceHistoryRequest.java new file mode 100644 index 00000000000..a5ad1e9cbef --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddDeinstallInstanceHistoryRequest.java @@ -0,0 +1,84 @@ +package io.openems.common.jsonrpc.request; + +import java.util.UUID; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to add a deinstall app history entry. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by Edge. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "addDeinstallInstanceHistory",
      + *   "params": {
      + *     "appId": String,
      + *     "instanceId": UUID,
      + *     "userId": String
      + *   }
      + * }
      + * 
      + */ +public class AppCenterAddDeinstallInstanceHistoryRequest extends JsonrpcRequest { + + public static final String METHOD = "addDeinstallInstanceHistory"; + + /** + * Creates a {@link AppCenterAddDeinstallInstanceHistoryRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return the {@link AppCenterAddDeinstallInstanceHistoryRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterAddDeinstallInstanceHistoryRequest from(JsonrpcRequest r) + throws OpenemsNamedException { + final var p = r.getParams(); + return new AppCenterAddDeinstallInstanceHistoryRequest(r, // + JsonUtils.getAsString(p, "appId"), // + JsonUtils.getAsUUID(p, "instanceId"), // + JsonUtils.getAsOptionalString(p, "userId").orElse(null) // + ); + } + + public final String appId; + public final UUID instanceId; + public final String userId; + + private AppCenterAddDeinstallInstanceHistoryRequest(JsonrpcRequest request, String appId, UUID instanceId, + String userId) { + super(request, AppCenterAddDeinstallInstanceHistoryRequest.METHOD); + this.appId = appId; + this.instanceId = instanceId; + this.userId = userId; + } + + public AppCenterAddDeinstallInstanceHistoryRequest(String appId, UUID instanceId, String userId) { + super(AppCenterAddDeinstallInstanceHistoryRequest.METHOD); + this.appId = appId; + this.instanceId = instanceId; + this.userId = userId; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("appId", this.appId) // + .addProperty("instanceId", this.instanceId.toString()) // + .addPropertyIfNotNull("userId", this.userId) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddInstallInstanceHistoryRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddInstallInstanceHistoryRequest.java new file mode 100644 index 00000000000..db1ad1afde9 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddInstallInstanceHistoryRequest.java @@ -0,0 +1,89 @@ +package io.openems.common.jsonrpc.request; + +import java.util.UUID; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to add a install app history entry. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by Edge. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "addInstallInstanceHistory",
      + *   "params": {
      + *     "key": String,
      + *     "appId": String,
      + *     "instanceId": UUID,
      + *     "userId": String
      + *   }
      + * }
      + * 
      + */ +public class AppCenterAddInstallInstanceHistoryRequest extends JsonrpcRequest { + + public static final String METHOD = "addInstallInstanceHistory"; + + /** + * Creates a {@link AppCenterAddInstallInstanceHistoryRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterAddInstallInstanceHistoryRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterAddInstallInstanceHistoryRequest from(JsonrpcRequest r) throws OpenemsNamedException { + final var p = r.getParams(); + return new AppCenterAddInstallInstanceHistoryRequest(r, // + JsonUtils.getAsString(p, "key"), // + JsonUtils.getAsString(p, "appId"), // + JsonUtils.getAsUUID(p, "instanceId"), // + JsonUtils.getAsOptionalString(p, "userId").orElse(null) // + ); + } + + public final String key; + public final String appId; + public final UUID instanceId; + public final String userId; + + private AppCenterAddInstallInstanceHistoryRequest(JsonrpcRequest request, String key, String appId, UUID instanceId, + String userId) { + super(request, AppCenterAddInstallInstanceHistoryRequest.METHOD); + this.key = key; + this.appId = appId; + this.instanceId = instanceId; + this.userId = userId; + } + + public AppCenterAddInstallInstanceHistoryRequest(String key, String appId, UUID instanceId, String userId) { + super(AppCenterAddInstallInstanceHistoryRequest.METHOD); + this.key = key; + this.appId = appId; + this.instanceId = instanceId; + this.userId = userId; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("key", this.key) // + .addProperty("appId", this.appId) // + .addProperty("instanceId", this.instanceId.toString()) // + .addPropertyIfNotNull("userId", this.userId) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddRegisterKeyHistoryRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddRegisterKeyHistoryRequest.java new file mode 100644 index 00000000000..ee25432d9b4 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddRegisterKeyHistoryRequest.java @@ -0,0 +1,68 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to register a key for an app and edge. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by UI. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "addRegisterKeyHistory",
      + *   "params": {
      + *     "key": String,
      + *     "appId": String
      + *   }
      + * }
      + * 
      + */ +public class AppCenterAddRegisterKeyHistoryRequest extends JsonrpcRequest { + + public static final String METHOD = "addRegisterKeyHistory"; + + /** + * Creates a {@link AppCenterAddRegisterKeyHistoryRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterAddRegisterKeyHistoryRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterAddRegisterKeyHistoryRequest from(JsonrpcRequest r) throws OpenemsNamedException { + final var p = r.getParams(); + return new AppCenterAddRegisterKeyHistoryRequest(r, // + JsonUtils.getAsString(p, "key"), // + JsonUtils.getAsOptionalString(p, "appId").orElse(null) // + ); + } + + public final String key; + public final String appId; + + private AppCenterAddRegisterKeyHistoryRequest(JsonrpcRequest request, String key, String appId) { + super(request, AppCenterAddRegisterKeyHistoryRequest.METHOD); + this.key = key; + this.appId = appId; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("key", this.key) // + .addPropertyIfNotNull("appId", this.appId) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddUnregisterKeyHistoryRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddUnregisterKeyHistoryRequest.java new file mode 100644 index 00000000000..f73ef10108e --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterAddUnregisterKeyHistoryRequest.java @@ -0,0 +1,68 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to unregister a registered key. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by UI. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "addUnregisterKeyHistory",
      + *   "params": {
      + *     "key": String,
      + *     "appId": String
      + *   }
      + * }
      + * 
      + */ +public class AppCenterAddUnregisterKeyHistoryRequest extends JsonrpcRequest { + + public static final String METHOD = "addUnregisterKeyHistory"; + + /** + * Creates a {@link AppCenterAddUnregisterKeyHistoryRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterAddUnregisterKeyHistoryRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterAddUnregisterKeyHistoryRequest from(JsonrpcRequest r) throws OpenemsNamedException { + var p = r.getParams(); + return new AppCenterAddUnregisterKeyHistoryRequest(r, // + JsonUtils.getAsString(p, "key"), // + JsonUtils.getAsOptionalString(p, "appId").orElse(null) // + ); + } + + public final String key; + public final String appId; + + private AppCenterAddUnregisterKeyHistoryRequest(JsonrpcRequest request, String key, String appId) { + super(request, AppCenterAddUnregisterKeyHistoryRequest.METHOD); + this.key = key; + this.appId = appId; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("key", this.key) // + .addPropertyIfNotNull("appId", this.appId) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetInstalledAppsRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetInstalledAppsRequest.java new file mode 100644 index 00000000000..cfd5b4ab7d2 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetInstalledAppsRequest.java @@ -0,0 +1,60 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to get the installed apps that are defined in + * the backend metadata on the edge that send the request. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by Edge. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getInstalledApps",
      + *   "params": {
      + *   }
      + * }
      + * 
      + */ +public class AppCenterGetInstalledAppsRequest extends JsonrpcRequest { + + public static final String METHOD = "getInstalledApps"; + + /** + * Creates a {@link AppCenterGetInstalledAppsRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterGetInstalledAppsRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterGetInstalledAppsRequest from(JsonrpcRequest r) throws OpenemsNamedException { + return new AppCenterGetInstalledAppsRequest(r); + } + + private AppCenterGetInstalledAppsRequest(JsonrpcRequest request) { + super(request, AppCenterGetInstalledAppsRequest.METHOD); + } + + public AppCenterGetInstalledAppsRequest() { + super(AppCenterGetInstalledAppsRequest.METHOD); + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetPossibleAppsRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetPossibleAppsRequest.java new file mode 100644 index 00000000000..cf5e0eff780 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetPossibleAppsRequest.java @@ -0,0 +1,68 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to get all possible apps to install with a key. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by Edge and UI. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getPossibleApps",
      + *   "params": {
      + *     "key": String
      + *   }
      + * }
      + * 
      + */ +public class AppCenterGetPossibleAppsRequest extends JsonrpcRequest { + + public static final String METHOD = "getPossibleApps"; + + /** + * Creates a {@link AppCenterGetPossibleAppsRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterGetPossibleAppsRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterGetPossibleAppsRequest from(JsonrpcRequest r) throws OpenemsNamedException { + final var p = r.getParams(); + return new AppCenterGetPossibleAppsRequest(r, // + JsonUtils.getAsString(p, "key") // + ); + } + + public final String key; + + private AppCenterGetPossibleAppsRequest(JsonrpcRequest request, String key) { + super(request, AppCenterGetPossibleAppsRequest.METHOD); + this.key = key; + } + + public AppCenterGetPossibleAppsRequest(String key) { + super(AppCenterGetPossibleAppsRequest.METHOD); + this.key = key; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("key", this.key) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetRegisteredKeysRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetRegisteredKeysRequest.java new file mode 100644 index 00000000000..fc4b363ecdb --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterGetRegisteredKeysRequest.java @@ -0,0 +1,63 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to get all registered keys. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by UI. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "getRegisteredKeys",
      + *   "params": {
      + *     "appId": String
      + *   }
      + * }
      + * 
      + */ +public class AppCenterGetRegisteredKeysRequest extends JsonrpcRequest { + + public static final String METHOD = "getRegisteredKeys"; + + /** + * Creates a {@link AppCenterGetRegisteredKeysRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterGetRegisteredKeysRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterGetRegisteredKeysRequest from(JsonrpcRequest r) throws OpenemsNamedException { + final var p = r.getParams(); + return new AppCenterGetRegisteredKeysRequest(r, // + JsonUtils.getAsOptionalString(p, "appId").orElse(null) // + ); + } + + public final String appId; + + private AppCenterGetRegisteredKeysRequest(JsonrpcRequest request, String appId) { + super(request, AppCenterGetRegisteredKeysRequest.METHOD); + this.appId = appId; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addPropertyIfNotNull("appId", this.appId) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterInstallAppWithSuppliedKeyRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterInstallAppWithSuppliedKeyRequest.java new file mode 100644 index 00000000000..3c45f1ba0cb --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterInstallAppWithSuppliedKeyRequest.java @@ -0,0 +1,64 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.GenericJsonrpcRequest; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to get all registered keys. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by UI. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "installAppWithSuppliedKey",
      + *   "params": {
      + *     "installRequest": {@link JsonObject}
      + *   }
      + * }
      + * 
      + */ +public class AppCenterInstallAppWithSuppliedKeyRequest extends JsonrpcRequest { + + public static final String METHOD = "installAppWithSuppliedKey"; + + /** + * Creates a {@link AppCenterInstallAppWithSuppliedKeyRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterInstallAppWithSuppliedKeyRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterInstallAppWithSuppliedKeyRequest from(JsonrpcRequest r) throws OpenemsNamedException { + final var p = r.getParams(); + return new AppCenterInstallAppWithSuppliedKeyRequest(r, // + GenericJsonrpcRequest.from(JsonUtils.getAsJsonObject(p, "installRequest")) // + ); + } + + public final JsonrpcRequest installRequest; + + private AppCenterInstallAppWithSuppliedKeyRequest(JsonrpcRequest request, JsonrpcRequest installRequest) { + super(request, AppCenterInstallAppWithSuppliedKeyRequest.METHOD); + this.installRequest = installRequest; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .add("installRequest", this.installRequest.toJsonObject()) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterIsAppFreeRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterIsAppFreeRequest.java new file mode 100644 index 00000000000..a337c031acc --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterIsAppFreeRequest.java @@ -0,0 +1,63 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to get if a app is free and can be installed + * with a {@link AppCenterInstallAppWithSuppliedKeyRequest}. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by UI. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "isAppFree",
      + *   "params": {
      + *     "appId": String
      + *   }
      + * }
      + * 
      + */ +public class AppCenterIsAppFreeRequest extends JsonrpcRequest { + + public static final String METHOD = "isAppFree"; + + /** + * Creates a {@link AppCenterIsAppFreeRequest} from a {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterIsAppFreeRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterIsAppFreeRequest from(JsonrpcRequest r) throws OpenemsNamedException { + final var p = r.getParams(); + return new AppCenterIsAppFreeRequest(r, // + JsonUtils.getAsString(p, "appId") // + ); + } + + public final String appId; + + private AppCenterIsAppFreeRequest(JsonrpcRequest request, String appId) { + super(request, AppCenterIsAppFreeRequest.METHOD); + this.appId = appId; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("appId", this.appId) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterIsKeyApplicableRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterIsKeyApplicableRequest.java new file mode 100644 index 00000000000..dc845a93998 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterIsKeyApplicableRequest.java @@ -0,0 +1,74 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Request to determine if a key can be applied. + * + *

      + * NOTE: in order to get this request handled by the backend the request needs + * to be wrapped in a {@link AppCenterRequest}. + * + *

      + * This is used by Edge and UI. + * + *

      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "isKeyApplicable",
      + *   "params": {
      + *     "key": String,
      + *     "appId": String
      + *   }
      + * }
      + * 
      + */ +public class AppCenterIsKeyApplicableRequest extends JsonrpcRequest { + + public static final String METHOD = "isKeyApplicable"; + + /** + * Creates a {@link AppCenterIsKeyApplicableRequest} from a + * {@link JsonrpcRequest}. + * + * @param r the {@link JsonrpcRequest} + * @return a {@link AppCenterIsKeyApplicableRequest} + * @throws OpenemsNamedException on error + */ + public static final AppCenterIsKeyApplicableRequest from(JsonrpcRequest r) throws OpenemsNamedException { + final var p = r.getParams(); + return new AppCenterIsKeyApplicableRequest(r, // + JsonUtils.getAsString(p, "key"), // + JsonUtils.getAsOptionalString(p, "appId").orElse(null) // + ); + } + + public final String key; + public final String appId; + + private AppCenterIsKeyApplicableRequest(JsonrpcRequest request, String key, String appId) { + super(request, AppCenterIsKeyApplicableRequest.METHOD); + this.key = key; + this.appId = appId; + } + + public AppCenterIsKeyApplicableRequest(String key, String appId) { + super(AppCenterIsKeyApplicableRequest.METHOD); + this.key = key; + this.appId = appId; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .addProperty("key", this.key) // + .addPropertyIfNotNull("appId", this.appId) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterRequest.java new file mode 100644 index 00000000000..9dc27d80a7c --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/request/AppCenterRequest.java @@ -0,0 +1,68 @@ +package io.openems.common.jsonrpc.request; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.GenericJsonrpcRequest; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.utils.JsonUtils; + +/** + * Wraps a JSON-RPC Request from an app center request. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "method": "appCenter",
      + *   "params": {
      + *     "payload": {@link JsonrpcRequest}
      + *   }
      + * }
      + * 
      + */ +public class AppCenterRequest extends JsonrpcRequest { + + public static final String METHOD = "appCenter"; + + /** + * Create {@link AppCenterRequest} from a template {@link JsonrpcRequest}. + * + * @param r the template {@link JsonrpcRequest} + * @return the {@link AppCenterRequest} + * @throws OpenemsNamedException on parse error + */ + public static AppCenterRequest from(JsonrpcRequest r) throws OpenemsNamedException { + var p = r.getParams(); + var payload = GenericJsonrpcRequest.from(JsonUtils.getAsJsonObject(p, "payload")); + return new AppCenterRequest(r, payload); + } + + private final JsonrpcRequest payload; + + public AppCenterRequest(JsonrpcRequest payload) { + super(AppCenterRequest.METHOD); + this.payload = payload; + } + + public AppCenterRequest(JsonrpcRequest request, JsonrpcRequest payload) { + super(request, AppCenterRequest.METHOD); + this.payload = payload; + } + + /** + * Gets the Payload {@link JsonrpcRequest}. + * + * @return Payload + */ + public JsonrpcRequest getPayload() { + return this.payload; + } + + @Override + public JsonObject getParams() { + return JsonUtils.buildJsonObject() // + .add("payload", this.payload.toJsonObject()) // + .build(); + } +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetInstalledAppsResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetInstalledAppsResponse.java new file mode 100644 index 00000000000..57effe5e5f1 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetInstalledAppsResponse.java @@ -0,0 +1,130 @@ +package io.openems.common.jsonrpc.response; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Response for getting all installed apps that are + * defined in the backend metadata. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *     "installedApps": {@link Instance}[]
      + *   }
      + * }
      + * 
      + */ +public class AppCenterGetInstalledAppsResponse extends JsonrpcResponseSuccess { + + public final List installedApps; + + /** + * Creates a {@link AppCenterGetInstalledAppsResponse} from a + * {@link JsonrpcResponseSuccess}. + * + * @param r the {@link JsonrpcResponseSuccess} + * @return a {@link AppCenterGetInstalledAppsResponse} + * @throws OpenemsNamedException on error + */ + public static final AppCenterGetInstalledAppsResponse from(JsonrpcResponseSuccess r) throws OpenemsNamedException { + final var result = r.getResult(); + return AppCenterGetInstalledAppsResponse.from(r.getId(), result); + } + + /** + * Creates a {@link AppCenterGetInstalledAppsResponse} from a + * {@link JsonObject}. + * + * @param id the id of the request + * @param jsonObject the {@link JsonObject} to parse + * @return a {@link AppCenterGetInstalledAppsResponse} + * @throws OpenemsNamedException on error + */ + public static final AppCenterGetInstalledAppsResponse from(UUID id, JsonObject jsonObject) + throws OpenemsNamedException { + final var installedAppsJsonArray = JsonUtils.getAsJsonArray(jsonObject, "installedApps"); + final var installedApps = AppCenterGetInstalledAppsResponse.getInstancesFrom(installedAppsJsonArray); + + return new AppCenterGetInstalledAppsResponse(id, installedApps); + } + + private static final List getInstancesFrom(JsonArray a) { + return JsonUtils.stream(a) // + .map(JsonElement::getAsJsonObject) // + .map(Instance::from) // + .collect(Collectors.toList()); + } + + public AppCenterGetInstalledAppsResponse(UUID id, List installedApps) { + super(id); + this.installedApps = installedApps; + } + + @Override + public JsonObject getResult() { + return JsonUtils.buildJsonObject() // + .add("installedApps", this.installedApps.stream() // + .map(Instance::toJsonObject) // + .collect(JsonUtils.toJsonArray())) // + .build(); + } + + /** + * Represents a OpenemsAppInstance from a + * {@link AppCenterGetInstalledAppsResponse}. + * + *
      +	 * { 
      +	 *   "appId": "App.Api.ModbusTcp.ReadOnly", 
      +	 *   "instanceId": {@link UUID} 
      +	 * }
      +	 * 
      + */ + public static final class Instance { + public final String appId; + public final UUID instanceId; + + /** + * Creates a {@link Instance} from a {@link JsonObject}. + * + * @param jsonObject the {@link JsonObject} to parse. + * @return {@link Instance} + */ + public static final Instance from(JsonObject jsonObject) { + final var appId = jsonObject.get("appId").getAsString(); + final var instanceId = JsonUtils.getAsOptionalUUID(jsonObject, "instanceId").orElse(null); + + return new Instance(appId, instanceId); + } + + public Instance(String appId, UUID instanceId) { + this.appId = appId; + this.instanceId = instanceId; + } + + /** + * Gets this object as a {@link JsonObject}. + * + * @return the {@link JsonObject} + */ + public final JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .addProperty("appId", this.appId) // + .addProperty("instanceId", this.instanceId.toString()) // + .build(); + } + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetPossibleAppsResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetPossibleAppsResponse.java new file mode 100644 index 00000000000..46b71af22fb --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetPossibleAppsResponse.java @@ -0,0 +1,138 @@ +package io.openems.common.jsonrpc.response; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Response for getting all possible apps to a key. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *     "bundles": {@link Bundle}[]
      + *   }
      + * }
      + * 
      + */ +public class AppCenterGetPossibleAppsResponse extends JsonrpcResponseSuccess { + + public final List possibleApps; + + /** + * Creates a {@link AppCenterGetPossibleAppsResponse} from a + * {@link JsonrpcResponseSuccess}. + * + * @param r the {@link JsonrpcResponseSuccess} + * @return a {@link AppCenterGetPossibleAppsResponse} + * @throws OpenemsNamedException on error + */ + public static final AppCenterGetPossibleAppsResponse from(JsonrpcResponseSuccess r) throws OpenemsNamedException { + final var result = r.getResult(); + final var bundles = JsonUtils.getAsJsonArray(result, "bundles"); + return from(r.getId(), bundles); + } + + /** + * Creates a {@link AppCenterGetPossibleAppsResponse} from a {@link List} of + * bundles of which every bundle has a {@link List} of {@link App}. + * + * @param id id of the request + * @param bundles the bundles + * @return the {@link AppCenterGetPossibleAppsResponse} + */ + public static final AppCenterGetPossibleAppsResponse from(UUID id, JsonArray bundles) { + return new AppCenterGetPossibleAppsResponse(id, // + JsonUtils.stream(bundles) // + .map(i -> i.getAsJsonArray()) // + .map(Bundle::from) // + .collect(Collectors.toList()) // + ); + } + + public AppCenterGetPossibleAppsResponse(UUID id, List possibleApps) { + super(id); + this.possibleApps = possibleApps; + } + + @Override + public JsonObject getResult() { + return JsonUtils.buildJsonObject() // + .add("bundles", this.possibleApps.stream() // + .map(Bundle::toJsonArray) // + .collect(JsonUtils.toJsonArray())) // + .build(); + } + + public static final class App { + public final String appId; + + /** + * Creates a {@link App} from an {@link JsonObject}. + * + * @param jsonObject the {@link JsonObject} to parse + * @return the {@link App} + */ + public static final App from(JsonObject jsonObject) { + return new App(jsonObject.get("appId").getAsString()); + } + + public App(String appId) { + this.appId = appId; + } + + /** + * Creates a {@link JsonObject} of this object. + * + * @return the {@link JsonObject} + */ + public final JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .addProperty("appId", this.appId) // + .build(); + } + } + + public static final class Bundle { + public final List apps; + + /** + * Creates a {@link Bundle} from an {@link JsonArray}. + * + * @param jsonArray the {@link JsonArray} to parse + * @return the {@link Bundle} + */ + public static final Bundle from(JsonArray jsonArray) { + return new Bundle(JsonUtils.stream(jsonArray) // + .map(t -> t.getAsJsonObject()) // + .map(App::from) // + .collect(Collectors.toList()) // + ); + } + + public Bundle(List apps) { + this.apps = apps; + } + + /** + * Creates a {@link JsonArray} of this object. + * + * @return the {@link JsonArray} + */ + public final JsonArray toJsonArray() { + return this.apps.stream() // + .map(App::toJsonObject) // + .collect(JsonUtils.toJsonArray()); + } + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetRegisteredKeysResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetRegisteredKeysResponse.java new file mode 100644 index 00000000000..d099dcd5f0d --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterGetRegisteredKeysResponse.java @@ -0,0 +1,55 @@ +package io.openems.common.jsonrpc.response; + +import java.util.UUID; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Response for getting all registed keys. + * + *
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *     "keys": [ { key: "XXXX-XXXX-XXXX-XXXX" }, ...]
      + *   }
      + * }
      + * 
      + */ +public class AppCenterGetRegisteredKeysResponse extends JsonrpcResponseSuccess { + + private final JsonArray keys; + + /** + * Creates a {@link AppCenterGetRegisteredKeysResponse} from a + * {@link JsonrpcResponseSuccess}. + * + * @param r the {@link JsonrpcResponseSuccess} + * @return a {@link AppCenterGetRegisteredKeysResponse} + */ + public static final AppCenterGetRegisteredKeysResponse from(JsonrpcResponseSuccess r) { + final var result = r.getResult(); + return new AppCenterGetRegisteredKeysResponse(r.getId(), // + JsonUtils.getAsOptionalJsonArray(result, "keys") // + .orElse(new JsonArray()) // + ); + } + + public AppCenterGetRegisteredKeysResponse(UUID id, JsonArray keys) { + super(id); + this.keys = keys; + } + + @Override + public JsonObject getResult() { + return JsonUtils.buildJsonObject() // + .add("keys", this.keys) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterIsAppFreeResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterIsAppFreeResponse.java new file mode 100644 index 00000000000..fdf3dbdd8a3 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterIsAppFreeResponse.java @@ -0,0 +1,67 @@ +package io.openems.common.jsonrpc.response; + +import java.util.UUID; + +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Response to validate if a app is free. + * + *
      + * success:
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *     "isAppFree": boolean
      + *   }
      + * }
      + * 
      + */ +public class AppCenterIsAppFreeResponse extends JsonrpcResponseSuccess { + + public final boolean isAppFree; + + /** + * Creates a {@link AppCenterIsAppFreeResponse} from a + * {@link JsonrpcResponseSuccess}. + * + * @param r the {@link JsonrpcResponseSuccess} + * @return a {@link AppCenterIsAppFreeResponse} + * @throws OpenemsNamedException on error + */ + public static final AppCenterIsAppFreeResponse from(JsonrpcResponseSuccess r) throws OpenemsNamedException { + return AppCenterIsAppFreeResponse.from(r.getId(), r.getResult()); + } + + /** + * Creates a {@link AppCenterIsAppFreeResponse} from a {@link JsonObject}. + * + * @param id the id of the request + * @param result the {@link JsonObject} + * @return a {@link AppCenterIsAppFreeResponse} + * @throws OpenemsNamedException on error + */ + public static final AppCenterIsAppFreeResponse from(UUID id, JsonObject result) throws OpenemsNamedException { + return new AppCenterIsAppFreeResponse(id, // + JsonUtils.getAsBoolean(result, "isAppFree") // + ); + } + + public AppCenterIsAppFreeResponse(UUID id, boolean isAppFree) { + super(id); + this.isAppFree = isAppFree; + } + + @Override + public JsonObject getResult() { + return JsonUtils.buildJsonObject() // + .addProperty("isAppFree", this.isAppFree) // + .build(); + } + +} diff --git a/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterIsKeyApplicableResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterIsKeyApplicableResponse.java new file mode 100644 index 00000000000..dbc32798cd4 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jsonrpc/response/AppCenterIsKeyApplicableResponse.java @@ -0,0 +1,214 @@ +package io.openems.common.jsonrpc.response; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.jsonrpc.response.AppCenterGetPossibleAppsResponse.Bundle; +import io.openems.common.utils.JsonUtils; + +/** + * Represents a JSON-RPC Response to validate if a key can be used. + * + *
      + * success:
      + * {
      + *   "jsonrpc": "2.0",
      + *   "id": "UUID",
      + *   "result": {
      + *     "isKeyApplicable": boolean
      + *     "additionalInfo": {
      + *          "keyId": String,
      + *          "bundles": {@link Bundle}[],
      + *          "registrations": {@link Registration}[],
      + *          "usages": {@link Usage}[]
      + *     }
      + *   }
      + * }
      + * 
      + */ +public class AppCenterIsKeyApplicableResponse extends JsonrpcResponseSuccess { + + public final boolean isKeyApplicable; + public final AdditionalInfo additionalInfo; + + /** + * Creates a {@link AppCenterIsKeyApplicableResponse} from a + * {@link JsonrpcResponseSuccess}. + * + * @param r the {@link JsonrpcResponseSuccess} + * @return a {@link AppCenterIsKeyApplicableResponse} + * @throws OpenemsNamedException on error + */ + public static final AppCenterIsKeyApplicableResponse from(JsonrpcResponseSuccess r) throws OpenemsNamedException { + return AppCenterIsKeyApplicableResponse.from(r.getId(), r.getResult()); + } + + /** + * Creates a {@link AppCenterIsKeyApplicableResponse} from a {@link JsonObject}. + * + * @param id the id of the request + * @param result the {@link JsonObject} + * @return a {@link AppCenterIsKeyApplicableResponse} + * @throws OpenemsNamedException on error + */ + public static final AppCenterIsKeyApplicableResponse from(UUID id, JsonObject result) throws OpenemsNamedException { + return new AppCenterIsKeyApplicableResponse(id, // + JsonUtils.getAsOptionalBoolean(result, "isKeyApplicable").orElse(false), // + AdditionalInfo.from(JsonUtils.getAsJsonObject(result, "additionalInfo")) // + ); + } + + public AppCenterIsKeyApplicableResponse(UUID id, boolean isKeyApplicable, AdditionalInfo additionalInfo) { + super(id); + this.isKeyApplicable = isKeyApplicable; + this.additionalInfo = additionalInfo; + } + + @Override + public JsonObject getResult() { + return JsonUtils.buildJsonObject() // + .addProperty("isKeyApplicable", this.isKeyApplicable) // + .add("additionalInfo", this.additionalInfo.toJsonObject()) // + .build(); + } + + public static final class AdditionalInfo { + public final String keyId; + public final List bundles; + public final List registrations; + public final List usages; + + /** + * Creates a {@link AdditionalInfo} from an {@link JsonObject}. + * + * @param jsonObject the {@link JsonObject} to parse + * @return the {@link AdditionalInfo} + */ + public static final AdditionalInfo from(JsonObject jsonObject) throws OpenemsNamedException { + return new AdditionalInfo(JsonUtils.getAsString(jsonObject, "keyId"), // + JsonUtils.stream(JsonUtils.getAsJsonArray(jsonObject, "bundles")) // + .map(JsonElement::getAsJsonArray) // + .map(Bundle::from) // + .collect(Collectors.toList()), // + JsonUtils.stream(JsonUtils.getAsJsonArray(jsonObject, "registrations")) // + .map(JsonElement::getAsJsonObject) // + .map(Registration::from) // + .collect(Collectors.toList()), // + JsonUtils.stream(JsonUtils.getAsJsonArray(jsonObject, "usages")) // + .map(JsonElement::getAsJsonObject) // + .map(Usage::from) // + .collect(Collectors.toList()) // + ); + } + + public AdditionalInfo(String keyId, List bundles, List registrations, + List usages) { + this.keyId = keyId; + this.bundles = bundles; + this.registrations = registrations; + this.usages = usages; + } + + /** + * Creates a {@link JsonObject} of this object. + * + * @return the {@link JsonObject} + */ + public final JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .addProperty("keyId", this.keyId) // + .add("bundles", this.bundles.stream() // + .map(Bundle::toJsonArray) // + .collect(JsonUtils.toJsonArray())) // + .add("registrations", this.registrations.stream() // + .map(Registration::toJsonObject) // + .collect(JsonUtils.toJsonArray())) // + .add("usages", this.usages.stream() // + .map(Usage::toJsonObject) // + .collect(JsonUtils.toJsonArray())) // + .build(); + } + + } + + public static final class Registration { + public final String edgeId; + // if appId is null the registration is for the whole system + public final String appId; + + /** + * Creates a {@link Registration} from an {@link JsonObject}. + * + * @param jsonObject the {@link JsonObject} to parse + * @return the {@link Registration} + */ + public static final Registration from(JsonObject jsonObject) { + return new Registration(// + jsonObject.get("edgeId").getAsString(), // + JsonUtils.getAsOptionalString(jsonObject, "appId").orElse(null) // + ); + } + + public Registration(String edgeId, String appId) { + this.appId = appId; + this.edgeId = edgeId; + } + + /** + * Creates a {@link JsonObject} of this object. + * + * @return the {@link JsonObject} + */ + public JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .addProperty("edgeId", this.edgeId) // + .addProperty("appId", this.appId) // + .build(); + } + + } + + public static final class Usage { + public final String appId; + // TODO maybe deviceIds? + public final int installedInstances; + + /** + * Creates a {@link Usage} from an {@link JsonObject}. + * + * @param jsonObject the {@link JsonObject} to parse + * @return the {@link Usage} + */ + public static final Usage from(JsonObject jsonObject) { + return new Usage(// + jsonObject.get("appId").getAsString(), // + jsonObject.get("installedInstances").getAsInt() // + ); + } + + public Usage(String appId, int installedInstances) { + this.appId = appId; + this.installedInstances = installedInstances; + } + + /** + * Creates a {@link JsonObject} of this object. + * + * @return the {@link JsonObject} + */ + public JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .addProperty("appId", this.appId) // + .addProperty("installedInstances", this.installedInstances) // + .build(); + } + + } + +} diff --git a/io.openems.common/src/io/openems/common/utils/EnumUtils.java b/io.openems.common/src/io/openems/common/utils/EnumUtils.java index fecb288370e..f2465312c5d 100644 --- a/io.openems.common/src/io/openems/common/utils/EnumUtils.java +++ b/io.openems.common/src/io/openems/common/utils/EnumUtils.java @@ -30,6 +30,25 @@ public static > Optional getAsOptionalBoolean(E } } + /** + * Gets the {@link JsonElement} as {@link Optional} {@link Enum}. + * + * @param the type {@link EnumMap} + * @param the {@link Enum} type + * @param enumType the class of the {@link Enum} + * @param map the {@link EnumMap} + * @param member the member of the {@link EnumMap} + * @return the enum value + */ + public static , E extends Enum> Optional getAsOptionalEnum(Class enumType, + EnumMap map, ENUM member) { + try { + return JsonUtils.getAsOptionalEnum(enumType, getAsPrimitive(map, member)); + } catch (OpenemsNamedException e) { + return Optional.empty(); + } + } + /** * Gets the member of the {@link EnumMap} as {@link Optional} {@link String}. * @@ -110,6 +129,22 @@ public static > Boolean getAsBoolean(EnumMap the type {@link EnumMap} + * @param the {@link Enum} type + * @param enumType the class of the {@link Enum} + * @param map the {@link EnumMap} + * @param member the member + * @return the enum value + * @throws OpenemsNamedException on error + */ + public static , E extends Enum> E getAsEnum(Class enumType, + EnumMap map, ENUM member) throws OpenemsNamedException { + return JsonUtils.getAsEnum(enumType, getAsPrimitive(map, member)); + } + /** * Gets the member of the {@link EnumMap} as {@link String}. * diff --git a/io.openems.common/src/io/openems/common/utils/JsonUtils.java b/io.openems.common/src/io/openems/common/utils/JsonUtils.java index 88703f3c83d..7b0c897ad7b 100644 --- a/io.openems.common/src/io/openems/common/utils/JsonUtils.java +++ b/io.openems.common/src/io/openems/common/utils/JsonUtils.java @@ -1738,6 +1738,28 @@ private static JsonObject toJsonObject(JsonElement jElement) { return null; } + /** + * Returns a {@link Collector} that accumulates the input elements into a new + * {@link JsonObject}. + * + * @param the type of the input + * @param keyMapper the key mapper + * @param valueMapper the value mapper + * @return the {@link Collector} + */ + public static Collector toJsonObject(// + final Function keyMapper, // + final Function valueMapper // + ) { + return Collector.of(JsonObject::new, // + (t, u) -> { + t.add(keyMapper.apply(u), valueMapper.apply(u)); + }, (t, u) -> { + u.entrySet().forEach(entry -> t.add(entry.getKey(), entry.getValue())); + return t; + }); + } + /** * Returns a Collector that accumulates the input elements into a new JsonArray. * diff --git a/io.openems.common/src/io/openems/common/utils/ServiceUtils.java b/io.openems.common/src/io/openems/common/utils/ServiceUtils.java new file mode 100644 index 00000000000..f9d9f21a65b --- /dev/null +++ b/io.openems.common/src/io/openems/common/utils/ServiceUtils.java @@ -0,0 +1,69 @@ +package io.openems.common.utils; + +import java.util.Objects; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +public class ServiceUtils { + + public static class CloseableService implements AutoCloseable { + + private final BundleContext bundleContext; + private final ServiceReference serviceReference; + private final T service; + + public CloseableService(BundleContext bundleContext, Class clazz) { + this.bundleContext = Objects.requireNonNull(bundleContext); + this.serviceReference = bundleContext.getServiceReference(Objects.requireNonNull(clazz)); + if (this.serviceReference == null) { + this.service = null; + return; + } + this.service = bundleContext.getService(this.serviceReference); + } + + @Override + public void close() throws Exception { + if (this.serviceReference == null) { + return; + } + this.bundleContext.ungetService(this.serviceReference); + } + + public final T getService() { + return this.service; + } + + } + + private ServiceUtils() { + } + + /** + * Creates a {@link CloseableService} with the given parameters. + * + *

      + * Usage:
      + * + *

      +	 * try (var componentManagerService =
      +	 * 	    ServiceUtils.useService(bundleContext, ComponentManager.class)) {
      +	 *     var componentManager = componentManagerService.getService();
      +	 *     // use componentManager here (may be null) ... 
      +	 * } catch (Exception e) { }
      +	 * 
      + * + * @param the type of the service + * @param bundleContext the {@link BundleContext} of the service + * @param clazz the class type of the service + * @return the {@link CloseableService} + */ + public static CloseableService useService(// + final BundleContext bundleContext, // + final Class clazz // + ) { + return new CloseableService<>(bundleContext, clazz); + } + +} diff --git a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/BackendApi.java b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/BackendApi.java index 2cbebcd29e1..c06c256bcfe 100644 --- a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/BackendApi.java +++ b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/BackendApi.java @@ -10,9 +10,10 @@ import io.openems.edge.common.channel.StateChannel; import io.openems.edge.common.channel.StringReadChannel; import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.common.jsonapi.JsonApi; import io.openems.edge.controller.api.Controller; -public interface BackendApi extends Controller, OpenemsComponent, PaxAppender, EventHandler { +public interface BackendApi extends Controller, JsonApi, OpenemsComponent, PaxAppender, EventHandler { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { API_WORKER_LOG(Doc.of(OpenemsType.STRING) // @@ -56,4 +57,11 @@ public default StringReadChannel getApiWorkerLogChannel() { public default StateChannel getUnableToSendChannel() { return this.channel(ChannelId.UNABLE_TO_SEND); } + + /** + * Gets if the edge is currently connected to the backend. + * + * @return true if it is connected + */ + public boolean isConnected(); } diff --git a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/BackendApiImpl.java b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/BackendApiImpl.java index 02e094edbce..c63b6257366 100644 --- a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/BackendApiImpl.java +++ b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/BackendApiImpl.java @@ -6,6 +6,8 @@ import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -32,6 +34,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; import io.openems.common.jsonrpc.notification.EdgeConfigNotification; import io.openems.common.jsonrpc.notification.SystemLogNotification; import io.openems.common.types.EdgeConfig; @@ -42,6 +46,8 @@ import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.cycle.Cycle; import io.openems.edge.common.event.EdgeEventConstants; +import io.openems.edge.common.jsonapi.JsonApi; +import io.openems.edge.common.user.User; import io.openems.edge.controller.api.Controller; import io.openems.edge.controller.api.common.ApiWorker; import io.openems.edge.timedata.api.Timedata; @@ -59,7 +65,7 @@ EdgeEventConstants.TOPIC_CONFIG_UPDATE // }) public class BackendApiImpl extends AbstractOpenemsComponent - implements BackendApi, Controller, OpenemsComponent, PaxAppender, EventHandler { + implements BackendApi, Controller, JsonApi, OpenemsComponent, PaxAppender, EventHandler { protected static final String COMPONENT_NAME = "Controller.Api.Backend"; @@ -221,8 +227,11 @@ public void handleEvent(Event event) { } } + @Override public boolean isConnected() { - return this.websocket.isConnected(); + return Optional.ofNullable(this.websocket) // + .map(WebsocketClient::isConnected) // + .orElse(false); } /** @@ -251,4 +260,12 @@ public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialD } return this.executor.scheduleWithFixedDelay(command, initialDelay, delay, unit); } + + @Override + public CompletableFuture handleJsonrpcRequest(User user, JsonrpcRequest request) + throws OpenemsNamedException { + // delegates request to actual backend + return this.websocket.sendRequest(request); + } + } diff --git a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/package-info.java b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/package-info.java new file mode 100644 index 00000000000..cd7e2d65c23 --- /dev/null +++ b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/package-info.java @@ -0,0 +1,3 @@ +@org.osgi.annotation.versioning.Version("1.0.0") +@org.osgi.annotation.bundle.Export +package io.openems.edge.controller.api.backend; diff --git a/io.openems.edge.core/bnd.bnd b/io.openems.edge.core/bnd.bnd index 43654fae5a7..46caa7deb27 100644 --- a/io.openems.edge.core/bnd.bnd +++ b/io.openems.edge.core/bnd.bnd @@ -8,6 +8,7 @@ Bundle-Version: 1.0.0.${tstamp} io.openems.common,\ io.openems.edge.common,\ io.openems.edge.controller.api,\ + io.openems.edge.controller.api.backend,\ io.openems.edge.ess.api,\ io.openems.edge.io.api,\ io.openems.edge.meter.api,\ diff --git a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiReadOnly.java b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiReadOnly.java index 1429ce86351..6aa759b2be3 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiReadOnly.java +++ b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiReadOnly.java @@ -1,33 +1,38 @@ package io.openems.edge.app.api; -import java.util.EnumMap; -import java.util.List; +import java.util.Map; +import java.util.function.Function; 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.Component; import org.osgi.service.component.annotations.Reference; import com.google.common.collect.Lists; 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.types.EdgeConfig; -import io.openems.common.utils.EnumUtils; import io.openems.common.utils.JsonUtils; import io.openems.edge.app.api.ModbusTcpApiReadOnly.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.AbstractOpenemsAppWithProps; import io.openems.edge.core.appmanager.AppConfiguration; +import io.openems.edge.core.appmanager.AppDef; 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; +import io.openems.edge.core.appmanager.Type; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; /** * Describes a App for ReadOnly Modbus/TCP Api. @@ -48,15 +53,48 @@ } *
      */ -@org.osgi.service.component.annotations.Component(name = "App.Api.ModbusTcp.ReadOnly") -public class ModbusTcpApiReadOnly extends AbstractOpenemsApp implements OpenemsApp { +@Component(name = "App.Api.ModbusTcp.ReadOnly") +public class ModbusTcpApiReadOnly + extends AbstractOpenemsAppWithProps + implements OpenemsApp { - public static enum Property { + public static enum Property + implements Type, Nameable { // Components - CONTROLLER_ID, // + CONTROLLER_ID(AppDef.of(ModbusTcpApiReadOnly.class) // + .setDefaultValue("ctrlApiModbusTcp0")), // // Properties - ACTIVE, // + ALIAS(AppDef.of(ModbusTcpApiReadOnly.class) // + .setDefaultValueToAppName()), + ACTIVE(AppDef.of(ModbusTcpApiReadOnly.class) // + .setDefaultValue((app, prop, l, param) -> { + var active = app.componentManager.getEdgeConfig() + .getComponentIdsByFactory("Controller.Api.ModbusTcp.ReadWrite").size() == 0; + return new JsonPrimitive(active); + })), // ; + + private AppDef def; + + private Property(AppDef def) { + this.def = def; + } + + @Override + public AppDef def() { + return this.def; + } + + @Override + public Property self() { + return this; + } + + @Override + public Function, BundleParameter> getParamter() { + return Type.Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } + } @Activate @@ -65,12 +103,6 @@ public ModbusTcpApiReadOnly(@Reference ComponentManager componentManager, Compon super(componentManager, context, cm, componentUtil); } - @Override - public AppAssistant getAppAssistant(Language language) { - return AppAssistant.create(this.getName(language)) // - .build(); - } - @Override public AppDescriptor getAppDescriptor() { return AppDescriptor.create() // @@ -78,7 +110,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.API }; } @@ -88,15 +120,15 @@ public OpenemsAppCardinality getCardinality() { } @Override - protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() { + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { return (t, p, l) -> { - if (!EnumUtils.getAsOptionalBoolean(p, Property.ACTIVE).orElse(true)) { + if (!this.getBoolean(p, Property.ACTIVE)) { return new AppConfiguration(); } - var controllerId = this.getId(t, p, Property.CONTROLLER_ID, "ctrlApiModbusTcp0"); + var controllerId = this.getId(t, p, Property.CONTROLLER_ID); - List components = Lists.newArrayList(// + var components = Lists.newArrayList(// new EdgeConfig.Component(controllerId, this.getName(l), "Controller.Api.ModbusTcp.ReadOnly", JsonUtils.buildJsonObject() // .build())); @@ -106,8 +138,13 @@ protected ThrowingTriFunction getPropertyClass() { - return Property.class; + protected Property[] propertyValues() { + return Property.values(); + } + + @Override + protected ModbusTcpApiReadOnly getApp() { + return this; } } diff --git a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiReadWrite.java b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiReadWrite.java index 5c05c21009e..0511fd27ee7 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiReadWrite.java +++ b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiReadWrite.java @@ -19,6 +19,7 @@ import io.openems.edge.app.api.ModbusTcpApiReadWrite.Property; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.modbusslave.ModbusSlave; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -27,6 +28,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -60,9 +62,9 @@ *
      */ @org.osgi.service.component.annotations.Component(name = "App.Api.ModbusTcp.ReadWrite") -public class ModbusTcpApiReadWrite extends AbstractOpenemsApp implements OpenemsApp { +public class ModbusTcpApiReadWrite extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs CONTROLLER_ID, // // Properties @@ -117,7 +119,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.API }; } @@ -149,6 +151,14 @@ protected ThrowingTriFunction */ @org.osgi.service.component.annotations.Component(name = "App.Api.Mqtt") -public class MqttApi extends AbstractOpenemsApp implements OpenemsApp { +public class MqttApi extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Components CONTROLLER_ID, // // User-Values @@ -117,7 +119,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.API }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/api/RestJsonApiReadOnly.java b/io.openems.edge.core/src/io/openems/edge/app/api/RestJsonApiReadOnly.java index c247fc5acdb..c2c0862e6c4 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/api/RestJsonApiReadOnly.java +++ b/io.openems.edge.core/src/io/openems/edge/app/api/RestJsonApiReadOnly.java @@ -1,32 +1,40 @@ package io.openems.edge.app.api; -import java.util.EnumMap; +import java.util.Map; +import java.util.function.Function; 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.Component; import org.osgi.service.component.annotations.Reference; import com.google.common.collect.Lists; 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.types.EdgeConfig; -import io.openems.common.utils.EnumUtils; import io.openems.common.utils.JsonUtils; import io.openems.edge.app.api.RestJsonApiReadOnly.Property; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.AbstractOpenemsAppWithProps; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; +import io.openems.edge.core.appmanager.AppDef; 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; +import io.openems.edge.core.appmanager.Type; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; /** * Describes a App for ReadOnly Rest JSON Api. @@ -47,15 +55,47 @@ } * */ -@org.osgi.service.component.annotations.Component(name = "App.Api.RestJson.ReadOnly") -public class RestJsonApiReadOnly extends AbstractOpenemsApp implements OpenemsApp { +@Component(name = "App.Api.RestJson.ReadOnly") +public class RestJsonApiReadOnly extends AbstractOpenemsAppWithProps + implements OpenemsApp { - public static enum Property { + public static enum Property implements Type, Nameable { // Components - CONTROLLER_ID, // + CONTROLLER_ID(AppDef.of(RestJsonApiReadOnly.class) // + .setDefaultValue("ctrlApiRest0")), // // Properties - ACTIVE, // + ALIAS(AppDef.of(RestJsonApiReadOnly.class) // + .setDefaultValueToAppName()), + ACTIVE(AppDef.of(RestJsonApiReadOnly.class) // + .setDefaultValue((app, prop, l, param) -> { + var active = app.componentManager.getEdgeConfig() + .getComponentIdsByFactory("Controller.Api.Rest.ReadWrite").isEmpty(); + return new JsonPrimitive(active); + }) // + .setField(JsonFormlyUtil::buildCheckbox)), // ; + + private final AppDef def; + + private Property(AppDef def) { + this.def = def; + } + + @Override + public AppDef def() { + return this.def; + } + + @Override + public Property self() { + return this; + } + + @Override + public Function, BundleParameter> getParamter() { + return Type.Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } + } @Activate @@ -77,7 +117,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.API }; } @@ -87,12 +127,12 @@ public OpenemsAppCardinality getCardinality() { } @Override - protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() { + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { return (t, p, l) -> { - if (!EnumUtils.getAsOptionalBoolean(p, Property.ACTIVE).orElse(true)) { + if (!this.getBoolean(p, Property.ACTIVE)) { return new AppConfiguration(); } - var controllerId = this.getId(t, p, Property.CONTROLLER_ID, "ctrlApiRest0"); + var controllerId = this.getId(t, p, Property.CONTROLLER_ID); var components = Lists.newArrayList(// new EdgeConfig.Component(controllerId, this.getName(l), "Controller.Api.Rest.ReadOnly", @@ -105,8 +145,13 @@ protected ThrowingTriFunction getPropertyClass() { - return Property.class; + protected Property[] propertyValues() { + return Property.values(); + } + + @Override + protected RestJsonApiReadOnly getApp() { + return this; } } diff --git a/io.openems.edge.core/src/io/openems/edge/app/api/RestJsonApiReadWrite.java b/io.openems.edge.core/src/io/openems/edge/app/api/RestJsonApiReadWrite.java index 42d8196a6e3..79fbb333e88 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/api/RestJsonApiReadWrite.java +++ b/io.openems.edge.core/src/io/openems/edge/app/api/RestJsonApiReadWrite.java @@ -18,6 +18,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.api.RestJsonApiReadWrite.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -26,6 +27,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -58,9 +60,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.Api.RestJson.ReadWrite") -public class RestJsonApiReadWrite extends AbstractOpenemsApp implements OpenemsApp { +public class RestJsonApiReadWrite extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs CONTROLLER_ID, // // Properties @@ -99,7 +101,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.API }; } @@ -122,6 +124,14 @@ protected ThrowingTriFunction defaultDef() { + return AppDef.of() // + .setTranslationBundleSupplier(BundleParameter::getBundle); + } + + /** + * Creates a {@link AppDef} for a alias. + * + * @return the {@link AppDef} + */ + public static final AppDef alias() { + return CommonProps.defaultDef() // + .setTranslatedLabel("alias") // + .setDefaultValueToAppName() // + .setField(JsonFormlyUtil::buildInputFromNameable); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/common/props/CommunicationProps.java b/io.openems.edge.core/src/io/openems/edge/app/common/props/CommunicationProps.java new file mode 100644 index 00000000000..bc950a321a0 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/common/props/CommunicationProps.java @@ -0,0 +1,56 @@ +package io.openems.edge.app.common.props; + +import io.openems.edge.core.appmanager.AppDef; +import io.openems.edge.core.appmanager.JsonFormlyUtil; +import io.openems.edge.core.appmanager.Nameable; +import io.openems.edge.core.appmanager.OpenemsApp; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; + +public final class CommunicationProps { + + private CommunicationProps() { + } + + /** + * Creates a {@link AppDef} for a ip-address. + * + * @return the {@link AppDef} + */ + public static final AppDef ip() { + return CommonProps.defaultDef() // + .setTranslatedLabel("ipAddress") // + .setDefaultValue("192.168.178.85") // + .setField(JsonFormlyUtil::buildInputFromNameable, (app, prop, l, param, f) -> // + f.setValidation(JsonFormlyUtil.InputBuilder.Validation.IP)); + } + + /** + * Creates a {@link AppDef} for a port. + * + * @return the {@link AppDef} + */ + public static final AppDef port() { + return CommonProps.defaultDef() // + .setTranslatedLabel("port") // + .setTranslatedDescription("port.description") // + .setDefaultValue(502) // + .setField(JsonFormlyUtil::buildInputFromNameable, (app, prop, l, param, f) -> // + f.setInputType(JsonFormlyUtil.InputBuilder.Type.NUMBER) // + .setMin(0)); + } + + /** + * Creates a {@link AppDef} for a modbusUnitId. + * + * @return the {@link AppDef} + */ + public static final AppDef modbusUnitId() { + return CommonProps.defaultDef() // + .setTranslatedLabel("modbusUnitId") // + .setTranslatedDescription("modbusUnitId.description") // + .setField(JsonFormlyUtil::buildInputFromNameable, (app, prop, l, param, f) -> // + f.setInputType(JsonFormlyUtil.InputBuilder.Type.NUMBER) // + .setMin(0)); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/enums/OptionsFactory.java b/io.openems.edge.core/src/io/openems/edge/app/enums/OptionsFactory.java new file mode 100644 index 00000000000..988069f1494 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/enums/OptionsFactory.java @@ -0,0 +1,57 @@ +package io.openems.edge.app.enums; + +import java.util.Arrays; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; + +import io.openems.common.session.Language; + +/** + * Options-Factory for setting options with their translations. + * + *
      + * Usage:
      + * public static OptionsFactory optionsFactory() {
      + * 	return OptionsFactory.of(values());
      + * }
      + * or:
      + * OptionsFactory.of(Enum.class)
      + * 
      + * + */ +public interface OptionsFactory { + + /** + * Creates a {@link OptionsFactory} of the given {@link TranslatableEnum} + * values. + * + * @param values the values to create a {@link OptionsFactory} from + * @return the {@link OptionsFactory} + */ + public static OptionsFactory of(TranslatableEnum[] values) { + return l -> Arrays.stream(values) // + .map(e -> Map.entry(e.getTranslation(l), e.name())) // + .collect(Collectors.toSet()); + } + + /** + * Creates a {@link OptionsFactory} of the given {@link TranslatableEnum} class. + * + * @param the type of the enum {@link Class} + * @param enumClass the {@link Class EnumClass} to get the values from. + * @return the {@link OptionsFactory} + */ + public static & TranslatableEnum> OptionsFactory of(Class enumClass) { + return of(enumClass.getEnumConstants()); + } + + /** + * Gets the options of the current instance. + * + * @param l the language of the options + * @return the options where the key is the label and the value the value + */ + public Set> options(Language l); +} \ No newline at end of file diff --git a/io.openems.edge.core/src/io/openems/edge/app/enums/Parity.java b/io.openems.edge.core/src/io/openems/edge/app/enums/Parity.java new file mode 100644 index 00000000000..85eb28d8c54 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/enums/Parity.java @@ -0,0 +1,17 @@ +package io.openems.edge.app.enums; + +/** + * Copy of {@link io.openems.edge.bridge.modbus.api.Parity}. + * + */ +public enum Parity { + NONE, // + ODD, // + EVEN, // + MARK, // + SPACE; + + private Parity() { + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/enums/Phase.java b/io.openems.edge.core/src/io/openems/edge/app/enums/Phase.java new file mode 100644 index 00000000000..d03e5f23dbd --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/enums/Phase.java @@ -0,0 +1,28 @@ +package io.openems.edge.app.enums; + +import io.openems.common.session.Language; +import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.TranslationUtil; + +/** + * Copy of {@link io.openems.edge.bridge.modbus.api.Parity}. + */ +public enum Phase implements TranslatableEnum { + ALL("all"), // + L1("l1"), // + L2("l2"), // + L3("l3"), // + ; + + private final String translationKey; + + private Phase(String translationKey) { + this.translationKey = translationKey; + } + + @Override + public final String getTranslation(Language l) { + final var bundle = AbstractOpenemsApp.getTranslationBundle(l); + return TranslationUtil.getTranslation(bundle, this.translationKey); + } +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/enums/SafetyCountry.java b/io.openems.edge.core/src/io/openems/edge/app/enums/SafetyCountry.java new file mode 100644 index 00000000000..b3fcbc77da0 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/enums/SafetyCountry.java @@ -0,0 +1,37 @@ +package io.openems.edge.app.enums; + +import io.openems.common.session.Language; +import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.TranslationUtil; + +public enum SafetyCountry implements TranslatableEnum { + GERMANY("germany"), // + AUSTRIA("austria"), // + SWITZERLAND("switzerland"), // + SWEDEN("sweden"), // + CZECH("czech"), // + HOLLAND("netherlands"), // + ; + + private final String translationKey; + + private SafetyCountry(String translationKey) { + this.translationKey = translationKey; + } + + @Override + public final String getTranslation(Language l) { + final var bundle = AbstractOpenemsApp.getTranslationBundle(l); + return TranslationUtil.getTranslation(bundle, this.translationKey); + } + + /** + * Creates a {@link OptionsFactory} of this enum. + * + * @return the {@link OptionsFactory} + */ + public static final OptionsFactory optionsFactory() { + return OptionsFactory.of(values()); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/enums/TranslatableEnum.java b/io.openems.edge.core/src/io/openems/edge/app/enums/TranslatableEnum.java new file mode 100644 index 00000000000..a4272b68943 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/enums/TranslatableEnum.java @@ -0,0 +1,16 @@ +package io.openems.edge.app.enums; + +import io.openems.common.session.Language; +import io.openems.edge.core.appmanager.Nameable; + +public interface TranslatableEnum extends Nameable { + + /** + * Gets the translation of the current value. + * + * @param language the language of the value + * @return the translated value + */ + public String getTranslation(Language language); + +} \ No newline at end of file diff --git a/io.openems.edge.core/src/io/openems/edge/app/ess/PrepareBatteryExtension.java b/io.openems.edge.core/src/io/openems/edge/app/ess/PrepareBatteryExtension.java new file mode 100644 index 00000000000..2d14266a630 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/ess/PrepareBatteryExtension.java @@ -0,0 +1,184 @@ +package io.openems.edge.app.ess; + +import java.util.Map; +import java.util.function.Function; + +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.Component; +import org.osgi.service.component.annotations.Reference; + +import com.google.common.collect.Lists; +import com.google.gson.JsonElement; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.function.ThrowingTriFunction; +import io.openems.common.session.Language; +import io.openems.common.session.Role; +import io.openems.common.types.EdgeConfig; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.app.ess.PrepareBatteryExtension.Property; +import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.AbstractOpenemsAppWithProps; +import io.openems.edge.core.appmanager.AppConfiguration; +import io.openems.edge.core.appmanager.AppDef; +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.Nameable; +import io.openems.edge.core.appmanager.OpenemsApp; +import io.openems.edge.core.appmanager.OpenemsAppCardinality; +import io.openems.edge.core.appmanager.OpenemsAppCategory; +import io.openems.edge.core.appmanager.OpenemsAppPermissions; +import io.openems.edge.core.appmanager.Type; +import io.openems.edge.core.appmanager.Type.Parameter; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; + +/** + * Describes a prepare battery extension app. + * + *
      +  {
      +    "appId":"App.Ess.PrepareBatteryExtension",
      +    "alias":"Batterie Nachrüstung",
      +    "instanceId": UUID,
      +    "image": base64,
      +    "properties":{
      +      "CTRL_PREPARE_BATTERY_EXTENSION_ID": "ctrlPrepareBatteryExtension0",
      +      "TARGET_SOC": 30
      +    },
      +    "appDescriptor": {
      +    	"websiteUrl": {@link AppDescriptor#getWebsiteUrl()}
      +    }
      +  }
      + * 
      + */ +@Component(name = "App.Ess.PrepareBatteryExtension") +public class PrepareBatteryExtension + extends AbstractOpenemsAppWithProps + implements OpenemsApp { + + public enum Property implements Type, Nameable { + // Components + CTRL_PREPARE_BATTERY_EXTENSION_ID(AppDef.of(PrepareBatteryExtension.class) // + .setDefaultValue("ctrlPrepareBatteryExtension0")), // + + // Properties + ALIAS(AppDef.of(PrepareBatteryExtension.class) // + .setDefaultValueToAppName()), // + TARGET_SOC(AppDef.of(PrepareBatteryExtension.class) // + .setTranslatedLabelWithAppPrefix(".targetSoc.label") // + .setDefaultValue(30) // + .setField(JsonFormlyUtil::buildRange, // + (app, prop, l, param, f) -> f.isRequired(true) // + .setMin(0) // + .setMax(100))), // + ; + + private final AppDef def; + + private Property(AppDef def) { + this.def = def; + } + + @Override + public Property self() { + return this; + } + + @Override + public AppDef def() { + return this.def; + } + + @Override + public Function, BundleParameter> getParamter() { + return Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } + } + + @Activate + public PrepareBatteryExtension(// + @Reference final ComponentManager componentManager, // + final ComponentContext componentContext, // + @Reference final ConfigurationAdmin cm, // + @Reference final ComponentUtil componentUtil // + ) { + super(componentManager, componentContext, cm, componentUtil); + } + + @Override + public AppDescriptor getAppDescriptor() { + return AppDescriptor.create() // + .build(); + } + + @Override + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.ESS }; + } + + @Override + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.SINGLE; + } + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { + return (t, p, l) -> { + final var ctrlPrepareBatteryExtensionId = this.getId(t, p, Property.CTRL_PREPARE_BATTERY_EXTENSION_ID); + + final var alias = this.getString(p, l, Property.ALIAS); + final var targetSoc = this.getInt(p, Property.TARGET_SOC); + + final var components = Lists.newArrayList(// + new EdgeConfig.Component(ctrlPrepareBatteryExtensionId, alias, + "Controller.Ess.PrepareBatteryExtension", // + JsonUtils.buildJsonObject() // + .addProperty("enabled", true) // + .addProperty("targetSoc", targetSoc) // + .onlyIf(t == ConfigurationTarget.ADD, // + b -> b.addProperty("enabled", true) // + .addProperty("ess_id", "ess0") // + .addProperty("isRunning", false) // + .addProperty("targetTimeSpecified", false) // + .addProperty("targetTimeBuffer", 30) // + .addProperty("selfTermination", true) // + .addProperty("terminationBuffer", 120) // + .addProperty("conditionalTermination", true) // + .addProperty("endCondition", "CAPACITY_CHANGED")) + .build()) // + ); + + final var schedulerIds = Lists.newArrayList(// + ctrlPrepareBatteryExtensionId, // + "ctrlEmergencyCapacityReserve0", // + "ctrlGridOptimizedCharge0", // + "ctrlEssSurplusFeedToGrid0", // + "ctrlBalancing0" // + ); + + return new AppConfiguration(components, schedulerIds); + }; + } + + @Override + public OpenemsAppPermissions getAppPermissions() { + return OpenemsAppPermissions.create() // + .setCanSee(Role.ADMIN) // + .build(); + } + + @Override + protected Property[] propertyValues() { + return Property.values(); + } + + @Override + protected PrepareBatteryExtension getApp() { + return this; + } +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/evcs/AbstractEvcsApp.java b/io.openems.edge.core/src/io/openems/edge/app/evcs/AbstractEvcsApp.java index 595ac70c3a7..bc27dc6616d 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/evcs/AbstractEvcsApp.java +++ b/io.openems.edge.core/src/io/openems/edge/app/evcs/AbstractEvcsApp.java @@ -10,11 +10,13 @@ import io.openems.common.types.EdgeConfig; import io.openems.common.utils.JsonUtils; import io.openems.edge.common.component.ComponentManager; -import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.ComponentUtil; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsAppCategory; -public abstract class AbstractEvcsApp> extends AbstractOpenemsApp { +public abstract class AbstractEvcsApp & Nameable> + extends AbstractEnumOpenemsApp { protected AbstractEvcsApp(ComponentManager componentManager, ComponentContext componentContext, ConfigurationAdmin cm, ComponentUtil componentUtil) { @@ -22,7 +24,7 @@ protected AbstractEvcsApp(ComponentManager componentManager, ComponentContext co } @Override - public final OpenemsAppCategory[] getCategorys() { + public final OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.EVCS }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/evcs/EvcsCluster.java b/io.openems.edge.core/src/io/openems/edge/app/evcs/EvcsCluster.java index 773f8effd4a..ed352e485a4 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/evcs/EvcsCluster.java +++ b/io.openems.edge.core/src/io/openems/edge/app/evcs/EvcsCluster.java @@ -1,6 +1,7 @@ package io.openems.edge.app.evcs; -import java.util.EnumMap; +import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; import org.osgi.service.cm.ConfigurationAdmin; @@ -15,21 +16,23 @@ import io.openems.common.function.ThrowingTriFunction; import io.openems.common.session.Language; import io.openems.common.types.EdgeConfig; -import io.openems.common.utils.EnumUtils; import io.openems.common.utils.JsonUtils; import io.openems.edge.app.evcs.EvcsCluster.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.AbstractOpenemsAppWithProps; import io.openems.edge.core.appmanager.AppConfiguration; +import io.openems.edge.core.appmanager.AppDef; 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; -import io.openems.edge.core.appmanager.TranslationUtil; +import io.openems.edge.core.appmanager.Type; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; /** * Describes a evcs cluster. @@ -51,15 +54,51 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.Evcs.Cluster") -public class EvcsCluster extends AbstractOpenemsApp implements OpenemsApp { +public class EvcsCluster extends AbstractOpenemsAppWithProps + implements OpenemsApp { - public static enum Property { + public static enum Property implements Type, Nameable { // Component-IDs - EVCS_CLUSTER_ID, // + EVCS_CLUSTER_ID(AppDef.of(EvcsCluster.class) // + .setDefaultValue("evcsCluster0")), // // Properties - ALIAS, // - EVCS_IDS // + ALIAS(AppDef.of(EvcsCluster.class) // + .setDefaultValueToAppName()), // + EVCS_IDS(AppDef.of(EvcsCluster.class) // + .setLabel("EVCS-IDs") // + .setTranslatedDescriptionWithAppPrefix(".evcsIds.description") // + .setField(JsonFormlyUtil::buildSelect, (app, prop, l, param, f) -> { + f.setOptions( + app.componentUtil.getEnabledComponentsOfStartingId("evcs").stream() + .filter(t -> !t.id().startsWith("evcsCluster")).collect(Collectors.toList()), + JsonFormlyUtil.SelectBuilder.DEFAULT_COMPONENT_2_LABEL, + JsonFormlyUtil.SelectBuilder.DEFAULT_COMPONENT_2_VALUE) // + .isRequired(true) // + .isMulti(true); + }) // + .bidirectional(EVCS_CLUSTER_ID, "evcs.ids", a -> a.componentManager)) // ; + + private final AppDef def; + + private Property(AppDef def) { + this.def = def; + } + + @Override + public Property self() { + return this; + } + + @Override + public AppDef def() { + return this.def; + } + + @Override + public Function, BundleParameter> getParamter() { + return BundleParameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } } @Activate @@ -69,18 +108,18 @@ public EvcsCluster(@Reference ComponentManager componentManager, ComponentContex } @Override - protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() { + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { return (t, p, l) -> { - var evcsClusterId = this.getId(t, p, Property.EVCS_CLUSTER_ID, "evcsCluster0"); + var evcsClusterId = this.getId(t, p, Property.EVCS_CLUSTER_ID); - var alias = this.getValueOrDefault(p, Property.ALIAS, this.getName(l)); - var ids = EnumUtils.getAsJsonArray(p, Property.EVCS_IDS); + var alias = this.getString(p, l, Property.ALIAS); + var ids = this.getJsonArray(p, Property.EVCS_IDS); var components = Lists.newArrayList(// new EdgeConfig.Component(evcsClusterId, alias, "Evcs.Cluster.PeakShaving", JsonUtils.buildJsonObject() // - .onlyIf(t.isAddOrUpdate(), j -> j.add("evcs.ids", ids)) // + .add("evcs.ids", ids) // .build()) // ); @@ -88,26 +127,6 @@ protected ThrowingTriFunction !t.id().startsWith("evcsCluster")).collect(Collectors.toList()), - JsonFormlyUtil.SelectBuilder.DEFAULT_COMPONENT_2_LABEL, - JsonFormlyUtil.SelectBuilder.DEFAULT_COMPONENT_2_VALUE) - .isRequired(true) // - .isMulti(true) // - .build()) - .build()) - .build(); - } - @Override public AppDescriptor getAppDescriptor() { return AppDescriptor.create() // @@ -115,13 +134,13 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.EVCS }; } @Override - protected Class getPropertyClass() { - return Property.class; + protected Property[] propertyValues() { + return Property.values(); } @Override @@ -129,4 +148,9 @@ public OpenemsAppCardinality getCardinality() { return OpenemsAppCardinality.SINGLE; } + @Override + protected EvcsCluster getApp() { + return this; + } + } diff --git a/io.openems.edge.core/src/io/openems/edge/app/evcs/HardyBarthEvcs.java b/io.openems.edge.core/src/io/openems/edge/app/evcs/HardyBarthEvcs.java index 7c04f142618..c9eeecedfb3 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/evcs/HardyBarthEvcs.java +++ b/io.openems.edge.core/src/io/openems/edge/app/evcs/HardyBarthEvcs.java @@ -1,6 +1,9 @@ package io.openems.edge.app.evcs; -import java.util.EnumMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import java.util.function.Function; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentContext; @@ -8,29 +11,45 @@ import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.exceptions.OpenemsException; import io.openems.common.function.ThrowingTriFunction; import io.openems.common.session.Language; -import io.openems.common.utils.EnumUtils; +import io.openems.common.types.EdgeConfig; import io.openems.common.utils.JsonUtils; -import io.openems.edge.app.evcs.HardyBarthEvcs.Property; +import io.openems.edge.app.common.props.CommonProps; +import io.openems.edge.app.common.props.CommunicationProps; +import io.openems.edge.app.evcs.HardyBarthEvcs.PropertyParent; 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.AbstractOpenemsAppWithProps; import io.openems.edge.core.appmanager.AppConfiguration; +import io.openems.edge.core.appmanager.AppDef; 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.DefaultEnum; import io.openems.edge.core.appmanager.InterfaceConfiguration; import io.openems.edge.core.appmanager.JsonFormlyUtil; -import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Validation; +import io.openems.edge.core.appmanager.JsonFormlyUtil.Case; +import io.openems.edge.core.appmanager.JsonFormlyUtil.DefaultValueOptions; +import io.openems.edge.core.appmanager.JsonFormlyUtil.ExpressionBuilder; +import io.openems.edge.core.appmanager.JsonFormlyUtil.ExpressionBuilder.Operator; +import io.openems.edge.core.appmanager.JsonFormlyUtil.FormlyBuilder; +import io.openems.edge.core.appmanager.JsonFormlyUtil.Wrappers; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; +import io.openems.edge.core.appmanager.OpenemsAppCategory; import io.openems.edge.core.appmanager.TranslationUtil; +import io.openems.edge.core.appmanager.Type; +import io.openems.edge.core.appmanager.Type.Parameter; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; /** * Describes a Hardy Barth evcs App. @@ -44,7 +63,12 @@ "properties":{ "EVCS_ID": "evcs0", "CTRL_EVCS_ID": "ctrlEvcs0", - "IP":"192.168.25.30" + "IP": "192.168.25.30", + "NUMBER_OF_CHARGING_STATIONS": 1, + "EVCS_ID_CP_2": "evcs0", + "CTRL_EVCS_ID_CP_2": "ctrlEvcs0", + "ALIAS_CP_2": "eCharge Hardy Barth Ladestation - Rechts", + "IP_CP_2": "192.168.25.31" }, "appDescriptor": { "websiteUrl": {@link AppDescriptor#getWebsiteUrl()} @@ -53,26 +77,180 @@ * */ @Component(name = "App.Evcs.HardyBarth") -public class HardyBarthEvcs extends AbstractEvcsApp implements OpenemsApp { +public class HardyBarthEvcs extends + AbstractOpenemsAppWithProps implements OpenemsApp { - public static enum Property implements DefaultEnum { + public interface PropertyParent extends Nameable, Type { + + } + + public static enum Property implements PropertyParent { // Component-IDs - EVCS_ID("evcs0"), // - CTRL_EVCS_ID("ctrlEvcs0"), // + EVCS_ID(AppDef.componentId("evcs0")), // + CTRL_EVCS_ID(AppDef.componentId("ctrlEvcs0")), // + EVCS_ID_CP_2(AppDef.componentId("evcs0")), // + CTRL_EVCS_ID_CP_2(AppDef.componentId("ctrlEvcs0")), // // Properties - ALIAS("eCharge Hardy Barth Ladestation"), // - IP("192.168.25.30") // + NUMBER_OF_CHARGING_STATIONS(AppDef.of(HardyBarthEvcs.class) // + .setTranslatedLabelWithAppPrefix(".numberOfChargingStations.label") // + .setDefaultValue(1) // + .setField(JsonFormlyUtil::buildSelectFromNameable, (app, property, l, parameter, field) -> // + field.setOptions(Lists.newArrayList(1, 2), JsonPrimitive::new, JsonPrimitive::new))), // + WRAPPER_FIRST_CHARGE_POINT(AppDef.of(HardyBarthEvcs.class) // + .setTranslatedLabel("App.Evcs.chargingStation.label", 1) + .setField(JsonFormlyUtil::buildFieldGroupFromNameable, (app, property, l, parameter, field) -> { + field.addWrapper(Wrappers.PANEL) // + .setFieldGroup(SubPropertyFirstChargepoint.fields(app, l, parameter)) // + .setLabelExpression( + ExpressionBuilder.of(Property.NUMBER_OF_CHARGING_STATIONS, Operator.EQ, "1"), // + "", TranslationUtil.getTranslation(parameter.bundle, + "App.Evcs.chargingStation.label", 1)) + .hideKey(); // + })), // + WRAPPER_SECOND_CHARGE_POINT(AppDef.of(HardyBarthEvcs.class) // + .setTranslatedLabel("App.Evcs.chargingStation.label", 2) + .setField(JsonFormlyUtil::buildFieldGroupFromNameable, (app, property, l, parameter, field) -> { + field.addWrapper(Wrappers.PANEL) // + .setFieldGroup(SubPropertySecondChargepoint.fields(app, l, parameter)) // + .onlyShowIfValueEquals(NUMBER_OF_CHARGING_STATIONS, "2") // + .hideKey(); + })), // + ; + + private final AppDef def; + + private Property(AppDef def) { + this.def = def; + } + + @Override + public Type self() { + return this; + } + + @Override + public AppDef def() { + return this.def; + } + + @Override + public Function, BundleParameter> getParamter() { + return Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } + + } + + public enum SubPropertyFirstChargepoint implements PropertyParent { + ALIAS(AppDef.copyOfGeneric(CommonProps.alias()) // + .setAutoGenerateField(false) // + .setDefaultValue((app, property, l, parameter) -> // + new JsonPrimitive(TranslationUtil.getTranslation(parameter.bundle, "App.Evcs.HardyBarth.alias.value", // + TranslationUtil.getTranslation(parameter.bundle, "right")))) // + .wrapField((app, property, l, parameter, field) -> field.isRequired(true) // + .setDefaultValueCases(new DefaultValueOptions(Property.NUMBER_OF_CHARGING_STATIONS, // + new Case(1, app.getName(l)), // + new Case(2, TranslationUtil.getTranslation(parameter.bundle, // + "App.Evcs.HardyBarth.alias.value", // + TranslationUtil.getTranslation(parameter.bundle, "right"))))))), // + IP(AppDef.copyOfGeneric(CommunicationProps.ip()) // + .setDefaultValue("192.168.25.30") // + .setAutoGenerateField(false) // + .wrapField((app, property, l, parameter, field) -> field.isRequired(true))), // + ; + + private final AppDef def; + + private SubPropertyFirstChargepoint(AppDef def) { + this.def = def; + } + + /** + * Gets the {@link AppDef}. + * + * @return the {@link AppDef} + */ + public AppDef def() { + return this.def; + } + + /** + * Gets the fields of this enum. + * + * @param app the input {@link OpenemsApp} + * @param l the {@link Language} + * @param param the parameter values + * @return the input fields + */ + public static JsonArray fields(HardyBarthEvcs app, Language l, BundleParameter param) { + return Arrays.stream(SubPropertyFirstChargepoint.values()) // + .map(prop -> prop.def.getField().get(app, prop, l, param)) // + .map(FormlyBuilder::build) // + .collect(JsonUtils.toJsonArray()); + } + + @Override + public Function, BundleParameter> getParamter() { + return Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } + + @Override + public Type self() { + return this; + } + + } + + public enum SubPropertySecondChargepoint implements PropertyParent { + ALIAS_CP_2(AppDef.copyOfGeneric(CommonProps.alias()) // + .setAutoGenerateField(false) // + .setDefaultValue((app, property, l, parameter) -> // + new JsonPrimitive(TranslationUtil.getTranslation(parameter.bundle, "App.Evcs.HardyBarth.alias.value", // + TranslationUtil.getTranslation(parameter.bundle, "left")))) // + .wrapField((app, property, l, parameter, field) -> field.isRequired(true))), // + IP_CP_2(AppDef.copyOfGeneric(CommunicationProps.ip()) // + .setDefaultValue("192.168.25.31") // + .setAutoGenerateField(false) // + .wrapField((app, property, l, parameter, field) -> field.isRequired(true))), // ; - private final String defaultValue; + private final AppDef def; - private Property(String defaultValue) { - this.defaultValue = defaultValue; + private SubPropertySecondChargepoint(AppDef def) { + this.def = def; + } + + /** + * Gets the {@link AppDef}. + * + * @return the {@link AppDef} + */ + public AppDef def() { + return this.def; + } + + /** + * Gets the fields of this enum. + * + * @param app the input {@link OpenemsApp} + * @param l the {@link Language} + * @param param the parameter values + * @return the input fields + */ + public static JsonArray fields(HardyBarthEvcs app, Language l, BundleParameter param) { + return Arrays.stream(SubPropertySecondChargepoint.values()) // + .map(prop -> prop.def.getField().get(app, prop, l, param)) // + .map(FormlyBuilder::build) // + .collect(JsonUtils.toJsonArray()); } @Override - public String getDefaultValue() { - return this.defaultValue; + public Function, BundleParameter> getParamter() { + return Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } + + @Override + public Type self() { + return this; } } @@ -84,48 +262,68 @@ public HardyBarthEvcs(@Reference ComponentManager componentManager, ComponentCon } @Override - protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() { + protected ThrowingTriFunction, // + Language, // + AppConfiguration, // + OpenemsNamedException> appPropertyConfigurationFactory() { return (t, p, l) -> { - // values the user enters - var ip = EnumUtils.getAsOptionalString(p, Property.IP).orElse(Property.IP.getDefaultValue()); - var alias = this.getValueOrDefault(p, Property.ALIAS, this.getName(l)); + final var controllerAlias = TranslationUtil.getTranslation(AbstractOpenemsApp.getTranslationBundle(l), + "App.Evcs.controller.alias"); + + final var numberOfChargingStations = this.getInt(p, Property.NUMBER_OF_CHARGING_STATIONS); + if (numberOfChargingStations <= 0 || numberOfChargingStations > 2) { + throw new OpenemsException("Number of charging stations can only be 0 < n <= 2."); + } - // values which are being auto generated by the appManager - var evcsId = this.getId(t, p, Property.EVCS_ID); - var ctrlEvcsId = this.getId(t, p, Property.CTRL_EVCS_ID); + final var schedulerIds = new ArrayList(); - var components = this.getComponents(evcsId, alias, "Evcs.HardyBarth", ip, ctrlEvcsId); + final var alias = this.getString(p, l, SubPropertyFirstChargepoint.ALIAS); + final var ip = this.getString(p, l, SubPropertyFirstChargepoint.IP); + final var evcsId = this.getId(t, p, Property.EVCS_ID); + final var ctrlEvcsId = this.getId(t, p, Property.CTRL_EVCS_ID); + schedulerIds.add(ctrlEvcsId); - var ips = Lists.newArrayList(// + final var factorieId = "Evcs.HardyBarth"; + final var components = Lists.newArrayList(// + new EdgeConfig.Component(evcsId, alias, factorieId, JsonUtils.buildJsonObject() // + .addProperty("ip", ip) // + .build()), // + new EdgeConfig.Component(ctrlEvcsId, controllerAlias, "Controller.Evcs", JsonUtils.buildJsonObject() // + .addProperty("evcs.id", evcsId) // + .build())// + ); + + if (numberOfChargingStations == 2) { + final var aliasCp2 = this.getString(p, l, SubPropertySecondChargepoint.ALIAS_CP_2); + final var ipCp2 = this.getString(p, l, SubPropertySecondChargepoint.IP_CP_2); + final var evcsIdCp2 = this.getId(t, p, Property.EVCS_ID_CP_2); + final var ctrlEvcsIdCp2 = this.getId(t, p, Property.CTRL_EVCS_ID_CP_2); + schedulerIds.add(ctrlEvcsIdCp2); + + components.add(new EdgeConfig.Component(evcsIdCp2, aliasCp2, factorieId, JsonUtils.buildJsonObject() // + .addProperty("ip", ipCp2) // + .build())); + components.add(new EdgeConfig.Component(ctrlEvcsIdCp2, controllerAlias, "Controller.Evcs", + JsonUtils.buildJsonObject() // + .addProperty("evcs.id", evcsIdCp2) // + .build())); + } + + final var ips = Lists.newArrayList(// new InterfaceConfiguration("eth0") // .addIp("Evcs", "192.168.25.10/24") // ); + schedulerIds.add("ctrlBalancing0"); return new AppConfiguration(// components, // - Lists.newArrayList(ctrlEvcsId, "ctrlBalancing0"), // + schedulerIds, // ip.startsWith("192.168.25.") ? ips : null // ); }; } - @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, this.getAppId() + ".ip.description")) - .setDefaultValue(Property.IP.getDefaultValue()) // - .isRequired(true) // - .setValidation(Validation.IP) // - .build()) // - .build()) // - .build(); - } - @Override public AppDescriptor getAppDescriptor() { return AppDescriptor.create() // @@ -133,8 +331,12 @@ public AppDescriptor getAppDescriptor() { } @Override - protected Class getPropertyClass() { - return Property.class; + protected PropertyParent[] propertyValues() { + return ImmutableList.builder() // + .addAll(Arrays.asList(Property.values())) // + .addAll(Arrays.asList(SubPropertyFirstChargepoint.values())) // + .addAll(Arrays.asList(SubPropertySecondChargepoint.values())) // + .build().toArray(PropertyParent[]::new); } @Override @@ -142,4 +344,14 @@ public OpenemsAppCardinality getCardinality() { return OpenemsAppCardinality.MULTIPLE; } + @Override + protected HardyBarthEvcs getApp() { + return this; + } + + @Override + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.EVCS }; + } + } diff --git a/io.openems.edge.core/src/io/openems/edge/app/evcs/IesKeywattEvcs.java b/io.openems.edge.core/src/io/openems/edge/app/evcs/IesKeywattEvcs.java index e899ba177f7..64efed395b6 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/evcs/IesKeywattEvcs.java +++ b/io.openems.edge.core/src/io/openems/edge/app/evcs/IesKeywattEvcs.java @@ -28,6 +28,7 @@ import io.openems.edge.core.appmanager.DefaultEnum; import io.openems.edge.core.appmanager.JsonFormlyUtil; import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Type; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.TranslationUtil; @@ -56,7 +57,7 @@ @Component(name = "App.Evcs.IesKeywatt") public class IesKeywattEvcs extends AbstractEvcsApp implements OpenemsApp { - public static enum Property implements DefaultEnum { + public static enum Property implements DefaultEnum, Nameable { // Component-IDs EVCS_ID("evcs0"), // CTRL_EVCS_ID("ctrlEvcs0"), // diff --git a/io.openems.edge.core/src/io/openems/edge/app/evcs/KebaEvcs.java b/io.openems.edge.core/src/io/openems/edge/app/evcs/KebaEvcs.java index 1ead2173f0f..0b3ac4e5bfa 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/evcs/KebaEvcs.java +++ b/io.openems.edge.core/src/io/openems/edge/app/evcs/KebaEvcs.java @@ -27,6 +27,7 @@ import io.openems.edge.core.appmanager.InterfaceConfiguration; import io.openems.edge.core.appmanager.JsonFormlyUtil; import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Validation; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.TranslationUtil; @@ -54,7 +55,7 @@ @Component(name = "App.Evcs.Keba") public class KebaEvcs extends AbstractEvcsApp implements OpenemsApp { - public enum Property implements DefaultEnum { + public enum Property implements DefaultEnum, Nameable { // Component-IDs EVCS_ID("evcs0"), // CTRL_EVCS_ID("ctrlEvcs0"), // @@ -115,8 +116,7 @@ public AppAssistant getAppAssistant(Language language) { .fields(JsonUtils.buildJsonArray() // .add(JsonFormlyUtil.buildInput(Property.IP) // .setLabel(TranslationUtil.getTranslation(bundle, "ipAddress")) // - .setDescription( - TranslationUtil.getTranslation(bundle, this.getAppId() + ".ip.description")) + .setDescription(TranslationUtil.getTranslation(bundle, "App.Evcs.ip.description")) .setDefaultValue(Property.IP.getDefaultValue()) // .isRequired(true) // .setValidation(Validation.IP) // diff --git a/io.openems.edge.core/src/io/openems/edge/app/hardware/KMtronic8Channel.java b/io.openems.edge.core/src/io/openems/edge/app/hardware/KMtronic8Channel.java index 58f341a28ff..309429aa0de 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/hardware/KMtronic8Channel.java +++ b/io.openems.edge.core/src/io/openems/edge/app/hardware/KMtronic8Channel.java @@ -17,6 +17,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.hardware.KMtronic8Channel.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -26,6 +27,7 @@ import io.openems.edge.core.appmanager.InterfaceConfiguration; import io.openems.edge.core.appmanager.JsonFormlyUtil; import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Validation; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -52,9 +54,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.Hardware.KMtronic8Channel") -public class KMtronic8Channel extends AbstractOpenemsApp implements OpenemsApp { +public class KMtronic8Channel extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs IO_ID, // MODBUS_ID, // @@ -126,7 +128,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.HARDWARE }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/heat/CombinedHeatAndPower.java b/io.openems.edge.core/src/io/openems/edge/app/heat/CombinedHeatAndPower.java index dee1c1906f3..4104e197d99 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/heat/CombinedHeatAndPower.java +++ b/io.openems.edge.core/src/io/openems/edge/app/heat/CombinedHeatAndPower.java @@ -20,6 +20,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.heat.CombinedHeatAndPower.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -28,6 +29,7 @@ import io.openems.edge.core.appmanager.ConfigurationTarget; import io.openems.edge.core.appmanager.DefaultEnum; import io.openems.edge.core.appmanager.JsonFormlyUtil; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -63,9 +65,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.Heat.CHP") -public class CombinedHeatAndPower extends AbstractOpenemsApp implements OpenemsApp { +public class CombinedHeatAndPower extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property implements DefaultEnum { + public static enum Property implements DefaultEnum, Nameable { // Component-IDs CTRL_CHP_SOC_ID("ctrlChpSoc0"), // // Properties @@ -152,8 +154,8 @@ public AppAssistant getAppAssistant(Language language) { }) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".outputChannel.label")) // - .setDescription(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".outputChannel.description")) // + .setDescription(TranslationUtil.getTranslation(bundle, // + "App.Heat.outputChannel.description")) // .build()) .build()) .build(); @@ -166,7 +168,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.HEAT }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/heat/HeatPump.java b/io.openems.edge.core/src/io/openems/edge/app/heat/HeatPump.java index 6e21f2ddcd5..7aa91f9131d 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/heat/HeatPump.java +++ b/io.openems.edge.core/src/io/openems/edge/app/heat/HeatPump.java @@ -20,6 +20,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.heat.HeatPump.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -27,6 +28,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -63,9 +65,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.Heat.HeatPump") -public class HeatPump extends AbstractOpenemsApp implements OpenemsApp { +public class HeatPump extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs CTRL_IO_HEAT_PUMP_ID, // // Properties @@ -136,16 +138,16 @@ public AppAssistant getAppAssistant(Language language) { .onlyIf(relays != null, t -> t.setDefaultValue(relays[0])) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".outputChannel1.label")) - .setDescription(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".outputChannel1.description")) + .setDescription(TranslationUtil.getTranslation(bundle, // + "App.Heat.outputChannel.description")) // .build()) .add(JsonFormlyUtil.buildSelect(Property.OUTPUT_CHANNEL_2) // .setOptions(options) // .onlyIf(relays != null, t -> t.setDefaultValue(relays[1])) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".outputChannel2.label")) - .setDescription(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".outputChannel2.description")) + .setDescription(TranslationUtil.getTranslation(bundle, // + "App.Heat.outputChannel.description")) // .build()) .build()) .build(); @@ -158,7 +160,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.HEAT }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/heat/HeatingElement.java b/io.openems.edge.core/src/io/openems/edge/app/heat/HeatingElement.java index 79d49151b4b..bde42bad2ce 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/heat/HeatingElement.java +++ b/io.openems.edge.core/src/io/openems/edge/app/heat/HeatingElement.java @@ -17,9 +17,11 @@ import io.openems.common.function.ThrowingTriFunction; import io.openems.common.session.Language; import io.openems.common.types.EdgeConfig; +import io.openems.common.utils.EnumUtils; import io.openems.common.utils.JsonUtils; import io.openems.edge.app.heat.HeatingElement.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -28,6 +30,8 @@ import io.openems.edge.core.appmanager.ConfigurationTarget; import io.openems.edge.core.appmanager.DefaultEnum; import io.openems.edge.core.appmanager.JsonFormlyUtil; +import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Type; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -50,7 +54,8 @@ "CTRL_IO_HEATING_ELEMENT_ID": "ctrlIoHeatingElement0", "OUTPUT_CHANNEL_PHASE_L1": "io0/Relay1", "OUTPUT_CHANNEL_PHASE_L2": "io0/Relay2", - "OUTPUT_CHANNEL_PHASE_L3": "io0/Relay3" + "OUTPUT_CHANNEL_PHASE_L3": "io0/Relay3", + "POWER_PER_PHASE": 2000 }, "dependencies": [ { @@ -65,9 +70,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.Heat.HeatingElement") -public class HeatingElement extends AbstractOpenemsApp implements OpenemsApp { +public class HeatingElement extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property implements DefaultEnum { + public static enum Property implements DefaultEnum, Nameable { // Component-IDs CTRL_IO_HEATING_ELEMENT_ID("ctrlIoHeatingElement0"), // // Properties @@ -75,6 +80,7 @@ public static enum Property implements DefaultEnum { OUTPUT_CHANNEL_PHASE_L1("io0/Relay1"), // OUTPUT_CHANNEL_PHASE_L2("io0/Relay2"), // OUTPUT_CHANNEL_PHASE_L3("io0/Relay3"), // + POWER_PER_PHASE("2000") // ; private final String defaultValue; @@ -107,11 +113,15 @@ protected ThrowingTriFunction t.setDefaultValue(relays[0])) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".outputChannelPhaseL1.label")) - .setDescription(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".outputChannelPhaseL1.description")) + .setDescription(TranslationUtil.getTranslation(bundle, // + "App.Heat.outputChannel.description")) // .build()) .add(JsonFormlyUtil.buildSelect(Property.OUTPUT_CHANNEL_PHASE_L2) // .setOptions(options) // .onlyIf(relays != null, t -> t.setDefaultValue(relays[1])) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".outputChannelPhaseL2.label")) - .setDescription(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".outputChannelPhaseL2.description")) + .setDescription(TranslationUtil.getTranslation(bundle, // + "App.Heat.outputChannel.description")) // .build()) .add(JsonFormlyUtil.buildSelect(Property.OUTPUT_CHANNEL_PHASE_L3) // .setOptions(options) // .onlyIf(relays != null, t -> t.setDefaultValue(relays[2])) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".outputChannelPhaseL3.label")) + .setDescription(TranslationUtil.getTranslation(bundle, // + "App.Heat.outputChannel.description")) // + .build()) + .add(JsonFormlyUtil.buildInput(Property.POWER_PER_PHASE) // + .setLabel(TranslationUtil.getTranslation(bundle, + this.getAppId() + ".powerPerPhase.label")) .setDescription(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".outputChannelPhaseL3.description")) + this.getAppId() + ".powerPerPhase.description")) + .setInputType(Type.NUMBER) // + .setMin(0) // + .setDefaultValue(2000) // + .isRequired(true) // .build()) .build()) .build(); @@ -184,7 +204,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.HEAT }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/integratedsystem/FeneconHome.java b/io.openems.edge.core/src/io/openems/edge/app/integratedsystem/FeneconHome.java index 910e303422f..437c9e9d0d7 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/integratedsystem/FeneconHome.java +++ b/io.openems.edge.core/src/io/openems/edge/app/integratedsystem/FeneconHome.java @@ -5,7 +5,15 @@ import java.util.ArrayList; import java.util.EnumMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentContext; @@ -22,11 +30,17 @@ import io.openems.common.types.EdgeConfig; import io.openems.common.utils.EnumUtils; import io.openems.common.utils.JsonUtils; +import io.openems.edge.app.enums.OptionsFactory; +import io.openems.edge.app.enums.Parity; +import io.openems.edge.app.enums.SafetyCountry; +import io.openems.edge.app.ess.PrepareBatteryExtension; import io.openems.edge.app.integratedsystem.FeneconHome.Property; +import io.openems.edge.app.meter.KdkMeter; import io.openems.edge.app.meter.SocomecMeter; import io.openems.edge.app.pvselfconsumption.GridOptimizedCharge; import io.openems.edge.app.pvselfconsumption.SelfConsumptionOptimization; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -35,6 +49,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -77,6 +92,10 @@ { "key": "SELF_CONSUMTION_OPTIMIZATION", "instanceId": UUID + }, + { + "key": "PREPARE_BATTERY_EXTENSION", + "instanceId": UUID } ], "appDescriptor": { @@ -86,9 +105,9 @@ * */ @Component(name = "App.FENECON.Home") -public class FeneconHome extends AbstractOpenemsApp implements OpenemsApp { +public class FeneconHome extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Battery Inverter SAFETY_COUNTRY, // MAX_FEED_IN_POWER, // @@ -99,6 +118,7 @@ public static enum Property { // External AC PV HAS_AC_METER, // + AC_METER_TYPE, // // DC PV Charger 1 HAS_DC_PV1, // @@ -118,6 +138,80 @@ public static enum Property { ; } + private static enum AcMeterType { + SOCOMEC("App.Meter.Socomec.Name", Parity.NONE, AcMeterType::socomecMeter), // + KDK("App.Meter.Kdk.Name", Parity.EVEN, AcMeterType::kdkMeter), // + ; + + private final String displayName; + private final Parity parity; + private final Function dependencyFunction; + + private AcMeterType(String displayName, Parity parity, + Function dependencyFunction) { + this.displayName = Objects.requireNonNull(displayName); + this.parity = Objects.requireNonNull(parity); + this.dependencyFunction = Objects.requireNonNull(dependencyFunction); + } + + public Parity getParity() { + return this.parity; + } + + public String getDisplayName(ResourceBundle resourceBundle) { + return TranslationUtil.getTranslation(resourceBundle, this.displayName); + } + + public final DependencyDeclaration getDependency(String modbusIdExternal) { + return this.dependencyFunction.apply(modbusIdExternal); + } + + private static DependencyDeclaration meter(DependencyDeclaration.AppDependencyConfig config) { + return new DependencyDeclaration("AC_METER", // + DependencyDeclaration.CreatePolicy.ALWAYS, // + DependencyDeclaration.UpdatePolicy.ALWAYS, // + DependencyDeclaration.DeletePolicy.IF_MINE, // + DependencyDeclaration.DependencyUpdatePolicy.ALLOW_ONLY_UNCONFIGURED_PROPERTIES, // + DependencyDeclaration.DependencyDeletePolicy.NOT_ALLOWED, // + config); + } + + private static DependencyDeclaration socomecMeter(String modbusIdExternal) { + return meter(DependencyDeclaration.AppDependencyConfig.create() // + .setAppId("App.Meter.Socomec") // + .setInitialProperties(JsonUtils.buildJsonObject() // + .addProperty(SocomecMeter.Property.TYPE.name(), "PRODUCTION") // + .addProperty(SocomecMeter.Property.MODBUS_ID.name(), modbusIdExternal) // + .addProperty(SocomecMeter.Property.MODBUS_UNIT_ID.name(), 6) // + .build()) + .setProperties(JsonUtils.buildJsonObject() // + .addProperty(SocomecMeter.Property.MODBUS_ID.name(), modbusIdExternal) // + .build()) + .build()); + } + + private static DependencyDeclaration kdkMeter(String modbusIdExternal) { + return meter(DependencyDeclaration.AppDependencyConfig.create() // + .setAppId("App.Meter.Kdk") // + .setInitialProperties(JsonUtils.buildJsonObject() // + .addProperty(KdkMeter.Property.TYPE.name(), "PRODUCTION") // + .addProperty(KdkMeter.Property.MODBUS_ID.name(), modbusIdExternal) // + .addProperty(KdkMeter.Property.MODBUS_UNIT_ID.name(), 6) // + .build()) + .setProperties(JsonUtils.buildJsonObject() // + .addProperty(KdkMeter.Property.MODBUS_ID.name(), modbusIdExternal) // + .build()) + .build()); + } + + public static final Set> getMeterTypeOptions(ResourceBundle resourceBundle) { + return Stream.of(AcMeterType.values()) // + .map(t -> Map.entry(t.getDisplayName(resourceBundle), t.name())) // + .collect(Collectors.toSet()); + } + + } + @Activate public FeneconHome(@Reference ComponentManager componentManager, ComponentContext context, @Reference ConfigurationAdmin cm, @Reference ComponentUtil componentUtil) { @@ -135,22 +229,27 @@ public AppDescriptor getAppDescriptor() { protected ThrowingTriFunction, Language, // AppConfiguration, OpenemsNamedException> appConfigurationFactory() { return (t, p, l) -> { - var essId = "ess0"; - var modbusIdInternal = "modbus0"; - var modbusIdExternal = "modbus1"; + final var essId = "ess0"; + final var modbusIdInternal = "modbus0"; + final var modbusIdExternal = "modbus1"; - var hasEmergencyReserve = EnumUtils.getAsOptionalBoolean(p, Property.HAS_EMERGENCY_RESERVE).orElse(false); - var emergencyReserveEnabled = EnumUtils.getAsOptionalBoolean(p, Property.EMERGENCY_RESERVE_ENABLED) + final var hasEmergencyReserve = EnumUtils.getAsOptionalBoolean(p, Property.HAS_EMERGENCY_RESERVE) .orElse(false); - var rippleControlReceiverActive = EnumUtils.getAsOptionalBoolean(p, Property.RIPPLE_CONTROL_RECEIVER_ACTIV) + final var emergencyReserveEnabled = EnumUtils.getAsOptionalBoolean(p, Property.EMERGENCY_RESERVE_ENABLED) .orElse(false); - var shadowManagmentDisabled = EnumUtils.getAsOptionalBoolean(p, Property.SHADOW_MANAGEMENT_DISABLED) + final var rippleControlReceiverActive = EnumUtils + .getAsOptionalBoolean(p, Property.RIPPLE_CONTROL_RECEIVER_ACTIV).orElse(false); + final var shadowManagmentDisabled = EnumUtils.getAsOptionalBoolean(p, Property.SHADOW_MANAGEMENT_DISABLED) .orElse(false); + final var hasAcMeter = EnumUtils.getAsOptionalBoolean(p, Property.HAS_AC_METER).orElse(false); + // for older versions this property is undefined + final var acType = EnumUtils.getAsOptionalEnum(AcMeterType.class, p, Property.AC_METER_TYPE) // + .orElse(AcMeterType.SOCOMEC); // Battery-Inverter Settings - var safetyCountry = EnumUtils.getAsString(p, Property.SAFETY_COUNTRY); - int maxFeedInPower; - String feedInSetting = EnumUtils.getAsOptionalString(p, Property.FEED_IN_SETTING).orElse("UNDEFINED"); + final var safetyCountry = EnumUtils.getAsEnum(SafetyCountry.class, p, Property.SAFETY_COUNTRY); + final int maxFeedInPower; + final String feedInSetting = EnumUtils.getAsOptionalString(p, Property.FEED_IN_SETTING).orElse("UNDEFINED"); if (!rippleControlReceiverActive) { maxFeedInPower = EnumUtils.getAsInt(p, Property.MAX_FEED_IN_POWER); } else { @@ -180,7 +279,7 @@ AppConfiguration, OpenemsNamedException> appConfigurationFactory() { .addProperty("baudRate", 9600) // .addProperty("databits", 8) // .addProperty("stopbits", "ONE") // - .addProperty("parity", "NONE") // + .addProperty("parity", (!hasAcMeter ? Parity.NONE : acType.getParity()).name()) // .addProperty("logVerbosity", "NONE") // .onlyIf(t == ConfigurationTarget.ADD, // j -> j.addProperty("invalidateElementsAfterReadErrors", 1)) // @@ -216,7 +315,7 @@ AppConfiguration, OpenemsNamedException> appConfigurationFactory() { .addProperty("enabled", true) // .addProperty("modbus.id", modbusIdExternal) // .addProperty("modbusUnitId", 247) // - .addProperty("safetyCountry", safetyCountry) // + .addProperty("safetyCountry", safetyCountry.name()) // .addProperty("backupEnable", // hasEmergencyReserve ? "ENABLE" : "DISABLE") // .addProperty("feedPowerEnable", rippleControlReceiverActive ? "DISABLE" : "ENABLE") // @@ -300,20 +399,6 @@ AppConfiguration, OpenemsNamedException> appConfigurationFactory() { .build())); } - var hasAcMeter = EnumUtils.getAsOptionalBoolean(p, Property.HAS_AC_METER).orElse(false); - - // remove components that were in the old configuration but now are a dependency - if (t == ConfigurationTarget.DELETE) { - components.add(new EdgeConfig.Component("ctrlGridOptimizedCharge0", "", - "Controller.Ess.GridOptimizedCharge", JsonUtils.buildJsonObject().build())); - components.add(new EdgeConfig.Component("ctrlBalancing0", "", "Controller.Symmetric.Balancing", - JsonUtils.buildJsonObject().build())); - if (hasAcMeter) { - components.add(new EdgeConfig.Component("meter1", "", "Meter.Socomec.Threephase", - JsonUtils.buildJsonObject().build())); - } - } - /* * Set Execution Order for Scheduler. */ @@ -355,27 +440,23 @@ AppConfiguration, OpenemsNamedException> appConfigurationFactory() { .addProperty(SelfConsumptionOptimization.Property.ESS_ID.name(), essId) // .addProperty(SelfConsumptionOptimization.Property.METER_ID.name(), "meter0") // .build()) + .build()), + new DependencyDeclaration("PREPARE_BATTERY_EXTENSION", // + DependencyDeclaration.CreatePolicy.IF_NOT_EXISTING, // + DependencyDeclaration.UpdatePolicy.NEVER, // + DependencyDeclaration.DeletePolicy.IF_MINE, // + DependencyDeclaration.DependencyUpdatePolicy.ALLOW_ONLY_UNCONFIGURED_PROPERTIES, // + DependencyDeclaration.DependencyDeletePolicy.NOT_ALLOWED, // + DependencyDeclaration.AppDependencyConfig.create() // + .setAppId("App.Ess.PrepareBatteryExtension") // + .setProperties(JsonUtils.buildJsonObject() // + .addProperty(PrepareBatteryExtension.Property.TARGET_SOC.name(), 30) // + .build()) .build()) // ); if (hasAcMeter) { - dependencies.add(new DependencyDeclaration("AC_METER", // - DependencyDeclaration.CreatePolicy.ALWAYS, // - DependencyDeclaration.UpdatePolicy.ALWAYS, // - DependencyDeclaration.DeletePolicy.IF_MINE, // - DependencyDeclaration.DependencyUpdatePolicy.ALLOW_ONLY_UNCONFIGURED_PROPERTIES, // - DependencyDeclaration.DependencyDeletePolicy.NOT_ALLOWED, // - DependencyDeclaration.AppDependencyConfig.create() // - .setAppId("App.Meter.Socomec") // - .setInitialProperties(JsonUtils.buildJsonObject() // - .addProperty(SocomecMeter.Property.TYPE.name(), "PRODUCTION") // - .addProperty(SocomecMeter.Property.MODBUS_ID.name(), modbusIdExternal) // - .addProperty(SocomecMeter.Property.MODBUS_UNIT_ID.name(), 6) // - .build()) - .setProperties(JsonUtils.buildJsonObject() // - .addProperty(SocomecMeter.Property.MODBUS_ID.name(), modbusIdExternal) // - .build()) - .build())); + dependencies.add(acType.getDependency(modbusIdExternal)); } return new AppConfiguration(components, schedulerExecutionOrder, null, dependencies); @@ -396,26 +477,11 @@ public AppAssistant getAppAssistant(Language language) { .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".safetyCountry.label")) // .isRequired(true) // - .setOptions(JsonUtils.buildJsonArray() // - .add(JsonUtils.buildJsonObject() // - .addProperty("label", // - TranslationUtil.getTranslation(bundle, "germany")) // - .addProperty("value", "GERMANY") // - .build()) // - .add(JsonUtils.buildJsonObject() // - .addProperty("label", // - TranslationUtil.getTranslation(bundle, "austria")) // - .addProperty("value", "AUSTRIA") // - .build()) // - .add(JsonUtils.buildJsonObject() // - .addProperty("label", // - TranslationUtil.getTranslation(bundle, "switzerland")) // - .addProperty("value", "SWITZERLAND") // - .build()) // - .build()) // + .setOptions(OptionsFactory.of(SafetyCountry.class), language) // .onlyIf(batteryInverter.isPresent(), f -> { - f.setDefaultValue(batteryInverter.get() // + final var setting = SafetyCountry.valueOf(batteryInverter.get() // .getProperty("safetyCountry").get().getAsString()); + f.setDefaultValue(setting.name()); }).build()) .add(JsonFormlyUtil.buildCheckbox(Property.RIPPLE_CONTROL_RECEIVER_ACTIV) // .setLabel(TranslationUtil.getTranslation(bundle, @@ -453,13 +519,20 @@ public AppAssistant getAppAssistant(Language language) { .get().getAsString()); }).build()) .add(JsonFormlyUtil.buildCheckbox(Property.HAS_AC_METER) // - .setLabel(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".hasAcMeterSocomec.label")) // + .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".hasAcMeter.label")) // .isRequired(true) // .setDefaultValue(this.componentUtil // .getComponent("meter1", "Meter.Socomec.Threephase") // .isPresent()) // .build()) + .add(JsonFormlyUtil.buildSelect(Property.AC_METER_TYPE) // + .setLabel( + TranslationUtil.getTranslation(bundle, this.getAppId() + ".acMeterType.label")) // + .setOptions(AcMeterType.getMeterTypeOptions(bundle)) // + .onlyShowIfChecked(Property.HAS_AC_METER) // + .setDefaultValue(AcMeterType.SOCOMEC.name()) // + .isRequired(true) // + .build()) // .add(JsonFormlyUtil.buildCheckbox(Property.HAS_DC_PV1) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".hasDcPV1.label")) // .isRequired(true) // @@ -549,7 +622,7 @@ private final Optional getBatteryInverter() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.INTEGRATED_SYSTEM }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/loadcontrol/ManualRelayControl.java b/io.openems.edge.core/src/io/openems/edge/app/loadcontrol/ManualRelayControl.java index 86361d77923..58d03b917a7 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/loadcontrol/ManualRelayControl.java +++ b/io.openems.edge.core/src/io/openems/edge/app/loadcontrol/ManualRelayControl.java @@ -20,6 +20,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.loadcontrol.ManualRelayControl.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -28,6 +29,7 @@ import io.openems.edge.core.appmanager.ConfigurationTarget; import io.openems.edge.core.appmanager.DefaultEnum; import io.openems.edge.core.appmanager.JsonFormlyUtil; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -55,9 +57,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.LoadControl.ManualRelayControl") -public class ManualRelayControl extends AbstractOpenemsApp implements OpenemsApp { +public class ManualRelayControl extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property implements DefaultEnum { + public static enum Property implements DefaultEnum, Nameable { // Component-IDs CTRL_IO_FIX_DIGITAL_OUTPUT_ID("ctrlIoFixDigitalOutput0"), // // Properties @@ -135,7 +137,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.LOAD_CONTROL }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/loadcontrol/ThresholdControl.java b/io.openems.edge.core/src/io/openems/edge/app/loadcontrol/ThresholdControl.java index bd5e4e8904a..42b18bdbaf7 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/loadcontrol/ThresholdControl.java +++ b/io.openems.edge.core/src/io/openems/edge/app/loadcontrol/ThresholdControl.java @@ -21,6 +21,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.loadcontrol.ThresholdControl.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -29,6 +30,7 @@ import io.openems.edge.core.appmanager.ConfigurationTarget; import io.openems.edge.core.appmanager.DefaultEnum; import io.openems.edge.core.appmanager.JsonFormlyUtil; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -56,9 +58,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.LoadControl.ThresholdControl") -public class ThresholdControl extends AbstractOpenemsApp implements OpenemsApp { +public class ThresholdControl extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property implements DefaultEnum { + public static enum Property implements DefaultEnum, Nameable { // Component-IDs CTRL_IO_CHANNEL_SINGLE_THRESHOLD_ID("ctrlIoChannelSingleThreshold0"), // // Properties @@ -140,7 +142,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.LOAD_CONTROL }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/meter/AbstractMeterApp.java b/io.openems.edge.core/src/io/openems/edge/app/meter/AbstractMeterApp.java index dfb4b45b3a9..7e2074091f6 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/meter/AbstractMeterApp.java +++ b/io.openems.edge.core/src/io/openems/edge/app/meter/AbstractMeterApp.java @@ -8,12 +8,15 @@ import io.openems.common.session.Language; import io.openems.common.utils.JsonUtils; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.ComponentUtil; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsAppCategory; import io.openems.edge.core.appmanager.TranslationUtil; -public abstract class AbstractMeterApp> extends AbstractOpenemsApp { +public abstract class AbstractMeterApp & Nameable> + extends AbstractEnumOpenemsApp { protected AbstractMeterApp(ComponentManager componentManager, ComponentContext componentContext, ConfigurationAdmin cm, ComponentUtil componentUtil) { @@ -21,7 +24,7 @@ protected AbstractMeterApp(ComponentManager componentManager, ComponentContext c } @Override - public final OpenemsAppCategory[] getCategorys() { + public final OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.METER }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/meter/CarloGavazziMeter.java b/io.openems.edge.core/src/io/openems/edge/app/meter/CarloGavazziMeter.java index 7dba47fbf93..59fa0dcf32e 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/meter/CarloGavazziMeter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/meter/CarloGavazziMeter.java @@ -27,6 +27,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.TranslationUtil; @@ -54,7 +55,7 @@ @Component(name = "App.Meter.CarloGavazzi") public class CarloGavazziMeter extends AbstractMeterApp implements OpenemsApp { - public enum Property { + public enum Property implements Nameable { // Component-IDs METER_ID, // // Properties @@ -114,7 +115,8 @@ public AppAssistant getAppAssistant(Language language) { .build()) // .add(JsonFormlyUtil.buildInput(Property.MODBUS_UNIT_ID) // .setLabel(TranslationUtil.getTranslation(bundle, "modbusUnitId")) // - .setDescription(TranslationUtil.getTranslation(bundle, "modbusUnitId.description")) // + .setDescription( + TranslationUtil.getTranslation(bundle, "App.Meter.modbusUnitId.description")) // .setInputType(Type.NUMBER) // .setDefaultValue(6) // .setMin(0) // diff --git a/io.openems.edge.core/src/io/openems/edge/app/meter/JanitzaMeter.java b/io.openems.edge.core/src/io/openems/edge/app/meter/JanitzaMeter.java index 6fe82237bce..16d1a67e8a4 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/meter/JanitzaMeter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/meter/JanitzaMeter.java @@ -32,6 +32,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.TranslationUtil; @@ -62,7 +63,7 @@ @Component(name = "App.Meter.Janitza") public class JanitzaMeter extends AbstractMeterApp implements OpenemsApp { - public enum Property { + public enum Property implements Nameable { // Component-IDs METER_ID, // MODBUS_ID, // @@ -139,7 +140,8 @@ public AppAssistant getAppAssistant(Language language) { .build()) .add(JsonFormlyUtil.buildInput(Property.MODBUS_UNIT_ID) // .setLabel(TranslationUtil.getTranslation(bundle, "modbusUnitId")) // - .setDescription(TranslationUtil.getTranslation(bundle, "modbusUnitId.description")) // + .setDescription( + TranslationUtil.getTranslation(bundle, "App.Meter.modbusUnitId.description")) // .setInputType(Type.NUMBER) // .setDefaultValue(1) // .setMin(0) // diff --git a/io.openems.edge.core/src/io/openems/edge/app/meter/KdkMeter.java b/io.openems.edge.core/src/io/openems/edge/app/meter/KdkMeter.java new file mode 100644 index 00000000000..028c3d27566 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/meter/KdkMeter.java @@ -0,0 +1,147 @@ +package io.openems.edge.app.meter; + +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.Component; +import org.osgi.service.component.annotations.Reference; + +import com.google.common.collect.Lists; +import com.google.gson.JsonElement; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.function.ThrowingTriFunction; +import io.openems.common.session.Language; +import io.openems.common.types.EdgeConfig; +import io.openems.common.utils.EnumUtils; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.app.meter.KdkMeter.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.Nameable; +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 a Kdk meter. + * + *
      +  {
      +    "appId":"App.Meter.Kdk",
      +    "alias":"Kdk Meter",
      +    "instanceId": UUID,
      +    "image": base64,
      +    "properties":{
      +    	"METER_ID": "meter1",
      +    	"TYPE": "PRODUCTION",
      +    	"MODBUS_ID": "modbus1",
      +    	"MODBUS_UNIT_ID": 1
      +    },
      +    "appDescriptor": {
      +    	"websiteUrl": {@link AppDescriptor#getWebsiteUrl()}
      +    }
      +  }
      + * 
      + */ +@Component(name = "App.Meter.Kdk") +public class KdkMeter extends AbstractMeterApp implements OpenemsApp { + + public enum Property implements Nameable { + // Component-IDs + METER_ID, // + // Properties + ALIAS, // + TYPE, // + MODBUS_ID, // + MODBUS_UNIT_ID, // + ; + } + + @Activate + public KdkMeter(@Reference ComponentManager componentManager, ComponentContext componentContext, + @Reference ConfigurationAdmin cm, @Reference ComponentUtil componentUtil) { + super(componentManager, componentContext, cm, componentUtil); + } + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() { + return (t, p, l) -> { + + var meterId = this.getId(t, p, Property.METER_ID, "meter1"); + + var alias = this.getValueOrDefault(p, Property.ALIAS, this.getName(l)); + var type = this.getValueOrDefault(p, Property.TYPE, "PRODUCTION"); + var modbusUnitId = EnumUtils.getAsInt(p, Property.MODBUS_UNIT_ID); + var modbusId = this.getValueOrDefault(p, Property.MODBUS_ID, "modbus1"); + + var components = Lists.newArrayList(// + new EdgeConfig.Component(meterId, alias, "Meter.KDK.2PUCT", // + JsonUtils.buildJsonObject() // + .addProperty("modbus.id", modbusId) // + .addProperty("modbusUnitId", modbusUnitId) // + .addProperty("type", type) // + .build()) // + ); + + 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.buildSelect(Property.TYPE) // + .setLabel(TranslationUtil.getTranslation(bundle, "App.Meter.mountType.label")) // + .setOptions(this.buildMeterOptions(language)) // + .setDefaultValue("PRODUCTION") // + .build()) // + .add(JsonFormlyUtil.buildSelect(Property.MODBUS_ID) // + .setLabel(TranslationUtil.getTranslation(bundle, "modbusId")) // + .setDescription(TranslationUtil.getTranslation(bundle, "modbusId.description")) // + .setOptions(this.componentUtil.getEnabledComponentsOfStartingId("modbus"), + JsonFormlyUtil.SelectBuilder.DEFAULT_COMPONENT_2_LABEL, + JsonFormlyUtil.SelectBuilder.DEFAULT_COMPONENT_2_VALUE) // + .isRequired(true) // + .build()) // + .add(JsonFormlyUtil.buildInput(Property.MODBUS_UNIT_ID) // + .setLabel(TranslationUtil.getTranslation(bundle, "modbusUnitId")) // + .setDescription( + TranslationUtil.getTranslation(bundle, "App.Meter.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 getPropertyClass() { + return Property.class; + } + + @Override + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.MULTIPLE; + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/meter/SocomecMeter.java b/io.openems.edge.core/src/io/openems/edge/app/meter/SocomecMeter.java index b052b776c9e..50221ded6f2 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/meter/SocomecMeter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/meter/SocomecMeter.java @@ -27,6 +27,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.TranslationUtil; @@ -55,7 +56,7 @@ @Component(name = "App.Meter.Socomec") public class SocomecMeter extends AbstractMeterApp implements OpenemsApp { - public enum Property { + public enum Property implements Nameable { // Component-IDs METER_ID, // // Properties @@ -115,7 +116,8 @@ public AppAssistant getAppAssistant(Language language) { .build()) // .add(JsonFormlyUtil.buildInput(Property.MODBUS_UNIT_ID) // .setLabel(TranslationUtil.getTranslation(bundle, "modbusUnitId")) // - .setDescription(TranslationUtil.getTranslation(bundle, "modbusUnitId.description")) // + .setDescription( + TranslationUtil.getTranslation(bundle, "App.Meter.modbusUnitId.description")) // .setInputType(Type.NUMBER) // .setDefaultValue(6) // .setMin(0) // diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/AbstractPvInverter.java b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/AbstractPvInverter.java index 7059d5fa8d1..d3655517073 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/AbstractPvInverter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/AbstractPvInverter.java @@ -13,16 +13,19 @@ 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.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.ComponentUtil; import io.openems.edge.core.appmanager.JsonFormlyUtil; import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder; import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Type; import io.openems.edge.core.appmanager.JsonFormlyUtil.InputBuilder.Validation; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsAppCategory; import io.openems.edge.core.appmanager.TranslationUtil; -public abstract class AbstractPvInverter> extends AbstractOpenemsApp { +public abstract class AbstractPvInverter & Nameable> + extends AbstractEnumOpenemsApp { protected AbstractPvInverter(ComponentManager componentManager, ComponentContext componentContext, ConfigurationAdmin cm, ComponentUtil componentUtil) { @@ -30,7 +33,7 @@ protected AbstractPvInverter(ComponentManager componentManager, ComponentContext } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.PV_INVERTER }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/CommonPvInverterConfiguration.java b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/CommonPvInverterConfiguration.java new file mode 100644 index 00000000000..08eab927ed6 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/CommonPvInverterConfiguration.java @@ -0,0 +1,115 @@ +package io.openems.edge.app.pvinverter; + +import java.util.List; +import java.util.function.Consumer; + +import com.google.common.collect.Lists; + +import io.openems.common.types.EdgeConfig; +import io.openems.common.types.EdgeConfig.Component; +import io.openems.common.utils.JsonUtils; +import io.openems.common.utils.JsonUtils.JsonObjectBuilder; +import io.openems.edge.core.appmanager.AppDef; +import io.openems.edge.core.appmanager.JsonFormlyUtil; +import io.openems.edge.core.appmanager.Nameable; +import io.openems.edge.core.appmanager.OpenemsApp; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; + +public final class CommonPvInverterConfiguration { + + private CommonPvInverterConfiguration() { + } + + private static final AppDef defaultDef() { + return AppDef.of() // + .setTranslationBundleSupplier(BundleParameter::getBundle); + } + + /** + * Creates a {@link AppDef} for a PV-Inverter ip-address. + * + * @return the {@link AppDef} + */ + public static final AppDef ip() { + return defaultDef() // + .setTranslatedLabel("ipAddress") // + .setTranslatedDescription("App.PvInverter.ip.description") // + .setDefaultValue("192.168.178.85") // + .setField(JsonFormlyUtil::buildInputFromNameable, (app, prop, l, param, f) -> // + f.isRequired(true) // + .setValidation(JsonFormlyUtil.InputBuilder.Validation.IP)); + } + + /** + * Creates a {@link AppDef} for a PV-Inverter port. + * + * @return the {@link AppDef} + */ + public static final AppDef port() { + return defaultDef() // + .setTranslatedLabel("port") // + .setTranslatedDescription("App.PvInverter.port.description") // + .setDefaultValue(502) // + .setField(JsonFormlyUtil::buildInputFromNameable, (app, prop, l, param, f) -> // + f.setInputType(JsonFormlyUtil.InputBuilder.Type.NUMBER) // + .setMin(0)); + } + + /** + * Creates a {@link AppDef} for a PV-Inverter modbusUnitId. + * + * @return the {@link AppDef} + */ + public static final AppDef modbusUnitId() { + return defaultDef() // + .setTranslatedLabel("modbusUnitId") // + .setTranslatedDescription("App.PvInverter.modbusUnitId.description") // + .setField(JsonFormlyUtil::buildInputFromNameable, (app, prop, l, param, f) -> // + f.setInputType(JsonFormlyUtil.InputBuilder.Type.NUMBER) // + .setMin(0)); + } + + /** + * Creates the commonly used components for a PV-Inverter. + * + * @param factoryId the factoryId of the PV-Inverter + * @param pvInverterId the id of the PV-Inverter + * @param modbusId the id of the modbus component + * @param alias the alias of the inverter + * @param ip the ip of the modbus connection + * @param port the port of the modbus connection + * @param additionalInverterProperties consumer for additional configuration for + * the inverter + * @param additionalBridgeProperties consumer for additional configuration for + * the modbus component + * @return the components + */ + public static final List getComponents(// + final String factoryId, // + final String pvInverterId, // + final String modbusId, // + final String alias, // + final String ip, // + final int port, // + final Consumer additionalInverterProperties, // + final Consumer additionalBridgeProperties // + ) { + final var inverterProperties = JsonUtils.buildJsonObject() // + .addProperty("modbus.id", modbusId); + if (additionalInverterProperties != null) { + additionalInverterProperties.accept(inverterProperties); + } + final var bridgeProperties = JsonUtils.buildJsonObject() // + .addProperty("ip", ip) // + .addProperty("port", port); + if (additionalBridgeProperties != null) { + additionalBridgeProperties.accept(bridgeProperties); + } + + return Lists.newArrayList(// + new EdgeConfig.Component(pvInverterId, alias, factoryId, inverterProperties.build()), // + new EdgeConfig.Component(modbusId, alias, "Bridge.Modbus.Tcp", bridgeProperties.build())// + ); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/FroniusPvInverter.java b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/FroniusPvInverter.java index 3bc98610f9b..9da6347aa4a 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/FroniusPvInverter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/FroniusPvInverter.java @@ -23,6 +23,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; @@ -51,7 +52,7 @@ @org.osgi.service.component.annotations.Component(name = "App.PvInverter.Fronius") public class FroniusPvInverter extends AbstractPvInverter implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs PV_INVERTER_ID, // MODBUS_ID, // diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/KacoPvInverter.java b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/KacoPvInverter.java index ff046481150..4285103ef76 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/KacoPvInverter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/KacoPvInverter.java @@ -21,6 +21,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; @@ -48,7 +49,7 @@ @org.osgi.service.component.annotations.Component(name = "App.PvInverter.Kaco") public class KacoPvInverter extends AbstractPvInverter implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs PV_INVERTER_ID, // MODBUS_ID, // diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/KostalPvInverter.java b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/KostalPvInverter.java index e9f237ec223..c8d4f79bf2b 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/KostalPvInverter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/KostalPvInverter.java @@ -23,6 +23,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; @@ -51,7 +52,7 @@ @org.osgi.service.component.annotations.Component(name = "App.PvInverter.Kostal") public class KostalPvInverter extends AbstractPvInverter implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs PV_INVERTER_ID, // MODBUS_ID, // diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/SmaPvInverter.java b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/SmaPvInverter.java index 6a9180f7ee2..58f9f37a4c8 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/SmaPvInverter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/SmaPvInverter.java @@ -1,6 +1,7 @@ package io.openems.edge.app.pvinverter; -import java.util.EnumMap; +import java.util.Map; +import java.util.function.Function; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentContext; @@ -8,23 +9,29 @@ 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.enums.OptionsFactory; +import io.openems.edge.app.enums.Phase; import io.openems.edge.app.pvinverter.SmaPvInverter.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.AbstractOpenemsAppWithProps; import io.openems.edge.core.appmanager.AppConfiguration; +import io.openems.edge.core.appmanager.AppDef; 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; +import io.openems.edge.core.appmanager.OpenemsAppCategory; +import io.openems.edge.core.appmanager.Type; +import io.openems.edge.core.appmanager.Type.Parameter; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; /** * Describes a App for SMA PV-Inverter. @@ -49,18 +56,60 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.PvInverter.Sma") -public class SmaPvInverter extends AbstractPvInverter implements OpenemsApp { +public class SmaPvInverter extends AbstractOpenemsAppWithProps + implements OpenemsApp { - public static enum Property { + public static enum Property implements Type, Nameable { // Component-IDs - PV_INVERTER_ID, // - MODBUS_ID, // + PV_INVERTER_ID(AppDef.of(SmaPvInverter.class) // + .setDefaultValue("pvInverter0")), // + MODBUS_ID(AppDef.of(SmaPvInverter.class) // + .setDefaultValue("modbus0")), // // Properties - ALIAS, // - IP, // - PORT, // - MODBUS_UNIT_ID // - ; + ALIAS(AppDef.of(SmaPvInverter.class) // + .setDefaultValueToAppName()), // + IP(AppDef.copyOf(Property.class, CommonPvInverterConfiguration.ip()) // + .wrapField((app, property, l, parameter, field) -> { + field.isRequired(true); + })), // + PORT(AppDef.copyOf(Property.class, CommonPvInverterConfiguration.port()) // + .wrapField((app, property, l, parameter, field) -> { + field.isRequired(true); + })), // + MODBUS_UNIT_ID(AppDef.copyOf(Property.class, CommonPvInverterConfiguration.modbusUnitId()) // + .setTranslatedDescriptionWithAppPrefix(".modbusUnitId.description") // + .wrapField((app, property, l, parameter, field) -> { + field.isRequired(true); + })), // + PHASE(AppDef.of(SmaPvInverter.class) // + .setTranslatedLabelWithAppPrefix(".phase.label") // ) + .setTranslatedDescriptionWithAppPrefix(".phase.description") // + .setDefaultValue(Phase.ALL.name()) // + .bidirectional(PV_INVERTER_ID, "phase", a -> a.componentManager) // + .setField(JsonFormlyUtil::buildSelect, (app, property, l, parameter, field) -> // + field.setOptions(OptionsFactory.of(Phase.class), l) // + .isRequired(true))); + + private final AppDef def; + + private Property(AppDef def) { + this.def = def; + } + + @Override + public Property self() { + return this; + } + + @Override + public AppDef def() { + return this.def; + } + + @Override + public Function, BundleParameter> getParamter() { + return Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } } @Activate @@ -70,55 +119,51 @@ public SmaPvInverter(@Reference ComponentManager componentManager, ComponentCont } @Override - protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() { + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { 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.SMA.SunnyTripower"; - var components = this.getComponents(factoryIdInverter, pvInverterId, modbusId, alias, ip, port); - var inverter = AbstractOpenemsApp.getComponentWithFactoryId(components, factoryIdInverter); - inverter.getProperties().put("modbusUnitId", new JsonPrimitive(modbusUnitId)); - + final var alias = this.getString(p, l, Property.ALIAS); + final var ip = this.getString(p, l, Property.IP); + final var port = this.getInt(p, Property.PORT); + final var modbusUnitId = this.getInt(p, Property.MODBUS_UNIT_ID); + final var phase = this.getEnum(p, Phase.class, Property.PHASE); + + final var modbusId = this.getId(t, p, Property.MODBUS_ID); + final var pvInverterId = this.getId(t, p, Property.PV_INVERTER_ID); + + final var factoryIdInverter = "PV-Inverter.SMA.SunnyTripower"; + final var components = CommonPvInverterConfiguration.getComponents(// + factoryIdInverter, pvInverterId, modbusId, alias, ip, port, + b -> b.addProperty("modbusUnitId", modbusUnitId) // + .addProperty("phase", phase), + null); return new AppConfiguration(components); }; } @Override - public AppAssistant getAppAssistant(Language language) { - return AppAssistant.create(this.getName(language)) // - .fields(JsonUtils.buildJsonArray() // - .add(AbstractPvInverter.buildIp(language, Property.IP) // - .build()) // - .add(AbstractPvInverter.buildPort(language, Property.PORT) // - .build()) // - .add(AbstractPvInverter.buildModbusUnitId(language, Property.MODBUS_UNIT_ID) // - .setDefaultValue(126) // - .build()) // - .build()) + public AppDescriptor getAppDescriptor() { + return AppDescriptor.create() // .build(); } @Override - public AppDescriptor getAppDescriptor() { - return AppDescriptor.create() // - .build(); + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.MULTIPLE; } @Override - protected Class getPropertyClass() { - return Property.class; + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.PV_INVERTER }; } @Override - public OpenemsAppCardinality getCardinality() { - return OpenemsAppCardinality.MULTIPLE; + protected SmaPvInverter getApp() { + return this; + } + + @Override + protected Property[] propertyValues() { + return Property.values(); } } diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/SolarEdgePvInverter.java b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/SolarEdgePvInverter.java index 6b38882e3e7..7134987434b 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/pvinverter/SolarEdgePvInverter.java +++ b/io.openems.edge.core/src/io/openems/edge/app/pvinverter/SolarEdgePvInverter.java @@ -21,6 +21,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; @@ -48,7 +49,7 @@ @org.osgi.service.component.annotations.Component(name = "App.PvInverter.SolarEdge") public class SolarEdgePvInverter extends AbstractPvInverter implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs PV_INVERTER_ID, // MODBUS_ID, // diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvselfconsumption/GridOptimizedCharge.java b/io.openems.edge.core/src/io/openems/edge/app/pvselfconsumption/GridOptimizedCharge.java index 70291aa77a4..d1a82b76cf5 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/pvselfconsumption/GridOptimizedCharge.java +++ b/io.openems.edge.core/src/io/openems/edge/app/pvselfconsumption/GridOptimizedCharge.java @@ -1,6 +1,10 @@ package io.openems.edge.app.pvselfconsumption; import java.util.EnumMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.ResourceBundle; +import java.util.Set; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentContext; @@ -8,6 +12,7 @@ import org.osgi.service.component.annotations.Reference; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.google.gson.JsonElement; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; @@ -18,6 +23,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.pvselfconsumption.GridOptimizedCharge.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -26,6 +32,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -52,9 +59,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.PvSelfConsumption.GridOptimizedCharge") -public class GridOptimizedCharge extends AbstractOpenemsApp implements OpenemsApp { +public class GridOptimizedCharge extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs CTRL_GRID_OPTIMIZED_CHARGE_ID, // Properties @@ -119,8 +126,6 @@ public AppAssistant getAppAssistant(Language language) { .add(JsonFormlyUtil.buildCheckbox(Property.SELL_TO_GRID_LIMIT_ENABLED) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".sellToGridLimitEnabled.label")) // - .setDescription(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".sellToGridLimitEnabled.description")) // .build()) .add(JsonFormlyUtil.buildInput(Property.MAXIMUM_SELL_TO_GRID_POWER) // .setInputType(Type.NUMBER) // @@ -129,18 +134,29 @@ public AppAssistant getAppAssistant(Language language) { .onlyShowIfChecked(Property.SELL_TO_GRID_LIMIT_ENABLED) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".maximumSellToGridPower.label")) // - .setDescription(TranslationUtil.getTranslation(bundle, - this.getAppId() + ".maximumSellToGridPower.description")) // .build()) .add(JsonFormlyUtil.buildSelect(Property.MODE) // .setLabel(TranslationUtil.getTranslation(bundle, this.getAppId() + ".mode.label")) // - .setOptions(Lists.newArrayList("OFF", "AUTOMATIC", "MANUAL")) // + .setOptions(getModeOptions(bundle)) // .setDefaultValue("AUTOMATIC") // .build()) .build()) .build(); } + @SuppressWarnings("unchecked") + private static final Set> getModeOptions(ResourceBundle bundle) { + return Sets.newHashSet(// + Map.entry(TranslationUtil.getTranslation(bundle, "App.PvSelfConsumption.GridOptimizedCharge.mode.off"), + "OFF"), // + Map.entry(TranslationUtil.getTranslation(bundle, + "App.PvSelfConsumption.GridOptimizedCharge.mode.automatic"), "AUTOMATIC"), // + Map.entry( + TranslationUtil.getTranslation(bundle, "App.PvSelfConsumption.GridOptimizedCharge.mode.manual"), + "MANUAL") // + ); + } + @Override public AppDescriptor getAppDescriptor() { return AppDescriptor.create() // @@ -148,7 +164,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.PV_SELF_CONSUMPTION }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/pvselfconsumption/SelfConsumptionOptimization.java b/io.openems.edge.core/src/io/openems/edge/app/pvselfconsumption/SelfConsumptionOptimization.java index a62c8e320e5..53a4f17c87e 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/pvselfconsumption/SelfConsumptionOptimization.java +++ b/io.openems.edge.core/src/io/openems/edge/app/pvselfconsumption/SelfConsumptionOptimization.java @@ -18,6 +18,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.pvselfconsumption.SelfConsumptionOptimization.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -25,6 +26,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -52,9 +54,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.PvSelfConsumption.SelfConsumptionOptimization") -public class SelfConsumptionOptimization extends AbstractOpenemsApp implements OpenemsApp { +public class SelfConsumptionOptimization extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs METER_ID, // // Properties @@ -123,12 +125,11 @@ public AppAssistant getAppAssistant(Language language) { @Override public AppDescriptor getAppDescriptor() { return AppDescriptor.create() // - .setWebsiteUrl("https://fenecon.de/fems-2-2/fems-app-eigenverbrauchsoptimierung-2/") // .build(); } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.PV_SELF_CONSUMPTION }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/AwattarHourly.java b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/AwattarHourly.java index f6ce848f219..a459419a67a 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/AwattarHourly.java +++ b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/AwattarHourly.java @@ -17,12 +17,13 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.timeofusetariff.AwattarHourly.Property; import io.openems.edge.common.component.ComponentManager; -import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -47,9 +48,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.TimeOfUseTariff.Awattar") -public class AwattarHourly extends AbstractOpenemsApp implements OpenemsApp { +public class AwattarHourly extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs CTRL_ESS_TIME_OF_USE_TARIF_DISCHARGE_ID, // TIME_OF_USE_TARIF_ID, // @@ -102,7 +103,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.TIME_OF_USE_TARIFF }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/StromdaoCorrently.java b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/StromdaoCorrently.java index cfd28f4f6f6..1ab0f1a6824 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/StromdaoCorrently.java +++ b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/StromdaoCorrently.java @@ -18,6 +18,7 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.timeofusetariff.StromdaoCorrently.Property; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; import io.openems.edge.core.appmanager.AbstractOpenemsApp; import io.openems.edge.core.appmanager.AppAssistant; import io.openems.edge.core.appmanager.AppConfiguration; @@ -25,6 +26,7 @@ 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -51,9 +53,9 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.TimeOfUseTariff.Stromdao") -public class StromdaoCorrently extends AbstractOpenemsApp implements OpenemsApp { +public class StromdaoCorrently extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { // Component-IDs CTRL_ESS_TIME_OF_USE_TARIF_DISCHARGE_ID, // TIME_OF_USE_TARIF_ID, // @@ -116,7 +118,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.TIME_OF_USE_TARIFF }; } diff --git a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/Tibber.java b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/Tibber.java index 17430cab2a1..b06e4691fea 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/Tibber.java +++ b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/Tibber.java @@ -1,6 +1,7 @@ package io.openems.edge.app.timeofusetariff; -import java.util.EnumMap; +import java.util.Map; +import java.util.function.Function; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentContext; @@ -19,17 +20,19 @@ import io.openems.edge.app.timeofusetariff.Tibber.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.AbstractOpenemsAppWithProps; import io.openems.edge.core.appmanager.AppConfiguration; +import io.openems.edge.core.appmanager.AppDef; 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; +import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; -import io.openems.edge.core.appmanager.TranslationUtil; +import io.openems.edge.core.appmanager.Type; /** * Describes a App for Tibber. @@ -52,13 +55,48 @@ * */ @org.osgi.service.component.annotations.Component(name = "App.TimeOfUseTariff.Tibber") -public class Tibber extends AbstractOpenemsApp implements OpenemsApp { - - public static enum Property { - ALIAS, // - CTRL_ESS_TIME_OF_USE_TARIF_DISCHARGE_ID, // - TIME_OF_USE_TARIF_ID, // - ACCESS_TOKEN; +public class Tibber extends AbstractOpenemsAppWithProps + implements OpenemsApp { + + public static enum Property implements Type, Nameable { + // Components + CTRL_ESS_TIME_OF_USE_TARIF_DISCHARGE_ID(AppDef.of(Tibber.class) // + .setDefaultValue("ctrlEssTimeOfUseTariffDischarge0")), // + TIME_OF_USE_TARIF_ID(AppDef.of(Tibber.class) // + .setDefaultValue("timeOfUseTariff0")), // + + // Properties + ALIAS(AppDef.of(Tibber.class) // + .setDefaultValueToAppName()), + ACCESS_TOKEN(AppDef.of(Tibber.class) // + .setTranslatedLabelWithAppPrefix(".accessToken.label") // + .setTranslatedDescriptionWithAppPrefix(".accessToken.description") // + .setField(JsonFormlyUtil::buildInput, (app, prop, l, params, f) -> // + f.setInputType(InputBuilder.Type.PASSWORD) // + .isRequired(true)) // + .setAllowedToSave(false)), // + ; + + private final AppDef def; + + private Property(AppDef def) { + this.def = def; + } + + @Override + public Property self() { + return this; + } + + @Override + public AppDef def() { + return this.def; + } + + @Override + public Function, Type.Parameter.BundleParameter> getParamter() { + return Type.Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } } @@ -69,13 +107,8 @@ public Tibber(@Reference ComponentManager componentManager, ComponentContext con } @Override - protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() { + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { return (t, p, l) -> { - if (t == ConfigurationTarget.DELETE_NOT_SAVED_PROPERTIES) { - p.remove(Property.ACCESS_TOKEN); - return new AppConfiguration(); - } - final var alias = this.getValueOrDefault(p, Property.ALIAS, this.getName(l)); final var accessToken = this.getValueOrDefault(p, Property.ACCESS_TOKEN, null); @@ -103,23 +136,6 @@ protected ThrowingTriFunction getPropertyClass() { - return Property.class; + protected Property[] propertyValues() { + return Property.values(); } @Override @@ -141,4 +157,9 @@ public OpenemsAppCardinality getCardinality() { return OpenemsAppCardinality.SINGLE_IN_CATEGORY; } + @Override + protected Tibber getApp() { + return this; + } + } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractEnumOpenemsApp.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractEnumOpenemsApp.java new file mode 100644 index 00000000000..c48c699ed4a --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractEnumOpenemsApp.java @@ -0,0 +1,80 @@ +package io.openems.edge.core.appmanager; + +import java.util.EnumMap; +import java.util.Map; + +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; + +import com.google.gson.JsonElement; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.function.ThrowingTriFunction; +import io.openems.common.session.Language; +import io.openems.edge.common.component.ComponentManager; + +public abstract class AbstractEnumOpenemsApp & Nameable> + extends AbstractOpenemsApp { + + protected AbstractEnumOpenemsApp(ComponentManager componentManager, ComponentContext componentContext, + ConfigurationAdmin cm, ComponentUtil componentUtil) { + super(componentManager, componentContext, cm, componentUtil); + } + + protected abstract ThrowingTriFunction, // + Language, // + AppConfiguration, // + OpenemsNamedException> appConfigurationFactory(); + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { + return (t, m, l) -> { + final var map = new EnumMap(this.getPropertyClass()); + m.forEach((k, v) -> map.put(k, v)); + return this.appConfigurationFactory().apply(t, map, l); + }; + } + + @Override + protected PROPERTY[] propertyValues() { + return this.getPropertyClass().getEnumConstants(); + } + + /** + * Gets the id of the map with the given DefaultEnum + * + *

      + * e. g. defaultValue: "ess0" => the next available id with the base-name "ess" + * and the the next available number + * + * @param t the configuration target + * @param map the configuration map + * @param key the key to be searched for + * @return the found id + */ + protected String getId(ConfigurationTarget t, Map map, DefaultEnum key) { + try { + return this.getId(t, map, Enum.valueOf(this.getPropertyClass(), key.name()), key.getDefaultValue()); + } catch (IllegalArgumentException ex) { + // not a enum of property + } + return key.getDefaultValue(); + } + + /** + * Gets the value of the property name in the map or the defaulValue if the + * property was not found. + * + * @param map the configuration map + * @param property the property to be searched for + * @return the String value + */ + protected String getValueOrDefault(EnumMap map, DefaultEnum property) { + var key = Enum.valueOf(this.getPropertyClass(), property.name()); + return this.getValueOrDefault(map, key, property.getDefaultValue()); + } + + protected abstract Class getPropertyClass(); + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractOpenemsApp.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractOpenemsApp.java index be48d0f6f45..d8b16af6224 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractOpenemsApp.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractOpenemsApp.java @@ -3,21 +3,22 @@ import java.io.IOException; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.Base64; -import java.util.EnumMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.ResourceBundle; import java.util.TreeMap; +import java.util.function.Function; import java.util.stream.Collectors; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentConstants; import org.osgi.service.component.ComponentContext; +import com.google.common.collect.ImmutableMap; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -37,7 +38,8 @@ import io.openems.edge.core.appmanager.validator.Checkable; import io.openems.edge.core.appmanager.validator.ValidatorConfig; -public abstract class AbstractOpenemsApp> implements OpenemsApp { +public abstract class AbstractOpenemsApp // + implements OpenemsApp { protected final ComponentManager componentManager; protected final ConfigurationAdmin cm; @@ -56,16 +58,15 @@ protected AbstractOpenemsApp(ComponentManager componentManager, ComponentContext * Provides a factory for {@link AppConfiguration AppConfigurations}. * * @return a {@link ThrowingFunction} that creates a {@link AppConfiguration} - * from a {@link EnumMap} of configuration properties for a given + * from a {@link Map} of configuration properties for a given * {@link ConfigurationTarget} in the specified language. */ protected abstract ThrowingTriFunction, // configuration properties - Language, // the language - AppConfiguration, // return value of the function - OpenemsNamedException> // Exception on error - appConfigurationFactory(); + ConfigurationTarget, // + Map, // + Language, // + AppConfiguration, // + OpenemsNamedException> appPropertyConfigurationFactory(); protected final void assertCheckables(ConfigurationTarget t, Checkable... checkables) throws OpenemsNamedException { if (t != ConfigurationTarget.ADD && t != ConfigurationTarget.UPDATE) { @@ -92,9 +93,9 @@ protected final void assertCheckables(ConfigurationTarget t, Checkable... checka * @return the {@link AppConfiguration} or null */ private AppConfiguration configuration(ArrayList errors, ConfigurationTarget configurationTarget, - Language language, EnumMap properties) { + Language language, Map properties) { try { - return this.appConfigurationFactory().apply(configurationTarget, properties, language); + return this.appPropertyConfigurationFactory().apply(configurationTarget, properties, language); } catch (OpenemsNamedException e) { errors.add(e.getMessage()); return null; @@ -102,71 +103,49 @@ private AppConfiguration configuration(ArrayList errors, ConfigurationTa } /** - * Convert JsonObject with Properties to EnumMap. + * Convert JsonObject with Properties to Map. * * @param errors a collection of validation errors * @param properties the configured App properties - * @return a typed {@link EnumMap} of Properties + * @return a typed {@link Map} of Properties */ - private EnumMap convertToEnumMap(ArrayList errors, JsonObject properties) { - var clazz = this.getPropertyClass(); - var result = new EnumMap(clazz); - var unknownProperties = new ArrayList(); - for (Entry entry : properties.entrySet()) { - final PROPERTY key; - try { - key = Enum.valueOf(clazz, entry.getKey()); - } catch (IllegalArgumentException e) { - // ignore ALIAS if passed but not used - if (!entry.getKey().equals("ALIAS")) { - unknownProperties.add(entry.getKey()); + private Map convertToMap(List errors, JsonObject properties) { + final var nameableByName = Arrays.stream(this.propertyValues()) // + .collect(Collectors.toMap(t -> t.name(), Function.identity())); + final var resultMap = ImmutableMap.builder(); + final var unknownProperties = new ArrayList(); + for (var entry : properties.entrySet()) { + final var name = entry.getKey(); + if (!nameableByName.containsKey(name)) { + if ("ALIAS".equals(name)) { + // ignore alias if passed but not used + continue; } + unknownProperties.add(entry.getKey()); continue; } - result.put(key, entry.getValue()); + // TODO maybe type validation of value + resultMap.put(nameableByName.get(entry.getKey()), entry.getValue()); } if (!unknownProperties.isEmpty()) { errors.add("Unknown Configuration Propert" // + (unknownProperties.size() > 1 ? "ies" : "y") + ":" // + unknownProperties.stream().collect(Collectors.joining(","))); } - return result; + return resultMap.build(); } @Override public AppConfiguration getAppConfiguration(ConfigurationTarget target, JsonObject config, Language language) throws OpenemsNamedException { var errors = new ArrayList(); - var enumMap = this.convertToEnumMap(target != ConfigurationTarget.TEST ? errors : new ArrayList<>(), config); - var c = this.configuration(errors, target, language, enumMap); - - // TODO remove and maybe add @AttributeDefinition above enums - // this is for removing passwords so they do not get saved - if (config.size() != enumMap.size()) { - // remove entries that got removed - var toRemoveKeys = new LinkedList(); - for (var configEntry : config.entrySet()) { - var key = configEntry.getKey(); - var contains = false; - for (var entry : enumMap.entrySet()) { - if (entry.getKey().name().equals(key)) { - contains = true; - break; - } - } - if (!contains) { - toRemoveKeys.add(key); - } - } - for (var key : toRemoveKeys) { - config.remove(key); - } - } + var enumMap = this.convertToMap(target != ConfigurationTarget.TEST ? errors : new ArrayList<>(), config); + var configuration = this.configuration(errors, target, language, enumMap); if (!errors.isEmpty()) { throw new OpenemsException(errors.stream().collect(Collectors.joining("|"))); } - return c; + return configuration; } @Override @@ -174,27 +153,6 @@ public String getAppId() { return this.componentContext.getProperties().get(ComponentConstants.COMPONENT_NAME).toString(); } - /** - * Gets the id of the map with the given DefaultEnum - * - *

      - * e. g. defaultValue: "ess0" => the next available id with the base-name "ess" - * and the the next available number - * - * @param t the configuration target - * @param map the configuration map - * @param key the key to be searched for - * @return the found id - */ - protected String getId(ConfigurationTarget t, EnumMap map, DefaultEnum key) { - try { - return this.getId(t, map, Enum.valueOf(this.getPropertyClass(), key.name()), key.getDefaultValue()); - } catch (IllegalArgumentException ex) { - // not a enum of property - } - return key.getDefaultValue(); - } - /** * Gets the id of the map with the given default id * @@ -208,18 +166,15 @@ protected String getId(ConfigurationTarget t, EnumMap map * @param defaultId the defaultId to be used * @return the found id */ - protected String getId(ConfigurationTarget t, EnumMap map, PROPERTY p, String defaultId) { + protected String getId(ConfigurationTarget t, Map map, PROPERTY p, String defaultId) { if (t == ConfigurationTarget.TEST) { - if (map.containsKey(p)) { - return map.get(p).getAsString() + p.name() + ":" + defaultId; - } - return p.name(); + return JsonUtils.getAsOptionalString(map.get(p)) // + .map(id -> id + p.name() + ":" + defaultId) // + .orElse(p.name()); } return this.getValueOrDefault(map, p, defaultId); } - protected abstract Class getPropertyClass(); - /** * Validate the App configuration. * @@ -227,10 +182,10 @@ protected String getId(ConfigurationTarget t, EnumMap map * @param dependecies the dependencies of the current instance * @return a list of validation errors. Empty list says 'no errors' */ - private List getValidationErrors(JsonObject jProperties, List dependecies) { + protected List getValidationErrors(JsonObject jProperties, List dependecies) { final var errors = new ArrayList(); - final var properties = this.convertToEnumMap(errors, jProperties); + final var properties = this.convertToMap(errors, jProperties); final var appConfiguration = this.configuration(errors, ConfigurationTarget.VALIDATE, null, properties); if (appConfiguration == null) { return errors; @@ -276,19 +231,6 @@ protected ValidatorConfig.Builder getValidateBuilder() { return ValidatorConfig.create(); } - /** - * Gets the value of the property name in the map or the defaulValue if the - * property was not found. - * - * @param map the configuration map - * @param property the property to be searched for - * @return the String value - */ - protected String getValueOrDefault(EnumMap map, DefaultEnum property) { - var key = Enum.valueOf(this.getPropertyClass(), property.name()); - return this.getValueOrDefault(map, key, property.getDefaultValue()); - } - /** * Gets the value of the property in the map or the defaulValue if the property * was not found. @@ -298,7 +240,7 @@ protected String getValueOrDefault(EnumMap map, DefaultEn * @param defaultValue the default value * @return the String value */ - protected String getValueOrDefault(EnumMap map, PROPERTY property, String defaultValue) { + protected String getValueOrDefault(Map map, PROPERTY property, String defaultValue) { var element = map.get(property); if (element != null) { return JsonUtils.getAsOptionalString(element).orElse(defaultValue); @@ -313,13 +255,8 @@ protected String getValueOrDefault(EnumMap map, PROPERTY * @return true if it is included else false */ public boolean hasProperty(String property) { - try { - Enum.valueOf(this.getPropertyClass(), property); - return true; - } catch (IllegalArgumentException ex) { - // property not an enum property - } - return false; + return Arrays.stream(this.propertyValues()) // + .anyMatch(t -> t.name().equals(property)); } /** @@ -335,7 +272,7 @@ public boolean hasProperty(String property) { */ protected ThrowingBiFunction, // configuration properties + Map, // configuration properties Map>, // return value of the function OpenemsNamedException> // Exception on error installationValidation() { @@ -360,18 +297,18 @@ public void validate(OpenemsAppInstance instance) throws OpenemsNamedException { */ private void validateComponentConfigurations(ArrayList errors, EdgeConfig actualEdgeConfig, AppConfiguration expectedAppConfiguration) { - var missingComponents = new ArrayList(); - for (Component expectedComponent : expectedAppConfiguration.components) { + var missingComponents = new ArrayList(); + for (var expectedComponent : expectedAppConfiguration.components) { var componentId = expectedComponent.getId(); // Get Actual Component Configuration Component actualComponent; - try { - - actualComponent = actualEdgeConfig.getComponentOrError(componentId); - } catch (OpenemsNamedException e) { - missingComponents.add(componentId); + var tempFoundComponent = actualEdgeConfig.getComponent(componentId); + if (tempFoundComponent.isEmpty()) { + missingComponents.add(expectedComponent); continue; + } else { + actualComponent = tempFoundComponent.get(); } // ALIAS should not be validated because it can be different depending on the // language @@ -381,7 +318,9 @@ private void validateComponentConfigurations(ArrayList errors, EdgeConfi if (!missingComponents.isEmpty()) { errors.add("Missing Component" // + (missingComponents.size() > 1 ? "s" : "") + ":" // - + missingComponents.stream().collect(Collectors.joining(","))); + + missingComponents.stream() // + .map(c -> c.getId() + "[" + c.getFactoryId() + "]") // + .collect(Collectors.joining(","))); } } @@ -567,6 +506,11 @@ private static final void checkProperties(List errors, JsonObject actual } } + @Override + public OpenemsAppPermissions getAppPermissions() { + return OpenemsAppPermissions.create().build(); + } + @Override public String getName(Language language) { return AbstractOpenemsApp.getTranslation(language, this.getAppId() + ".Name"); @@ -582,11 +526,30 @@ public String getImage() { return OpenemsApp.FALLBACK_IMAGE; } + @Override + public OpenemsAppPropertyDefinition[] getProperties() { + throw new UnsupportedOperationException(); + } + + protected abstract PROPERTY[] propertyValues(); + + protected final PROPERTY getPropertyByName(String name) { + return Arrays.stream(this.propertyValues()) // + .filter(t -> t.name().equals(name)) // + .findFirst().orElse(null); // + } + protected static String getTranslation(Language language, String key) { return TranslationUtil.getTranslation(getTranslationBundle(language), key); } - protected static ResourceBundle getTranslationBundle(Language language) { + /** + * Gets the {@link ResourceBundle} based on the given {@link Language}. + * + * @param language the {@link Language} of the translations + * @return the {@link ResourceBundle} + */ + public static ResourceBundle getTranslationBundle(Language language) { if (language == null) { language = Language.DEFAULT; } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractOpenemsAppWithProps.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractOpenemsAppWithProps.java new file mode 100644 index 00000000000..cb9de0ec35b --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AbstractOpenemsAppWithProps.java @@ -0,0 +1,304 @@ +package io.openems.edge.core.appmanager; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; + +import com.google.gson.JsonArray; +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.session.Language; +import io.openems.common.utils.JsonUtils; +import io.openems.common.utils.StringUtils; +import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.Type.GetParameterValues; +import io.openems.edge.core.appmanager.dependency.Dependency; + +public abstract class AbstractOpenemsAppWithProps, // + PROPERTY extends Type & Nameable, // + PARAMETER extends Type.Parameter // +> extends AbstractOpenemsApp implements OpenemsApp { + + protected AbstractOpenemsAppWithProps(ComponentManager componentManager, ComponentContext componentContext, + ConfigurationAdmin cm, ComponentUtil componentUtil) { + super(componentManager, componentContext, cm, componentUtil); + } + + protected String getId(ConfigurationTarget target, Map map, PROPERTY property) + throws OpenemsException { + final var parameter = this.singletonParameter(Language.DEFAULT); + var componentId = Optional.ofNullable(property.def().getDefaultValue()) + .map(t -> t.get(this.getApp(), property, Language.DEFAULT, parameter.get()).getAsString()) + .orElseThrow(() -> new OpenemsException( + "No default value set for Property '" + property + "' in app '" + this.getAppId() + "'")); + return super.getId(target, map, property, componentId); + } + + protected JsonElement getValueOrDefault(// + final Map map, // + final Language l, // + final PROPERTY property, // + final Function> mapper) + throws OpenemsNamedException { + if (map.containsKey(property)) { + return map.get(property); + } + final var parameter = this.singletonParameter(l); + final var def = mapper.apply(property); + if (def.getDefaultValue() == null) { + throw OpenemsError.JSON_HAS_NO_MEMBER.exception(property, + StringUtils.toShortString(map.toString(), 100).replace("%", "%%")); + } + return def.getDefaultValue().get(this.getApp(), property, l, parameter.get()); + } + + protected String getString(// + final Map map, // + final Language l, // + final PROPERTY property, // + final Function> mapper // + ) throws OpenemsNamedException { + return JsonUtils.getAsString(this.getValueOrDefault(map, l, property, mapper)); + } + + protected String getString(// + final Map map, // + final Language l, // + final PROPERTY property // + ) throws OpenemsNamedException { + return this.getString(map, l, property, PROPERTY::def); + } + + protected JsonArray getJsonArray(// + final Map map, // + final PROPERTY property // + ) throws OpenemsNamedException { + return JsonUtils.getAsJsonArray(this.getValueOrDefault(map, Language.DEFAULT, property, PROPERTY::def)); + } + + protected int getInt(// + final Map map, // + final PROPERTY property, // + final Function> mapper // + ) throws OpenemsNamedException { + return JsonUtils.getAsInt(this.getValueOrDefault(map, Language.DEFAULT, property, mapper)); + } + + protected int getInt(// + final Map map, // + final PROPERTY property // + ) throws OpenemsNamedException { + return this.getInt(map, property, PROPERTY::def); + } + + protected > E getEnum(// + final Map map, // + final Class enumType, // + final PROPERTY property, // + final Function> mapper // + ) throws OpenemsNamedException { + return JsonUtils.getAsEnum(enumType, this.getValueOrDefault(map, Language.DEFAULT, property, mapper)); + } + + protected > E getEnum(// + final Map map, // + final Class enumType, // + final PROPERTY property // + ) throws OpenemsNamedException { + return this.getEnum(map, enumType, property, PROPERTY::def); + } + + protected boolean getBoolean(// + final Map map, // + final PROPERTY property, // + final Function> mapper // + ) throws OpenemsNamedException { + return JsonUtils.getAsBoolean(this.getValueOrDefault(map, Language.DEFAULT, property, mapper)); + } + + protected boolean getBoolean(// + final Map map, // + final PROPERTY property // + ) throws OpenemsNamedException { + return this.getBoolean(map, property, PROPERTY::def); + } + + @Override + public OpenemsAppPropertyDefinition[] getProperties() { + final var parameter = this.singletonParameter(Language.DEFAULT); + return Arrays.stream(this.propertyValues()) // + .map(t -> { + return new OpenemsAppPropertyDefinition(// + t.name(), // + this.mapDefaultValue(t, parameter.get()), // + t.def().isAllowedToSave(), // + this.mapBidirectionalValue(t, parameter.get()) // + ); + }) // + .toArray(OpenemsAppPropertyDefinition[]::new); + } + + @Override + public AppAssistant getAppAssistant(Language language) { + final var parameter = this.singletonParameter(language); + final var alias = this.getAlias(language, parameter.get()); + return AppAssistant.create(this.getName(language)) // + .onlyIf(alias != null, t -> t.setAlias(alias)) // + .fields(Arrays.stream(this.propertyValues()) // + .filter(p -> p.def().isAutoGenerateField()) // + .filter(p -> p.def().getField() != null) // + .map(p -> p.def().getField().get(this.getApp(), p, language, parameter.get()).build()) // + .collect(JsonUtils.toJsonArray())) // + .build(); + } + + private final String getAlias(Language language, PARAMETER parameter) { + return Arrays.stream(this.propertyValues()) // + .filter(p -> p.name().equals("ALIAS")) // + .findFirst() // + .flatMap(p -> { + return Optional.ofNullable(p.def().getDefaultValue()) // + .map(t -> t.get(this.getApp(), p, language, parameter)) // ; + .flatMap(JsonUtils::getAsOptionalString); + }).orElse(null); + } + + @Override + public AppConfiguration getAppConfiguration(// + final ConfigurationTarget target, // + final JsonObject config, // + final Language language // + ) throws OpenemsNamedException { + return super.getAppConfiguration(// + target, // + this.fillUpProperties(config), // + language // + ); + } + + @Override + protected List getValidationErrors(// + final JsonObject jProperties, // + final List dependecies // + ) { + return super.getValidationErrors(// + this.fillUpProperties(jProperties), // + dependecies // + ); + } + + /** + * Creates a copy of the original configuration and fills up properties which + * are binded bidirectional. + * + *

      + * e. g. a property in a component is the same as one configured in the app so + * it directly gets stored in the component configuration and not twice to avoid + * miss matching errors. + * + * @param original the original configuration + * @return a copy of the original one with the filled up properties + */ + public JsonObject fillUpProperties(// + final JsonObject original // + ) { + final var copy = original.deepCopy(); + for (var prop : this.getProperties()) { + if (copy.has(prop.name)) { + continue; + } + if (prop.bidirectionalValue == null) { + continue; + } + var value = prop.bidirectionalValue.apply(copy); + if (value == null) { + continue; + } + // add value to configuration + copy.add(prop.name, value); + } + return copy; + } + + private Function mapDefaultValue(// + final PROPERTY property, // + final PARAMETER parameter // + ) { + return this.functionMapper(property, AppDef::getDefaultValue, defaultValue -> { + return l -> { + return defaultValue.get(this.getApp(), property, l, parameter); + }; + }); + } + + private Function mapBidirectionalValue(// + final PROPERTY property, // + final PARAMETER parameter // + ) { + return this.functionMapper(property, AppDef::getBidirectionalValue, bidirectionalValue -> { + return config -> { + return bidirectionalValue.apply(this.getApp(), property, // + Language.DEFAULT, parameter, config // + ); + }; + }); + } + + private R functionMapper(// + final PROPERTY property, // + final Function, M> mapper, // + final Function resultMapper // + ) { + final var firstResult = mapper.apply(property.def()); + if (firstResult == null) { + return null; + } + + return resultMapper.apply(firstResult); + } + + private Singleton singletonParameter(Language l) { + var values = this.propertyValues(); + if (values.length == 0) { + return null; + } + return new Singleton<>(() -> values[0].getParamter().apply(new GetParameterValues<>(this.getApp(), l))); + } + + public static final class Singleton { + + private final Supplier objectSupplier; + private T object = null; + + public Singleton(Supplier objectSupplier) { + this.objectSupplier = objectSupplier; + } + + /** + * Gets the value. If the value hasn't been created yet it gets created. + * + * @return the value + */ + public final T get() { + if (this.object == null) { + this.object = this.objectSupplier.get(); + } + return this.object; + } + + } + + protected abstract APP getApp(); + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppAssistant.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppAssistant.java index 3f46f03197f..ce001806fdd 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppAssistant.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppAssistant.java @@ -10,7 +10,7 @@ public class AppAssistant { /** * A temporary builder class for an {@link AppAssistant}. */ - public static class Builder { + public static class Builder implements Self, OnlyIf { private String name; private String alias; @@ -61,6 +61,11 @@ public Builder setAppName(String name) { return this; } + @Override + public Builder self() { + return this; + } + } /** diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppCenterBackendUtil.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppCenterBackendUtil.java new file mode 100644 index 00000000000..426d9e64396 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppCenterBackendUtil.java @@ -0,0 +1,71 @@ +package io.openems.edge.core.appmanager; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.jsonrpc.response.AppCenterGetInstalledAppsResponse.Instance; +import io.openems.common.jsonrpc.response.AppCenterGetPossibleAppsResponse.Bundle; +import io.openems.edge.common.user.User; + +public interface AppCenterBackendUtil { + + /** + * Gets from the backend if the given key can be applied to the given appId. + * + * @param user the executing user + * @param key the key to be validated + * @param appId the id of the {@link OpenemsApp} + * @return true if the key can be applied + */ + public boolean isKeyApplicable(User user, String key, String appId); + + /** + * Adds a install app history entry to the given key. + * + * @param user the executing user + * @param key the key the app should get installed with + * @param appId the app id of the created instance + * @param instanceId the instanceId of the created instance + * @throws OpenemsNamedException on error + */ + public void addInstallAppInstanceHistory(User user, String key, String appId, UUID instanceId) + throws OpenemsNamedException; + + /** + * Adds a deinstall app history entry to the key which installed the instance. + * + * @param user the executing user + * @param appId the app id of the removed instance + * @param instanceId the instanceId of the removed instance + * @return the {@link CompletableFuture} of the request + * @throws OpenemsNamedException on error + */ + public CompletableFuture addDeinstallAppInstanceHistory(User user, String appId, + UUID instanceId) throws OpenemsNamedException; + + /** + * Gets if this edge is connected to the backend. + * + * @return true if this edge is connected to the backend + */ + public boolean isConnected(); + + /** + * Gets the possible apps that can be installed with the given key. + * + * @param key the key that the apps can be installed with + * @return a list of bundles with a list of their apps + */ + public List getPossibleApps(String key); + + /** + * Gets the installed apps that were logged in the backend. + * + * @return the instances that should be installed + */ + public List getInstalledApps() throws OpenemsNamedException; + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppCenterBackendUtilImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppCenterBackendUtilImpl.java new file mode 100644 index 00000000000..e0220bb2b68 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppCenterBackendUtilImpl.java @@ -0,0 +1,137 @@ +package io.openems.edge.core.appmanager; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.base.JsonrpcRequest; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.jsonrpc.request.AppCenterAddDeinstallInstanceHistoryRequest; +import io.openems.common.jsonrpc.request.AppCenterAddInstallInstanceHistoryRequest; +import io.openems.common.jsonrpc.request.AppCenterGetInstalledAppsRequest; +import io.openems.common.jsonrpc.request.AppCenterGetPossibleAppsRequest; +import io.openems.common.jsonrpc.request.AppCenterIsKeyApplicableRequest; +import io.openems.common.jsonrpc.request.AppCenterRequest; +import io.openems.common.jsonrpc.response.AppCenterGetInstalledAppsResponse; +import io.openems.common.jsonrpc.response.AppCenterGetInstalledAppsResponse.Instance; +import io.openems.common.jsonrpc.response.AppCenterGetPossibleAppsResponse; +import io.openems.common.jsonrpc.response.AppCenterGetPossibleAppsResponse.Bundle; +import io.openems.common.jsonrpc.response.AppCenterIsKeyApplicableResponse; +import io.openems.edge.common.user.User; +import io.openems.edge.controller.api.backend.BackendApi; + +@Component +public class AppCenterBackendUtilImpl implements AppCenterBackendUtil { + + @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) + private volatile BackendApi backend; + + @Activate + public AppCenterBackendUtilImpl() { + } + + @Override + public boolean isKeyApplicable(User user, String key, String appId) { + try { + var response = this.handleRequest(user, new AppCenterIsKeyApplicableRequest(key, appId)); + return AppCenterIsKeyApplicableResponse.from(response).isKeyApplicable; + } catch (OpenemsNamedException e) { + return false; + } + } + + @Override + public void addInstallAppInstanceHistory(User user, String key, String appId, UUID instanceId) + throws OpenemsNamedException { + this.handleRequest(user, new AppCenterAddInstallInstanceHistoryRequest(key, // + appId, instanceId, Optional.ofNullable(user).map(u -> u.getId()).orElse(null))); + } + + @Override + public CompletableFuture addDeinstallAppInstanceHistory(User user, String appId, + UUID instanceId) throws OpenemsNamedException { + return this.handleRequestAsync(user, new AppCenterAddDeinstallInstanceHistoryRequest(appId, // + instanceId, Optional.ofNullable(user).map(u -> u.getId()).orElse(null))); + } + + @Override + public List getPossibleApps(String key) { + try { + var response = this.handleRequest(null, new AppCenterGetPossibleAppsRequest(key)); + return AppCenterGetPossibleAppsResponse.from(response).possibleApps; + } catch (OpenemsNamedException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public List getInstalledApps() throws OpenemsNamedException { + var response = this.handleRequest(null, new AppCenterGetInstalledAppsRequest()); + return AppCenterGetInstalledAppsResponse.from(response).installedApps; + } + + @Override + public boolean isConnected() { + if (this.backend == null) { + return false; + } + return this.backend.isConnected(); + } + + private final CompletableFuture handleRequestAsync(User user, + JsonrpcRequest request) throws OpenemsNamedException { + return this.getBackend().handleJsonrpcRequest(user, new AppCenterRequest(request)); + } + + private final JsonrpcResponseSuccess handleRequest(User user, JsonrpcRequest request) throws OpenemsNamedException { + try { + return this.handleRequestAsync(user, request).get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + throw getOpenemsException(e); + } + } + + private final BackendApi getBackend() throws OpenemsNamedException { + if (!this.isConnected()) { + throw new OpenemsException("Backend not connected!"); + } + return this.backend; + } + + private static final OpenemsNamedException getOpenemsException(Throwable e) { + return getOpenemsException(e, true); + } + + private static final OpenemsNamedException getOpenemsException(Throwable e, boolean isRootException) { + if (e instanceof OpenemsNamedException) { + return (OpenemsNamedException) e; + } + + if (e.getCause() != null) { + final var foundOpenemsException = getOpenemsException(e.getCause(), false); + if (foundOpenemsException != null) { + return foundOpenemsException; + } + } + + if (!isRootException) { + return null; + } + + return new OpenemsException(e.getMessage()); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppDef.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppDef.java new file mode 100644 index 00000000000..ad1c0cc8645 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppDef.java @@ -0,0 +1,814 @@ +package io.openems.edge.core.appmanager; + +import java.util.Objects; +import java.util.Optional; +import java.util.ResourceBundle; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import io.openems.common.session.Language; +import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.JsonFormlyUtil.FormlyBuilder; +import io.openems.edge.core.appmanager.Type.Parameter; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; + +/** + * AppDef short for definition of a property for an app. + * + * @param the type of the app + * @param the type of the property + * @param the type of the paramters + */ +public class AppDef // + implements OnlyIf>, Self> { + + private static final Logger LOG = LoggerFactory.getLogger(AppDef.class); + + /** + * Functional interface function with field values. + * + * @param the type of the app + * @param

      the type of the property + * @param the type of the parameter + * @param the type of the return parameter + */ + @FunctionalInterface + public static interface FieldValuesSupplier { + + /** + * A function with the values of the current field. + * + * @param app the current app + * @param property the current property + * @param l the current language + * @param parameter the current provided parameters + * @return the output of the function + */ + public O get(A app, P property, Language l, M parameter); + + } + + /** + * Functional interface with field values and a extra parameter and and return + * value. + * + * @param the type of the app + * @param

      the type of the property + * @param the type of the parameter + * @param the type of the additional parameter + * @param the type of the return parameter + */ + @FunctionalInterface + public static interface FieldValuesFunction { + + /** + * A function with the values of the current field and one extra parameter. + * + * @param app the current app + * @param property the current property + * @param l the current language + * @param parameter the current provided parameters + * @param first the extra parameter + * @return the output of the function + */ + public O apply(A app, P property, Language l, M parameter, T first); + + } + + /** + * Functional interface with field values and a extra parameter. + * + * @param the type of the app + * @param

      the type of the property + * @param the type of the parameter + * @param the type of the additional parameter + */ + @FunctionalInterface + public static interface FieldValuesConsumer { + + /** + * A Consumer with the values of the current field and one extra parameter. + * + * @param app the current app + * @param property the current property + * @param l the current language + * @param parameter the current provided parameters + * @param first the extra parameter + */ + public void accept(A app, P property, Language l, M parameter, T first); + + } + + /** + * Function to get the label of the field. + */ + private FieldValuesSupplier label; + + /** + * Function to get the description of the field. + */ + private FieldValuesSupplier description; + + /** + * Function to get the default value of the field (can be any JsonElement => + * JsonArray, JsonPrimitiv(Number, String, Boolean, Character). + */ + private FieldValuesSupplier defaultValue; + + /** + * Function to get the {@link FormlyBuilder} for the input. + */ + private FieldValuesSupplier> field; + + /** + * Determines if the field gets added to the {@link AppAssistant} automatically. + */ + private boolean autoGenerateField = true; + + /** + * Determines if the property should get visibly saved in the AppManager + * configuration. + */ + private boolean isAllowedToSave = true; + + /** + * Function for bidirectional binding of a component. + */ + private FieldValuesFunction bidirectionalValue; + + /** + * Function to get the {@link ResourceBundle} for translations. + */ + private Function translationBundleSupplier; + + /** + * Creates a {@link AppDef} with the componentId as the default value. + * + * @param the type of the {@link OpenemsApp} + * @param the type of the {@link Nameable} + * @param the type of the {@link Parameter} + * @param componentId the id of the component + * @return the {@link AppDef} + */ + public static final AppDef componentId(String componentId) { + return new AppDef() // + .setDefaultValue(componentId); + } + + /** + * Creates a {@link AppDef} of a subclass of an + * {@link AbstractOpenemsAppWithProps}. + * + * @param the type of the app + * @param the type of the property + * @param the type of the parameter + * @return the {@link AppDef} + */ + public static final AppDef of() { + return new AppDef(); + } + + /** + * Creates a {@link AppDef} of a subclass of an + * {@link AbstractOpenemsAppWithProps}. + * + * @param the type of the app + * @param the type of the property + * @param the type of the parameter + * @param clazz the {@link Class} of the + * {@link AbstractOpenemsAppWithProps} + * @return the {@link AppDef} + */ + public static final , // + PROPERTY extends Type & Nameable, // + PARAMETER extends Type.Parameter.BundleParameter> AppDef of(// + final Class clazz // + ) { + return new AppDef() // + .setTranslationBundleSupplier(BundleParameter::getBundle); + } + + /** + * Creates a {@link AppDef} of a subclass of an {@link OpenemsApp}. + * + * @param the type of the app + * @param the type of the property + * @param the type of the parameter + * @param propertyClass the {@link Class} of the PROPERTY + * @return the {@link AppDef} + */ + public static final , // + PARAMETER extends Type.Parameter> AppDef genericOf(// + final Class propertyClass // + ) { + return new AppDef(); + } + + /** + * Creates a copy of the otherDef. + * + * @param the type of the app + * @param the type of the property + * @param the type of the parameter + * @param propertyClass the class of the current property + * @param otherDef the other {@link AppDef} + * @return the new {@link AppDef} // + */ + public static final & OpenemsApp, // + PROPERTY extends Enum & Nameable & Type, // + PARAMETER extends Type.Parameter.BundleParameter> // + AppDef copyOf(// + final Class propertyClass, // + final AppDef otherDef // + ) { + final var def = new AppDef(); + def.translationBundleSupplier = otherDef.translationBundleSupplier; + def.label = otherDef.label; + def.description = otherDef.description; + def.defaultValue = otherDef.defaultValue; + def.field = otherDef.field; + def.autoGenerateField = otherDef.autoGenerateField; + def.isAllowedToSave = otherDef.isAllowedToSave; + def.bidirectionalValue = otherDef.bidirectionalValue; + return def; + } + + /** + * Creates a copy of the otherDef. + * + * @param the type of the app + * @param the type of the property + * @param the type of the parameter + * @param the type of the app from the otherDef + * @param the type of the property from the otherDef + * @param the type of the parameter from the otherDef + * @param otherDef the other {@link AppDef} + * @return the new {@link AppDef} + */ + public static final AppDef copyOfGeneric(// + final AppDef otherDef // + ) { + final var def = new AppDef(); + def.translationBundleSupplier = otherDef.translationBundleSupplier; + def.label = otherDef.label; + def.description = otherDef.description; + def.defaultValue = otherDef.defaultValue; + def.field = otherDef.field; + def.autoGenerateField = otherDef.autoGenerateField; + def.isAllowedToSave = otherDef.isAllowedToSave; + def.bidirectionalValue = otherDef.bidirectionalValue; + return def; + } + + /** + * Sets if the property is allowed to be saved. May be used for passwords and + * apiKeys. + * + *

      + * DefaultValue: {@link Boolean#TRUE} + * + * @param isAllowedToSave if the property is allowed to be saved + * @return this + */ + public AppDef setAllowedToSave(// + final boolean isAllowedToSave // + ) { + this.isAllowedToSave = isAllowedToSave; + return this; + } + + public final AppDef setTranslationBundleSupplier(// + final Function bundleSupplier // + ) { + this.translationBundleSupplier = bundleSupplier; + return this; + } + + /** + * Gets if the property is allowed to be saved. + * + * @return if the property is allowed to be saved + */ + public boolean isAllowedToSave() { + return this.isAllowedToSave; + } + + /** + * Sets the function as the label. + * + * @param label the function to get the label + * @return this + */ + public final AppDef setLabel(// + final FieldValuesSupplier label // + ) { + this.label = label; + return this; + } + + /** + * Sets the given string label as the return of the function label. + * + * @param label the label to set + * @return this + */ + public final AppDef setLabel(// + final String label // + ) { + return this.setLabel((app, prop, t, param) -> label); + } + + /** + * Sets the value of the translation as the label. + * + *

      + * Note: If this method is used {@link Type#translationBundleSupplier()} must be + * overridden and return a non null value. + * + * @param key the key of the translation + * @param params the parameter of the translation + * @return this + */ + public final AppDef setTranslatedLabel(// + final String key, // + final Object... params // + ) { + this.label = this.translate(key, params); + return this; + } + + /** + * Sets the value of the translation with the {@link OpenemsApp#getAppId()} as + * prefixed as the label. + * + *

      + * Note: If this method is used {@link Type#translationBundleSupplier()} must be + * overridden and return a non null value. + * + * @param key the key of the translation + * @param params the parameter of the translation + * @return this + */ + public final AppDef setTranslatedLabelWithAppPrefix(// + final String key, // + final Object... params // + ) { + this.label = this.translateWithAppPrefix(key, params); + return this; + } + + /** + * Sets the function as the description. + * + * @param description the function to get the description + * @return this + */ + public final AppDef setDescription(// + final FieldValuesSupplier description // + ) { + this.description = description; + return this; + } + + /** + * Sets the value of the translation as the description. + * + *

      + * Note: If this method is used {@link Type#translationBundleSupplier()} must be + * overridden and return a non null value. + * + * @param key the key of the translation + * @return this + */ + public final AppDef setTranslatedDescription(// + final String key // + ) { + this.description = this.translate(key); + return this; + } + + /** + * Sets the value of the translation with the {@link OpenemsApp#getAppId()} as + * prefixed as the description. + * + *

      + * Note: If this method is used {@link Type#translationBundleSupplier()} must be + * overridden and return a non null value. + * + * @param key the key of the translation + * @param params the parameter of the translation + * @return this + */ + public final AppDef setTranslatedDescriptionWithAppPrefix(// + final String key, // + final Object... params // + ) { + this.description = this.translateWithAppPrefix(key, params); + return this; + } + + /** + * Sets the function as the defaultValue. + * + * @param defaultValue the function to get the defaultValue + * @return this + */ + public final AppDef setDefaultValue(// + final FieldValuesSupplier defaultValue // + ) { + this.defaultValue = defaultValue; + return this; + } + + private final AppDef setDefaultValue(// + final Function converter, // + final FieldValuesSupplier value // + ) { + return this.setDefaultValue((app, prop, l, param) -> converter.apply(value.get(app, prop, l, param))); + } + + /** + * Wraps the {@link String} in a {@link JsonPrimitive} and sets it as the + * default value with {@link AppDef#setDefaultValue(Function)}. + * + * @param s the {@link String} as the default value + * @return this + */ + public final AppDef setDefaultValue(// + final String s // + ) { + return this.setDefaultValue(JsonPrimitive::new, (app, prop, l, param) -> s); + } + + /** + * Wraps the {@link Boolean} in a {@link JsonPrimitive} and sets it as the + * default value with {@link AppDef#setDefaultValue(Function)}. + * + * @param b the {@link Boolean} as the default value + * @return this + */ + public final AppDef setDefaultValue(// + final Boolean b // + ) { + return this.setDefaultValue(JsonPrimitive::new, (app, prop, l, param) -> b); + } + + /** + * Wraps the {@link Number} in a {@link JsonPrimitive} and sets it as the + * default value with {@link AppDef#setDefaultValue(Function)}. + * + * @param n the {@link Number} as the default value + * @return this + */ + public final AppDef setDefaultValue(// + final Number n // + ) { + return this.setDefaultValue(JsonPrimitive::new, (app, prop, l, param) -> n); + } + + /** + * Wraps the {@link Character} in a {@link JsonPrimitive} and sets it as the + * default value with {@link AppDef#setDefaultValue(Function)}. + * + * @param c the {@link Character} as the default value + * @return this + */ + public final AppDef setDefaultValue(// + final Character c // + ) { + return this.setDefaultValue(JsonPrimitive::new, (app, prop, l, param) -> c); + } + + /** + * Sets the function as the defaultValue. + * + * @param defaultValue the function to get the defaultValue + * @return this + */ + public final AppDef setDefaultValueString(// + final FieldValuesSupplier defaultValue // + ) { + return this.setDefaultValue(JsonPrimitive::new, defaultValue); + } + + /** + * Sets the function as the defaultValue. + * + * @param defaultValue the function to get the defaultValue + * @return this + */ + public final AppDef setDefaultValueNumber(// + final FieldValuesSupplier defaultValue // + ) { + return this.setDefaultValue(JsonPrimitive::new, defaultValue); + } + + /** + * Sets the function as the defaultValue. + * + * @param defaultValue the function to get the defaultValue + * @return this + */ + public final AppDef setDefaultValueBoolean(// + final FieldValuesSupplier defaultValue // + ) { + return this.setDefaultValue(JsonPrimitive::new, defaultValue); + } + + /** + * Sets the function as the defaultValue. + * + * @param defaultValue the function to get the defaultValue + * @return this + */ + public final AppDef setDefaultValueCharacter(// + final FieldValuesSupplier defaultValue // + ) { + return this.setDefaultValue(JsonPrimitive::new, defaultValue); + } + + /** + * Sets a function as the default value which returns the result of + * {@link OpenemsApp#getName(Language)}. + * + * @return this + */ + public final AppDef setDefaultValueToAppName() { + return this.setDefaultValueString(AppDef::fieldValuesToAppName); + } + + private static final // + String fieldValuesToAppName(// + final APP app, // + final PROPERTY prop, // + final Language language, // + final PARAMETER param // + ) { + return app.getName(language); + } + + public AppDef setFieldFunction(// + final FieldValuesSupplier> field // + ) { + this.field = field; + return this; + } + + /** + * Sets the field of the input. + * + * @param the type of the input + * @param fieldSupplier the supplier to get the {@link FormlyBuilder} + * @param additionalSettings the additional settings on the input + * @return this + */ + public final > AppDef setField(// + final Function fieldSupplier, // + final FieldValuesConsumer additionalSettings // + ) { + Objects.requireNonNull(fieldSupplier); + this.field = (app, property, language, parameter) -> { + final var field = fieldSupplier.apply(property); + if (additionalSettings != null) { + additionalSettings.accept(app, property, language, parameter, field); + } + return field; + }; + return this; + } + + /** + * Sets the field of the input. + * + * @param the type of the input + * @param fieldSupplier the supplier to get the {@link FormlyBuilder} + * @return this + */ + public final > AppDef setField(// + final Function fieldSupplier // + ) { + return this.setField(fieldSupplier, null); + } + + public AppDef setAutoGenerateField(boolean autoGenerateField) { + this.autoGenerateField = autoGenerateField; + return this; + } + + public boolean isAutoGenerateField() { + return this.autoGenerateField; + } + + /** + * Wraps the existing field. If the existing field is not set the wrapper will + * not be executed. + * + * @param wrapper the wrapper of the current field + * @return this + */ + public final AppDef wrapField(// + final FieldValuesConsumer> wrapper// + ) { + final var oldField = this.field; + if (oldField == null) { + return this; + } + Objects.requireNonNull(wrapper); + this.field = (app, prop, l, param) -> { + var field = oldField.get(app, prop, l, param); + wrapper.accept(app, prop, l, param, field); + return field; + }; + return this; + } + + /** + * Executes the {@link Consumer} if the valueProvider can provide an instance + * with the given values. + * + * @param the type of the {@link OpenemsApp} + * @param the type of the property + * @param the type of the parameters + * @param the type of the provided instance + * @param app the app + * @param property the property + * @param language the {@link Language} + * @param parameter the parameter + * @param valueProvider the provider of the instance + * @param consumer the consumer to consume the instance + */ + private static final void doIfPresent(// + final APP app, // + final PROPERTY property, // + final Language language, // + final PARAMETER parameter, // + final FieldValuesSupplier valueProvider, // + final Consumer consumer // + ) { + if (valueProvider == null) { + return; + } + var result = valueProvider.get(app, property, language, parameter); + consumer.accept(result); + } + + private final Optional usingTranslation(// + final PARAMETER parameter // + ) { + return Optional.ofNullable(this.translationBundleSupplier) // + .map(t -> t.apply(parameter)); + } + + private final FieldValuesSupplier translate(// + final String key, // + final Object... params // + ) { + return (app, prop, t, param) -> { + return this.usingTranslation(param) // + .map(b -> TranslationUtil.getTranslation(b, key, params)) // + .orElse(null); // + }; + } + + private final FieldValuesSupplier translateWithAppPrefix(// + final String key, // + final Object... params // + ) { + return (app, prop, t, param) -> { + return this.usingTranslation(param) // + .map(b -> TranslationUtil.getTranslation(b, app.getAppId() + key, params)) // + .orElseGet(() -> { + LOG.warn("No bundle supplier for Key '" + key + "'!"); + return key; + }); + }; + } + + /** + * Gets the function to get the label. + * + * @return the function + */ + public FieldValuesSupplier getLabel() { + return this.label; + } + + /** + * Gets the function to get the description. + * + * @return the function + */ + public FieldValuesSupplier getDescription() { + return this.description; + } + + /** + * Gets the function to get the label. + * + * @return the function + */ + public final FieldValuesSupplier getDefaultValue() { + return this.defaultValue; + } + + /** + * Gets the function to get the {@link FormlyBuilder}. + * + * @return the function + */ + public final FieldValuesSupplier> getField() { + if (this.field == null) { + return null; + } + return (app, property, l, parameter) -> { + final var field = this.field.get(app, property, l, parameter); + doIfPresent(app, property, l, parameter, this.label, field::setLabel); + doIfPresent(app, property, l, parameter, this.description, field::setDescription); + doIfPresent(app, property, l, parameter, this.defaultValue, field::setDefaultValue); + return field; + }; + } + + /** + * Gets the function to get the bidirectional value. + * + *

      + * This value may be obtained from a component + * + * @return the function to get the value + */ + public FieldValuesFunction getBidirectionalValue() { + return this.bidirectionalValue; + } + + @Override + public AppDef self() { + return this; + } + + /** + * Binds a property bidirectional. + * + *

      + * The property itself will not be stored in the app configuration only in the + * component. If the user doesn't provide the value of a property and there is a + * bidirectional binding for it it will be filled up with the value of the + * bidirectional binding. If there is no component id in the configuration or + * the component doesn't exist or the property of the value is null then null is + * returned inside the bidirectional function. + * + * @param propOfComponentId the key to get the component id from a + * configuration + * @param property the property of the component + * @param componentManagerFunction the function to get the component manager + * @return this + */ + public AppDef bidirectional(// + final PROPERTY propOfComponentId, // + final String property, // + final Function componentManagerFunction // + ) { + this.bidirectionalValue = (app, prop, l, param, properties) -> { + if (properties == null) { + return null; + } + final var componentId = properties.get(propOfComponentId.name()); + if (componentId == null) { + return null; + } + final var componentManager = componentManagerFunction.apply(app); + final var optionalComponent = componentManager.getEdgeConfig() // + .getComponent(componentId.getAsString()); + return optionalComponent.map(component -> { + return component.getProperty(property).orElse(null); + }).orElse(null); + }; + // set allowedToSave automatically to false + this.isAllowedToSave = false; + return this.self(); + } + +} \ No newline at end of file diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppInstallWorker.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppInstallWorker.java index 1e9d7d6cf21..14337f33f4a 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppInstallWorker.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppInstallWorker.java @@ -1,21 +1,41 @@ package io.openems.edge.core.appmanager; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collector; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; + import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; -import io.openems.common.utils.JsonUtils; +import io.openems.common.jsonrpc.response.AppCenterGetPossibleAppsResponse.Bundle; +import io.openems.common.session.Language; import io.openems.common.worker.AbstractWorker; import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; public class AppInstallWorker extends AbstractWorker { + private final Object keyForFreeAppsLock = new Object(); + private String keyForFreeApps = null; + /** * Time to wait before doing the check. This allows the system to completely - * boot and read configurations. And enough time to allow the user to delete the - * ReadOnly App and let him install the ReadWrite ones. + * boot and read configurations. */ private static final int INITIAL_WAIT_TIME = 60_000; // in ms + private static final int INACTIVE_WAIT_TIME = 1_000 * 60 * 60 * 24; // 1 day + private static final int RELOAD_FREE_APPS_TIME = 10; // every 10 days + + private int reloadFreeApps = 0; + private List freeApps = null; private final Logger log = LoggerFactory.getLogger(this.getClass()); @@ -26,41 +46,111 @@ public AppInstallWorker(AppManagerImpl parent) { } private void installFreeApps() { - this.installReadOnlyApi("App.Api.ModbusTcp.ReadOnly", "App.Api.ModbusTcp.ReadWrite", - "Controller.Api.ModbusTcp.ReadWrite"); - this.installReadOnlyApi("App.Api.RestJson.ReadOnly", "App.Api.RestJson.ReadWrite", - "Controller.Api.Rest.ReadWrite"); + final var appsToInstall = this.freeApps; + if (appsToInstall == null) { + return; + } + for (var bundle : appsToInstall) { + // only install first successfully installed app + for (var app : bundle.apps) { + if (this.parent.getInstantiatedApps().stream().anyMatch(t -> t.appId.equals(app.appId))) { + break; + } + try { + this.installApp(app.appId); + break; + } catch (Throwable e) { + this.log.info("Unable to install free App[" + app.appId + "]"); + e.printStackTrace(); + } + } + } } - private final void installReadOnlyApi(String readOnly, String readWrite, String readWriteController) { - if (this.parent.getInstantiatedApps().stream() - .noneMatch(t -> t.appId.equals(readOnly) || t.appId.equals(readWrite))) { + private void installApp(String appId) throws OpenemsNamedException { + var app = this.parent.findAppById(appId); - // TODO this is only required if the ReadWrite controller exists without an App - if (this.parent.componentManager.getEdgeConfig().getComponentIdsByFactory(readWriteController) - .size() == 0) { + JsonObject requestProperties; + try { + var properties = app.getProperties(); + requestProperties = Arrays.stream(properties) // + .map(p -> { + return Map.entry(p.name, // + p.getDefaultValue(Language.DEFAULT) // + .orElse(JsonNull.INSTANCE)); + }) // + .collect(Collector., JsonObject>of(JsonObject::new, + (t, u) -> t.add(u.getKey(), u.getValue()), (t, u) -> { + t.entrySet().forEach(e -> { + if (!e.getValue().equals(JsonNull.INSTANCE)) { + u.add(e.getKey(), e.getValue()); + } + }); + return u; + })) // + ; + } catch (UnsupportedOperationException e) { + requestProperties = new JsonObject(); + } - try { - this.parent.handleAddAppInstanceRequest(null, - new AddAppInstance.Request(readOnly, "", JsonUtils.buildJsonObject().build())); - } catch (OpenemsNamedException e) { - this.log.info("Unable to install free App[" + readOnly + "]"); - } - } else { - this.log.warn("Unable to create App[" + readOnly + "] because a " + "Component with the FactoryId[" - + readWrite + "] exists!"); - } + final var alias = Optional.ofNullable(requestProperties.get("ALIAS")) // + .map(j -> j.getAsString()) // + .orElse(app.getName(Language.DEFAULT)); + + this.parent.handleAddAppInstanceRequest(null, + new AddAppInstance.Request(appId, this.keyForFreeApps, alias, requestProperties)); + } + + private void reloadFreeApps() { + if (!this.parent.backendUtil.isConnected()) { + this.freeApps = null; + return; } + final String key = this.keyForFreeApps; + if (key == null) { + return; + } + this.freeApps = this.parent.backendUtil.getPossibleApps(key); } @Override protected void forever() throws Throwable { + if (this.reloadFreeApps == RELOAD_FREE_APPS_TIME) { + this.reloadFreeApps(); + } this.installFreeApps(); } @Override protected int getCycleTime() { - return INITIAL_WAIT_TIME; + if (this.keyForFreeApps == null || this.keyForFreeApps.isBlank()) { + return ALWAYS_WAIT_FOR_TRIGGER_NEXT_RUN; + } + this.reloadFreeApps--; + if (this.reloadFreeApps < 0) { + this.reloadFreeApps = RELOAD_FREE_APPS_TIME; + } + if (!this.isValidBackendResponse()) { + return INITIAL_WAIT_TIME; + } + return INACTIVE_WAIT_TIME; + } + + public void setKeyForFreeApps(String key) { + if (Objects.equals(this.keyForFreeApps, key)) { + return; + } + synchronized (this.keyForFreeAppsLock) { + this.keyForFreeApps = key; + if (key != null) { + this.reloadFreeApps = 0; + this.triggerNextRun(); + } + } + } + + private boolean isValidBackendResponse() { + return this.freeApps != null; } } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManager.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManager.java index 3e3aee1eac1..46bbe033d65 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManager.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManager.java @@ -18,6 +18,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { DEFECTIVE_APP(Doc.of(Level.INFO) // // TODO should be a WARNING eventually .text("Defective App detected")), // + APPS_NOT_SYNCED_WITH_BACKEND(Doc.of(Level.INFO) // + .text("The currently installed apps are not the same as logged in the backend")), // ; private final Doc doc; @@ -56,6 +58,16 @@ public default void _setWrongAppConfiguration(boolean value) { this.getWrongAppConfigurationChannel().setNextValue(value); } + /** + * Internal method to set the 'nextValue' on + * {@link ChannelId#APPS_NOT_SYNCED_WITH_BACKEND} Channel. + * + * @param value the next value + */ + public default void _setAppsNotSyncedWithBackend(boolean value) { + this.getAppsNotSyncedWithBackendChannel().setNextValue(value); + } + /** * Gets the Defective-App Warning State. See {@link ChannelId#DEFECTIVE_APP}. * @@ -93,4 +105,23 @@ public default StateChannel getWrongAppConfigurationChannel() { return this.channel(ChannelId.WRONG_APP_CONFIGURATION); } + /** + * Gets the Apps-Not-Synced-With-Backend Warning State. See + * {@link ChannelId#APPS_NOT_SYNCED_WITH_BACKEND}. + * + * @return the Channel {@link Value} + */ + public default Value getAppsNotSyncedWithBackend() { + return this.getAppsNotSyncedWithBackendChannel().value(); + } + + /** + * Gets the channel for {@link ChannelId#APPS_NOT_SYNCED_WITH_BACKEND}. + * + * @return the Channel + */ + public default StateChannel getAppsNotSyncedWithBackendChannel() { + return this.channel(ChannelId.APPS_NOT_SYNCED_WITH_BACKEND); + } + } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerImpl.java index 1938915b4f5..5a66ff9da45 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerImpl.java @@ -12,6 +12,7 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -20,19 +21,26 @@ import org.osgi.service.cm.ConfigurationEvent; import org.osgi.service.cm.ConfigurationListener; import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.ComponentServiceObjects; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Modified; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; import org.osgi.service.metatype.annotations.Designate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.gson.JsonArray; import io.openems.common.exceptions.OpenemsError; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.function.ThrowingFunction; +import io.openems.common.function.ThrowingSupplier; import io.openems.common.jsonrpc.base.GenericJsonrpcResponseSuccess; import io.openems.common.jsonrpc.base.JsonrpcRequest; import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; @@ -40,6 +48,7 @@ import io.openems.common.jsonrpc.request.UpdateComponentConfigRequest.Property; import io.openems.common.session.Role; import io.openems.common.utils.JsonUtils; +import io.openems.common.utils.Mutex; import io.openems.edge.common.component.AbstractOpenemsComponent; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.component.OpenemsComponent; @@ -47,6 +56,7 @@ import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.dependency.AppManagerAppHelper; import io.openems.edge.core.appmanager.dependency.Dependency; +import io.openems.edge.core.appmanager.dependency.UpdateValues; import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; import io.openems.edge.core.appmanager.jsonrpc.DeleteAppInstance; import io.openems.edge.core.appmanager.jsonrpc.GetApp; @@ -68,9 +78,11 @@ public class AppManagerImpl extends AbstractOpenemsComponent implements AppManager, OpenemsComponent, JsonApi, ConfigurationListener { - // TODO maybe a worker which resolves defective apps + private final Logger log = LoggerFactory.getLogger(this.getClass()); + private final AppValidateWorker worker; private final AppInstallWorker appInstallWorker; + private final AppSynchronizeWorker appSynchronizeWorker; @Reference private ConfigurationAdmin cm; @@ -79,7 +91,7 @@ public class AppManagerImpl extends AbstractOpenemsComponent protected volatile List availableApps; @Reference - private AppManagerAppHelper appHelper; + private ComponentServiceObjects csoAppManagerAppHelper; @Reference protected ComponentManager componentManager; @@ -90,8 +102,19 @@ public class AppManagerImpl extends AbstractOpenemsComponent @Reference protected Validator validator; + @Reference(policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MANDATORY) + protected AppCenterBackendUtil backendUtil; + protected final List instantiatedApps = new ArrayList<>(); + /** + * Blocks until all changes to an app have been applied to the list of + * instantiatedApps and the appManagerConfiguration. + */ + private boolean aquiredMutex = false; + private final Mutex mutexForUpdatingConfig = new Mutex(true); + private UpdateValues lastUpdate = null; + public AppManagerImpl() { super(// OpenemsComponent.ChannelId.values(), // @@ -99,15 +122,23 @@ public AppManagerImpl() { ); this.worker = new AppValidateWorker(this); this.appInstallWorker = new AppInstallWorker(this); + this.appSynchronizeWorker = new AppSynchronizeWorker(this); } @Activate - private void activate(ComponentContext componentContext, Config config) { + protected void activate(ComponentContext componentContext, Config config) { super.activate(componentContext, SINGLETON_COMPONENT_ID, SINGLETON_SERVICE_PID, true); this.applyConfig(config); this.worker.activate(this.id()); this.appInstallWorker.activate(this.id()); + this.appSynchronizeWorker.activate(this.id()); + + this.appInstallWorker.setKeyForFreeApps(config.keyForFreeApps()); + + // resolve dependencies + CompletableFuture.delayedExecutor(1, TimeUnit.MINUTES) // + .execute(new ResolveDependencies(componentContext.getBundleContext())); if (OpenemsComponent.validateSingleton(this.cm, SINGLETON_SERVICE_PID, SINGLETON_COMPONENT_ID)) { return; @@ -115,12 +146,16 @@ private void activate(ComponentContext componentContext, Config config) { } @Modified - private void modified(ComponentContext componentContext, Config config) throws OpenemsNamedException { + protected void modified(ComponentContext componentContext, Config config) throws OpenemsNamedException { super.modified(componentContext, SINGLETON_COMPONENT_ID, SINGLETON_SERVICE_PID, true); this.applyConfig(config); this.worker.modified(this.id()); this.appInstallWorker.modified(this.id()); + this.appSynchronizeWorker.modified(this.id()); + + this.appInstallWorker.setKeyForFreeApps(config.keyForFreeApps()); + this.worker.triggerNextRun(); if (OpenemsComponent.validateSingleton(this.cm, SINGLETON_SERVICE_PID, SINGLETON_COMPONENT_ID)) { return; @@ -133,6 +168,15 @@ protected void deactivate() { super.deactivate(); this.worker.deactivate(); this.appInstallWorker.deactivate(); + this.appSynchronizeWorker.deactivate(); + } + + @Override + public void _setAppsNotSyncedWithBackend(boolean value) { + AppManager.super._setAppsNotSyncedWithBackend(value); + if (value) { + this.appSynchronizeWorker.triggerNextRun(); + } } /** @@ -141,7 +185,7 @@ protected void deactivate() { * @return the list of instantiated apps */ public final List getInstantiatedApps() { - return Collections.unmodifiableList(this.instantiatedApps); + return Collections.unmodifiableList(new ArrayList<>(this.instantiatedApps)); } /** @@ -195,23 +239,62 @@ private static List parseInstantiatedApps(JsonArray apps) th } private synchronized void applyConfig(Config config) { - var apps = config.apps(); - if (apps.isBlank()) { - apps = "[]"; // default to empty array - } - try { - var instApps = parseInstantiatedApps(JsonUtils.parseToJsonArray(apps)); + boolean isResultOfRpcRequest = false; + synchronized (this.instantiatedApps) { + try { + var apps = config.apps(); + if (apps.isBlank()) { + apps = "[]"; // default to empty array + } + try { + var instApps = parseInstantiatedApps(JsonUtils.parseToJsonArray(apps)); + + // always replace old apps with the new ones + var currentApps = new ArrayList<>(this.instantiatedApps); + + // if equal the applyConfig is because of a + // installation/modification/removing of an app via JsonrpcRequest + if (currentApps.containsAll(instApps)// + && instApps.size() == currentApps.size()) { + isResultOfRpcRequest = true; + } else if (this.lastUpdate != null // + && (!instApps.containsAll(this.lastUpdate.modifiedOrCreatedApps) // + || instApps.stream().anyMatch(t -> this.lastUpdate.deletedApps.stream() // + .anyMatch(o -> o.equals(t))))) { + // the last update was not applied + this.logWarn(this.log, "Modified AppManager config properties directly. " // + + "If there was an installation/modification/deinstallation of an App " // + + "running there might be lost configuration changes. Expected: " // + + "Installed/Modified: " // + + JsonUtils.prettyToString(this.lastUpdate.modifiedOrCreatedApps.stream() // + .map(OpenemsAppInstance::toJsonObject) // + .collect(JsonUtils.toJsonArray())) + + Optional.ofNullable(this.lastUpdate.deletedApps) // + .map(deletedApps -> { + return System.lineSeparator() + "Removed: " // + + JsonUtils.prettyToString(this.lastUpdate.deletedApps.stream() // + .map(OpenemsAppInstance::toJsonObject) // + .collect(JsonUtils.toJsonArray())); + }).orElse("")); + } - // always replace old apps with the new ones - this.instantiatedApps.clear(); - this.instantiatedApps.addAll(instApps); + this.instantiatedApps.clear(); + this.instantiatedApps.addAll(instApps); - this._setWrongAppConfiguration(false); + this._setWrongAppConfiguration(false); - } catch (OpenemsNamedException e) { - this._setWrongAppConfiguration(true); - e.printStackTrace(); - return; + } catch (OpenemsNamedException e) { + this._setWrongAppConfiguration(true); + e.printStackTrace(); + return; + } + } finally { + if (isResultOfRpcRequest && this.aquiredMutex) { + this.lastUpdate = null; + this.aquiredMutex = false; + this.mutexForUpdatingConfig.release(); + } + } } } @@ -378,36 +461,98 @@ public final List getOtherAppConfigurations(UUID... ignoreIds) return allOtherConfigs; } + private final OpenemsAppInstance createInstanceWithFilledProperties(// + final OpenemsApp openemsApp, // + final OpenemsAppInstance instance // + ) { + var properties = instance.properties; + if (openemsApp instanceof AbstractOpenemsAppWithProps) { + properties = ((AbstractOpenemsAppWithProps) openemsApp).fillUpProperties(properties); + } + return new OpenemsAppInstance(// + instance.appId, instance.alias, instance.instanceId, // + properties, instance.dependencies // + ); + } + /** * Handles {@link AddAppInstance}. * - * @param user the User - * @param request the {@link AddAppInstance} Request + * @param user the User + * @param request the {@link AddAppInstance} Request + * @param ignoreBackend should only be used internally * @return the Future JSON-RPC Response * @throws OpenemsNamedException on error */ - public CompletableFuture handleAddAppInstanceRequest(User user, - AddAppInstance.Request request) throws OpenemsNamedException { - var openemsApp = this.findAppById(request.appId); - synchronized (this.instantiatedApps) { + public CompletableFuture handleAddAppInstanceRequest(User user, + AddAppInstance.Request request, boolean ignoreBackend) throws OpenemsNamedException { + // check if key is valid for this app + if (!ignoreBackend && !this.backendUtil.isKeyApplicable(user, request.key, request.appId)) { + throw new OpenemsException("Key not applicable!"); + } - final var instance = new OpenemsAppInstance(request.appId, request.alias, UUID.randomUUID(), + var openemsApp = this.findAppById(request.appId); + final var response = this.lockModifyingApps(() -> { + List warnings = new ArrayList<>(); + var instance = new OpenemsAppInstance(openemsApp.getAppId(), request.alias, UUID.randomUUID(), request.properties, null); - var installedValues = this.appHelper.installApp(user, instance, openemsApp); + if (!ignoreBackend) { + try { + // try to send the backend the install request + this.backendUtil.addInstallAppInstanceHistory(user, request.key, request.appId, + instance.instanceId); + } catch (OpenemsNamedException e) { + // if timeout happens but the backend registered the app as installed it may + // need to be synchronized again + if (e.getMessage().contains("Read timed out")) { + this.appSynchronizeWorker.setValidBackendResponse(false); + this.appSynchronizeWorker.triggerNextRun(); + } + throw e; + } + } - // Update App-Manager configuration try { - // replace old instances with new ones + final var installedValues = this.lastUpdate = this.useAppManagerAppHelper(appHelper -> { + // actually install the app + return appHelper.installApp(user, instance, openemsApp); + }); + + warnings.addAll(installedValues.warnings); this.instantiatedApps.removeAll(installedValues.modifiedOrCreatedApps); this.instantiatedApps.addAll(installedValues.modifiedOrCreatedApps); - this.updateAppManagerConfiguration(user, this.instantiatedApps); - } catch (OpenemsNamedException e) { - throw new OpenemsException( - "AddAppInstance: unable to update App-Manager configuration: " + e.getMessage()); + } catch (Throwable e) { + // installation failed but already registered in the backend so still add the + // instance + warnings.add("Installation failed: " + e.getMessage()); + this.instantiatedApps.add(instance); } - return CompletableFuture.completedFuture( - new AddAppInstance.Response(request.id, installedValues.rootInstance, installedValues.warnings)); + var instanceWithFilledProperties = this.createInstanceWithFilledProperties(openemsApp, instance); + return CompletableFuture.completedFuture(// + new AddAppInstance.Response(request.id, instanceWithFilledProperties, warnings)); + }); + try { + // Update App-Manager configuration + this.updateAppManagerConfiguration(user, this.instantiatedApps); + } catch (OpenemsNamedException e) { + this.appSynchronizeWorker.setValidBackendResponse(false); + this.appSynchronizeWorker.triggerNextRun(); + throw new OpenemsException("AddAppInstance: unable to update App-Manager configuration: " + e.getMessage()); } + return response; + } + + /** + * Handles {@link AddAppInstance}. + * + * @param user the User + * @param request the {@link AddAppInstance} Request + * @return the Future JSON-RPC Response + * @throws OpenemsNamedException on error + */ + public CompletableFuture handleAddAppInstanceRequest(User user, + AddAppInstance.Request request) throws OpenemsNamedException { + return this.handleAddAppInstanceRequest(user, request, false); } /** @@ -420,29 +565,49 @@ public CompletableFuture handleAddAppInstanceRequest(Use */ public CompletableFuture handleDeleteAppInstanceRequest(User user, DeleteAppInstance.Request request) throws OpenemsNamedException { - - synchronized (this.instantiatedApps) { - + final var updatedResultPair = this.lockModifyingApps(() -> { final OpenemsAppInstance instance; try { instance = this.findInstanceById(request.instanceId); } catch (NoSuchElementException e) { - return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(request.id)); + return null; } - var result = this.appHelper.deleteApp(user, instance); + final var result = this.lastUpdate = this.useAppManagerAppHelper(appHelper -> { + return appHelper.deleteApp(user, instance); + }); + this.instantiatedApps.removeAll(result.deletedApps); + // replace modified apps + this.instantiatedApps.removeAll(result.modifiedOrCreatedApps); + this.instantiatedApps.addAll(result.modifiedOrCreatedApps); + return new Pair<>(result, instance); + }); + + final var updatedResult = updatedResultPair.first; + final var removedInstance = updatedResultPair.second; - try { - this.instantiatedApps.removeAll(result.deletedApps); - // replace modified apps - this.instantiatedApps.removeAll(result.modifiedOrCreatedApps); - this.instantiatedApps.addAll(result.modifiedOrCreatedApps); - this.updateAppManagerConfiguration(user, this.instantiatedApps); - } catch (OpenemsNamedException e) { - throw new OpenemsException("Unable to update App-Manager configuration for ID [" + request.instanceId - + "]: " + e.getMessage()); + try { + this.updateAppManagerConfiguration(user, this.instantiatedApps); + } catch (OpenemsNamedException e) { + throw new OpenemsException("Unable to update App-Manager configuration for ID [" + request.instanceId + + "]: " + e.getMessage()); + } + + var backendDeinstallFuture = this.backendUtil.addDeinstallAppInstanceHistory(user, removedInstance.appId, + removedInstance.instanceId); + backendDeinstallFuture.whenComplete((r, t) -> { + if (t == null) { + return; } - return CompletableFuture.completedFuture(new DeleteAppInstance.Response(request.id, result.warnings)); + // unable to write to the backend that the app got deinstalled + this.log.error("Unable to send deinstall app instance to backend!", t); + this._setAppsNotSyncedWithBackend(true); + }); + if (updatedResult == null) { + return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(request.id)); + } else { + return CompletableFuture + .completedFuture(new DeleteAppInstance.Response(request.id, updatedResult.warnings)); } } @@ -495,7 +660,14 @@ private CompletableFuture handleGetAppInstancesRequest(U GetAppInstances.Request request) throws OpenemsNamedException { var instances = this.instantiatedApps.stream() // .filter(i -> i.appId.equals(request.appId)) // - .collect(Collectors.toList()); + .map(t -> { + final var app = this.findAppById(t.appId); + var properties = t.properties; + if (app instanceof AbstractOpenemsAppWithProps) { + properties = ((AbstractOpenemsAppWithProps) app).fillUpProperties(properties); + } + return new OpenemsAppInstance(t.appId, t.alias, t.instanceId, properties, t.dependencies); + }); return CompletableFuture.completedFuture(new GetAppInstances.Response(request.id, instances)); } @@ -517,17 +689,17 @@ private CompletableFuture handleGetAppRequest(User user, } /** - * Handles a {@link GetAppsRequest}. + * Handles a {@link GetApps.Request}. * * @param user the User - * @param request the {@link GetAppsRequest} + * @param request the {@link GetApps.Request} * @return the Future JSON-RPC Response * @throws OpenemsNamedException on error */ private CompletableFuture handleGetAppsRequest(User user, GetApps.Request request) throws OpenemsNamedException { return CompletableFuture.completedFuture(new GetApps.Response(request.id, this.availableApps, - this.instantiatedApps, user.getLanguage(), this.validator)); + this.instantiatedApps, user.getRole(), user.getLanguage(), this.validator)); } @Override @@ -553,7 +725,7 @@ public CompletableFuture handleJsonrpcRequest( return this.handleGetAppInstancesRequest(user, GetAppInstances.Request.from(request)); case AddAppInstance.METHOD: - return this.handleAddAppInstanceRequest(user, AddAppInstance.Request.from(request)); + return this.handleAddAppInstanceRequest(user, AddAppInstance.Request.from(request), false); case UpdateAppInstance.METHOD: return this.handleUpdateAppInstanceRequest(user, UpdateAppInstance.Request.from(request)); @@ -574,12 +746,11 @@ public CompletableFuture handleJsonrpcRequest( * @return the Future JSON-RPC Response * @throws OpenemsNamedException on error */ - private CompletableFuture handleUpdateAppInstanceRequest(User user, + public CompletableFuture handleUpdateAppInstanceRequest(User user, UpdateAppInstance.Request request) throws OpenemsNamedException { - - synchronized (this.instantiatedApps) { - OpenemsAppInstance oldApp = null; - OpenemsApp app = null; + final var response = this.lockModifyingApps(() -> { + final OpenemsAppInstance oldApp; + final OpenemsApp app; try { oldApp = this.findInstanceById(request.instanceId); @@ -587,26 +758,28 @@ private CompletableFuture handleUpdateAppInstanceRequest } catch (NoSuchElementException e) { throw new OpenemsException("App-Instance-ID [" + request.instanceId + "] is unknown."); } + final var updatedInstance = new OpenemsAppInstance(oldApp.appId, request.alias, oldApp.instanceId, + request.properties, oldApp.dependencies); - final var instance = new OpenemsAppInstance(oldApp.appId, request.alias, oldApp.instanceId, - request.properties, null); - var result = this.appHelper.updateApp(user, oldApp, instance, app); - + var result = this.lastUpdate = this.useAppManagerAppHelper(appHelper -> { + return appHelper.updateApp(user, oldApp, updatedInstance, app); + }); // Update App-Manager configuration - try { - this.instantiatedApps.removeAll(result.deletedApps); - // replace old instances with new ones - this.instantiatedApps.removeAll(result.modifiedOrCreatedApps); - this.instantiatedApps.addAll(result.modifiedOrCreatedApps); - this.updateAppManagerConfiguration(user, this.instantiatedApps); - } catch (OpenemsNamedException e) { - throw new OpenemsException("Unable to update App-Manager configuration for ID [" + request.instanceId - + "]: " + e.getMessage()); - } - var newInstance = this.findInstanceById(request.instanceId); - return CompletableFuture - .completedFuture(new UpdateAppInstance.Response(request.id, newInstance, result.warnings)); + this.instantiatedApps.removeAll(result.deletedApps); + // replace old instances with new ones + this.instantiatedApps.removeAll(result.modifiedOrCreatedApps); + this.instantiatedApps.addAll(result.modifiedOrCreatedApps); + return CompletableFuture.completedFuture(// + new UpdateAppInstance.Response(request.id, // + this.createInstanceWithFilledProperties(app, result.rootInstance), result.warnings)); + }); + try { + this.updateAppManagerConfiguration(user, this.instantiatedApps); + } catch (OpenemsNamedException e) { + throw new OpenemsException("Unable to update App-Manager configuration for ID [" + request.instanceId + + "]: " + e.getMessage()); } + return response; } /** @@ -646,4 +819,43 @@ public Integer apply(Integer t, Integer u) { return value + aliasValue + instanceValue; }); } + + private T useAppManagerAppHelper(ThrowingFunction consumer) + throws OpenemsNamedException { + final var service = this.csoAppManagerAppHelper.getService(); + try { + return consumer.apply(service); + } finally { + if (service != null) { + this.csoAppManagerAppHelper.ungetService(service); + } + } + } + + private T lockModifyingApps(ThrowingSupplier supplier) throws OpenemsNamedException { + try { + this.mutexForUpdatingConfig.await(); + this.aquiredMutex = true; + } catch (InterruptedException e) { + throw new OpenemsException(e); + } + synchronized (this.appSynchronizeWorker.getSynchronizationLock()) { + synchronized (this.instantiatedApps) { + return supplier.get(); + } + } + } + + private final class Pair { + public final F first; + public final S second; + + public Pair(F first, S second) { + super(); + this.first = first; + this.second = second; + } + + } + } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerUtil.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerUtil.java index b240ef67d32..6e52202fb9d 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerUtil.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerUtil.java @@ -1,5 +1,6 @@ package io.openems.edge.core.appmanager; +import java.util.List; import java.util.NoSuchElementException; import java.util.UUID; @@ -90,4 +91,13 @@ public default AppConfiguration getAppConfiguration(ConfigurationTarget target, return this.getAppConfiguration(target, this.getAppById(instance.appId), instance, language); } + /** + * Gets all {@link OpenemsAppInstance Instances} which have a dependency to the + * given {@link OpenemsAppInstance instance}. + * + * @param instance the instance which is referenced + * @return the referencing instances + */ + public List getAppsWithDependencyTo(OpenemsAppInstance instance); + } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerUtilImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerUtilImpl.java index d9a49da3247..c59f95917ec 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerUtilImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppManagerUtilImpl.java @@ -1,7 +1,9 @@ package io.openems.edge.core.appmanager; +import java.util.List; import java.util.NoSuchElementException; import java.util.UUID; +import java.util.stream.Collectors; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -39,20 +41,21 @@ public AppConfiguration getAppConfiguration(ConfigurationTarget target, OpenemsA if (alias != null) { properties.addProperty("ALIAS", alias); } - AppConfiguration config = null; - OpenemsNamedException error = null; try { - config = app.getAppConfiguration(target, properties, language); - } catch (OpenemsNamedException e) { - error = e; + return app.getAppConfiguration(target, properties, language); + } finally { + if (alias != null) { + properties.remove("ALIAS"); + } } - if (alias != null) { - properties.remove("ALIAS"); - } - if (error != null) { - throw error; - } - return config; + } + + @Override + public List getAppsWithDependencyTo(OpenemsAppInstance instance) { + return this.getAppManagerImpl().getInstantiatedApps().stream() + .filter(t -> t.dependencies != null && !t.dependencies.isEmpty()) + .filter(t -> t.dependencies.stream().anyMatch(d -> d.instanceId.equals(instance.instanceId))) + .collect(Collectors.toList()); } private final AppManagerImpl getAppManagerImpl() { diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppSynchronizeWorker.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppSynchronizeWorker.java new file mode 100644 index 00000000000..8bdaaea70d9 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/AppSynchronizeWorker.java @@ -0,0 +1,137 @@ +package io.openems.edge.core.appmanager; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.response.AppCenterGetInstalledAppsResponse.Instance; +import io.openems.common.worker.AbstractWorker; + +public class AppSynchronizeWorker extends AbstractWorker { + + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + // usual cycle time if not explicit triggered + private static final int CYCLE_TIME = 15 * 60_000; + + // try to get a valid response from the backend every 5 minutes + private static final int NO_BACKEND_CONNECTION_CYCLE_TIME = 5 * 60_000; + + private final AppManagerImpl parent; + private boolean shouldRun = true; + private boolean validBackendResponse = false; + + private static final int WAIT_AFTER_TRIGGER_TIME = 3 * 60_000; + private boolean wasTriggered = false; + private boolean isTriggered = false; + + private final Object synchronizationLock = new Object(); + + protected AppSynchronizeWorker(AppManagerImpl parent) { + this.parent = parent; + } + + @Override + protected void forever() throws Throwable { + if (this.isTriggered) { + this.isTriggered = false; + this.wasTriggered = true; + return; + } + this.syncAppsWithBackend(); + } + + /** + * Synchronizes the apps with the backend. + * + * @return true if successful else false + */ + public boolean syncAppsWithBackend() throws InterruptedException { + synchronized (this.synchronizationLock) { + List installedAppsOfBackend; + try { + installedAppsOfBackend = this.parent.backendUtil.getInstalledApps(); + } catch (OpenemsNamedException ex) { + this.validBackendResponse = false; + return false; + } + var installedAppsOfEdge = this.parent.getInstantiatedApps(); + + var appsWhichNotExist = new ArrayList(); + // only validates the installed apps from the backend; not validating instance + // that are installed on the edge and are not logged in the backend + for (var installedBackendApp : installedAppsOfBackend) { + if (installedAppsOfEdge.stream() // + .anyMatch(t -> t.appId.equals(installedBackendApp.appId) + && t.instanceId.equals(installedBackendApp.instanceId))) { + // app exists like it should + continue; + } else { + // app does not exist + appsWhichNotExist.add(installedBackendApp); + } + } + + this.parent._setAppsNotSyncedWithBackend(!appsWhichNotExist.isEmpty()); + + if (appsWhichNotExist.isEmpty()) { + this.shouldRun = false; + } else { + for (var instance : appsWhichNotExist) { + try { + this.parent.backendUtil.addDeinstallAppInstanceHistory(null, instance.appId, + instance.instanceId); + } catch (OpenemsNamedException ex) { + this.log.error("Can not add deintall app instance entry to database!", ex); + } + } + } + return true; + } + } + + /** + * Gets the lock for synchronizing apps with the backend. Should be used when + * apps get installed/updated/removed. + * + * @return the lock + */ + public final Object getSynchronizationLock() { + return this.synchronizationLock; + } + + @Override + protected int getCycleTime() { + if (!this.shouldRun) { + return ALWAYS_WAIT_FOR_TRIGGER_NEXT_RUN; + } + if (this.wasTriggered) { + this.wasTriggered = false; + return WAIT_AFTER_TRIGGER_TIME; + } + if (!this.validBackendResponse) { + return NO_BACKEND_CONNECTION_CYCLE_TIME; + } + return CYCLE_TIME; + } + + /** + * Sets if the last request was a valid response from the backend. + * + * @param validBackendResponse if the last response was valid + */ + public void setValidBackendResponse(boolean validBackendResponse) { + this.validBackendResponse = validBackendResponse; + } + + @Override + public void triggerNextRun() { + this.shouldRun = true; + this.isTriggered = true; + super.triggerNextRun(); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/ComponentUtil.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/ComponentUtil.java index d7454c40e52..ad82b7a87b7 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/ComponentUtil.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/ComponentUtil.java @@ -112,15 +112,15 @@ public interface ComponentUtil { /** * Gets the next available id with the baseName. * - * @param baseName like ess, meter without a number - * @param components the used components from the other apps, because if the - * user updates multiple instances very quickly and components - * of the same type are created they are not instantly added - * to the componentManager + * @param baseName like ess, meter without a number + * @param componentIds the used componentIds from the other apps, because if the + * user updates multiple instances very quickly and + * components of the same type are created they are not + * instantly added to the componentManager * @return the id */ - public default String getNextAvailableId(String baseName, List components) { - return this.getNextAvailableId(baseName, 0, components); + public default String getNextAvailableId(String baseName, List componentIds) { + return this.getNextAvailableId(baseName, 0, componentIds); } /** @@ -129,13 +129,13 @@ public default String getNextAvailableId(String baseName, List compon * * @param baseName like ess, meter without a number * @param startingNumber the number at the end of the id to start from - * @param components the used components from the other apps, because if the - * user updates multiple instances very quickly and + * @param componentIds the used componentIds from the other apps, because if + * the user updates multiple instances very quickly and * components of the same type are created they are not * instantly added to the componentManager * @return the id */ - public String getNextAvailableId(String baseName, int startingNumber, List components); + public String getNextAvailableId(String baseName, int startingNumber, List componentIds); /** * Gets the preferred relays. If the default ports are are already taken the diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/ComponentUtilImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/ComponentUtilImpl.java index 50b65592fe5..b6aea8a3b3d 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/ComponentUtilImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/ComponentUtilImpl.java @@ -10,6 +10,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -18,7 +19,6 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Reference; -import com.google.common.base.Objects; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -72,7 +72,7 @@ public ComponentUtilImpl(@Reference ComponentManager componentManager, @Referenc * @return true if they match */ public static boolean equals(JsonElement expected, JsonElement actual) { - if (Objects.equal(expected, actual)) { + if (Objects.equals(expected, actual)) { return true; } @@ -182,7 +182,7 @@ private static boolean isSameConfiguration(List errors, Component expect } // Validate the Component Factory (i.e. is the Component of the correct type) - if (!Objects.equal(expectedComponent.getFactoryId(), actualComponent.getFactoryId())) { + if (!Objects.equals(expectedComponent.getFactoryId(), actualComponent.getFactoryId())) { componentErrors.add("Factory-ID: " // + "expected '" + expectedComponent.getFactoryId() + "', " // + "got '" + actualComponent.getFactoryId() + "'"); @@ -241,7 +241,7 @@ private static boolean isSameConfigurationFast(Component expectedComponent, Comp } // Validate the Component Factory (i.e. is the Component of the correct type) - if (!Objects.equal(expectedComponent.getFactoryId(), actualComponent.getFactoryId())) { + if (!Objects.equals(expectedComponent.getFactoryId(), actualComponent.getFactoryId())) { return false; } @@ -314,6 +314,9 @@ public static boolean isSameConfigurationWithoutIdAndAlias(List errors, */ public static List order(List components) { var copy = new ArrayList<>(components); + if (components.size() <= 1) { + return copy; + } for (Component component : components) { // determine which id s the component needs List ids = new ArrayList<>(); @@ -421,13 +424,12 @@ public List getAvailableRelays(String ioId) throws OpenemsNamedException @Override public List getAvailableRelays(String ioId, List ignoreIds) throws OpenemsNamedException { var digitalOutput = this.componentManager.getComponent(ioId); - if (digitalOutput instanceof DigitalOutput) { - return new ArrayList<>(); + if (!(digitalOutput instanceof DigitalOutput)) { + return Collections.emptyList(); } List availableIos = new LinkedList<>(); - var component = digitalOutput; for (var i = 0; i < ((DigitalOutput) digitalOutput).digitalOutputChannels().length; i++) { - var ioName = component.id() + "/Relay" + (i + 1); + var ioName = digitalOutput.id() + "/Relay" + (i + 1); if (!this.anyComponentUses(ioName, ignoreIds)) { availableIos.add(ioName); } @@ -471,16 +473,13 @@ public List getEnabledComponentsOfType(Class } @Override - public String getNextAvailableId(String baseName, int startingNumber, List components) { + public String getNextAvailableId(String baseName, int startingNumber, List componentIds) { for (var i = startingNumber; true; i++) { var id = baseName + i; - try { - this.componentManager.getComponent(id); + if (this.componentManager.getEdgeConfig().getComponent(id).isPresent()) { continue; - } catch (OpenemsNamedException e) { - // component with id not found } - if (components.stream().anyMatch(t -> t.getId().equals(id))) { + if (componentIds.stream().anyMatch(t -> t.equals(id))) { continue; } return id; diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/Config.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/Config.java index 7aebe35bf90..de69579952a 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/Config.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/Config.java @@ -8,6 +8,9 @@ description = "The global manager for OpenEMS Apps. (Changes are only applied to the components if the App gets updated via UI or JSONRPC-Request)") @interface Config { + @AttributeDefinition(name = "OpenEMS Key", description = "OpenEMS Key for installing the free apps.") // + String keyForFreeApps() default "0000-0000-0000-0000"; + @AttributeDefinition(name = "OpenEMS Apps", description = "OpenEMS App properties as a JSON Array") // String apps() default "[]"; diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/ConfigurationTarget.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/ConfigurationTarget.java index 2000c890929..eca31d35042 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/ConfigurationTarget.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/ConfigurationTarget.java @@ -1,7 +1,5 @@ package io.openems.edge.core.appmanager; -import org.osgi.service.metatype.annotations.AttributeDefinition; - public enum ConfigurationTarget { /** @@ -21,16 +19,6 @@ public enum ConfigurationTarget { */ DELETE, - /** - * Configuration will be used to remove properties that should not be saved in - * the configuration. e.g. removes passwords - * - *

      - * NOTE: this will be removed when the properties also have something like - * {@link AttributeDefinition}. - */ - DELETE_NOT_SAVED_PROPERTIES, - /** * Configuration will be used to test which ids can be replaced even though it * has errors e. g. not all passed values can be converted to enums but still diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/JsonFormlyUtil.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/JsonFormlyUtil.java index d8ae885654d..cd3e551bc67 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/JsonFormlyUtil.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/JsonFormlyUtil.java @@ -1,22 +1,27 @@ package io.openems.edge.core.appmanager; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; -import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.session.Language; import io.openems.common.utils.JsonUtils; -import io.openems.common.utils.JsonUtils.JsonObjectBuilder; +import io.openems.edge.app.enums.OptionsFactory; import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.core.host.NetworkConfiguration; /** * Source https://formly.dev/examples/introduction. @@ -34,7 +39,17 @@ private JsonFormlyUtil() { * @return a {@link CheckboxBuilder} */ public static > CheckboxBuilder buildCheckbox(T property) { - return new CheckboxBuilder(property); + return new CheckboxBuilder(toNameable(property)); + } + + /** + * Creates a JsonObject Formly Checkbox Builder for the given enum. + * + * @param nameable the {@link Nameable} property + * @return a {@link CheckboxBuilder} + */ + public static CheckboxBuilder buildCheckboxFromNameable(Nameable nameable) { + return new CheckboxBuilder(nameable); } /** @@ -45,7 +60,38 @@ public static > CheckboxBuilder buildCheckbox(T property) { * @return a {@link InputBuilder} */ public static > InputBuilder buildInput(T property) { - return new InputBuilder(property); + return new InputBuilder(toNameable(property)); + } + + /** + * Creates a JsonObject Formly Input Builder for the given enum. + * + * @param nameable the {@link Nameable} property + * @return a {@link InputBuilder} + */ + public static InputBuilder buildInputFromNameable(Nameable nameable) { + return new InputBuilder(nameable); + } + + /** + * Creates a JsonObject Formly Input Builder for the given enum. + * + * @param the type of the enum + * @param property the enum property + * @return a {@link InputBuilder} + */ + public static > FieldGroupBuilder buildFieldGroup(T property) { + return new FieldGroupBuilder(toNameable(property)); + } + + /** + * Creates a JsonObject Formly Input Builder for the given enum. + * + * @param nameable the {@link Nameable} property + * @return a {@link InputBuilder} + */ + public static FieldGroupBuilder buildFieldGroupFromNameable(Nameable nameable) { + return new FieldGroupBuilder(nameable); } /** @@ -56,7 +102,17 @@ public static > InputBuilder buildInput(T property) { * @return a {@link SelectBuilder} */ public static > SelectBuilder buildSelect(T property) { - return new SelectBuilder(property); + return new SelectBuilder(toNameable(property)); + } + + /** + * Creates a JsonObject Formly Select Builder for the given enum. + * + * @param nameable the {@link Nameable} property + * @return a {@link SelectBuilder} + */ + public static SelectBuilder buildSelectFromNameable(Nameable nameable) { + return new SelectBuilder(nameable); } /** @@ -67,7 +123,17 @@ public static > SelectBuilder buildSelect(T property) { * @return a {@link RangeBuilder} */ public static > RangeBuilder buildRange(T property) { - return new RangeBuilder(property); + return new RangeBuilder(toNameable(property)); + } + + /** + * Creates a JsonObject Formly Range Builder for the given enum. + * + * @param nameable the {@link Nameable} property + * @return a {@link RangeBuilder} + */ + public static RangeBuilder buildRangeFromNameable(Nameable nameable) { + return new RangeBuilder(nameable); } /** @@ -78,7 +144,119 @@ public static > RangeBuilder buildRange(T property) { * @return a {@link RepeatBuilder} */ public static > RepeatBuilder buildRepeat(T property) { - return new RepeatBuilder(property); + return new RepeatBuilder(toNameable(property)); + } + + /** + * Creates a JsonObject Formly Repeat Builder for the given enum. + * + * @param nameable the {@link Nameable} property + * @return a {@link RepeatBuilder} + */ + public static RepeatBuilder buildRepeat(Nameable nameable) { + return new RepeatBuilder(nameable); + } + + private static > Nameable toNameable(T property) { + return new StaticNameable(property.name()); + } + + public static final class StaticNameable implements Nameable { + + private final String name; + + public StaticNameable(String name) { + super(); + this.name = name; + } + + @Override + public String name() { + return this.name; + } + + } + + public enum Wrappers { + /** + * Wrapper for setting the default value dynamically based on the different + * {@link Case Cases}. + */ + DEFAULT_OF_CASES("formly-wrapper-default-of-cases"), // + + /** + * Wrapper for a panel. + */ + PANEL("panel"), // + ; + + private final String wrapperClass; + + private Wrappers(String wrapperClass) { + this.wrapperClass = wrapperClass; + } + + public String getWrapperClass() { + return this.wrapperClass; + } + + } + + public static class DefaultValueOptions { + + private final Nameable field; + private final List cases; + + public DefaultValueOptions(Nameable field, Case... cases) { + super(); + this.field = field; + this.cases = Arrays.stream(cases).collect(Collectors.toList()); + } + + /** + * Creates a {@link JsonObject} from this {@link DefaultValueOptions}. + * + * @return the {@link JsonObject} + */ + public JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .addProperty("field", this.field.name()) // + .add("cases", this.cases.stream().map(Case::toJsonObject).collect(JsonUtils.toJsonArray())) // + .build(); + } + + } + + public static class Case { + private final JsonElement value; + private final JsonElement defaultValue; + + public Case(JsonElement value, JsonElement defaultValue) { + super(); + this.value = value; + this.defaultValue = defaultValue; + } + + public Case(String value, String defaultValue) { + this(new JsonPrimitive(value), new JsonPrimitive(defaultValue)); + } + + public Case(Number value, String defaultValue) { + this(new JsonPrimitive(value), new JsonPrimitive(defaultValue)); + } + + /** + * Creates a {@link JsonObject} from this {@link Case}. + * + * @return the {@link JsonObject} + */ + public JsonObject toJsonObject() { + return JsonUtils.buildJsonObject() // + .add("case", this.value) // + .add("defaultValue", this.defaultValue) // + .build(); + } + } /** @@ -96,18 +274,20 @@ public static > RepeatBuilder buildRepeat(T property) { * "templateOptions.required": "model.PROPERTY" * }, * "hideExpression": "!model.PROPERTY", - * "defaultValue": "defaultValue" + * "defaultValue": "defaultValue", + * "wrappers": []{@link Wrappers} * } * * */ - private abstract static class FormlyBuilder> { + public abstract static class FormlyBuilder> implements OnlyIf, Self { protected final JsonObject jsonObject = new JsonObject(); protected final JsonObject templateOptions = new JsonObject(); private JsonObject expressionProperties = null; + private final List wrappers = new ArrayList<>(); - private > FormlyBuilder(PROPERTY property) { + private FormlyBuilder(Nameable property) { this.setKey(property.name()); this.setType(this.getType()); this.setLabel(property.name()); @@ -121,8 +301,12 @@ private FormlyBuilder(DefaultEnum property) { } private final T setType(String type) { + if (type == null) { + this.jsonObject.remove("type"); + return this.self(); + } this.jsonObject.addProperty("type", type); - return this.getSelf(); + return this.self(); } public final T setKey(String key) { @@ -131,7 +315,7 @@ public final T setKey(String key) { } else if (this.jsonObject.has("key")) { this.jsonObject.remove("key"); } - return this.getSelf(); + return this.self(); } public final T setDefaultValue(String defaultValue) { @@ -141,7 +325,7 @@ public final T setDefaultValue(String defaultValue) { this.jsonObject.remove("defaultValue"); } - return this.getSelf(); + return this.self(); } public final T setDefaultValue(Boolean defaultValue) { @@ -151,7 +335,7 @@ public final T setDefaultValue(Boolean defaultValue) { this.jsonObject.remove("defaultValue"); } - return this.getSelf(); + return this.self(); } public final T setDefaultValue(Number defaultValue) { @@ -161,7 +345,7 @@ public final T setDefaultValue(Number defaultValue) { this.jsonObject.remove("defaultValue"); } - return this.getSelf(); + return this.self(); } public final T setDefaultValue(JsonElement defaultValue) { @@ -171,7 +355,7 @@ public final T setDefaultValue(JsonElement defaultValue) { this.jsonObject.remove("defaultValue"); } - return this.getSelf(); + return this.self(); } public final T setDefaultValueWithStringSupplier(Supplier supplieDefaultValue) { @@ -182,13 +366,19 @@ public final T setDefaultValueWithBooleanSupplier(Supplier supplieDefau return this.setDefaultValue(supplieDefaultValue.get()); } + /** + * Sets if the input is required. Default: 'false' + * + * @param isRequired if the input is required + * @return this + */ public final T isRequired(boolean isRequired) { if (isRequired) { this.templateOptions.addProperty("required", isRequired); } else if (this.templateOptions.has("required")) { this.templateOptions.remove("required"); } - return this.getSelf(); + return this.self(); } public final T setLabel(String label) { @@ -197,38 +387,85 @@ public final T setLabel(String label) { } else if (this.templateOptions.has("label")) { this.templateOptions.remove("label"); } - return this.getSelf(); + return this.self(); } public final T setDescription(String description) { this.templateOptions.addProperty("description", description); - return this.getSelf(); + return this.self(); } /** - * Call a method on a FormlyBuilder if the expression is true. - * - * @param expression the expression - * @param consumer allows a lambda function on {@link FormlyBuilder} - * @return the {@link JsonObjectBuilder} + * Only shows the current input if the input of the given property is checked. + * + * @param nameable the {@link Nameable} + * @return this */ - public T onlyIf(boolean expression, Consumer consumer) { - if (expression) { - consumer.accept(this.getSelf()); - } - return this.getSelf(); + public final T onlyShowIfChecked(Nameable nameable) { + return this.onlyShowIf(ExpressionBuilder.of(nameable)); + } + + /** + * Only shows the current input if the input of the given property is not + * checked. + * + * @param nameable the {@link Nameable} + * @return this + */ + public final T onlyShowIfNotChecked(Nameable nameable) { + return this.onlyShowIf(ExpressionBuilder.of(nameable).negotiate()); + } + + /** + * Only shows the current input if the value of the input of the given property + * is the same as the given value. + * + * @param nameable the {@link Nameable} + * @param value the value to validate against + * @return this + */ + public final T onlyShowIfValueEquals(Nameable nameable, String value) { + return this.onlyShowIf(ExpressionBuilder.of(nameable, ExpressionBuilder.Operator.EQ, value)); } - public final > T onlyShowIfChecked(PROPERTEY property) { - this.getExpressionProperties().addProperty("templateOptions.required", "model." + property.name()); - this.jsonObject.addProperty("hideExpression", "!model." + property.name()); - return this.getSelf(); + private final T onlyShowIf(String expression) { + this.getExpressionProperties().addProperty("templateOptions.required", expression); + this.jsonObject.addProperty("hideExpression", "!(" + expression + ")"); + return this.self(); } - public final > T onlyShowIfNotChecked(PROPERTEY property) { - this.getExpressionProperties().addProperty("templateOptions.required", "!model." + property.name()); - this.jsonObject.addProperty("hideExpression", "model." + property.name()); - return this.getSelf(); + /** + * Only shows the current input if the given {@link ExpressionBuilder} returns + * true. + * + * @param expressionBuilder the {@link ExpressionBuilder} to set + * @return this + */ + public final T onlyShowIf(ExpressionBuilder expressionBuilder) { + return this.onlyShowIf(expressionBuilder.toString()); + } + + public final T setLabelExpression(ExpressionBuilder expression, String trueLabel, String falseLabel) { + this.getExpressionProperties().addProperty("templateOptions.label", + expression.toString() + " ? '" + trueLabel + "' : '" + falseLabel + "'"); + return this.self(); + } + + public final T setDefaultValueCases(DefaultValueOptions... defaultValueOptions) { + this.templateOptions.add("defaultValueOptions", Arrays.stream(defaultValueOptions) + .map(DefaultValueOptions::toJsonObject).collect(JsonUtils.toJsonArray())); + return this.addWrapper(Wrappers.DEFAULT_OF_CASES); + } + + /** + * Adds a wrapper to the current input. + * + * @param wrapper the {@link Wrappers} to add + * @return this + */ + public final T addWrapper(Wrappers wrapper) { + this.wrappers.add(wrapper.getWrapperClass()); + return this.self(); } public JsonObject build() { @@ -236,6 +473,10 @@ public JsonObject build() { if (this.expressionProperties != null && this.expressionProperties.size() > 0) { this.jsonObject.add("expressionProperties", this.expressionProperties); } + if (!this.wrappers.isEmpty()) { + this.jsonObject.add("wrappers", + this.wrappers.stream().map(JsonPrimitive::new).collect(JsonUtils.toJsonArray())); + } return this.jsonObject; } @@ -248,13 +489,231 @@ protected final JsonObject getExpressionProperties() { return this.expressionProperties; } + @Override @SuppressWarnings("unchecked") - private final T getSelf() { + public T self() { return (T) this; } } + public static final class ExpressionBuilder { + + public static enum Operator { + EQ("=="), // + NEQ("!="), // + ; + + private final String operation; + + private Operator(String operation) { + this.operation = operation; + } + + public String getOperation() { + return this.operation; + } + } + + private StringBuilder sb; + + /** + * Creates a {@link ExpressionBuilder} where the input of the given property + * gets validated against the given value. + * + * @param nameable the {@link Nameable} + * @param operator the {@link Operator} to validate against the value + * @param value the value to validate against + * @return the {@link ExpressionBuilder} + */ + public static final ExpressionBuilder of(Nameable nameable, Operator operator, String value) { + return new ExpressionBuilder(expressionOf(nameable, operator, value)); + } + + /** + * Creates a {@link ExpressionBuilder} where the value of the input of the given + * property gets validated. + * + * @param nameable the {@link Nameable} + * @return the {@link ExpressionBuilder} + */ + public static final ExpressionBuilder of(Nameable nameable) { + return new ExpressionBuilder(expressionOf(nameable)); + } + + private ExpressionBuilder(String baseExpression) { + this.sb = new StringBuilder(baseExpression); + } + + /** + * Combines the current expression with the given expression with an and. + * + * @param nameable the {@link Nameable} + * @param operator the {@link Operator} + * @param value the value to validate the input of the property + * @return this + */ + public ExpressionBuilder and(Nameable nameable, Operator operator, String value) { + return this.and(expressionOf(nameable, operator, value)); + } + + /** + * Combines the current expression with the given expression with an and. + * + * @param nameable the {@link Nameable} + * @return this + */ + public ExpressionBuilder and(Nameable nameable) { + return this.and(expressionOf(nameable)); + } + + /** + * Combines the current expression with the given expression with an and. + * + * @param builder the other expression + * @return this + */ + public ExpressionBuilder and(ExpressionBuilder builder) { + return this.and(builder.toString()); + } + + private final ExpressionBuilder and(String expression) { + this.sb.append(" && "); + this.sb.append(expression); + return this; + } + + /** + * Combines the current expression with the given expression with an or. + * + * @param nameable the {@link Nameable} + * @param operator the {@link Operator} + * @param value the value to validate the input of the property + * @return this + */ + public ExpressionBuilder or(Nameable nameable, Operator operator, String value) { + return this.or(expressionOf(nameable, operator, value)); + } + + /** + * Combines the current expression with the given expression with an or. + * + * @param nameable the {@link Nameable} + * @return this + */ + public ExpressionBuilder or(Nameable nameable) { + return this.or(expressionOf(nameable)); + } + + /** + * Combines the current expression with the given expression with an or. + * + * @param builder the other expression + * @return this + */ + public ExpressionBuilder or(ExpressionBuilder builder) { + return this.or(builder.toString()); + } + + private final ExpressionBuilder or(String expression) { + this.sb.append(" || "); + this.sb.append(expression); + return this; + } + + private static final String expressionOf(Nameable nameable, Operator operator, String value) { + return "model." + nameable.name() + " " + operator.getOperation() + " '" + value + "'"; + } + + private static final String expressionOf(Nameable nameable) { + return "model." + nameable.name(); + } + + private ExpressionBuilder addToFront(String string) { + final var nextBuilder = new StringBuilder(string); + this.sb = nextBuilder.append(this.sb); + return this; + } + + /** + * Puts the current statement in brackets. + * + * @return this + */ + public ExpressionBuilder inBrackets() { + this.sb.append(")"); + return this.addToFront("("); + } + + /** + * Negotiates the whole expression. + * + * @return this + */ + public ExpressionBuilder negotiate() { + this.sb.append(")"); + return this.addToFront("!("); + } + + @Override + public String toString() { + return this.sb.toString(); + } + + } + + public static final class FieldGroupBuilder extends FormlyBuilder { + + private JsonArray fieldGroup; + + private FieldGroupBuilder(Nameable property) { + super(property); + } + + private FieldGroupBuilder(DefaultEnum property) { + super(property); + } + + public FieldGroupBuilder setFieldGroup(JsonArray fieldGroup) { + this.fieldGroup = fieldGroup; + return this.self(); + } + + /** + * Hides the current key of the input. Results are all child inputs are not in + * the model as a JsonObject value of this key instead the are on the same level + * saved as this field. + * + * @return this + */ + public FieldGroupBuilder hideKey() { + this.setKey(null); + return this; + } + + @Override + protected String getType() { + return null; + } + + @Override + public JsonObject build() { + final var object = super.build(); + final var templateOptions = object.get("templateOptions").getAsJsonObject(); + templateOptions.remove("required"); + JsonUtils.getAsOptionalJsonObject(object, "expressionProperties") // + .map(t -> t.remove("templateOptions.required")); + object.add("fieldGroup", this.fieldGroup); + return JsonUtils.buildJsonObject() // + .add("hideExpression", object.remove("hideExpression")) // + .add("fieldGroup", JsonUtils.buildJsonArray() // + .add(object) // + .build()) + .build(); + } + + } + /** * A Builder for a Formly Input. * @@ -307,7 +766,8 @@ public String getFormlyTypeName() { } public static enum Validation { - IP("(\\d{1,3}\\.){3}\\d{1,3}", "Input is not a valid IP Address!"), // + // TODO translation + IP(NetworkConfiguration.PATTERN_INET4ADDRESS, "Input is not a valid IP Address!"), // ; private String pattern; @@ -331,7 +791,7 @@ public String getPattern() { private JsonObject validation = null; private Type type = Type.TEXT; - private > InputBuilder(PROPERTY property) { + private InputBuilder(Nameable property) { super(property); } @@ -494,7 +954,7 @@ protected final JsonObject getValidation() { public static final class RangeBuilder extends FormlyBuilder { - private > RangeBuilder(PROPERTY property) { + private RangeBuilder(Nameable property) { super(property); } @@ -561,7 +1021,7 @@ protected String getType() { */ public static final class CheckboxBuilder extends FormlyBuilder { - private > CheckboxBuilder(PROPERTY property) { + private CheckboxBuilder(Nameable property) { super(property); } @@ -605,11 +1065,12 @@ protected String getType() { */ public static final class SelectBuilder extends FormlyBuilder { - public static final Function DEFAULT_COMPONENT_2_LABEL = t -> t.alias() == null - || t.alias().isEmpty() ? t.id() : t.id() + ": " + t.alias(); - public static final Function DEFAULT_COMPONENT_2_VALUE = OpenemsComponent::id; + public static final Function DEFAULT_COMPONENT_2_LABEL = t -> new JsonPrimitive( + t.alias() == null || t.alias().isEmpty() ? t.id() : t.id() + ": " + t.alias()); + public static final Function DEFAULT_COMPONENT_2_VALUE = t -> new JsonPrimitive( + t.id()); - private > SelectBuilder(PROPERTY property) { + private SelectBuilder(Nameable property) { super(property); } @@ -646,21 +1107,25 @@ public SelectBuilder setOptions(Set> items, Function items) { - return this.setOptions(items, t -> t, t -> t); + return this.setOptions(items, JsonPrimitive::new, JsonPrimitive::new); } - public SelectBuilder setOptions(List items, Function item2Label, - Function item2Value) { + public SelectBuilder setOptions(List items, Function item2Label, + Function item2Value) { var options = JsonUtils.buildJsonArray(); for (var item : items) { options.add(JsonUtils.buildJsonObject() // - .addProperty("label", item2Label.apply(item)) // - .addProperty("value", item2Value.apply(item)) // + .add("label", item2Label.apply(item)) // + .add("value", item2Value.apply(item)) // .build()); } return this.setOptions(options.build()); } + public SelectBuilder setOptions(OptionsFactory factory, Language l) { + return this.setOptions(factory.options(l)); + } + /** * Sets if more than one options can be selected. * @@ -707,7 +1172,7 @@ public static final class RepeatBuilder extends FormlyBuilder { private JsonObject fieldArray; - private > RepeatBuilder(PROPERTY property) { + private RepeatBuilder(Nameable property) { super(property); } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/Nameable.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/Nameable.java new file mode 100644 index 00000000000..6e811538c42 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/Nameable.java @@ -0,0 +1,12 @@ +package io.openems.edge.core.appmanager; + +public interface Nameable { + + /** + * Gets the name of the current instance. + * + * @return the name + */ + public String name(); + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OnlyIf.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OnlyIf.java new file mode 100644 index 00000000000..e2e794292a9 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OnlyIf.java @@ -0,0 +1,21 @@ +package io.openems.edge.core.appmanager; + +import java.util.function.Consumer; + +public interface OnlyIf> extends Self { + + /** + * Only executes the given consumer if the expression is true. + * + * @param expression the expression + * @param consumer the {@link Consumer} to execute + * @return {@link Self#self()} + */ + public default T onlyIf(boolean expression, Consumer consumer) { + if (expression) { + consumer.accept(this.self()); + } + return this.self(); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsApp.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsApp.java index 79e141a1ac6..95a1c6bb09a 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsApp.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsApp.java @@ -49,7 +49,7 @@ public AppConfiguration getAppConfiguration(ConfigurationTarget target, JsonObje * * @return the category's */ - public OpenemsAppCategory[] getCategorys(); + public OpenemsAppCategory[] getCategories(); /** * Gets the image of the {@link OpenemsApp} in Base64 encoding. @@ -73,6 +73,15 @@ public AppConfiguration getAppConfiguration(ConfigurationTarget target, JsonObje */ public OpenemsAppCardinality getCardinality(); + /** + * Gets all {@link OpenemsAppPropertyDefinition} of the app. + * + * @return the {@link OpenemsAppPropertyDefinition + * OpenemsAppPropertyDefinitions} + * @throws UnsupportedOperationException if not implemented + */ + public OpenemsAppPropertyDefinition[] getProperties(); + /** * Gets the {@link ValidatorConfig} of this {@link OpenemsApp}. * @@ -80,6 +89,13 @@ public AppConfiguration getAppConfiguration(ConfigurationTarget target, JsonObje */ public ValidatorConfig getValidatorConfig(); + /** + * Gets the {@link OpenemsAppPermissions} of this {@link OpenemsApp}. + * + * @return the permissions + */ + public OpenemsAppPermissions getAppPermissions(); + /** * Validate the {@link OpenemsApp}. * @@ -87,54 +103,182 @@ public AppConfiguration getAppConfiguration(ConfigurationTarget target, JsonObje */ public void validate(OpenemsAppInstance instance) throws OpenemsNamedException; - public static final String FALLBACK_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY5" // - + "1AAABhWlDQ1BJQ0MgUHJvZmlsZQAAKM+VkT1Iw1AUhU9TpVIqgu0g4pChOlkQFXGUKBbBQmkrtOpg8tI/aNKQpLg4Cq4FB38Wqw" // - + "4uzro6uAqC4A+Io5OToouUeF9SaBEqeOHxPs5753DffYDQqDDN6pkANN02U3FJzOZWxcArfAghiEGEZWYZifRiBl3r655uU93Fe" // - + "Bb+V/1q3mKATySeY4ZpE28Qz2zaBud94ggrySrxOfG4SQ0SP3Jd8fiNc9FlgWdGzExqnjhCLBY7WOlgVjI14mniqKrplC9kPVY5" // - + "b3HWKjXW6pO/MJTXV9JcpzWCOJaQQBIiFNRQRgU2YrTrpFhI0bnUxT/s+pPkUshVBiPHAqrQILt+8D/4PVurMDXpJYUkoPfFcT5" // - + "GgcAu0Kw7zvex4zRPAP8zcKW3/dUGMPtJer2tRY+AgW3g4rqtKXvA5Q4w9GTIpuxKflpCoQC8n9E35YDwLRBc8+bWOsfpA5ChWS" // - + "3fAAeHwFiRste7vLuvc25/3nHnB+kHJSZyiKHoIYQAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAxQSURBVHhe7d15jCxVFQfgh+IaJ" // - + "YKCigsCCqKJCFGD0SCowYBhiyBGwR0VAm5RSXBFIgYIbiCSKKIR1EBccGFRUXEB1KjgCoobm1GMiLuI6DlT1TJvXr03XdXV3VXV" // - + "35f8cm/3Hz0901Onb1XdqrsGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" // - + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOiOjcoWhmKTyL1W5D+RPyzLzR" // - + "F6SMGiz7aNPD6yS9k+OnKHyGpuiWThuirytWW5NcIAXRL574Lnx5H7RCZxaOR7kfzGv63lVL3ntvKbyO6ReXhs5NTIdZGq99Y0W" // - + "ay+HHlL5BGRNp0Y+VOk6ucuSvLz2jcyc6+IVL2hRUxuOE29K1L1mn3JdyOz9PzIxZGq9zKNnBvZJzKpHSJVr7+IuToyc5+PVL2Z" // - + "RUzTDyC/aaper2/JXbJpe17kxkjVz59FfhR5VaQpX/Br55GRxsbZ319pu7Kl2GA3Lrq17Fy2fbdl2U5D7m5/JPKhsj8vuYG9I5K" // - + "HAA7MJ2p6aNlS2LpsG2lSsO5ZthTyrFRd25dt303rf+FZkRzZHLz0qBvyuNbZkZOWHo3P9rK2JtvL/zUpWHcqWwpNRliblm3f3b" // - + "Fs23Rk5GOR+y496p5XR+ocPG7y/zFkE9WPJgXrL2VL4a9lu4ja/l94aeQ9RbfTDijbcSzy/0eVif5nmhQsH8DtckLi34vuQvp92" // - + "bYhzwKeVnQ7r860B9vL2mZesM4rW4ozpovqJ2XakHO6zii6rfhbJOf9/DCSE0JzrtsvI3+MtKHO7uoFZcuaNf+IfKnozk6e9fhd" // - + "pOqU5aLlKZEmLoxUvV5fkhNH94i05bJI1c8ZNz+PvDuSB+sfHNmQPO72uMjhkdMj10aqXnNDqTtK+HSk6nUWLa+PTKTppTl3i+x" // - + "VdCeWo7x8H9ku74/aut+8b4jcUHQbGf1xl88WH/WXP5eTGHN+UBNZsOps8MdF3lt052L0O4/S5q7gayMnFN3arojkMa8PLj1qbs" // - + "/IQZGc8zWOLFh1z3bll1te1zipldvHyv4rIztGxpXF9DNFt7Gq7WPlc1dG8szv4I3+AOMmZxZ3Xd0R1lGRIco5Of+OVP3Oq+Wdk" // - + "bblrl5empMFuepnjpK7m111eaTqPa8vb4r0RlZkmJdjIk1O++cB+klmn69PHurIgpUTYt8ayZMqVSYZwXdNFq3eGGLB6tUHsOCa" // - + "XAx7WOTDRXdq8kLoN0e2ieSxsZW+U7bMmBEW87J3pO5xoOMjs5z6cE0kjwk9JJKXCI28v2yHwAhrzoyw+qHu6CqPddW9LKYteVb" // - + "0BZEHRjaP5HGioVCwYAx1C1aeDWx6VrYt10fyxn/MiREW85Cn3evegeH8sqVdRliwii3Kdlw3RS4quiwyIyzmoe6dGHImO9NhhA" // - + "WrqFuwflu2LDgjLOah7i6hZbmmxwgLVlF3hJUTOEHBYi5yyas6FKzpMcKCVeRZvzry2r68QwgLTsFiHprcSG+/sqVdRliwiiYFK" // - + "+/3zurqFiAFC1bRpGA9KfLEosuiUrCYh69G8hYudZ1YtrTHCAtWkYsR5K1569olsvw2LywYBYt5+VTZ1pX3XX9j0aVCr0ZMdSlY" // - + "zMsnI012C1Pevvh9RZcJ2SWEMfwzMslKQC+LnBsZyrL/bXGWEKYkly+bZOXsfSI/jjxn6RGDp2AxT7mcVhatSdw/cmbkrEjewnj" // - + "RGWHBFL0tkvdMn9SzI7mKcy5UUfdupvSEgkUX5AIPbXldJFe7yTUPN8snFowRFkzZVyIvKbqtyAulc0XjvPFfrrSTK0wzALkmf9" // - + "fV/QZ4WOTqottZuVT9HkV3LDlnabS8/W1lu6F+m34duaToTt0JkdcW3dadHjk5csXSo+HKRV4fU3THkusuVi0WS0OjjXDcPDTSd" // - + "aPi05fkP/Ws5MZT9R7aytmRXSND9e1I1e+9vrwi0ht2CRnHy8t2FnIDOrboTsWBkYsj50V2yycWXBat3lCwGEceA3pE0Z2JPP70" // - + "mqI7NXtG8tjZOZHH5hMD0asCVJeCxbg2KdtZyYPlT478cOnR9BwQyd2ovKh6lkW5K4ywGKR7lu0s5QjoUZFcpn7a8qLqnDWflwt" // - + "tlU/0lBEWhLz2b17yuNbTIrNY/fnwSJ4ZPXrp0fAZYTFI814b8AuRp0b2j1yWT0xZzsD/RiTvwdUnRlgsvLyl8Q+K7tzljf8eHz" // - + "k4Mu339ITIpZE8CUAHKFiMY5LbwExLXuy8YyQXp/hFPjFFeZnPKUW38wY9wjLTfT7qznT/bKSN4zfLZ8Mvz4ae/2Xk65Guy8KVx" // - + "5/yIP205BSIgyL5t+mqvCohR6DjOjLSl2LcCys3otUyxJnuR0UYT04MzbOLVX/HNnJBpMuyYFW97/XliEhv2CVkaHIUtHskD9Dn" // - + "bZjblmcr85rErsoiNFgKFkOVu9DPiOwUuTKfaFGOSmZ5uRIlBYuhuzyyQySPbX0kn2hJXqTdxWsRjbBgAPISn+dGHhfJOV1tsNz" // - + "YjClYLJq8X1Qeh8pb5vw7n5hAXut4SNHtDCMsGKDcpXtkJM8oTsKk0hlSsFhkP4/kKGmSY1s5jSYvnO4KIywYuDy29fai28i+Zc" // - + "uUKVhQyLsz5L3zm8iCdfeiyzQpWHC7F0eaXJeY21FXRll2CWFB5F0pmk4IzWXzmTIFC9aWi1N8v+jWcu+ynTcjLFgwp5VtHYu4y" // - + "vTMKViwribTHLpSsIywYMH8I3JD0R1bV3YJB03Bgmp548I6chm0jYvuXBlhwQKqW7BujNxadJkWBQuq3aVsx1V3F3JajLBgAT2g" // - + "bMf127JlihQsqKZgdZCCBevaNLJ10R2bXcIZULBgXXuXbR1GWDOgYMG6mlwXmJf0dIERFiyQrSK52k4d3478qugyTQoWs3ZY5Nz" // - + "Ii5Yedc/ry7aOz5VtFxhhQUsOiJwayV2uD0SuiOwf6YrHRA4turV0qWANmoLFLO1RtiO5VmCuznx6ZPN8Yo62j3y86Nbys0iT29" // - + "FMixEWtCRHMFVeGLkmckxkHrcazmL1+ci2S4/qOaFsmQEFi1m6R9lWuWskl8zKwnV8ZLvILOQCFN+MNClWuSuYo8MuMcKClmyoY" // - + "I3kbVpeF7kq8olI3TN248pR1VmRD0ea3hrmqLJlRjYq2y6r+43xsMjVRbezLoysPJ6zITniyIPV+bcYZZ5yxeTfF91ach3AXMev" // - + "rj9Fzo6cE/lG5J+Rpp4eycUm9lt61FyeTTyu6HbKBZFc2XpcR0ZOKbq0YflGOk6abBCzlgWr6r33KVk86spl4qteq24ui7wzclB" // - + "k18jOkfyiun8kR3H3izw8sktkz8ibI7n7lkW26vXq5qJIV50fqXrP68sREVpU9UfeUBSs2eU1kTo+Gql6nT7l65Fxdm3nZdAFyz" // - + "EsJrFX2Y7ri2XbVzmjPeeQ/XXpUTdlERqsPhSsQX8APbdl2Y7rjMglRbd3Lo9ksbpp6RFzYYTFJJrsGuXUheuLbm/khc15B4ffL" // - + "T3qNiOsORviBzCUb+kmZ5nzgHUeDG9y0H4e8jhdnlm8bukRc2WENR95OccQ/Lls68qN/5mRQyJduqxluYsjO0VOWnrUH0ZYczbE" // - + "D+CnZdt3dVeWWenMSE5JyMKV86u6IL9Mjo7sFsnjVlDLlZEsWuOmLwtavidS9f77lMMjbcrilfOr8vKcqp83zeRF2E3uNNo1J0e" // - + "qfr/15eAILcqJf9dGqv7Yy5PrwvVtEtzzI9+K/CHyrw7mlvUkdwWb3Nmgjt0jWdR/Eqn6vCfNfyJ5DeGxkW0iQ/GgSM52r/qdly" // - + "evFujdDPc+XJozkrcfyeu/st0icudIFqlM7pq44+Nw5eedB+ozOYM9Z7Vnxl07MItvfinkDPlLyzaTRWuo8m+zY2S0vWwWGW0vu" // - + "WBG3ousd/pUsGClHBnl1IrcOEfJ0UOOAG8uk/1Jrj0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" // - + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" // - + "AAAAAAAAAAABoyZo1/wOlH2CkLUZ0qwAAAABJRU5ErkJggg=="; + public static final String FALLBACK_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY5" + + "1AAABhWlDQ1BJQ0MgUHJvZmlsZQAAKM+VkT1Iw1AUhU9TpVIqgu0g4pChOlkQFXGUKBbBQmkrtOpg8tI/aNKQpLg4Cq4FB38Wqw" + + "4uzro6uAqC4A+Io5OToouUeF9SaBEqeOHxPs5753DffYDQqDDN6pkANN02U3FJzOZWxcArfAghiEGEZWYZifRiBl3r655uU93Fe" + + "Bb+V/1q3mKATySeY4ZpE28Qz2zaBud94ggrySrxOfG4SQ0SP3Jd8fiNc9FlgWdGzExqnjhCLBY7WOlgVjI14mniqKrplC9kPVY5" + + "b3HWKjXW6pO/MJTXV9JcpzWCOJaQQBIiFNRQRgU2YrTrpFhI0bnUxT/s+pPkUshVBiPHAqrQILt+8D/4PVurMDXpJYUkoPfFcT5" + + "GgcAu0Kw7zvex4zRPAP8zcKW3/dUGMPtJer2tRY+AgW3g4rqtKXvA5Q4w9GTIpuxKflpCoQC8n9E35YDwLRBc8+bWOsfpA5ChWS" + + "3fAAeHwFiRste7vLuvc25/3nHnB+kHJSZyiKHoIYQAAAAJcEhZcwAADsQAAA7EAZUrDhsAADEISURBVHhe7Z0JmCVVlaDPe7lVF" + + "UmJCAIqKuKKS4MMsilbVZajjmvj1oJAiy0qkFCVWYKgQCMo1AK0MCh0i5+oiIg66DgzVIIgUirqiA4O7QIiIo2KyFZ7Zr4+JyJO" + + "5nn33Rvbi3jLjfN/36k499z93hPnRUS9fAGKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoii" + + "KoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoi" + + "iKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKkkgtOnadRqMRaYqi9AO1WufDRz06Koqi9DwasBRF6Rs0YCmK0" + + "jdowFIUpW/QgKUoSt+gAUtRlL5BA5aiKH2Dt9/Dir4jkjUgz6Ik1ZFl2tH95dATB2Fk0ZWovR539kz4ybVXwiP3h3mtlLlW1AZB" + + "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" + + "hR/7h88BizbRtpFyzj7PX+k/mnzzR297xYHTW7aaL3Nlv6ay7N+V8WOfJ0pzyza/8m/7FcWG9FVTN0nK95rKTTiWNr4JoXSfV33" + + "1p8+JVMVTfD5D01wuyTJCL/Z/LJXOcMc79qVvh/crenmfAp8DFs2NnMB0BJtjkC1ciyBW9cy3PZRs9PNJz/7KRHquD89+XodYfA" + + "5YBM3PdAQ5Z9bnbRqr+hm5t/2IxTdzOWS/r4MTbyeGUJDiQOWap7efRErfIf2ViPSWK6xK+6zPAYvmRhK3wcb8m53jVdff+dZIV" + + "fqDfj6Z2V8ZwzetWAKc36RZlH6H5sibmWVTn3nH3+/9zUhX+oNu+TP1247E0HJLKMu7dG/xeZIUnDhA8TzN+RoBrMk5/oiiT7SU" + + "LEh/itNNYaQeEfvQ3VLeb3wOWDQ3kjiHMOaf639kOg3PK6/4TLdPYLm+rNOYzHXnvWBhzHI2KhekJGkWqN+hOdImmxst05EuLqh" + + "ClezSqVgvSgibPU7axdamSnsSh5mfVN4g9pZQYvFn/8i4eH0FbRpvHM2ThXHofJUVOIqrfFGU0WanME8QM81I3SRNnTRtuewM5S" + + "eVScI1jjTtcv8sReHyz372q1i8nRhCc+P5sZNIZ3E4TuxjqySncOUn1esERfXL60btST0N5vpzvTw6I+2EmWdCNrabOmPTZR8u3" + + "QWVkaLkxOfFk05nwzL3xGdY1CbXkzpBunRu2b9L7yRF9WvOmSlap/Fm1QlKmzod0+iE1Ampd4/kx6s0bkbqXtEbm1EevHE8z7j5" + + "Ylm+umryDnPzXY7h0qtCnjnHrZkraOTVqf2sdSVd2lP0Rfo13tgL/4A0c+h7vJ0YQnPj+aVxtvr8z8s0eUdZjtClEyCWduaaZ22" + + "4jgwmcl1cehxp6qRtS5JnfsWQHKwqQ/c2oXykU6abp/x5GftvzOdxdBe9uPY8PzoWOdck5Fok6XJcNp3KZdEJqfcYFK2cEcs1hx" + + "6eT3uwE/hI9rlJv+jsD+z3muP1sl/IsZk6r1danZH2MuE+ZF8JOn1wtjyiSFPfS+SmKbNyv61XWEnrZZ4EjEtnspQtmnb6Nk+Qo" + + "k+YuPZkHus0ZqkzaeaVZr7twn2kGVukt1xhkZ3Lxele4u3EkOwnT/Ivjia1aTuJCJfeC9jGRkfXOOPsvIBmfVcdxlbWtJltyL7k" + + "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" + + "HB143DBsvxO9RuvjmHpqaAz4WfTzN9+L0kXh2p+q4OV8+++ESY85t3YDhHT6PM4g67NuG0+740yLHAsh+00ew5JTnwoDgxh8ah/" + + "ClHwN2Q0YgCYxAP0mSIU/T/w6LEdvp3lxYAv5E3bzMdj46Ofg+1f69pyqU3sYB++vV3R7UcukzLmlccg4h6G6/eRQ7rmOTb4Ygl" + + "dlNSgoRcYG/e7Uv+At3tegVqcXk4o82ILpT8PM9Hlw00V5XqOlpEMDVp/hmpsMNmkCjwnXYYew6WnazNN3XuQYy2Fs8nXYCwaum" + + "ryKMmjcALOzEzC15reRoVOUP//ew8v5duqE6QauuclA0W7QyOoUacbUKcw+s45Blg/1g44dgtGdo9e9y+dUjbugUVsOt185BRvp" + + "O6hWqA3CHIPLXhSt82jFZU/CbJsoax4m3J9XdGrxukGvzc3m9GwzHTtOpyOTtg5h6lngehKy2dtZcupOMDB4DhZ5G94WngsbHr4" + + "C1l+V/D+I/uNes+LpVD+KoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoi" + + "iKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKo" + + "iiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKoiiKongEwH8CPRgCMWTNy0IAAAAASUVO" + + "RK5CYII="; + } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppCategory.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppCategory.java index b70c3a5a455..4d4d3e7958c 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppCategory.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppCategory.java @@ -29,6 +29,11 @@ public enum OpenemsAppCategory { */ HEAT("heat"), + /** + * Ess Controller. + */ + ESS("ess"), + /** * Load Control. */ diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppInstance.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppInstance.java index 80113ba11e4..7240d9a6c67 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppInstance.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppInstance.java @@ -23,9 +23,9 @@ public class OpenemsAppInstance { public OpenemsAppInstance(String appId, String alias, UUID instanceId, JsonObject properties, List dependencies) { - this.appId = appId; + this.appId = Objects.requireNonNull(appId); this.alias = alias; - this.instanceId = instanceId; + this.instanceId = Objects.requireNonNull(instanceId); this.properties = properties; this.dependencies = dependencies; } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppPermissions.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppPermissions.java new file mode 100644 index 00000000000..cddb33776d2 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppPermissions.java @@ -0,0 +1,43 @@ +package io.openems.edge.core.appmanager; + +import io.openems.common.session.Role; + +public class OpenemsAppPermissions { + + public final Role canSee; + + public static final class Builder { + private Role canSee = Role.OWNER; + + private Builder() { + super(); + } + + public Builder setCanSee(Role canSee) { + this.canSee = canSee; + return this; + } + + public OpenemsAppPermissions build() { + return new OpenemsAppPermissions(// + this.canSee // + ); + } + + } + + /** + * Creates a {@link Builder} for {@link OpenemsAppPermissions}. + * + * @return the builder + */ + public static final Builder create() { + return new Builder(); + } + + private OpenemsAppPermissions(Role canSee) { + super(); + this.canSee = canSee; + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppPropertyDefinition.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppPropertyDefinition.java new file mode 100644 index 00000000000..253a4b79b2c --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/OpenemsAppPropertyDefinition.java @@ -0,0 +1,44 @@ +package io.openems.edge.core.appmanager; + +import java.util.Optional; +import java.util.function.Function; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.openems.common.session.Language; + +public class OpenemsAppPropertyDefinition { + + public final String name; + + public final Function defaultValue; + + public final boolean isAllowedToSave; + + public final Function bidirectionalValue; + + public OpenemsAppPropertyDefinition(// + final String name, // + final Function defaultValue, // + final boolean isAllowedToSave, // + final Function bidirectionalValue // + ) { + this.name = name; + this.defaultValue = defaultValue; + this.isAllowedToSave = isAllowedToSave; + this.bidirectionalValue = bidirectionalValue; + } + + /** + * Gets an {@link Optional} of the defaultValue. + * + * @param language the {@link Language} of the value + * @return the defaultValue + */ + public final Optional getDefaultValue(Language language) { + return Optional.ofNullable(this.defaultValue) // + .map(t -> t.apply(language)); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/ResolveDependencies.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/ResolveDependencies.java new file mode 100644 index 00000000000..2d5003d4ddc --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/ResolveDependencies.java @@ -0,0 +1,158 @@ +package io.openems.edge.core.appmanager; + +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.session.Language; +import io.openems.common.utils.ServiceUtils; +import io.openems.edge.common.user.User; +import io.openems.edge.core.appmanager.dependency.DependencyDeclaration.AppDependencyConfig; +import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; + +public class ResolveDependencies implements Runnable { + + private static final Logger LOG = LoggerFactory.getLogger(ResolveDependencies.class); + + private final BundleContext bundleContext; + + public ResolveDependencies(// + BundleContext bundleContext // + ) { + super(); + this.bundleContext = bundleContext; + } + + @Override + public void run() { + try (var appManagerService = ServiceUtils.useService(this.bundleContext, AppManager.class); // + var appManagerUtilService = ServiceUtils.useService(this.bundleContext, AppManagerUtil.class)) { + final var appManager = appManagerService.getService(); + final var appManagerUtil = appManagerUtilService.getService(); + + if (appManager == null || appManagerUtil == null) { + LOG.warn("Unable to get references to AppManager and/or AppManagerUtil!"); + return; + } + + resolveDependencies(null, (AppManagerImpl) appManager, appManagerUtil); + LOG.info("Resolved dependencies."); + } catch (Exception e) { + // unable to get references or resolve + LOG.error("Could not resolve dependencies!", e); + } + } + + /** + * Resolves missing dependencies. + * + *

      + * protected so it can be used in a unit test + * + * @param user the executing {@link User} + * @param appManagerImpl the {@link AppManagerImpl} + * @param appManagerUtil the {@link AppManagerUtil} + */ + protected static void resolveDependencies(User user, AppManagerImpl appManagerImpl, AppManagerUtil appManagerUtil) { + final var instances = appManagerImpl.getInstantiatedApps(); + for (var instance : instances) { + try { + var configuration = appManagerUtil.getAppConfiguration(ConfigurationTarget.VALIDATE, instance, + Language.DEFAULT); + + // check if instance should have dependencies + if (configuration.dependencies == null || configuration.dependencies.isEmpty()) { + if (instance.dependencies != null && !instance.dependencies.isEmpty()) { + LOG.info(String.format("Instance %s has unnecessary dependencies!", instance.instanceId)); + } + continue; + } + + // remove satisfied dependencies + for (var dependency : configuration.dependencies) { + // dependency exists + if (instance.dependencies != null && instance.dependencies.stream() // + .anyMatch(t -> t.key.equals(dependency.key))) { + continue; + } + + // dependency not found + final var config = determineDependencyConfig(// + appManagerImpl, appManagerUtil, dependency.appConfigs// + ); + + if (config == null || config.appId == null) { + continue; + } + + var shouldInstallConfig = false; + switch (dependency.createPolicy) { + case NEVER: + // can not resolve dependency automatically + LOG.warn(String.format("Unable to automatically add dependency for %s and key %s.", + instance.instanceId, dependency.key)); + continue; + case IF_NOT_EXISTING: + if (!instances.stream().anyMatch(t -> t.appId.equals(config.appId))) { + shouldInstallConfig = true; + } + break; + case ALWAYS: + shouldInstallConfig = true; + break; + } + if (!shouldInstallConfig) { + continue; + } + + try { + LOG.info(String.format("Resolving dependency with installing %s!", config.appId)); + var future = appManagerImpl.handleAddAppInstanceRequest(user, // + new AddAppInstance.Request(// + config.appId, "key", // + config.alias, // + config.initialProperties), + true); + future.get(); + } catch (OpenemsNamedException | InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + } catch (OpenemsNamedException e) { + // unable to get configuration of instance + LOG.error("Unable to get AppConfiguration", e); + } + } + } + + private static AppDependencyConfig determineDependencyConfig(// + final AppManagerImpl appManagerImpl, // + final AppManagerUtil appManagerUtil, // + final List configs // + ) { + if (configs == null || configs.isEmpty()) { + return null; + } + // if there is already an instance which can be used for the dependency return + // null so no new instance gets installed + for (var config : configs) { + var instances = appManagerImpl.getInstantiatedApps().stream().filter(i -> i.appId.equals(config.appId)) + .collect(Collectors.toList()); + for (var instance : instances) { + var existingDependencies = appManagerUtil.getAppsWithDependencyTo(instance); + if (existingDependencies.isEmpty()) { + return null; + } + } + } + + return configs.get(0); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/Self.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/Self.java new file mode 100644 index 00000000000..74c04eb9e80 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/Self.java @@ -0,0 +1,12 @@ +package io.openems.edge.core.appmanager; + +public interface Self> { + + /** + * Gets itself. + * + * @return this + */ + public T self(); + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/TranslationUtil.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/TranslationUtil.java index a1a2f128088..5926d9f1e95 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/TranslationUtil.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/TranslationUtil.java @@ -2,6 +2,7 @@ import java.text.MessageFormat; import java.util.MissingResourceException; +import java.util.Objects; import java.util.ResourceBundle; public class TranslationUtil { @@ -17,7 +18,10 @@ public class TranslationUtil { */ public static String getTranslation(ResourceBundle translationBundle, String key, Object... params) { try { - var string = translationBundle.getString(key); + var string = Objects.requireNonNull(translationBundle).getString(Objects.requireNonNull(key)); + if (params == null || params.length == 0) { + return string; + } return MessageFormat.format(string, params); } catch (MissingResourceException | IllegalArgumentException e) { e.printStackTrace(); diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/Type.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/Type.java new file mode 100644 index 00000000000..d6132f07bc9 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/Type.java @@ -0,0 +1,123 @@ +package io.openems.edge.core.appmanager; + +import java.util.ResourceBundle; +import java.util.function.Function; +import java.util.function.Supplier; + +import io.openems.common.session.Language; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; + +public interface Type

      // + extends Self> { + + public class Parameter { + + public static class BundleParameter extends Parameter { + public final ResourceBundle bundle; + + public BundleParameter(ResourceBundle bundle) { + this.bundle = bundle; + } + + public final ResourceBundle getBundle() { + return this.bundle; + } + + } + + /** + * Creates a {@link BundleParameter} of a {@link ResourceBundle}. + * + * @param bundle the {@link ResourceBundle} + * @return the {@link BundleParameter} + */ + public static final BundleParameter of(ResourceBundle bundle) { + return new BundleParameter(bundle); + } + + /** + * Creates a {@link BundleParameter} of a {@link ResourceBundle}. + * + * @param bundle the {@link ResourceBundle} + * @return the {@link BundleParameter} + */ + public static final Supplier supplierOf(ResourceBundle bundle) { + return () -> of(bundle); + } + + /** + * Creates a {@link Function} to get a instance of {@link BundleParameter}. + * + * @param the type of the {@link OpenemsApp} + * @param resourceBundleSupplier the supplier to get the {@link ResourceBundle} + * @return the {@link Function} + */ + public static final Function, BundleParameter> functionOf( + Function resourceBundleSupplier) { + return t -> of(resourceBundleSupplier.apply(t.language)); + } + + /** + * Creates a Empty {@link Parameter}. + * + * @return the {@link Parameter} + */ + public static final Parameter empty() { + return new Parameter(); + } + + } + + /** + * Gets the {@link AppDef} of the property. + * + * @return the {@link AppDef} + */ + public AppDef def(); + + /** + * Gets the name of the property. + * + * @return the name + */ + public String name(); + + public static final class GetParameterValues { + public final APP app; + public final Language language; + + public GetParameterValues(APP app, Language language) { + this.app = app; + this.language = language; + } + + } + + /** + * Gets a function to get the parameters. + * + * @return the function + */ + public Function, M> getParamter(); + + /** + * Gets a function to get a {@link ResourceBundle} for translation. + * + *

      + * If the {@link Parameter} type is a BundleParamter, + * {@link BundleParameter#bundle} will get returned. + * + * @return the function + */ + public default Function translationBundleSupplier() { + return p -> { + if (p instanceof BundleParameter) { + return ((BundleParameter) p).bundle; + } + return null; + }; + } + +} \ No newline at end of file diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/AppManagerAppHelper.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/AppManagerAppHelper.java index b50f680991d..2d5eb15d54b 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/AppManagerAppHelper.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/AppManagerAppHelper.java @@ -13,7 +13,7 @@ public interface AppManagerAppHelper { * @param user the executing user * @param instance the settings of the new {@link OpenemsAppInstance} * @param app the {@link OpenemsApp} - * @return s a list of the created {@link OpenemsAppInstance}s + * @return a list of the created {@link OpenemsAppInstance OpenemsAppInstances} * @throws OpenemsNamedException on error */ public UpdateValues installApp(User user, OpenemsAppInstance instance, OpenemsApp app) throws OpenemsNamedException; @@ -26,7 +26,7 @@ public interface AppManagerAppHelper { * configurations. * @param instance the settings of the new {@link OpenemsAppInstance} * @param app the {@link OpenemsApp} - * @return s a list of the replaced {@link OpenemsAppInstance}s + * @return a list of the replaced {@link OpenemsAppInstance OpenemsAppInstances} * @throws OpenemsNamedException on error */ public UpdateValues updateApp(User user, OpenemsAppInstance oldInstance, OpenemsAppInstance instance, @@ -37,7 +37,7 @@ public UpdateValues updateApp(User user, OpenemsAppInstance oldInstance, Openems * * @param user the executing user * @param instance the instance to delete - * @return s a list of the removed {@link OpenemsAppInstance}s + * @return a list of the removed {@link OpenemsAppInstance OpenemsAppInstances} * @throws OpenemsNamedException on error */ public UpdateValues deleteApp(User user, OpenemsAppInstance instance) throws OpenemsNamedException; diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/AppManagerAppHelperImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/AppManagerAppHelperImpl.java index 0ffd0719c44..1f59dcd73fa 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/AppManagerAppHelperImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/AppManagerAppHelperImpl.java @@ -8,6 +8,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; @@ -26,6 +27,7 @@ import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; import org.osgi.service.component.annotations.ReferencePolicyOption; +import org.osgi.service.component.annotations.ServiceScope; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,15 +56,26 @@ import io.openems.edge.core.appmanager.dependency.DependencyDeclaration.AppDependencyConfig; import io.openems.edge.core.appmanager.validator.Validator; -@Component +@Component(// + immediate = true, // + scope = ServiceScope.SINGLETON // +) public class AppManagerAppHelperImpl implements AppManagerAppHelper { private final Logger log = LoggerFactory.getLogger(this.getClass()); - @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) + @Reference(// + policy = ReferencePolicy.DYNAMIC, // + policyOption = ReferencePolicyOption.GREEDY, // + cardinality = ReferenceCardinality.OPTIONAL // + ) private volatile AppManager appManager; - @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) + @Reference(// + policy = ReferencePolicy.DYNAMIC, // + policyOption = ReferencePolicyOption.GREEDY, // + cardinality = ReferenceCardinality.OPTIONAL // + ) private volatile AppManagerUtil appManagerUtil; private final ComponentManager componentManager; @@ -80,10 +93,14 @@ public class AppManagerAppHelperImpl implements AppManagerAppHelper { private TemporaryApps temporaryApps; @Activate - public AppManagerAppHelperImpl(@Reference ComponentManager componentManager, @Reference ComponentUtil componentUtil, - @Reference Validator validator, @Reference AggregateTask.ComponentAggregateTask componentsTask, - @Reference AggregateTask.SchedulerAggregateTask schedulerTask, - @Reference AggregateTask.StaticIpAggregateTask staticIpTask) { + public AppManagerAppHelperImpl(// + @Reference ComponentManager componentManager, // + @Reference ComponentUtil componentUtil, // + @Reference Validator validator, // + @Reference AggregateTask.ComponentAggregateTask componentsTask, // + @Reference AggregateTask.SchedulerAggregateTask schedulerTask, // + @Reference AggregateTask.StaticIpAggregateTask staticIpTask // + ) { this.componentManager = componentManager; this.componentUtil = componentUtil; this.validator = validator; @@ -112,6 +129,7 @@ public UpdateValues deleteApp(User user, OpenemsAppInstance instance) throws Ope private UpdateValues usingTemporaryApps(User user, ThrowingSupplier supplier) throws OpenemsNamedException { + Objects.requireNonNull(supplier); // to make sure the temporaryApps get set to null this.resetTasks(); this.temporaryApps = new TemporaryApps(); @@ -128,9 +146,11 @@ private UpdateValues usingTemporaryApps(User user, ThrowingSupplier { + try { + entry.getKey().create(user, otherAppConfigs); + } catch (OpenemsNamedException e) { + final var errorMessage = TranslationUtil.getTranslation(bundle, entry.getValue()); + this.log.error(errorMessage, e); + errors.add(errorMessage); + } + }); if (!errors.isEmpty()) { throw new OpenemsException(errors.stream().collect(Collectors.joining("|"))); @@ -180,8 +191,9 @@ private UpdateValues usingTemporaryApps(User user, ThrowingSupplier(); final var language = user == null ? null : user.getLanguage(); + + final var warnings = new LinkedList(); final var bundle = getTranslationBundle(language); final var toCreateInstances = new ArrayList(); if (oldInstance == null) { @@ -244,80 +256,18 @@ private UpdateValues updateAppInternal(final User user, OpenemsAppInstance oldIn } var errors = new LinkedList(); - - var oldInstances = new TreeMap(); // the DependencyConfig of the parent app, the instance of the DependencyConfig var dependencieInstances = new HashMap(); - // get all existing app dependencies - if (oldInstance != null) { - this.foreachExistingDependency(oldInstance, ConfigurationTarget.UPDATE, language, null, dc -> { - if (!dc.isDependency()) { - return true; - } - oldInstances.put(new AppIdKey(dc.parentInstance, dc.parentInstance.appId, dc.sub.key), dc); - return true; - }); - } - - BiFunction includeDependency = (a, d) -> { - - var oldAppConfig = oldInstances.get(new AppIdKey(a.getAppId(), d.key)); - - var possibleInstance = this.findNeededApp(d, this.determineDependencyConfig(d.appConfigs)); - - if (oldAppConfig == null // - && (d.createPolicy == DependencyDeclaration.CreatePolicy.ALWAYS // - || (d.createPolicy == DependencyDeclaration.CreatePolicy.IF_NOT_EXISTING - && possibleInstance.isEmpty()))) { - var config = this.determineDependencyConfig(d.appConfigs); - String appId; - UUID id = null; - List dependencies = null; - if (config.appId != null) { - appId = config.appId; - id = UUID.randomUUID(); - } else { - var instance = this.appManagerUtil.getInstanceById(config.specificInstanceId); - appId = instance.appId; - id = instance.instanceId; - dependencies = instance.dependencies; - } - try { - // check if an instance can be created - this.appManagerUtil.getAppConfiguration(ConfigurationTarget.ADD, config.appId, config.alias, - config.initialProperties, language); - var instance = new OpenemsAppInstance(appId, config.alias, id, config.initialProperties, - dependencies); - this.temporaryApps.currentlyCreatingApps().add(instance); - toCreateInstances.add(instance); - return IncludeApp.INCLUDE_WITH_DEPENDENCIES; - } catch (NoSuchElementException | OpenemsNamedException ex) { - // app not found or config cant be get - return IncludeApp.NOT_INCLUDED; - } - } - // do not include apps twice - if (possibleInstance != null && possibleInstance.isPresent()) { - if (this.temporaryApps.currentlyCreatingApps().stream() - .anyMatch(t -> t.equals(possibleInstance.get()))) { - return IncludeApp.NOT_INCLUDED; - } - } - // remove dependencies which got not included because the app already exists - oldInstances.entrySet().stream() // - .filter(t -> Objects.equals(t.getKey().parent, oldAppConfig.instance)) // - .map(t -> t.getKey()) // - .collect(Collectors.toList()) // - .forEach(t -> oldInstances.remove(t)); + var oldInstances = this.getOldDependencies(oldInstance, language); - // do not include the dependencies if the app already exists - return IncludeApp.INCLUDE_ONLY_APP; - }; final var lastCreatedOrModifiedApp = new AtomicReference(); // update app and its dependencies - this.foreachDependency(errors, app, newInstance.alias, newInstance.properties, ConfigurationTarget.UPDATE, - language, this::determineDependencyConfig, includeDependency, dc -> { + this.foreachDependency(errors, app, newInstance.alias, newInstance.properties, // + ConfigurationTarget.UPDATE, language, // + this::determineDependencyConfig, // + this.includeDependency(oldInstances, toCreateInstances, language), // + dc -> { // get old instance if existing ExistingDependencyConfig oldAppConfig = null; if (oldInstance != null) { @@ -340,9 +290,7 @@ private UpdateValues updateAppInternal(final User user, OpenemsAppInstance oldIn } catch (OpenemsNamedException e) { this.log.error(e.getMessage()); - errors.add(TranslationUtil.getTranslation(bundle, "canNotGetAppConfiguration")); } - var appDependencyConfig = DependencyDeclaration.AppDependencyConfig.create() // .setAppId(app.getAppId()) // .setAlias(oldInstance.alias) // @@ -468,10 +416,11 @@ private UpdateValues updateAppInternal(final User user, OpenemsAppInstance oldIn for (var list : Lists.newArrayList(this.temporaryApps.currentlyCreatingApps(), this.temporaryApps.currentlyModifiedApps())) { modifiedOrCreatedApps = list; - replaceApp = modifiedOrCreatedApps.stream() // + var foundReplaceApp = modifiedOrCreatedApps.stream() // .filter(i -> i.equals(instance)) // .findAny().orElse(null); - if (replaceApp != null) { + if (foundReplaceApp != null) { + replaceApp = foundReplaceApp; break; } } @@ -567,9 +516,18 @@ private UpdateValues updateAppInternal(final User user, OpenemsAppInstance oldIn if (isNotAllowedToUpdate) { newAppInstance = oldAppConfig.instance; } else { - var newInstanceProperties = oldAppConfig.instance.properties.deepCopy(); - for (var entry : dc.appDependencyConfig.properties.entrySet()) { - newInstanceProperties.add(entry.getKey(), entry.getValue()); + var newInstanceProperties = dc.appDependencyConfig.properties; + // only add old configuration properties to updated app when it got updated by a + // parent app. This ensures that a property can be modified by the user on a + // child app and also not overwrite it when updating the parent app + // TODO child app may have inconsistent properties + if (dc.isDependency()) { + for (var entry : oldAppConfig.instance.properties.entrySet()) { + if (newInstanceProperties.has(entry.getKey())) { + continue; + } + newInstanceProperties.add(entry.getKey(), entry.getValue()); + } } newAppInstance = new OpenemsAppInstance(dc.app.getAppId(), newInstanceAlias, oldAppConfig.instance.instanceId, newInstanceProperties, dependencies); @@ -633,19 +591,137 @@ private UpdateValues updateAppInternal(final User user, OpenemsAppInstance oldIn this.temporaryApps.currentlyDeletingApps(), warnings); } + private Map getOldDependencies(// + final OpenemsAppInstance oldInstance, // + final Language language // + ) throws OpenemsNamedException { + if (oldInstance == null) { + return Collections.emptyMap(); + } + try { + final var oldInstances = new TreeMap(); + // get all existing app dependencies + this.foreachExistingDependency(oldInstance, ConfigurationTarget.UPDATE, language, null, dc -> { + if (!dc.isDependency()) { + return true; + } + oldInstances.put(new AppIdKey(dc.parentInstance, dc.parentInstance.appId, dc.sub.key), dc); + return true; + }); + return oldInstances; + } catch (OpenemsNamedException e) { + return Collections.emptyMap(); + } + } + + private BiFunction includeDependency(// + final Map oldInstances, // + final List toCreateInstances, // + final Language language // + ) { + return (a, d) -> { + + var oldAppConfig = oldInstances.get(new AppIdKey(a.getAppId(), d.key)); + + if (oldAppConfig != null) { + final var appIdOfExistingInstance = oldAppConfig.instance.appId; + if (!d.appConfigs.stream() // + .anyMatch(c -> Objects.equals(c.appId, appIdOfExistingInstance))) { + + // remove dependencies which got not included because the app already exists + removeAppsWithParent(oldInstances, oldAppConfig.instance); + + // if the current dependency is of a factory which is not anymore in the + // available configurations then removed and added with a unique appIdKey with + // the factory id for removing it at the end + oldInstances.remove(new AppIdKey(a.getAppId(), d.key)); + oldInstances.put(new AppIdKey(a.getAppId(), d.key, oldAppConfig.instance.appId), oldAppConfig); + oldAppConfig = null; + + // TODO maybe be able to reference this instance if it should be created in + // another dependency + } + } + + var possibleInstance = this.findNeededApp(d, this.determineDependencyConfig(d.appConfigs)); + + if (oldAppConfig == null // + && (d.createPolicy == DependencyDeclaration.CreatePolicy.ALWAYS // + || (d.createPolicy == DependencyDeclaration.CreatePolicy.IF_NOT_EXISTING + && possibleInstance.isEmpty()))) { + var config = this.determineDependencyConfig(d.appConfigs); + String appId; + UUID id = null; + List dependencies = null; + if (config.appId != null) { + appId = config.appId; + id = UUID.randomUUID(); + } else { + var instance = this.appManagerUtil.getInstanceById(config.specificInstanceId); + appId = instance.appId; + id = instance.instanceId; + dependencies = instance.dependencies; + } + try { + // check if an instance can be created + this.appManagerUtil.getAppConfiguration(ConfigurationTarget.ADD, config.appId, config.alias, + config.initialProperties, language); + var instance = new OpenemsAppInstance(appId, config.alias, id, config.initialProperties, + dependencies); + this.temporaryApps.currentlyCreatingApps().add(instance); + toCreateInstances.add(instance); + return IncludeApp.INCLUDE_WITH_DEPENDENCIES; + } catch (NoSuchElementException | OpenemsNamedException ex) { + // app not found or config cant be get + return IncludeApp.NOT_INCLUDED; + } + } + // do not include apps twice + if (possibleInstance != null && possibleInstance.isPresent()) { + if (this.temporaryApps.currentlyCreatingApps().stream() + .anyMatch(t -> t.equals(possibleInstance.get()))) { + return IncludeApp.NOT_INCLUDED; + } + } + + if (oldAppConfig == null) { + return IncludeApp.INCLUDE_ONLY_APP; + } + + // remove dependencies which got not included because the app already exists + removeAppsWithParent(oldInstances, oldAppConfig.instance); + + // do not include the dependencies if the app already exists + return IncludeApp.INCLUDE_ONLY_APP; + }; + } + + private static void removeAppsWithParent(// + final Map instances, // + final OpenemsAppInstance parent // + ) { + instances.entrySet().stream() // + .filter(t -> Objects.equals(t.getKey().parent, parent)) // + .map(t -> t.getKey()) // + .collect(Collectors.toList()) // + .forEach(t -> instances.remove(t)); + } + /** * Removes properties which should not get saved e. g. passwords. * * @param instance The {@link OpenemsAppInstance} to remove the properties from */ private void removeNotAllowedToSavedProperties(OpenemsAppInstance instance) { - // TODO needs to be changed if the properties have something similar to - // AttributeDefinition try { - this.appManagerUtil.getAppConfiguration(ConfigurationTarget.DELETE_NOT_SAVED_PROPERTIES, instance, - Language.DEFAULT); - } catch (OpenemsNamedException e) { - e.printStackTrace(); + final var app = this.appManagerUtil.getAppById(instance.appId); + Arrays.stream(app.getProperties()) // + .filter(t -> !t.isAllowedToSave) // + .forEach(t -> instance.properties.remove(t.name)); + } catch (NoSuchElementException e) { + // app not found + } catch (UnsupportedOperationException e) { + // getting properties not supported } } @@ -697,15 +773,25 @@ private static class AppIdKey implements Comparable { public final String appId; public final String key; - public AppIdKey(OpenemsAppInstance parent, String appId, String key) { + public final String actualAppId; + + public AppIdKey(OpenemsAppInstance parent, String appId, String key, String actualAppId) { this.parent = parent; this.appId = appId; this.key = key; + this.actualAppId = actualAppId; + } + + public AppIdKey(OpenemsAppInstance parent, String appId, String key) { + this(parent, appId, key, null); + } + public AppIdKey(String appId, String key, String actualAppId) { + this(null, appId, key, actualAppId); } public AppIdKey(String appId, String key) { - this(null, appId, key); + this(null, appId, key, null); } @Override @@ -724,7 +810,8 @@ public int compareTo(AppIdKey o) { @Override public String toString() { - return this.appId + ":" + this.key; + return this.appId + ":" + this.key // + + (this.actualAppId != null ? ":" + this.actualAppId : ""); } } @@ -964,9 +1051,9 @@ private static List mapAppConfiguration(List configs, * @param declaration the current {@link DependencyConfig} * @param config the current * {@link DependencyDeclaration.AppDependencyConfig} - * @return s null if the app can not be added; {@link Optional#absent()} if the - * app needs to be created; the {@link OpenemsAppInstance} if an - * existing app can be used + * @return null if the app can not be added; {@link Optional#empty()} if the app + * needs to be created; the {@link OpenemsAppInstance} if an existing + * app can be used */ private Optional findNeededApp(DependencyDeclaration declaration, DependencyDeclaration.AppDependencyConfig config) { @@ -983,7 +1070,7 @@ private Optional findNeededApp(DependencyDeclaration declara .collect(Collectors.toList()); OpenemsAppInstance availableApp = null; for (var neededApp : neededApps) { - if (this.getAppsWithDependencyTo(neededApp).isEmpty()) { + if (this.appManagerUtil.getAppsWithDependencyTo(neededApp).isEmpty()) { availableApp = neededApp; break; } @@ -1000,13 +1087,6 @@ private Optional findNeededApp(DependencyDeclaration declara return null; } - private List getAppsWithDependencyTo(OpenemsAppInstance instance) { - return this.getAppManagerImpl().getInstantiatedApps().stream() - .filter(t -> t.dependencies != null && !t.dependencies.isEmpty()) - .filter(t -> t.dependencies.stream().anyMatch(d -> d.instanceId.equals(instance.instanceId))) - .collect(Collectors.toList()); - } - private static enum IncludeApp { NOT_INCLUDED, // INCLUDE_ONLY_APP, // @@ -1040,7 +1120,7 @@ private static enum IncludeApp { * @param includeResult the includeResult of the last iteration to * know if only the app without its * dependencies should be included - * @return s the last {@link DependencyConfig} + * @return the last {@link DependencyConfig} * @throws OpenemsNamedException on error */ private DependencyConfig foreachDependency(List errors, OpenemsApp app, AppDependencyConfig appConfig, @@ -1176,7 +1256,7 @@ private DependencyDeclaration.AppDependencyConfig determineDependencyConfig(List var instances = this.getAppManagerImpl().getInstantiatedApps().stream() .filter(i -> i.appId.equals(config.appId)).collect(Collectors.toList()); for (var instance : instances) { - var existingDependencies = this.getAppsWithDependencyTo(instance); + var existingDependencies = this.appManagerUtil.getAppsWithDependencyTo(instance); if (existingDependencies.isEmpty()) { return config; } @@ -1207,7 +1287,7 @@ private void foreachExistingDependency(OpenemsAppInstance instance, Configuratio * @param alreadyIteratedApps the already iterated app to avoid an endless loop * @param includeInstance parent, instance, if the instance should get * included - * @return s the last {@link DependencyConfig} + * @return the last {@link DependencyConfig} * @throws OpenemsNamedException on error */ private DependencyConfig foreachExistingDependency(OpenemsAppInstance instance, ConfigurationTarget target, @@ -1275,16 +1355,16 @@ private DependencyConfig foreachExistingDependency(OpenemsAppInstance instance, * @param app the components of which app * @param properties the default properties to create an app instance of this * app - * @return a map of the component id s that can be replaced mapped from id to - * key to put the next id + * @return a list of {@link ReplacableIds} * @throws OpenemsNamedException on error */ - protected final Map getReplaceableComponentIds(OpenemsApp app, JsonObject properties) + private final List getReplaceableComponentIds(OpenemsApp app, JsonObject properties) throws OpenemsNamedException { final var prefix = "?_?_"; var config = app.getAppConfiguration(ConfigurationTarget.TEST, properties, null); var copy = properties.deepCopy(); + Map defaultIdToCurrentId = new HashMap<>(); // remove already set ids for (var component : config.components) { String removeKey = null; @@ -1292,6 +1372,10 @@ protected final Map getReplaceableComponentIds(OpenemsApp app, J var id = JsonUtils.getAsOptionalString(entry.getValue()).orElse(null); if (id != null && component.getId().startsWith(id)) { removeKey = entry.getKey(); + final var myId = id; + final var defaultId = component.getId() // + .substring(component.getId().indexOf(':') + 1); + defaultIdToCurrentId.put(defaultId, myId); break; } } @@ -1317,10 +1401,27 @@ protected final Map getReplaceableComponentIds(OpenemsApp app, J var property = pieces[0]; // "meter0" var defaultId = pieces[1]; - replaceableComponentIds.put(defaultId, property); + replaceableComponentIds.put(property, defaultId); } } - return replaceableComponentIds; + + return replaceableComponentIds.entrySet().stream() // + .map(entry -> new ReplacableIds(defaultIdToCurrentId.get(entry.getValue()), // + entry.getValue(), entry.getKey())) // + .collect(Collectors.toList()); // + } + + private final class ReplacableIds { + public final String predefinedId; + public final String defaultId; + public final String key; + + public ReplacableIds(String predefinedId, String defaultId, String key) { + super(); + this.predefinedId = predefinedId == null ? defaultId : predefinedId; + this.defaultId = defaultId; + this.key = key; + } } /** @@ -1342,27 +1443,30 @@ private AppConfiguration getNewAppConfigWithReplacedIds(OpenemsApp app, OpenemsA var target = oldAppInstance == null ? ConfigurationTarget.ADD : ConfigurationTarget.UPDATE; - var newAppConfig = this.appManagerUtil.getAppConfiguration(target, app, newAppInstance, language); - final var replacableIds = this.getReplaceableComponentIds(app, newAppInstance.properties); + final var propertiesCopy = newAppInstance.properties.deepCopy(); + + var indexToId = new HashMap(); + var index = 0; + for (var id : replacableIds) { + propertiesCopy.addProperty(id.key, String.valueOf(index)); + indexToId.put(String.valueOf(index), id); + index++; + } - for (var comp : ComponentUtilImpl.order(newAppConfig.components)) { - // replace old id s with new ones - for (var entry : comp.getProperties().entrySet()) { - for (var replaceableId : replacableIds.entrySet()) { - if (entry.getValue().toString().contains(replaceableId.getKey())) { - var newId = entry.getValue().toString().replace(replaceableId.getKey(), - newAppInstance.properties.get(replaceableId.getValue()).getAsString()); - newId = newId.replace("\"", ""); - var newValue = JsonUtils.getAsJsonElement(newId); - comp.getProperties().put(entry.getKey(), newValue); - } - } - } + var newAppConfig = this.appManagerUtil.getAppConfiguration(target, app, newAppInstance.alias, propertiesCopy, + language); + + final var orderedComponents = ComponentUtilImpl.order(newAppConfig.components); + final var iterator = new ArrayList<>(orderedComponents).iterator(); + for (int i = 0; iterator.hasNext(); i++) { + final var comp = iterator.next(); var isNewComponent = true; - var id = comp.getId(); - var canBeReplaced = replacableIds.containsKey(id); + final var replacableId = indexToId.get(comp.getId()); + final var canBeReplaced = replacableId != null; + final var originalId = canBeReplaced ? replacableId.predefinedId : comp.getId(); + var id = originalId; EdgeConfig.Component foundComponent = null; // try to find a component with the necessary settings @@ -1377,8 +1481,8 @@ private AppConfiguration getNewAppConfigWithReplacedIds(OpenemsApp app, OpenemsA // use component based on the last configuration if (foundComponent == null && oldAppInstance != null && canBeReplaced - && oldAppInstance.properties.has(replacableIds.get(id))) { - id = oldAppInstance.properties.get(replacableIds.get(id)).getAsString(); + && oldAppInstance.properties.has(replacableId.key)) { + id = oldAppInstance.properties.get(replacableId.key).getAsString(); foundComponent = this.componentManager.getEdgeConfig().getComponent(id).orElse(null); final var tempId = id; // other app uses the same component because they had the same configuration @@ -1394,7 +1498,7 @@ private AppConfiguration getNewAppConfigWithReplacedIds(OpenemsApp app, OpenemsA if (isNewComponent) { // if the id is not already set and there is no component with the default id // then use the default id - foundComponent = this.componentManager.getEdgeConfig().getComponent(comp.getId()).orElse(null); + foundComponent = this.componentManager.getEdgeConfig().getComponent(originalId).orElse(null); if (foundComponent == null) { // find component for currently creating apps for (var entry : this.getAppManagerImpl().appConfigs( @@ -1408,10 +1512,36 @@ private AppConfiguration getNewAppConfigWithReplacedIds(OpenemsApp app, OpenemsA } } - if (foundComponent == null) { - id = comp.getId(); + var sameIdInComponents = orderedComponents.subList(0, i).stream() // + .map(c -> { + var repId = indexToId.get(c.getId()); + return repId != null ? repId.defaultId : c.getId(); + }) // + .anyMatch(t -> t.equals(originalId)); + + var usedInPreviousConfig = false; + final var alreadyUsedIds = new ArrayList(); + if (canBeReplaced && oldAppInstance != null) { + for (var entry : oldAppInstance.properties.entrySet()) { + if (entry.getKey().equals(replacableId.key)) { + continue; + } + var existingId = JsonUtils.getAsOptionalString(entry.getValue()).orElse(null); + if (existingId == null) { + continue; + } + alreadyUsedIds.add(existingId); + if (existingId.equals(originalId)) { + usedInPreviousConfig = true; + } + } + } + + if (foundComponent == null && !sameIdInComponents && !usedInPreviousConfig) { + id = originalId; } else { // replace number at the end and get the next available id + id = canBeReplaced ? replacableId.defaultId : id; var baseName = id.replaceAll("\\d+", ""); var startingNumberString = id.replace(baseName, ""); if (startingNumberString.isBlank()) { @@ -1422,8 +1552,13 @@ private AppConfiguration getNewAppConfigWithReplacedIds(OpenemsApp app, OpenemsA } } else { var startingNumber = Integer.parseInt(startingNumberString); - var nextAvailableId = this.componentUtil.getNextAvailableId(baseName, startingNumber, - otherAppComponents); + var ids = new ArrayList<>(orderedComponents).stream() // + .map(EdgeConfig.Component::getId) // + .collect(Collectors.toList()); + // add id if it was in the old configuration + ids.addAll(alreadyUsedIds); + + var nextAvailableId = this.componentUtil.getNextAvailableId(baseName, startingNumber, ids); if (!nextAvailableId.equals(id) && !canBeReplaced) { // component can not be created because the id is already used // and the id can not be set in the configuration @@ -1437,7 +1572,13 @@ private AppConfiguration getNewAppConfigWithReplacedIds(OpenemsApp app, OpenemsA } if (canBeReplaced) { - newAppInstance.properties.addProperty(replacableIds.get(comp.getId()), id); + // replace component with new id + final var component = orderedComponents.remove(i); + orderedComponents.add(i, + new EdgeConfig.Component(id, component.getAlias(), component.getFactoryId(), + component.getProperties().entrySet().stream() + .collect(JsonUtils.toJsonObject(Entry::getKey, Entry::getValue)))); + newAppInstance.properties.addProperty(replacableId.key, id); } } return this.appManagerUtil.getAppConfiguration(target, newAppInstance, language); diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/ComponentAggregateTaskImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/ComponentAggregateTaskImpl.java index 732711eeac6..0840cdec480 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/ComponentAggregateTaskImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/ComponentAggregateTaskImpl.java @@ -43,6 +43,8 @@ public ComponentAggregateTaskImpl(@Reference ComponentManager componentManager) public void reset() { this.components = new LinkedList<>(); this.components2Delete = new LinkedList<>(); + this.createdComponents = new LinkedList<>(); + this.deletedComponents = new LinkedList<>(); } @Override @@ -64,7 +66,6 @@ public void aggregate(AppConfiguration config, AppConfiguration oldConfig) { @Override public void create(User user, List otherAppConfigurations) throws OpenemsNamedException { - this.createdComponents = new ArrayList<>(this.components.size()); var errors = new LinkedList(); var otherAppComponents = AppManagerAppHelperImpl.getComponentsFromConfigs(otherAppConfigurations); // create components @@ -77,6 +78,12 @@ public void create(User user, List otherAppConfigurations) thr var foundComponentWithSameId = this.componentManager.getEdgeConfig().getComponent(comp.getId()) .orElse(null); if (foundComponentWithSameId != null) { + // check if the found component has the same factory id + if (!foundComponentWithSameId.getFactoryId().equals(comp.getFactoryId())) { + errors.add("Configuration of component with id '" + foundComponentWithSameId.getId() + + "' can not be rewritten. Because the component has a different factoryId."); + continue; + } var isSameConfigWithoutAlias = ComponentUtilImpl.isSameConfigurationWithoutAlias(null, comp, foundComponentWithSameId); @@ -132,7 +139,6 @@ public void create(User user, List otherAppConfigurations) thr if (!errors.isEmpty()) { throw new OpenemsException(errors.stream().collect(Collectors.joining("|"))); } - } /** @@ -143,7 +149,6 @@ public void create(User user, List otherAppConfigurations) thr */ @Override public void delete(User user, List otherAppConfigurations) throws OpenemsNamedException { - this.deletedComponents = new ArrayList<>(this.components2Delete.size()); List errors = new ArrayList<>(); var notMyComponents = AppManagerAppHelperImpl.getComponentsFromConfigs(otherAppConfigurations); for (var comp : this.components2Delete) { diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/DependencyUtil.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/DependencyUtil.java index b473a2b2167..8b22600491e 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/DependencyUtil.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/DependencyUtil.java @@ -71,8 +71,8 @@ public static final UUID getInstanceIdOfAppWhichHasComponent(ComponentManager co * NOTE: when calling this inside an app configuration it can lead to an endless * loop * - * @param componentManager a componentManager to get the appManager - * @param componentId the component id that the app should have + * @param componentManager a componentManager to get the appManager + * @param componentId the component id that the app should have * @return the found instanceId or null if no app has this component */ public final UUID getInstanceIdOfAppWhichHasComponentInternal(ComponentManager componentManager, diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/SchedulerAggregateTaskImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/SchedulerAggregateTaskImpl.java index d3642058500..71f677c0198 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/SchedulerAggregateTaskImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/SchedulerAggregateTaskImpl.java @@ -57,6 +57,13 @@ public void create(User user, List otherAppConfigurations) thr this.delete(user, otherAppConfigurations); } + /** + * removes id's from the scheduler that were aggregated. + * + * @param user the executing user + * @param otherAppConfigurations the other existing {@link AppConfiguration}s + * @throws OpenemsNamedException on error + */ @Override public void delete(User user, List otherAppConfigurations) throws OpenemsNamedException { this.removeIds.addAll(this.aggregateTask.getDeletedComponents()); diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/StaticIpAggregateTaskImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/StaticIpAggregateTaskImpl.java index 8890fd6232d..b4aba8735c3 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/StaticIpAggregateTaskImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/StaticIpAggregateTaskImpl.java @@ -16,6 +16,9 @@ @Component public class StaticIpAggregateTaskImpl implements AggregateTask, AggregateTask.StaticIpAggregateTask { + /** + * Setting ip configuration only works on Linux devices. + */ private final boolean isWindows = System.getProperty("os.name").startsWith("Windows"); private final ComponentUtil componentUtil; @@ -26,7 +29,6 @@ public class StaticIpAggregateTaskImpl implements AggregateTask, AggregateTask.S @Activate public StaticIpAggregateTaskImpl(@Reference ComponentUtil componentUtil) { this.componentUtil = componentUtil; - } @Override diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/AddAppInstance.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/AddAppInstance.java index 32f2580abdb..6eb47e5c592 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/AddAppInstance.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/AddAppInstance.java @@ -1,6 +1,7 @@ package io.openems.edge.core.appmanager.jsonrpc; import java.util.List; +import java.util.Optional; import java.util.UUID; import com.google.gson.JsonArray; @@ -60,25 +61,30 @@ public static class Request extends JsonrpcRequest { */ public static Request from(JsonrpcRequest r) throws OpenemsNamedException { var p = r.getParams(); + var key = JsonUtils.getAsString(p, "key"); var appId = JsonUtils.getAsString(p, "appId"); - var alias = JsonUtils.getAsString(p, "alias"); + var alias = JsonUtils.getAsOptionalString(p, "alias").orElse(null); var properties = JsonUtils.getAsJsonObject(p, "properties"); - return new Request(r, appId, alias, properties); + return new Request(r, key, appId, alias, properties); } + public final String key; + public final String appId; public final String alias; public final JsonObject properties; - private Request(JsonrpcRequest request, String appId, String alias, JsonObject properties) { + private Request(JsonrpcRequest request, String key, String appId, String alias, JsonObject properties) { super(request, METHOD); + this.key = key; this.appId = appId; this.alias = alias; this.properties = properties; } - public Request(String appId, String alias, JsonObject properties) { + public Request(String appId, String key, String alias, JsonObject properties) { super(METHOD); + this.key = key; this.appId = appId; this.alias = alias; this.properties = properties; @@ -88,7 +94,7 @@ public Request(String appId, String alias, JsonObject properties) { public JsonObject getParams() { return JsonUtils.buildJsonObject() // .addProperty("appId", this.appId) // - .addProperty("alias", this.alias) // + .addPropertyIfNotNull("alias", this.alias) // .add("properties", this.properties) // .build(); } @@ -102,8 +108,11 @@ public static class Response extends JsonrpcResponseSuccess { public Response(UUID id, OpenemsAppInstance instance, List warnings) { super(id); this.instance = instance; - this.warnings = warnings == null ? new JsonArray() - : warnings.stream().map(JsonPrimitive::new).collect(JsonUtils.toJsonArray()); + this.warnings = Optional.ofNullable(warnings) // + .map(t -> t.stream() // + .map(JsonPrimitive::new) // + .collect(JsonUtils.toJsonArray())) + .orElse(new JsonArray()); } @Override diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetApp.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetApp.java index 0f40a78ed63..aa71a309bcd 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetApp.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetApp.java @@ -1,17 +1,24 @@ package io.openems.edge.core.appmanager.jsonrpc; +import java.util.Arrays; import java.util.List; import java.util.UUID; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.exceptions.OpenemsException; import io.openems.common.jsonrpc.base.JsonrpcRequest; import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; import io.openems.common.session.Language; import io.openems.common.utils.JsonUtils; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppInstance; +import io.openems.edge.core.appmanager.validator.OpenemsAppStatus; import io.openems.edge.core.appmanager.validator.Validator; /** @@ -97,34 +104,12 @@ public JsonObject getParams() { public static class Response extends JsonrpcResponseSuccess { - private static JsonObject createAppObject(OpenemsApp app, List instantiatedApps, - Language language, Validator validator) { - - var instanceIds = JsonUtils.buildJsonArray(); - for (var instantiatedApp : instantiatedApps) { - instanceIds.add(instantiatedApp.instanceId.toString()); - } - var categorys = JsonUtils.buildJsonArray().build(); - for (var cat : app.getCategorys()) { - categorys.add(cat.toJsonObject(language)); - } - return JsonUtils.buildJsonObject() // - .add("categorys", categorys) // - .addProperty("cardinality", app.getCardinality().name()) // - .addProperty("appId", app.getAppId()) // - .addProperty("name", app.getName(language)) // - .addProperty("image", app.getImage()) // - .add("status", validator.toJsonObject(app.getValidatorConfig(), language)) // - .add("instanceIds", instanceIds.build()) // - .build(); - } - private final JsonObject app; public Response(UUID id, OpenemsApp app, List instantiatedApps, Language language, - Validator validator) { + Validator validator) throws OpenemsNamedException { super(id); - this.app = createAppObject(app, instantiatedApps, language, validator); + this.app = createJsonObjectOf(app, validator, instantiatedApps, language); } @Override @@ -135,4 +120,53 @@ public JsonObject getResult() { } } + /** + * Creates a {@link JsonObject} of the given {@link OpenemsApp}. + * + *

      + * Also adds the status of the app and the instances of the app. + * + * @param app the {@link OpenemsApp} + * @param validator a {@link Validator} to get the status of the app + * {@link OpenemsAppStatus} + * @param instantiatedApps all instances + * @param language the {@link Language} + * @return the created {@link JsonObject} + * @throws OpenemsNamedException on error + */ + public static final JsonObject createJsonObjectOf(// + final OpenemsApp app, // + final Validator validator, // + final List instantiatedApps, // + final Language language // + ) throws OpenemsNamedException { + + final var imageFuture = CompletableFuture.supplyAsync(app::getImage); + final var statusFuture = CompletableFuture + .supplyAsync(() -> validator.toJsonObject(app.getValidatorConfig(), language)); + try { + final var image = imageFuture.get(); + final var status = statusFuture.get(); + + return JsonUtils.buildJsonObject() // + .add("categorys", Arrays.stream(app.getCategories()) // + .map(cat -> cat.toJsonObject(language)) // + .collect(JsonUtils.toJsonArray())) // + .addProperty("cardinality", app.getCardinality().name()) // + .addProperty("appId", app.getAppId()) // + .addProperty("name", app.getName(language)) // + .addPropertyIfNotNull("image", image) // + .add("status", status) // + .add("instanceIds", instantiatedApps.stream() // + .filter(instance -> app.getAppId().equals(instance.appId)) // + .map(instance -> new JsonPrimitive(instance.instanceId.toString())) // + .collect(JsonUtils.toJsonArray())) // + .build(); + } catch (InterruptedException | CancellationException e) { + throw new OpenemsException(e); + } catch (ExecutionException e) { + throw new OpenemsException(e.getCause()); + } + } + } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetAppInstances.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetAppInstances.java index 86299849aa0..dea459eb9e9 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetAppInstances.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetAppInstances.java @@ -1,7 +1,7 @@ package io.openems.edge.core.appmanager.jsonrpc; -import java.util.List; import java.util.UUID; +import java.util.stream.Stream; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -86,10 +86,11 @@ public static class Response extends JsonrpcResponseSuccess { private final JsonArray instances; - public Response(UUID id, List instances) { + public Response(UUID id, Stream instances) { super(id); - this.instances = instances.stream().map(OpenemsAppInstance::toJsonObject).collect(JsonUtils.toJsonArray()); + this.instances = instances.map(OpenemsAppInstance::toJsonObject) // + .collect(JsonUtils.toJsonArray()); } @Override diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetApps.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetApps.java index abd6a975f96..70a2ddf8090 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetApps.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetApps.java @@ -1,6 +1,7 @@ package io.openems.edge.core.appmanager.jsonrpc; import java.util.List; +import java.util.Objects; import java.util.UUID; import com.google.gson.JsonArray; @@ -11,6 +12,7 @@ import io.openems.common.jsonrpc.base.JsonrpcRequest; import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; import io.openems.common.session.Language; +import io.openems.common.session.Role; import io.openems.common.utils.JsonUtils; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppInstance; @@ -94,43 +96,34 @@ public JsonObject getParams() { public static class Response extends JsonrpcResponseSuccess { private static JsonArray createAppsArray(List availableApps, - List instantiatedApps, Language language, Validator validator) { - var result = JsonUtils.buildJsonArray(); - for (var app : availableApps) { - // TODO don't show integrated systems for normal users - /* - * if(app.getCategory()==OpenemsAppCategory.INTEGRATED_SYSTEM) { continue; } - */ - // Map Instantiated-Apps to Available-Apps - var instanceIds = JsonUtils.buildJsonArray(); - for (var instantiatedApp : instantiatedApps) { - if (app.getAppId().equals(instantiatedApp.appId)) { - instanceIds.add(instantiatedApp.instanceId.toString()); - } - } - var categorys = JsonUtils.buildJsonArray().build(); - for (var cat : app.getCategorys()) { - categorys.add(cat.toJsonObject(language)); - } - result.add(JsonUtils.buildJsonObject() // - .add("categorys", categorys) // - .addProperty("cardinality", app.getCardinality().name()) // - .addProperty("appId", app.getAppId()) // - .addProperty("name", app.getName(language)) // - .addPropertyIfNotNull("image", app.getImage()) // - .add("status", validator.toJsonObject(app.getValidatorConfig(), language)) // - .add("instanceIds", instanceIds.build()) // - .build()); - } - return result.build(); + List instantiatedApps, Role userRole, Language language, Validator validator) { + return availableApps.stream() // + .filter(app -> { + final var permissions = app.getAppPermissions(); + if (!userRole.isAtLeast(permissions.canSee)) { + return false; + } + return true; + }) // + .parallel() // + .map(app -> { + try { + return GetApp.createJsonObjectOf(app, validator, instantiatedApps, language); + } catch (OpenemsNamedException e) { + e.printStackTrace(); + return null; + } + }) // + .filter(Objects::nonNull) // + .collect(JsonUtils.toJsonArray()); } private final JsonArray apps; public Response(UUID id, List availableApps, List instantiatedApps, - Language language, Validator validator) { + Role userRole, Language language, Validator validator) { super(id); - this.apps = createAppsArray(availableApps, instantiatedApps, language, validator); + this.apps = createAppsArray(availableApps, instantiatedApps, userRole, language, validator); } @Override diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/UpdateAppInstance.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/UpdateAppInstance.java index 8b0c531dca9..28f5b44a198 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/UpdateAppInstance.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/UpdateAppInstance.java @@ -96,8 +96,8 @@ public JsonObject getParams() { public static class Response extends JsonrpcResponseSuccess { - private final OpenemsAppInstance instance; - private final JsonArray warnings; + public final OpenemsAppInstance instance; + public final JsonArray warnings; public Response(UUID id, OpenemsAppInstance instance, List warnings) { super(id); diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/translation_de.properties b/io.openems.edge.core/src/io/openems/edge/core/appmanager/translation_de.properties index 1a2f8e8ceb2..cd52acccbf3 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/translation_de.properties +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/translation_de.properties @@ -2,26 +2,39 @@ integratedSystems = Integrierte Systeme timeOfUseTariff = Zeitvariable Stromtarife evcs = E-Mobilität -heat = Wärme +heat = Power-to-Heat loadControl = Laststeuerung hardware = Hardware pvInverter = PV-Wechselrichter pvSelfConsumption = PV-Eigenverbrauch -meter = Zähler +meter = Erzeugungs- und Verbrauchszähler api = Schnittstellen +ess = Speichersystemsteuerung # Global +alias = Alias ipAddress = IP-Adresse +ipAddress.description = IP-Adresse des Geräts. port = Port +port.description = Port des Geräts. modbusId = Modbus-ID modbusId.description = Modbus-ID der Modbus Komponente. modbusUnitId = Modbus Unit-ID modbusUnitId.description = Die Unit-ID von den Modbus Gerät. +all = Alle +l1 = L1 +l2 = L2 +l3 = L3 germany = Deutschland austria = Österreich switzerland = Schweiz +sweden = Schweden +czech = Tschechische Republik +netherlands = Niederlande username = Benutzername password = Passwort +left = Links +right = Rechts # Api App.Api.apiTimeout.label = Api-Timeout @@ -44,11 +57,18 @@ App.Api.RestJson.ReadOnly.Name = REST/JSON lesend App.Api.RestJson.ReadWrite.Name = REST/JSON Schreibzugriff # Evcs -App.Evcs.Cluster.Name = Multiladepunkt-Management +App.Evcs.controller.alias = Ladestation Steuerung +App.Evcs.ip.description = Die IP-Adresse der Ladestation. +App.Evcs.chargingStation.label = Ladepunkt {0} + +App.Evcs.Cluster.Name = Multiladepunkt Management App.Evcs.Cluster.evcsIds.description = IDs von Ladestationen. App.Evcs.HardyBarth.Name = eCharge Hardy Barth Ladestation -App.Evcs.HardyBarth.ip.description = Die IP-Adresse der Ladestation. Wenn die Ladestation zwei Anschlüsse hat, hat der zweite/slave Anschluss die IP 192.168.25.31. +App.Evcs.HardyBarth.alias.value = eCharge Hardy Barth Ladestation - {0} +App.Evcs.HardyBarth.alias.label = Alias Ladepunkt {0} +App.Evcs.HardyBarth.numberOfChargingStations.label = Anzahl Ladepunkte +App.Evcs.HardyBarth.ip.label = IP-Adresse Ladepunkt {0} App.Evcs.IesKeywatt.Name = IES Keywatt Ladestation App.Evcs.IesKeywatt.chargepoint.label = OCPP Zapfsäulen-Kennung @@ -57,28 +77,24 @@ App.Evcs.IesKeywatt.connector.label = OCPP Stecker-Kennung App.Evcs.IesKeywatt.connector.description = Die Anschlusskennung der Stromzapfsäule (z. B. wenn es zwei Anschlüsse gibt, hat die Stromzapfsäule zwei Kennungen 1 und 2). App.Evcs.Keba.Name = KEBA Ladestation -App.Evcs.Keba.ip.description = Die IP-Adresse der Ladestation. # Hardware -App.Hardware.KMtronic8Channel.Name = FEMS Relais 8-Kanal -App.Hardware.KMtronic8Channel.ip.description = Die IP-Adresse des Relaisboards. +App.Hardware.KMtronic8Channel.Name = FEMS Relaisboard 8-Kanal TCP +App.Hardware.KMtronic8Channel.ip.description = Die IP-Adresse des Relaisboards # Heat App.Heat.CHP.Name = Blockheizkraftwerk (BHKW) -App.Heat.CHP.outputChannel.label = Ausgangskanal -App.Heat.CHP.outputChannel.description = Kanaladresse des digitalen Ausgangs. +App.Heat.CHP.outputChannel.label = Ausgangskanal: App.Heat.HeatingElement.Name = Heizstab -App.Heat.HeatingElement.outputChannelPhaseL1.label = Ausgangskanal Phase L1 -App.Heat.HeatingElement.outputChannelPhaseL1.description = Kanaladresse des digitalen Ausgangs für Phase L1. -App.Heat.HeatingElement.outputChannelPhaseL2.label = Ausgangskanal Phase L2 -App.Heat.HeatingElement.outputChannelPhaseL2.description = Kanaladresse des digitalen Ausgangs für Phase L2. -App.Heat.HeatingElement.outputChannelPhaseL3.label = Ausgangskanal Phase L3 -App.Heat.HeatingElement.outputChannelPhaseL3.description = Kanaladresse des digitalen Ausgangs für Phase L3. +App.Heat.HeatingElement.outputChannelPhaseL1.label = Ausgangskanal Phase L1: +App.Heat.HeatingElement.outputChannelPhaseL2.label = Ausgangskanal Phase L2: +App.Heat.HeatingElement.outputChannelPhaseL3.label = Ausgangskanal Phase L3: +App.Heat.HeatingElement.powerPerPhase.label = Leistung pro Phase +App.Heat.HeatingElement.powerPerPhase.description = Leistung des Heizstabs auf einer Phase [Watt] App.Heat.HeatPump.Name = "SG-Ready" Wärmepumpe -App.Heat.HeatPump.outputChannel1.label = Ausgangskanal 1 -App.Heat.HeatPump.outputChannel1.description = Kanaladresse des digitalen Ausgangs für Eingang 1. -App.Heat.HeatPump.outputChannel2.label = Ausgangskanal 2 -App.Heat.HeatPump.outputChannel2.description = Kanaladresse des digitalen Ausgangs für Eingang 2. +App.Heat.HeatPump.outputChannel1.label = Ausgangskanal 1: +App.Heat.HeatPump.outputChannel2.label = Ausgangskanal 2: +App.Heat.outputChannel.description = Kanaladresse des digitalen Ausgangs # Load control App.LoadControl.ThresholdControl.Name = Schwellwertsteuerung @@ -95,7 +111,8 @@ App.FENECON.Home.rippleControlReceiver.label = Rundsteuerempfänger aktiviert? App.FENECON.Home.rippleControlReceiver.description = Externe Abregelung durch Netzbetreiber App.FENECON.Home.feedInLimit.label = Begrenzung der Einspeisung [W] App.FENECON.Home.feedInSettings.label = Einspeise-Einstellungen -App.FENECON.Home.hasAcMeterSocomec.label = Hat AC-Zähler (SOCOMEC) +App.FENECON.Home.hasAcMeter.label = Hat AC-Zähler +App.FENECON.Home.acMeterType.label = AC-Zähler Typ App.FENECON.Home.hasDcPV1.label = Hat DC-PV 1 (MPPT 1) App.FENECON.Home.hasDcPV2.label = Hat DC-PV 2 (MPPT 2) App.FENECON.Home.emergencyPowerSupply.label = Aktivieren der Notstromversorgung @@ -119,9 +136,10 @@ App.FENECON.Home.meter2.alias = Notstromverbraucher App.FENECON.Home.ctrlEmergencyCapacityReserve0.alias = Ansteuerung der Notstromreserve # Meter -App.Meter.mountType.label = Einbindungs Typ +App.Meter.mountType.label = Verwendungsart +App.Meter.modbusUnitId.description = Unit-ID des Zählers App.Meter.ip.description = Die IP-Adresse des Messgeräts. -App.Meter.production = Erzeugung +App.Meter.production = Erzeugungszähler App.Meter.gridMeter = Netzzähler App.Meter.consumtionMeter = Verbrauchszähler @@ -129,6 +147,7 @@ App.Meter.CarloGavazzi.Name = CARLO GAVAZZI Zähler App.Meter.Janitza.Name = Janitza Zähler App.Meter.Janitza.productModel = Produkt Model App.Meter.Socomec.Name = SOCOMEC Zähler +App.Meter.Kdk.Name = KDK Zähler # PV-Inverter App.PvInverter.ip.description = IP-Adresse des PV-Wechselrichters. @@ -139,27 +158,34 @@ 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 -App.PvInverter.Sma.modbusUnitId.description = Die Unit-ID des Modbus-Geräts. Beachten Sie, dass Sie laut Handbuch den Wert, den Sie in der SMA Webschnittstelle konfiguriert haben, um '123' ergänzen müssen. +App.PvInverter.Sma.modbusUnitId.description = Modbus Unit-ID des PV-Wechselrichters. Beachten Sie, dass Sie laut Handbuch zu dem Wert, den Sie in der SMA Webschnittstelle konfiguriert haben, den Wert '123' addieren müssen. +App.PvInverter.Sma.phase.label = Phasen +App.PvInverter.Sma.phase.description = Angeschlossene Phase(n) des Wechselrichters App.PvInverter.SolarEdge.Name = SolarEdge PV-Wechselrichter # Time of use Tarif App.TimeOfUseTariff.Awattar.Name = Awattar HOURLY App.TimeOfUseTariff.Stromdao.Name = Stromdao Corrently -App.TimeOfUseTariff.Stromdao.zipCode.label = Postleitzahl -App.TimeOfUseTariff.Stromdao.zipCode.description = Deutsche Postleitzahl des Ortes. +App.TimeOfUseTariff.Stromdao.zipCode.label = PLZ +App.TimeOfUseTariff.Stromdao.zipCode.description = Deutsche Postleitzahl des Wohnorts App.TimeOfUseTariff.Tibber.Name = Tibber -App.TimeOfUseTariff.Tibber.accessToken.label = Zugangstoken -App.TimeOfUseTariff.Tibber.accessToken.description = Zugangstoken für den Tibber Stromtarif. +App.TimeOfUseTariff.Tibber.accessToken.label = Token +App.TimeOfUseTariff.Tibber.accessToken.description = Personal Access Token von Tibber # PvSelfConsumption App.PvSelfConsumption.GridOptimizedCharge.Name = Netzdienliche Beladung -App.PvSelfConsumption.GridOptimizedCharge.sellToGridLimitEnabled.label = Ist der maximal Stromverkauf an das Netz aktiviert? -App.PvSelfConsumption.GridOptimizedCharge.sellToGridLimitEnabled.description = Ist die Logik für den maximal Stromverkauf an das Netz aktiviert? -App.PvSelfConsumption.GridOptimizedCharge.maximumSellToGridPower.label = Maximal zulässiger Stromverkauf an das Netz -App.PvSelfConsumption.GridOptimizedCharge.maximumSellToGridPower.description = Die Zielgrenze für den Verkauf von Strom an das Netz. -App.PvSelfConsumption.GridOptimizedCharge.mode.label = Mode +App.PvSelfConsumption.GridOptimizedCharge.sellToGridLimitEnabled.label = Ist die maximale Netzeinspeisung aktiviert? +App.PvSelfConsumption.GridOptimizedCharge.maximumSellToGridPower.label = Maximale Netzeinspeisung (in Watt) +App.PvSelfConsumption.GridOptimizedCharge.mode.label = Modus +App.PvSelfConsumption.GridOptimizedCharge.mode.off = Aus +App.PvSelfConsumption.GridOptimizedCharge.mode.automatic = Automatisch +App.PvSelfConsumption.GridOptimizedCharge.mode.manual = Manuell App.PvSelfConsumption.SelfConsumptionOptimization.Name = Eigenverbrauchsoptimierung App.PvSelfConsumption.SelfConsumptionOptimization.ess.label = Ess-ID -App.PvSelfConsumption.SelfConsumptionOptimization.ess.description = ID von den Ess Gerät. +App.PvSelfConsumption.SelfConsumptionOptimization.ess.description = ID des Speichersystems App.PvSelfConsumption.SelfConsumptionOptimization.meter.label = Netzzähler-ID -App.PvSelfConsumption.SelfConsumptionOptimization.meter.description = ID von den Netzzähler. +App.PvSelfConsumption.SelfConsumptionOptimization.meter.description = ID des Netzzählers + +# Ess +App.Ess.PrepareBatteryExtension.Name = Batterie Nachrüstung +App.Ess.PrepareBatteryExtension.targetSoc.label = Ziel Soc \ No newline at end of file diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/translation_en.properties b/io.openems.edge.core/src/io/openems/edge/core/appmanager/translation_en.properties index dc4f2b8ccfe..b7825d88e31 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/translation_en.properties +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/translation_en.properties @@ -1,27 +1,40 @@ # Categories integratedSystems = Integrated Systems -timeOfUseTariff = Time -evcs = e-mobility -heat = Heat +timeOfUseTariff = Time-of-use tariffs +evcs = E-Mobility +heat = Power-to-Heat loadControl = Load control hardware = Hardware -pvInverter = PV-Inverter +pvInverter = PV inverter pvSelfConsumption = PV self-consumption -meter = Meter -api = API's +meter = Production and consumption meter +api = Interfaces +ess = Energy Storage controller # Global +alias = Alias ipAddress = IP-Address +ipAddress.description = The IP address of the device. port = Port +port.description = Port of the device. modbusId = Modbus-ID modbusId.description = Modbus-ID of the Modbus Component. modbusUnitId = Modbus Unit-ID modbusUnitId.description = The Unit-ID of the Modbus device. +all = All +l1 = L1 +l2 = L2 +l3 = L3 germany = Germany austria = Austria switzerland = Switzerland +sweden = Sweden +czech = Czech Republic +netherlands = Netherlands username = Username password = Password +left = Left +right = Right # Api App.Api.apiTimeout.label = Api-Timeout @@ -29,7 +42,7 @@ App.Api.apiTimeout.description = Sets the timeout in seconds for updates on Chan App.Api.ModbusTcp.ReadOnly.Name = Modbus/TCP reading -App.Api.ModbusTcp.ReadWrite.Name = Modbus/TCP Write Access +App.Api.ModbusTcp.ReadWrite.Name = Modbus/TCP write access App.Api.ModbusTcp.ReadWrite.componentIds.label = Component-IDs App.Api.ModbusTcp.ReadWrite.componentIds.description = Components that should be made available via Modbus. @@ -41,50 +54,53 @@ App.Api.Mqtt.EdgeId.description = Client-ID for authentication at MQTT broker. App.Api.Mqtt.Uri.description = The connection Uri to MQTT broker. App.Api.RestJson.ReadOnly.Name = REST/JSON reading -App.Api.RestJson.ReadWrite.Name = REST/JSON Write Access +App.Api.RestJson.ReadWrite.Name = REST/JSON write access # Evcs -App.Evcs.Cluster.Name = Multi-charge point management +App.Evcs.controller.alias = Charging station control +App.Evcs.ip.description = The IP address of the charging station. +App.Evcs.chargingStation.label = Charging station {0} + +App.Evcs.Cluster.Name = Multi-charging point management App.Evcs.Cluster.evcsIds.description = IDs of EVCS devices. -App.Evcs.HardyBarth.Name = eCharge Hardy Barth Charging Station -App.Evcs.HardyBarth.ip.description = The IP address of the charging station. If the charger has two connectors, the second/slave evcs has the IP 192.168.25.31. +App.Evcs.HardyBarth.Name = eCharge Hardy Barth charging station +App.Evcs.HardyBarth.alias.value = eCharge Hardy Barth charging station - {0} +App.Evcs.HardyBarth.alias.label = Alias charging station {0} +App.Evcs.HardyBarth.numberOfChargingStations.label = Number of charging stations +App.Evcs.HardyBarth.ip.label = IP-Address charging station {0} -App.Evcs.IesKeywatt.Name = IES Keywatt Charging Station +App.Evcs.IesKeywatt.Name = IES Keywatt charging station App.Evcs.IesKeywatt.chargepoint.label = OCPP chargepoint identifier App.Evcs.IesKeywatt.chargepoint.description = The OCPP identifier of the charging station. App.Evcs.IesKeywatt.connector.label = OCPP connector identifier App.Evcs.IesKeywatt.connector.description = The connector id of the chargepoint (e.g. if there are two connectors, then the evcs has two id's 1 and 2). -App.Evcs.Keba.Name = KEBA Charging Station -App.Evcs.Keba.ip.description = The IP address of the charging station. +App.Evcs.Keba.Name = KEBA charging station # Hardware -App.Hardware.KMtronic8Channel.Name = FEMS Relay 8-Channel -App.Hardware.KMtronic8Channel.ip.description = The IP address of the relay board. +App.Hardware.KMtronic8Channel.Name = FEMS Relay board 8-channel TCP +App.Hardware.KMtronic8Channel.ip.description = The IP address of the relay board # Heat App.Heat.CHP.Name = Combined heat and power plant (CHP) -App.Heat.CHP.outputChannel.label = Output Channel Address -App.Heat.CHP.outputChannel.description = Channel address of the Digital Output that should be switched. -App.Heat.HeatingElement.Name = Heating rod -App.Heat.HeatingElement.outputChannelPhaseL1.label = Output Channel Phase L1 -App.Heat.HeatingElement.outputChannelPhaseL1.description = Channel address of the Digital Output for Phase L1. -App.Heat.HeatingElement.outputChannelPhaseL2.label = Output Channel Phase L2 -App.Heat.HeatingElement.outputChannelPhaseL2.description = Channel address of the Digital Output for Phase L2. -App.Heat.HeatingElement.outputChannelPhaseL3.label = Output Channel Phase L3 -App.Heat.HeatingElement.outputChannelPhaseL3.description = Channel address of the Digital Output for Phase L3. -App.Heat.HeatPump.Name = "SG-Ready" Heat Pump -App.Heat.HeatPump.outputChannel1.label = Output Channel 1 -App.Heat.HeatPump.outputChannel1.description = Channel address of the Digital Output for input 1. -App.Heat.HeatPump.outputChannel2.label = Output Channel 2 -App.Heat.HeatPump.outputChannel2.description = Channel address of the Digital Output for input 2. +App.Heat.CHP.outputChannel.label = Output Channel Address: +App.Heat.HeatingElement.Name = Heating element +App.Heat.HeatingElement.outputChannelPhaseL1.label = Output Channel Phase L1: +App.Heat.HeatingElement.outputChannelPhaseL2.label = Output Channel Phase L2: +App.Heat.HeatingElement.outputChannelPhaseL3.label = Output Channel Phase L3: +App.Heat.HeatingElement.powerPerPhase.label = Power per phase +App.Heat.HeatingElement.powerPerPhase.description = Power of the heating element per phase [Watt] +App.Heat.HeatPump.Name = "SG-Ready" heat pump +App.Heat.HeatPump.outputChannel1.label = Output Channel 1: +App.Heat.HeatPump.outputChannel2.label = Output Channel 2: +App.Heat.outputChannel.description = Channel address of the Digital Output # Load control -App.LoadControl.ThresholdControl.Name = Threshold Control +App.LoadControl.ThresholdControl.Name = Threshold control App.LoadControl.ThresholdControl.outputChannels.label = Output Channels App.LoadControl.ThresholdControl.outputChannels.description = Channel addresses of the Digital Outputs that should be switched. -App.LoadControl.ManualRelayControl.Name = Manual Relay Control +App.LoadControl.ManualRelayControl.Name = Manual relay control App.LoadControl.ManualRelayControl.outputChannel.label = Output Channel App.LoadControl.ManualRelayControl.outputChannel.description = Channel address of the Digital Output that should be switched. @@ -95,7 +111,8 @@ App.FENECON.Home.rippleControlReceiver.label = Ripple control receiver active? App.FENECON.Home.rippleControlReceiver.description = External balancing by grid operator App.FENECON.Home.feedInLimit.label = Feed-In limitation [W] App.FENECON.Home.feedInSettings.label = Feed-In Settings -App.FENECON.Home.hasAcMeterSocomec.label = Has AC meter (SOCOMEC) +App.FENECON.Home.hasAcMeter.label = Has AC meter +App.FENECON.Home.acMeterType.label = AC-Meter Type App.FENECON.Home.hasDcPV1.label = Has DC-PV 1 (MPPT 1) App.FENECON.Home.hasDcPV2.label = Has DC-PV 2 (MPPT 2) App.FENECON.Home.emergencyPowerSupply.label = Activate Emergency power supply @@ -120,46 +137,55 @@ App.FENECON.Home.ctrlEmergencyCapacityReserve0.alias = Control of the emergency # Meter App.Meter.mountType.label = Mount Type +App.Meter.modbusUnitId.description = Unit-ID of the Meter App.Meter.ip.description = The IP address of the Meter. -App.Meter.production = Production +App.Meter.production = Production-Meter App.Meter.gridMeter = Grid-Meter App.Meter.consumtionMeter = Consumption-Meter -App.Meter.CarloGavazzi.Name = CARLO GAVAZZI Meter -App.Meter.Janitza.Name = Janitza Meter +App.Meter.CarloGavazzi.Name = CARLO GAVAZZI meter +App.Meter.Janitza.Name = Janitza meter App.Meter.Janitza.productModel = Product Model -App.Meter.Socomec.Name = SOCOMEC Meter - -# PV-Inverter -App.PvInverter.ip.description = IP address of the PV-Inverter. -App.PvInverter.port.description = Port of the PV-Inverter. -App.PvInverter.modbusUnitId.description = Modbus Unit-ID 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 +App.Meter.Socomec.Name = SOCOMEC meter +App.Meter.Kdk.Name = KDK meter + +# PV inverter +App.PvInverter.ip.description = IP address of the PV inverter. +App.PvInverter.port.description = Port of the PV inverter. +App.PvInverter.modbusUnitId.description = Modbus Unit-ID 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 App.PvInverter.Sma.modbusUnitId.description = The Unit-ID of the Modbus device. Be aware, that according to the manual you need to add '123' to the value that you configured in the SMA web interface. -App.PvInverter.SolarEdge.Name = SolarEdge PV-Inverter +App.PvInverter.Sma.phase.label = Phase +App.PvInverter.Sma.phase.description = Connected phase(s) of the inverter +App.PvInverter.SolarEdge.Name = SolarEdge PV inverter # Time of use Tarif App.TimeOfUseTariff.Awattar.Name = Awattar HOURLY -App.TimeOfUseTariff.Stromdao.Name = Stromdao Corrently +App.TimeOfUseTariff.Stromdao.Name = STROMDAO Corrently App.TimeOfUseTariff.Stromdao.zipCode.label = ZIP Code -App.TimeOfUseTariff.Stromdao.zipCode.description = German ZIP Code of the location. +App.TimeOfUseTariff.Stromdao.zipCode.description = German postal code of place of residence App.TimeOfUseTariff.Tibber.Name = Tibber -App.TimeOfUseTariff.Tibber.accessToken.label = Access token -App.TimeOfUseTariff.Tibber.accessToken.description = Access token for the Tibber API. +App.TimeOfUseTariff.Tibber.accessToken.label = Token +App.TimeOfUseTariff.Tibber.accessToken.description = Personal access token from Tibber # PvSelfConsumption -App.PvSelfConsumption.GridOptimizedCharge.Name = Grid optimized charge +App.PvSelfConsumption.GridOptimizedCharge.Name = Grid-optimized charge App.PvSelfConsumption.GridOptimizedCharge.sellToGridLimitEnabled.label = Is Sell-To-Grid-Limit enabled? -App.PvSelfConsumption.GridOptimizedCharge.sellToGridLimitEnabled.description = Is the sell to grid limit logic enabled? -App.PvSelfConsumption.GridOptimizedCharge.maximumSellToGridPower.label = Maximum allowed Sell-To-Grid power -App.PvSelfConsumption.GridOptimizedCharge.maximumSellToGridPower.description = The target limit for sell-to-grid power. +App.PvSelfConsumption.GridOptimizedCharge.maximumSellToGridPower.label = Maximum allowed Sell-To-Grid power (in Watt) App.PvSelfConsumption.GridOptimizedCharge.mode.label = Mode -App.PvSelfConsumption.SelfConsumptionOptimization.Name = self-consumption optimisation +App.PvSelfConsumption.GridOptimizedCharge.mode.off = Off +App.PvSelfConsumption.GridOptimizedCharge.mode.automatic = Automatic +App.PvSelfConsumption.GridOptimizedCharge.mode.manual = Manual +App.PvSelfConsumption.SelfConsumptionOptimization.Name = Self-consumption optimisation App.PvSelfConsumption.SelfConsumptionOptimization.ess.label = Ess-ID -App.PvSelfConsumption.SelfConsumptionOptimization.ess.description = ID of Ess device. +App.PvSelfConsumption.SelfConsumptionOptimization.ess.description = ID of the Storage system App.PvSelfConsumption.SelfConsumptionOptimization.meter.label = Grid-Meter-ID -App.PvSelfConsumption.SelfConsumptionOptimization.meter.description = ID of the Grid-Meter. +App.PvSelfConsumption.SelfConsumptionOptimization.meter.description = ID of the Grid-Meter + +# Ess +App.Ess.PrepareBatteryExtension.Name = Prepare Battery Extension +App.Ess.PrepareBatteryExtension.targetSoc.label = Target Soc \ No newline at end of file diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckAppsNotInstalled.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckAppsNotInstalled.java index 7bde53f1965..7dc62944668 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckAppsNotInstalled.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckAppsNotInstalled.java @@ -9,12 +9,16 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ServiceScope; import io.openems.common.session.Language; import io.openems.edge.core.appmanager.AppManager; import io.openems.edge.core.appmanager.AppManagerImpl; -@Component(name = CheckAppsNotInstalled.COMPONENT_NAME) +@Component(// + name = CheckAppsNotInstalled.COMPONENT_NAME, // + scope = ServiceScope.PROTOTYPE // +) public class CheckAppsNotInstalled extends AbstractCheckable implements Checkable { public static final String COMPONENT_NAME = "Validator.Checkable.CheckAppsNotInstalled"; diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckCardinality.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckCardinality.java index 5783f96fe0e..d8227b5317b 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckCardinality.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckCardinality.java @@ -8,6 +8,7 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ServiceScope; import io.openems.common.session.Language; import io.openems.edge.core.appmanager.AppManager; @@ -18,7 +19,10 @@ import io.openems.edge.core.appmanager.OpenemsAppCategory; import io.openems.edge.core.appmanager.OpenemsAppInstance; -@Component(name = CheckCardinality.COMPONENT_NAME) +@Component(// + name = CheckCardinality.COMPONENT_NAME, // + scope = ServiceScope.PROTOTYPE // +) public class CheckCardinality extends AbstractCheckable implements Checkable { public static final String COMPONENT_NAME = "Validator.Checkable.CheckCardinality"; @@ -100,8 +104,8 @@ private OpenemsAppCategory getMatchingCategorie(AppManagerUtil appManagerUtil, if (app.getCardinality() != OpenemsAppCardinality.SINGLE_IN_CATEGORY) { continue; } - for (var cat : app.getCategorys()) { - for (var catOther : this.openemsApp.getCategorys()) { + for (var cat : app.getCategories()) { + for (var catOther : this.openemsApp.getCategories()) { if (cat == catOther) { return cat; } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckHome.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckHome.java index e8b53cc5280..263d408d670 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckHome.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckHome.java @@ -6,12 +6,16 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ServiceScope; import io.openems.common.OpenemsConstants; import io.openems.common.session.Language; import io.openems.edge.common.component.ComponentManager; -@Component(name = CheckHome.COMPONENT_NAME) +@Component(// + name = CheckHome.COMPONENT_NAME, // + scope = ServiceScope.PROTOTYPE // +) public class CheckHome extends AbstractCheckable implements Checkable { public static final String COMPONENT_NAME = "Validator.Checkable.CheckHome"; diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckHost.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckHost.java index 8d88c319866..cbd099ed598 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckHost.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckHost.java @@ -9,10 +9,14 @@ import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ServiceScope; import io.openems.common.session.Language; -@Component(name = CheckHost.COMPONENT_NAME) +@Component(// + name = CheckHost.COMPONENT_NAME, // + scope = ServiceScope.PROTOTYPE // +) public class CheckHost extends AbstractCheckable implements Checkable { public static final String COMPONENT_NAME = "Validator.Checkable.CheckHost"; diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckNoComponentInstalledOfFactoryId.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckNoComponentInstalledOfFactoryId.java index 42739394733..5411fbc15ec 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckNoComponentInstalledOfFactoryId.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckNoComponentInstalledOfFactoryId.java @@ -6,11 +6,15 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ServiceScope; import io.openems.common.session.Language; import io.openems.edge.common.component.ComponentManager; -@Component(name = CheckNoComponentInstalledOfFactoryId.COMPONENT_NAME) +@Component(// + name = CheckNoComponentInstalledOfFactoryId.COMPONENT_NAME, // + scope = ServiceScope.PROTOTYPE // +) public class CheckNoComponentInstalledOfFactoryId extends AbstractCheckable implements Checkable { public static final String COMPONENT_NAME = "Validator.Checkable.CheckNoComponentInstalledOfFactorieId"; diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckRelayCount.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckRelayCount.java index c5566b7ad39..0ec0fa50c10 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckRelayCount.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/CheckRelayCount.java @@ -1,31 +1,45 @@ package io.openems.edge.core.appmanager.validator; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ServiceScope; +import io.openems.common.OpenemsConstants; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.session.Language; import io.openems.edge.core.appmanager.ComponentUtil; +import io.openems.edge.core.appmanager.OpenemsApp; -@Component(name = CheckRelayCount.COMPONENT_NAME) +@Component(// + name = CheckRelayCount.COMPONENT_NAME, // + scope = ServiceScope.PROTOTYPE // +) public class CheckRelayCount extends AbstractCheckable implements Checkable { public static final String COMPONENT_NAME = "Validator.Checkable.CheckRelayCount"; private final ComponentUtil openemsAppUtil; + private final OpenemsApp relayApp; + private String io; private int count; + private int availableRelays; + @Activate - public CheckRelayCount(@Reference ComponentUtil openemsAppUtil, ComponentContext componentContext) { + public CheckRelayCount(// + @Reference ComponentUtil openemsAppUtil, // + ComponentContext componentContext, // + @Reference(target = "(" + OpenemsConstants.PROPERTY_OSGI_COMPONENT_NAME + + "=App.Hardware.KMtronic8Channel)") OpenemsApp relayApp // + ) { super(componentContext); this.openemsAppUtil = openemsAppUtil; + this.relayApp = relayApp; } private void init(String io, int count) { @@ -43,26 +57,44 @@ public void setProperties(Map properties) { @Override public boolean check() { try { - List availableRelays; + int availableRelays; if (this.io != null) { - availableRelays = this.openemsAppUtil.getAvailableRelays(this.io); + availableRelays = this.openemsAppUtil.getAvailableRelays(this.io).size(); } else { - var relay = this.openemsAppUtil.getAvailableRelays().stream().filter(t -> t.relays.size() >= this.count) - .findFirst().orElse(null); - availableRelays = relay != null ? relay.relays : new ArrayList<>(); + availableRelays = this.openemsAppUtil.getAvailableRelays().stream() // + .mapToInt(t -> t.relays.size()) // + .max() // + .orElse(0); } - if (this.count <= availableRelays.size()) { + this.availableRelays = availableRelays; + if (this.count <= availableRelays) { return true; } } catch (OpenemsNamedException e) { // io not found so there are none available + this.availableRelays = 0; } return false; } @Override public String getErrorMessage(Language language) { - return AbstractCheckable.getTranslation(language, "Validator.Checkable.CheckRelayCount.Message"); + final var messageBuilder = new StringBuilder(// + AbstractCheckable.getTranslation(language, // + "Validator.Checkable.CheckRelayCount.Message", // + this.count, this.availableRelays) // + ); + + // message to install additional relay + if (this.relayApp != null) { + messageBuilder.append(// + AbstractCheckable.getTranslation(language, // + "Validator.Checkable.CheckRelayCount.Message.AdditionalRelay", // + this.relayApp.getAppDescriptor().getWebsiteUrl(), // + this.relayApp.getName(language)) // + ); + } + return messageBuilder.toString(); } } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/ValidatorImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/ValidatorImpl.java index 0dfde77ee4f..a42bf726b06 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/ValidatorImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/ValidatorImpl.java @@ -1,20 +1,19 @@ package io.openems.edge.core.appmanager.validator; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; +import org.osgi.service.component.ComponentServiceObjects; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; +import org.osgi.service.component.annotations.ReferenceScope; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.collect.Lists; - import io.openems.common.OpenemsConstants; import io.openems.common.session.Language; import io.openems.edge.core.appmanager.validator.ValidatorConfig.CheckableConfig; @@ -24,6 +23,15 @@ public class ValidatorImpl implements Validator { private static final Logger LOG = LoggerFactory.getLogger(ValidatorImpl.class); + @Reference(// + cardinality = ReferenceCardinality.MULTIPLE, // + policy = ReferencePolicy.DYNAMIC, // + policyOption = ReferencePolicyOption.GREEDY, // + // requires prototype for thread safety + scope = ReferenceScope.PROTOTYPE_REQUIRED // + ) + private volatile List> checkableFactories; + @Activate public ValidatorImpl() { } @@ -35,64 +43,47 @@ public List getErrorMessages(List checkableConfigs, Lan return new ArrayList<>(); } var errorMessages = new ArrayList(checkableConfigs.size()); - var bundleContext = FrameworkUtil.getBundle(Checkable.class).getBundleContext(); - // build filter - var filterBuilder = new StringBuilder(); - if (checkableConfigs.size() > 1) { - filterBuilder.append("(|"); - } - checkableConfigs.forEach(t -> filterBuilder.append("(component.name=" + t.checkableComponentName + ")")); - if (checkableConfigs.size() > 1) { - filterBuilder.append(")"); - } - try { - // get all service references - Collection> serviceReferences = bundleContext - .getServiceReferences(Checkable.class, filterBuilder.toString()); - var noneExistingCheckables = Lists.newArrayList(); - checkableConfigs.forEach(c -> noneExistingCheckables.add(c)); - var isReturnedImmediate = false; - final var usedReferencens = new ArrayList>(serviceReferences.size()); - for (var reference : serviceReferences) { - var componentName = (String) reference.getProperty(OpenemsConstants.PROPERTY_OSGI_COMPONENT_NAME); - var checkableConfig = checkableConfigs.stream() - .filter(c -> c.checkableComponentName.equals(componentName)).findFirst().orElse(null); - var checkable = bundleContext.getService(reference); - if (checkable == null) { - errorMessages.add("Can not get Checkable[" + checkableConfig.checkableComponentName + "]"); - continue; - } - usedReferencens.add(reference); - if (checkableConfig.properties != null) { - checkable.setProperties(checkableConfig.properties); - } - noneExistingCheckables.removeIf(c -> c.equals(checkableConfig)); + + for (var config : checkableConfigs) { + // find the componentServiceObjects base on the given configuration name + final var cso = this.checkableFactories.stream()// + .filter(csoCheckable -> { + var sr = csoCheckable.getServiceReference(); + var srName = (String) sr.getProperty(OpenemsConstants.PROPERTY_OSGI_COMPONENT_NAME); + return srName.equals(config.checkableComponentName); + }).findAny().orElse(null); + + if (cso == null) { + LOG.info("Unable to get Checkable '" + config.checkableComponentName + "'!"); + continue; + } + + // get the service from the cso + final var checkable = cso.getService(); + + if (checkable == null) { + LOG.info("Unable to get Checkable '" + config.checkableComponentName + "'!"); + continue; + } + + try { + // validate checkable + checkable.setProperties(config.properties); var result = checkable.check(); - if (result == checkableConfig.invertResult) { + if (result == config.invertResult) { var errorMessage = checkable.getErrorMessage(language); - if (checkableConfig.invertResult) { + if (config.invertResult) { errorMessage = "Invert[" + errorMessage + "]"; } errorMessages.add(errorMessage); if (returnImmediate) { - isReturnedImmediate = true; - break; + return errorMessages; } } + } finally { + // free checkable from cso + cso.ungetService(checkable); } - - if (!noneExistingCheckables.isEmpty() && !isReturnedImmediate) { - LOG.warn("Checkables[" + noneExistingCheckables.stream().map(c -> c.checkableComponentName) - .collect(Collectors.joining(";")) + "] are not found!"); - } - - // free all service references - for (var reference : usedReferencens) { - bundleContext.ungetService(reference); - } - } catch (InvalidSyntaxException | IllegalStateException e) { - // Can not get service references - e.printStackTrace(); } return errorMessages; } diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/translation_de.properties b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/translation_de.properties index 9b38445dec1..7b3b2af3277 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/translation_de.properties +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/translation_de.properties @@ -1,7 +1,7 @@ Validator.Checkable.CheckAppsNotInstalled.Message = Apps mit der ID[{0}] sind installiert! Deinstalliere diese um diese App installieren zu können. -Validator.Checkable.CheckCardinality.Message.SingleInCategorie = Eine Instanz einer App mit der selben Kategorie "{0}" ist bereits erstellt worden! -Validator.Checkable.CheckCardinality.Message.Single = Eine Instanz der App[{0}] ist bereits erstellt worden! +Validator.Checkable.CheckCardinality.Message.SingleInCategorie = Es ist bereits eine App aus derselben Kategorie "{0}" installiert. +Validator.Checkable.CheckCardinality.Message.Single = Es ist bereits eine App "{0}" installiert. Validator.Checkable.CheckHome.Message = Kein Home System installiert! @@ -10,4 +10,5 @@ Validator.Checkable.CheckHost.WrongIp = IP "{0}" ist keine valide IP-Adresse! Validator.Checkable.CheckNoComponentInstalledOfFactorieId.Message = Komponenten mit der FaktorieID[{0}] sind installiert! Entferne diese um diese App installieren zu können. -Validator.Checkable.CheckRelayCount.Message = Es sind nicht genug Relais ports verfügbar! Installiere ein Relais um diese App installieren zu können. +Validator.Checkable.CheckRelayCount.Message = Es sind nicht genug freie Digital-/Relaisausgänge verfügbar.

      Benötigt: {0}
      Verfügbar: {1} +Validator.Checkable.CheckRelayCount.Message.AdditionalRelay =

      {1} für weitere Ausgänge erwerben. diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/translation_en.properties b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/translation_en.properties index 23147b16cc1..3906032e5f2 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/translation_en.properties +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/validator/translation_en.properties @@ -1,7 +1,7 @@ Validator.Checkable.CheckAppsNotInstalled.Message = Apps with ID[{0}] are installed! Delete them to be able to install this App. -Validator.Checkable.CheckCardinality.Message.SingleInCategorie = An instance of an app with the same category '{0}' is already created! -Validator.Checkable.CheckCardinality.Message.Single = An instance of the app[{0}] is already created! +Validator.Checkable.CheckCardinality.Message.SingleInCategorie = There is already an app of the same category "{0}" installed. +Validator.Checkable.CheckCardinality.Message.Single = There is already an app "{0}" installed. Validator.Checkable.CheckHome.Message = No Home system installed! @@ -10,4 +10,5 @@ Validator.Checkable.CheckHost.WrongIp = IP "{0}" is not a valid IP-Address! Validator.Checkable.CheckNoComponentInstalledOfFactorieId.Message = Components with the FactorieID[{0}] are installed! Remove them to be able to install this app. -Validator.Checkable.CheckRelayCount.Message = There are not enough Relay ports available! Install a Relay to be able to install this App. +Validator.Checkable.CheckRelayCount.Message = There are not enough Digital-/Relay ports available.

      Required: {0}
      Available: {1} +Validator.Checkable.CheckRelayCount.Message.AdditionalRelay =

      Buy {1} for more outputs. diff --git a/io.openems.edge.core/test/io/openems/edge/app/TestADependencyToC.java b/io.openems.edge.core/test/io/openems/edge/app/TestADependencyToC.java index d1cfffdc6d3..0dbf9b38671 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/TestADependencyToC.java +++ b/io.openems.edge.core/test/io/openems/edge/app/TestADependencyToC.java @@ -18,12 +18,13 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.TestADependencyToC.Property; import io.openems.edge.common.component.ComponentManager; -import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -34,9 +35,9 @@ * Test app for testing dependencies. */ @Component(name = "App.Test.TestADependencyToC") -public class TestADependencyToC extends AbstractOpenemsApp implements OpenemsApp { +public class TestADependencyToC extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { CREATE_POLICY, // UPDATE_POLICY, // DELETE_POLICY, // @@ -64,7 +65,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.TEST }; } diff --git a/io.openems.edge.core/test/io/openems/edge/app/TestBDependencyToC.java b/io.openems.edge.core/test/io/openems/edge/app/TestBDependencyToC.java index 4233da8514d..97fb25d95be 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/TestBDependencyToC.java +++ b/io.openems.edge.core/test/io/openems/edge/app/TestBDependencyToC.java @@ -17,12 +17,13 @@ import io.openems.common.utils.EnumUtils; import io.openems.edge.app.TestBDependencyToC.Property; import io.openems.edge.common.component.ComponentManager; -import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -33,9 +34,9 @@ * Test app for testing dependencies. */ @Component(name = "App.Test.TestBDependencyToC") -public class TestBDependencyToC extends AbstractOpenemsApp implements OpenemsApp { +public class TestBDependencyToC extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { CREATE_POLICY } @@ -58,7 +59,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.TEST }; } diff --git a/io.openems.edge.core/test/io/openems/edge/app/TestC.java b/io.openems.edge.core/test/io/openems/edge/app/TestC.java index d92d9cc80d2..b6f724d9151 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/TestC.java +++ b/io.openems.edge.core/test/io/openems/edge/app/TestC.java @@ -15,12 +15,13 @@ import io.openems.common.session.Language; import io.openems.edge.app.TestC.Property; import io.openems.edge.common.component.ComponentManager; -import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; 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.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; @@ -29,9 +30,9 @@ * Test app for testing dependencies. */ @Component(name = "App.Test.TestC") -public class TestC extends AbstractOpenemsApp implements OpenemsApp { +public class TestC extends AbstractEnumOpenemsApp implements OpenemsApp { - public static enum Property { + public static enum Property implements Nameable { NUMBER } @@ -54,7 +55,7 @@ public AppDescriptor getAppDescriptor() { } @Override - public OpenemsAppCategory[] getCategorys() { + public OpenemsAppCategory[] getCategories() { return new OpenemsAppCategory[] { OpenemsAppCategory.TEST }; } diff --git a/io.openems.edge.core/test/io/openems/edge/app/TestMultipleIds.java b/io.openems.edge.core/test/io/openems/edge/app/TestMultipleIds.java new file mode 100644 index 00000000000..d7297236b42 --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/app/TestMultipleIds.java @@ -0,0 +1,114 @@ +package io.openems.edge.app; + +import java.util.ArrayList; +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.Component; +import org.osgi.service.component.annotations.Reference; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.function.ThrowingTriFunction; +import io.openems.common.session.Language; +import io.openems.common.types.EdgeConfig; +import io.openems.common.utils.EnumUtils; +import io.openems.edge.app.TestMultipleIds.Property; +import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractEnumOpenemsApp; +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.Nameable; +import io.openems.edge.core.appmanager.OpenemsApp; +import io.openems.edge.core.appmanager.OpenemsAppCardinality; +import io.openems.edge.core.appmanager.OpenemsAppCategory; + +/** + * Test app for testing dependencies. + */ +@Component(name = "App.Test.TestMultipleIds") +public class TestMultipleIds extends AbstractEnumOpenemsApp implements OpenemsApp { + + public static enum Property implements Nameable { + SET_IDS, // + ID_1, // + ID_2, // + ID_3, // + ID_4, // + ; + } + + @Activate + public TestMultipleIds(@Reference ComponentManager componentManager, ComponentContext componentContext, + @Reference ConfigurationAdmin cm, @Reference ComponentUtil componentUtil) { + super(componentManager, componentContext, cm, componentUtil); + } + + @Override + public AppAssistant getAppAssistant(Language language) { + return AppAssistant.create(this.getName(language)) // + .build(); + } + + @Override + public AppDescriptor getAppDescriptor() { + return AppDescriptor.create() // + .build(); + } + + @Override + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.TEST }; + } + + @Override + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.MULTIPLE; + } + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appConfigurationFactory() { + return (t, m, l) -> { + final var setIds = EnumUtils.getAsOptionalInt(m, Property.SET_IDS).orElse(1); + + final var components = new ArrayList(); + + if (setIds >= 1) { + components.add(new EdgeConfig.Component(this.getId(t, m, Property.ID_1, "id0"), "alias", "factoryId", // + new JsonObject())); + } + if (setIds >= 2) { + components.add(new EdgeConfig.Component(this.getId(t, m, Property.ID_2, "id0"), "alias", "factoryId", // + new JsonObject())); + } + if (setIds >= 3) { + components.add(new EdgeConfig.Component(this.getId(t, m, Property.ID_3, "id0"), "alias", "factoryId", // + new JsonObject())); + } + if (setIds >= 4) { + components.add(new EdgeConfig.Component(this.getId(t, m, Property.ID_4, "id0"), "alias", "factoryId", // + new JsonObject())); + } + + return new AppConfiguration(components); + }; + } + + @Override + protected Class getPropertyClass() { + return Property.class; + } + + @Override + public String getName(Language language) { + return this.getAppId(); + } + +} diff --git a/io.openems.edge.core/test/io/openems/edge/app/api/TestModbusTcpApiReadWrite.java b/io.openems.edge.core/test/io/openems/edge/app/api/TestModbusTcpApiReadWrite.java index 75a6b539b72..33445e6cea2 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/api/TestModbusTcpApiReadWrite.java +++ b/io.openems.edge.core/test/io/openems/edge/app/api/TestModbusTcpApiReadWrite.java @@ -15,6 +15,7 @@ import io.openems.edge.common.test.DummyUser; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.AppManagerTestBundle; +import io.openems.edge.core.appmanager.Apps; import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; import io.openems.edge.core.appmanager.jsonrpc.DeleteAppInstance; @@ -30,12 +31,10 @@ public class TestModbusTcpApiReadWrite { @Before public void beforeEach() throws Exception { this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { - this.modbusTcpApiReadOnly = new ModbusTcpApiReadOnly(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Api.ModbusTcp.ReadOnly"), t.cm, t.componentUtil); - this.modbusTcpApiReadWrite = new ModbusTcpApiReadWrite(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Api.ModbusTcp.ReadWrite"), t.cm, t.componentUtil); - - return ImmutableList.of(this.modbusTcpApiReadOnly, this.modbusTcpApiReadWrite); + return ImmutableList.of(// + this.modbusTcpApiReadOnly = Apps.modbusTcpApiReadOnly(t), // + this.modbusTcpApiReadWrite = Apps.modbusTcpApiReadWrite(t) // + ); }); } @@ -43,7 +42,7 @@ public void beforeEach() throws Exception { public void testDeactivateReadOnly() throws Exception { // create ReadOnly app this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, new AddAppInstance.Request( - this.modbusTcpApiReadOnly.getAppId(), "alias", JsonUtils.buildJsonObject().build())); + this.modbusTcpApiReadOnly.getAppId(), "key", "alias", JsonUtils.buildJsonObject().build())); assertEquals(1, this.appManagerTestBundle.sut.getInstantiatedApps().size()); @@ -57,12 +56,13 @@ public void testDeactivateReadOnly() throws Exception { // create ReadWrite app this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.modbusTcpApiReadWrite.getAppId(), "alias", JsonUtils.buildJsonObject() // - .addProperty("API_TIMEOUT", 60) // - .add("COMPONENT_IDS", JsonUtils.buildJsonArray() // - .add("_sum") // - .build()) // - .build())); + new AddAppInstance.Request(this.modbusTcpApiReadWrite.getAppId(), "key", "alias", + JsonUtils.buildJsonObject() // + .addProperty("API_TIMEOUT", 60) // + .add("COMPONENT_IDS", JsonUtils.buildJsonArray() // + .add("_sum") // + .build()) // + .build())); assertEquals(2, this.appManagerTestBundle.sut.getInstantiatedApps().size()); diff --git a/io.openems.edge.core/test/io/openems/edge/app/evcs/TestHardyBarthEvcs.java b/io.openems.edge.core/test/io/openems/edge/app/evcs/TestHardyBarthEvcs.java new file mode 100644 index 00000000000..79ed50a31fe --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/app/evcs/TestHardyBarthEvcs.java @@ -0,0 +1,132 @@ +package io.openems.edge.app.evcs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +import io.openems.common.session.Language; +import io.openems.common.session.Role; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.common.test.DummyUser; +import io.openems.edge.common.user.User; +import io.openems.edge.core.appmanager.AppManagerTestBundle; +import io.openems.edge.core.appmanager.Apps; +import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; +import io.openems.edge.core.appmanager.jsonrpc.UpdateAppInstance; + +public class TestHardyBarthEvcs { + + private final User user = new DummyUser("1", "password", Language.DEFAULT, Role.ADMIN); + + private AppManagerTestBundle appManagerTestBundle; + + private HardyBarthEvcs hardyBarthEvcs; + + @Before + public void beforeEach() throws Exception { + this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { + return ImmutableList.of(// + this.hardyBarthEvcs = Apps.hardyBarthEvcs(t) // + ); + }); + } + + @Test + public void testInstallationAndUpdate() throws Exception { + final var installResponse = this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, + new AddAppInstance.Request(this.hardyBarthEvcs.getAppId(), "key", "alias", JsonUtils.buildJsonObject() // + .addProperty(HardyBarthEvcs.Property.NUMBER_OF_CHARGING_STATIONS.name(), 1) // + .addProperty(HardyBarthEvcs.SubPropertyFirstChargepoint.IP.name(), "192.168.1.30") // + .build())) + .get(); + + final var installProps = installResponse.instance.properties; + final var firstCreatedEvcsId = installProps.get(HardyBarthEvcs.Property.EVCS_ID.name()).getAsString(); + final var firstCreatedCtrlEvcsId = installProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID.name()).getAsString(); + assertTrue(installResponse.warnings == null || installResponse.warnings.isEmpty()); + assertEquals(1, this.appManagerTestBundle.sut.getInstantiatedApps().size()); + assertEquals("evcs0", firstCreatedEvcsId); + assertEquals("ctrlEvcs0", firstCreatedCtrlEvcsId); + assertFalse(installProps.has(HardyBarthEvcs.Property.EVCS_ID_CP_2.name())); + assertFalse(installProps.has(HardyBarthEvcs.Property.CTRL_EVCS_ID_CP_2.name())); + assertFalse(installProps.has(HardyBarthEvcs.SubPropertySecondChargepoint.ALIAS_CP_2.name())); + assertFalse(installProps.has(HardyBarthEvcs.SubPropertySecondChargepoint.IP_CP_2.name())); + + final var updateToDoubleResponse = this.appManagerTestBundle.sut.handleUpdateAppInstanceRequest(this.user, + new UpdateAppInstance.Request(installResponse.instance.instanceId, "alias", // + JsonUtils.buildJsonObject() // + .addProperty(HardyBarthEvcs.Property.NUMBER_OF_CHARGING_STATIONS.name(), 2) // + .addProperty(HardyBarthEvcs.SubPropertyFirstChargepoint.IP.name(), "192.168.1.30") // + .addProperty(HardyBarthEvcs.SubPropertySecondChargepoint.IP_CP_2.name(), "192.168.1.31") // + .addProperty(HardyBarthEvcs.SubPropertySecondChargepoint.ALIAS_CP_2.name(), "alias 2") // + .build())) + .get(); + + final var updateDoubleProps = updateToDoubleResponse.instance.properties; + final var firstCreatedEvcsIdOfSecond = updateDoubleProps.get(HardyBarthEvcs.Property.EVCS_ID_CP_2.name()) + .getAsString(); + final var firstCreatedCtrlEvcsIdOfSecond = updateDoubleProps + .get(HardyBarthEvcs.Property.CTRL_EVCS_ID_CP_2.name()).getAsString(); + assertTrue(updateToDoubleResponse.warnings == null || updateToDoubleResponse.warnings.isEmpty()); + assertEquals(1, this.appManagerTestBundle.sut.getInstantiatedApps().size()); + assertEquals(firstCreatedEvcsId, updateDoubleProps.get(HardyBarthEvcs.Property.EVCS_ID.name()).getAsString()); + assertEquals(firstCreatedCtrlEvcsId, + updateDoubleProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID.name()).getAsString()); + assertEquals("evcs1", firstCreatedEvcsIdOfSecond); + assertEquals("ctrlEvcs1", firstCreatedCtrlEvcsIdOfSecond); + assertNotEquals(updateDoubleProps.get(HardyBarthEvcs.Property.EVCS_ID.name()).getAsString(), + updateDoubleProps.get(HardyBarthEvcs.Property.EVCS_ID_CP_2.name()).getAsString()); + assertNotEquals(updateDoubleProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID.name()).getAsString(), + updateDoubleProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID_CP_2.name()).getAsString()); + assertTrue(updateDoubleProps.has(HardyBarthEvcs.SubPropertySecondChargepoint.ALIAS_CP_2.name())); + assertTrue(updateDoubleProps.has(HardyBarthEvcs.SubPropertySecondChargepoint.IP_CP_2.name())); + + final var updateBackToSingleResponse = this.appManagerTestBundle.sut.handleUpdateAppInstanceRequest(this.user, + new UpdateAppInstance.Request(installResponse.instance.instanceId, "alias", JsonUtils.buildJsonObject() // + .addProperty(HardyBarthEvcs.Property.NUMBER_OF_CHARGING_STATIONS.name(), 1) // + .addProperty(HardyBarthEvcs.SubPropertyFirstChargepoint.IP.name(), "192.168.1.30") // + .build())) + .get(); + + final var updateSingleProps = updateBackToSingleResponse.instance.properties; + assertTrue(updateBackToSingleResponse.warnings == null || updateBackToSingleResponse.warnings.isEmpty()); + assertEquals(1, this.appManagerTestBundle.sut.getInstantiatedApps().size()); + assertEquals(firstCreatedEvcsId, updateSingleProps.get(HardyBarthEvcs.Property.EVCS_ID.name()).getAsString()); + assertEquals(firstCreatedEvcsId, updateSingleProps.get(HardyBarthEvcs.Property.EVCS_ID.name()).getAsString()); + assertEquals(firstCreatedCtrlEvcsId, + updateSingleProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID.name()).getAsString()); + } + + @Test + public void testInstallationDouble() throws Exception { + final var installResponse = this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, + new AddAppInstance.Request(this.hardyBarthEvcs.getAppId(), "key", "alias", JsonUtils.buildJsonObject() // + .addProperty(HardyBarthEvcs.Property.NUMBER_OF_CHARGING_STATIONS.name(), 2) // + .addProperty(HardyBarthEvcs.SubPropertyFirstChargepoint.IP.name(), "192.168.1.30") // + .addProperty(HardyBarthEvcs.SubPropertySecondChargepoint.IP_CP_2.name(), "192.168.1.31") // + .addProperty(HardyBarthEvcs.SubPropertySecondChargepoint.ALIAS_CP_2.name(), "alias 2") // + .build())) + .get(); + final var updateProps = installResponse.instance.properties; + assertTrue(installResponse.warnings == null || installResponse.warnings.isEmpty()); + assertEquals(1, this.appManagerTestBundle.sut.getInstantiatedApps().size()); + assertTrue(updateProps.get(HardyBarthEvcs.Property.EVCS_ID.name()).getAsString().startsWith("evcs")); + assertTrue(updateProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID.name()).getAsString().startsWith("ctrlEvcs")); + assertTrue(updateProps.get(HardyBarthEvcs.Property.EVCS_ID_CP_2.name()).getAsString().startsWith("evcs")); + assertTrue( + updateProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID_CP_2.name()).getAsString().startsWith("ctrlEvcs")); + assertNotEquals(updateProps.get(HardyBarthEvcs.Property.EVCS_ID.name()).getAsString(), + updateProps.get(HardyBarthEvcs.Property.EVCS_ID_CP_2.name()).getAsString()); + assertNotEquals(updateProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID.name()).getAsString(), + updateProps.get(HardyBarthEvcs.Property.CTRL_EVCS_ID_CP_2.name()).getAsString()); + assertTrue(updateProps.has(HardyBarthEvcs.SubPropertySecondChargepoint.ALIAS_CP_2.name())); + assertTrue(updateProps.has(HardyBarthEvcs.SubPropertySecondChargepoint.IP_CP_2.name())); + } + +} diff --git a/io.openems.edge.core/test/io/openems/edge/app/heat/TestHeatPump.java b/io.openems.edge.core/test/io/openems/edge/app/heat/TestHeatPump.java index 4ddb80f7a17..298ce3a5b55 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/heat/TestHeatPump.java +++ b/io.openems.edge.core/test/io/openems/edge/app/heat/TestHeatPump.java @@ -14,13 +14,11 @@ import io.openems.edge.app.api.RestJsonApiReadOnly; import io.openems.edge.app.integratedsystem.FeneconHome; import io.openems.edge.app.integratedsystem.TestFeneconHome; -import io.openems.edge.app.meter.SocomecMeter; -import io.openems.edge.app.pvselfconsumption.GridOptimizedCharge; -import io.openems.edge.app.pvselfconsumption.SelfConsumptionOptimization; import io.openems.edge.common.test.ComponentTest; import io.openems.edge.common.test.DummyUser; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.AppManagerTestBundle; +import io.openems.edge.core.appmanager.Apps; import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; import io.openems.edge.core.appmanager.jsonrpc.UpdateAppInstance; import io.openems.edge.io.test.DummyInputOutput; @@ -42,25 +40,13 @@ public class TestHeatPump { public void beforeEach() throws Exception { this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { return ImmutableList.of( - this.heatPump = new HeatPump(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Heat.HeatPump"), t.cm, t.componentUtil), // - this.homeApp = new FeneconHome(t.componentManger, - AppManagerTestBundle.getComponentContext("App.FENECON.Home"), t.cm, t.componentUtil), // - new GridOptimizedCharge(t.componentManger, - AppManagerTestBundle.getComponentContext("App.PvSelfConsumption.GridOptimizedCharge"), t.cm, - t.componentUtil), // - new SelfConsumptionOptimization(t.componentManger, - AppManagerTestBundle.getComponentContext( - "App.PvSelfConsumption.SelfConsumptionOptimization"), - t.cm, t.componentUtil), // - new SocomecMeter(t.componentManger, AppManagerTestBundle.getComponentContext("App.Meter.Socomec"), - t.cm, t.componentUtil), // - this.modbusTcpApiReadOnly = new ModbusTcpApiReadOnly(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Api.ModbusTcp.ReadOnly"), t.cm, - t.componentUtil), // - this.restJsonApiReadOnly = new RestJsonApiReadOnly(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Api.RestJson.ReadOnly"), t.cm, - t.componentUtil) // + this.heatPump = Apps.heatPump(t), // + this.homeApp = Apps.feneconHome(t), // + Apps.gridOptimizedCharge(t), // + Apps.selfConsumptionOptimization(t), // + Apps.socomecMeter(t), // + this.modbusTcpApiReadOnly = Apps.modbusTcpApiReadOnly(t), // + this.restJsonApiReadOnly = Apps.restJsonApiReadOnly(t) // ); }); @@ -76,19 +62,20 @@ public void beforeEach() throws Exception { public void testNotRemovingDependenciesFromRelay() throws Exception { // install usual free apps this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, new AddAppInstance.Request( - this.modbusTcpApiReadOnly.getAppId(), "alias", JsonUtils.buildJsonObject().build())); + this.modbusTcpApiReadOnly.getAppId(), "key", "alias", JsonUtils.buildJsonObject().build())); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, new AddAppInstance.Request( - this.restJsonApiReadOnly.getAppId(), "alias", JsonUtils.buildJsonObject().build())); + this.restJsonApiReadOnly.getAppId(), "key", "alias", JsonUtils.buildJsonObject().build())); assertEquals(2, this.appManagerTestBundle.sut.getInstantiatedApps().size()); // install home this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.homeApp.getAppId(), "alias", TestFeneconHome.fullSettings())); + new AddAppInstance.Request(this.homeApp.getAppId(), "key", "alias", TestFeneconHome.fullSettings())); + assertEquals(6, this.appManagerTestBundle.sut.getInstantiatedApps().size()); // create heat pump - this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.heatPump.getAppId(), "alias", JsonUtils.buildJsonObject().build())); + this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, new AddAppInstance.Request( + this.heatPump.getAppId(), "key", "alias", JsonUtils.buildJsonObject().build())); assertEquals(7, this.appManagerTestBundle.sut.getInstantiatedApps().size()); diff --git a/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome.java b/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome.java index 1641c8bab56..48516850a1e 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome.java +++ b/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome.java @@ -6,18 +6,15 @@ import org.junit.Before; import org.junit.Test; -import com.google.common.collect.ImmutableList; import com.google.gson.JsonObject; import io.openems.common.session.Language; import io.openems.common.session.Role; import io.openems.common.utils.JsonUtils; -import io.openems.edge.app.meter.SocomecMeter; -import io.openems.edge.app.pvselfconsumption.GridOptimizedCharge; -import io.openems.edge.app.pvselfconsumption.SelfConsumptionOptimization; import io.openems.edge.common.test.DummyUser; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.AppManagerTestBundle; +import io.openems.edge.core.appmanager.Apps; import io.openems.edge.core.appmanager.OpenemsAppInstance; import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; import io.openems.edge.core.appmanager.jsonrpc.UpdateAppInstance; @@ -28,26 +25,16 @@ public class TestFeneconHome { private AppManagerTestBundle appManagerTestBundle; - private FeneconHome homeApp; - private GridOptimizedCharge gridOptimizedCharge; - private SelfConsumptionOptimization selfConsumptionOptimization; - private SocomecMeter socomecMeter; - @Before public void beforeEach() throws Exception { this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { - this.homeApp = new FeneconHome(t.componentManger, - AppManagerTestBundle.getComponentContext("App.FENECON.Home"), t.cm, t.componentUtil); - this.gridOptimizedCharge = new GridOptimizedCharge(t.componentManger, - AppManagerTestBundle.getComponentContext("App.PvSelfConsumption.GridOptimizedCharge"), t.cm, - t.componentUtil); - this.selfConsumptionOptimization = new SelfConsumptionOptimization(t.componentManger, - AppManagerTestBundle.getComponentContext("App.PvSelfConsumption.SelfConsumptionOptimization"), t.cm, - t.componentUtil); - this.socomecMeter = new SocomecMeter(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Meter.Socomec"), t.cm, t.componentUtil); - return ImmutableList.of(this.homeApp, this.gridOptimizedCharge, this.selfConsumptionOptimization, - this.socomecMeter); + return Apps.of(t, // + Apps::feneconHome, // + Apps::gridOptimizedCharge, // + Apps::selfConsumptionOptimization, // + Apps::socomecMeter, // + Apps::prepareBatteryExtension // + ); }); } @@ -80,14 +67,14 @@ public void testCreateAndUpdateHomeFullSettings() throws Exception { new UpdateAppInstance.Request(homeInstance.instanceId, "aliasrename", fullConfig)); // expect the same as before // make sure every dependency got installed - assertEquals(this.appManagerTestBundle.sut.getInstantiatedApps().size(), 4); + assertEquals(this.appManagerTestBundle.sut.getInstantiatedApps().size(), 5); // check properties of created apps for (var instance : this.appManagerTestBundle.sut.getInstantiatedApps()) { int expectedDependencies; switch (instance.appId) { case "App.FENECON.Home": - expectedDependencies = 3; + expectedDependencies = 4; break; case "App.PvSelfConsumption.GridOptimizedCharge": expectedDependencies = 0; @@ -98,9 +85,15 @@ public void testCreateAndUpdateHomeFullSettings() throws Exception { case "App.Meter.Socomec": expectedDependencies = 0; break; + case "App.Ess.PrepareBatteryExtension": + expectedDependencies = 0; + break; default: throw new Exception("App with ID[" + instance.appId + "] should not have been created!"); } + if (expectedDependencies == 0 && instance.dependencies == null) { + continue; + } assertEquals(expectedDependencies, instance.dependencies.size()); } } @@ -129,14 +122,14 @@ public void testRemoveAcMeter() throws Exception { new UpdateAppInstance.Request(homeInstance.instanceId, "aliasrename", configNoMeter)); // expect the same as before // make sure every dependency got installed - assertEquals(this.appManagerTestBundle.sut.getInstantiatedApps().size(), 3); + assertEquals(this.appManagerTestBundle.sut.getInstantiatedApps().size(), 4); // check properties of created apps for (var instance : this.appManagerTestBundle.sut.getInstantiatedApps()) { int expectedDependencies; switch (instance.appId) { case "App.FENECON.Home": - expectedDependencies = 2; + expectedDependencies = 3; break; case "App.PvSelfConsumption.GridOptimizedCharge": expectedDependencies = 0; @@ -144,9 +137,15 @@ public void testRemoveAcMeter() throws Exception { case "App.PvSelfConsumption.SelfConsumptionOptimization": expectedDependencies = 0; break; + case "App.Ess.PrepareBatteryExtension": + expectedDependencies = 0; + break; default: throw new Exception("App with ID[" + instance.appId + "] should not have been created!"); } + if (expectedDependencies == 0 && instance.dependencies == null) { + continue; + } assertEquals(expectedDependencies, instance.dependencies.size()); } @@ -156,17 +155,17 @@ private final OpenemsAppInstance createFullHome() throws Exception { var fullConfig = fullSettings(); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request("App.FENECON.Home", "alias", fullConfig)); + new AddAppInstance.Request("App.FENECON.Home", "key", "alias", fullConfig)); // make sure every dependency got installed - assertEquals(this.appManagerTestBundle.sut.getInstantiatedApps().size(), 4); + assertEquals(this.appManagerTestBundle.sut.getInstantiatedApps().size(), 5); // check properties of created apps for (var instance : this.appManagerTestBundle.sut.getInstantiatedApps()) { int expectedDependencies; switch (instance.appId) { case "App.FENECON.Home": - expectedDependencies = 3; + expectedDependencies = 4; break; case "App.PvSelfConsumption.GridOptimizedCharge": expectedDependencies = 0; @@ -177,9 +176,15 @@ private final OpenemsAppInstance createFullHome() throws Exception { case "App.Meter.Socomec": expectedDependencies = 0; break; + case "App.Ess.PrepareBatteryExtension": + expectedDependencies = 0; + break; default: throw new Exception("App with ID[" + instance.appId + "] should not have been created!"); } + if (expectedDependencies == 0 && instance.dependencies == null) { + continue; + } assertEquals(expectedDependencies, instance.dependencies.size()); } diff --git a/io.openems.edge.core/test/io/openems/edge/app/timeofusetariff/TestTibber.java b/io.openems.edge.core/test/io/openems/edge/app/timeofusetariff/TestTibber.java index dab4ecc7f71..8feb08e7325 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/timeofusetariff/TestTibber.java +++ b/io.openems.edge.core/test/io/openems/edge/app/timeofusetariff/TestTibber.java @@ -15,6 +15,7 @@ import io.openems.edge.common.test.DummyUser; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.AppManagerTestBundle; +import io.openems.edge.core.appmanager.Apps; import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; public class TestTibber { @@ -28,9 +29,7 @@ public class TestTibber { public void beforeEach() throws Exception { this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { return ImmutableList.of(// - this.tibber = new Tibber(t.componentManger, - AppManagerTestBundle.getComponentContext("App.TimeOfUseTariff.Tibber"), t.cm, - t.componentUtil)); + this.tibber = Apps.tibber(t)); }); } @@ -40,7 +39,7 @@ public void testRemoveAccessToken() throws Exception { .addProperty("ACCESS_TOKEN", "g78aw9ht2n112nb453") // .build(); var response = (AddAppInstance.Response) this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.tibber.getAppId(), "alias", properties)).get(); + new AddAppInstance.Request(this.tibber.getAppId(), "key", "alias", properties)).get(); assertFalse(response.instance.properties.has("ACCESS_TOKEN")); diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerAppHelperImplTest.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerAppHelperImplTest.java index 46a60e4502f..5c9604c10d4 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerAppHelperImplTest.java +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerAppHelperImplTest.java @@ -17,10 +17,6 @@ import io.openems.edge.app.TestADependencyToC; import io.openems.edge.app.TestBDependencyToC; import io.openems.edge.app.TestC; -import io.openems.edge.app.evcs.KebaEvcs; -import io.openems.edge.app.integratedsystem.FeneconHome; -import io.openems.edge.app.timeofusetariff.AwattarHourly; -import io.openems.edge.app.timeofusetariff.StromdaoCorrently; import io.openems.edge.common.test.DummyUser; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.dependency.DependencyDeclaration; @@ -34,11 +30,6 @@ public class AppManagerAppHelperImplTest { private AppManagerTestBundle appManagerTestBundle; - private FeneconHome homeApp; - private KebaEvcs kebaEvcsApp; - private AwattarHourly awattarApp; - private StromdaoCorrently stromdao; - private TestADependencyToC testAApp; private TestBDependencyToC testBApp; private TestC testCApp; @@ -46,24 +37,16 @@ public class AppManagerAppHelperImplTest { @Before public void beforeEach() throws Exception { this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { - this.homeApp = new FeneconHome(t.componentManger, - AppManagerTestBundle.getComponentContext("App.FENECON.Home"), t.cm, t.componentUtil); - this.kebaEvcsApp = new KebaEvcs(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Evcs.Keba"), t.cm, t.componentUtil); - this.awattarApp = new AwattarHourly(t.componentManger, - AppManagerTestBundle.getComponentContext("App.TimeVariablePrice.Awattar"), t.cm, t.componentUtil); - this.stromdao = new StromdaoCorrently(t.componentManger, - AppManagerTestBundle.getComponentContext("App.TimeVariablePrice.Stromdao"), t.cm, t.componentUtil); - - this.testAApp = new TestADependencyToC(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Test.TestADependencyToC"), t.cm, t.componentUtil); - this.testBApp = new TestBDependencyToC(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Test.TestBDependencyToC"), t.cm, t.componentUtil); - this.testCApp = new TestC(t.componentManger, AppManagerTestBundle.getComponentContext("App.Test.TestC"), - t.cm, t.componentUtil); - - return ImmutableList.of(this.homeApp, this.kebaEvcsApp, this.awattarApp, this.stromdao, this.testAApp, - this.testBApp, this.testCApp); + return ImmutableList.of(// + Apps.feneconHome(t), // + Apps.kebaEvcs(t), // + Apps.awattarHourly(t), // + Apps.stromdaoCorrently(t), // + + this.testAApp = Apps.testADependencyToC(t), // + this.testBApp = Apps.testBDependencyToC(t), // + this.testCApp = Apps.testC(t) // + ); }); } @@ -73,7 +56,7 @@ public void testCreatePolicyIfNotExisting() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("CREATE_POLICY", DependencyDeclaration.CreatePolicy.IF_NOT_EXISTING.name()) .build())); @@ -81,7 +64,7 @@ public void testCreatePolicyIfNotExisting() throws OpenemsNamedException { assertEquals(2, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testBApp.getAppId(), "", // + new AddAppInstance.Request(this.testBApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("CREATE_POLICY", DependencyDeclaration.CreatePolicy.IF_NOT_EXISTING.name()) .build())); @@ -94,7 +77,7 @@ public void testCreatePolicyAlways() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("CREATE_POLICY", DependencyDeclaration.CreatePolicy.ALWAYS.name()) .build())); @@ -102,7 +85,7 @@ public void testCreatePolicyAlways() throws OpenemsNamedException { assertEquals(2, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testBApp.getAppId(), "", // + new AddAppInstance.Request(this.testBApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("CREATE_POLICY", DependencyDeclaration.CreatePolicy.ALWAYS.name()) .build())); @@ -115,7 +98,7 @@ public void testCreatePolicyNever() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("CREATE_POLICY", DependencyDeclaration.CreatePolicy.NEVER.name()) .build())); @@ -123,7 +106,7 @@ public void testCreatePolicyNever() throws OpenemsNamedException { assertEquals(1, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testBApp.getAppId(), "", // + new AddAppInstance.Request(this.testBApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("CREATE_POLICY", DependencyDeclaration.CreatePolicy.NEVER.name()) .build())); @@ -136,7 +119,7 @@ public void testUpdatePolicyNever() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("UPDATE_POLICY", DependencyDeclaration.UpdatePolicy.NEVER.name()) // .addProperty("NUMBER", 1) // @@ -160,7 +143,7 @@ public void testUpdatePolicyAlways() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("UPDATE_POLICY", DependencyDeclaration.UpdatePolicy.ALWAYS.name()) // .addProperty("NUMBER", 1) // @@ -169,7 +152,7 @@ public void testUpdatePolicyAlways() throws OpenemsNamedException { assertEquals(2, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testBApp.getAppId(), "", // + new AddAppInstance.Request(this.testBApp.getAppId(), "key", "", // JsonUtils.buildJsonObject().build())); assertEquals(3, this.appManagerTestBundle.sut.getInstantiatedApps().size()); @@ -190,7 +173,7 @@ public void testUpdatePolicyIfMine() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("UPDATE_POLICY", DependencyDeclaration.UpdatePolicy.IF_MINE.name()) // .addProperty("NUMBER", 1) // @@ -209,7 +192,7 @@ public void testUpdatePolicyIfMine() throws OpenemsNamedException { assertEquals(2, instance.properties.get(TestC.Property.NUMBER.name()).getAsInt()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testBApp.getAppId(), "", // + new AddAppInstance.Request(this.testBApp.getAppId(), "key", "", // JsonUtils.buildJsonObject().build())); assertEquals(3, this.appManagerTestBundle.sut.getInstantiatedApps().size()); @@ -230,7 +213,7 @@ public void testDeletePolicyNever() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("DELETE_POLICY", DependencyDeclaration.DeletePolicy.NEVER.name()) // .build())); @@ -249,7 +232,7 @@ public void testDeletePolicyAlways() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("DELETE_POLICY", DependencyDeclaration.DeletePolicy.ALWAYS.name()) // .build())); @@ -257,7 +240,7 @@ public void testDeletePolicyAlways() throws OpenemsNamedException { assertEquals(2, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testBApp.getAppId(), "", // + new AddAppInstance.Request(this.testBApp.getAppId(), "key", "", // JsonUtils.buildJsonObject().build())); assertEquals(3, this.appManagerTestBundle.sut.getInstantiatedApps().size()); @@ -274,7 +257,7 @@ public void testDeletePolicyIfMine() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("DELETE_POLICY", DependencyDeclaration.DeletePolicy.IF_MINE.name()) // .build())); @@ -282,7 +265,7 @@ public void testDeletePolicyIfMine() throws OpenemsNamedException { assertEquals(2, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testBApp.getAppId(), "", // + new AddAppInstance.Request(this.testBApp.getAppId(), "key", "", // JsonUtils.buildJsonObject().build())); assertEquals(3, this.appManagerTestBundle.sut.getInstantiatedApps().size()); @@ -299,7 +282,7 @@ public void testDependencyDeletePolicyAllowed() throws OpenemsNamedException { assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("DEPENDENCY_DELETE_POLICY", DependencyDeclaration.DependencyDeletePolicy.ALLOWED.name()) // @@ -319,7 +302,7 @@ public void testDependencyDeletePolicyNotAllowed() throws OpenemsNamedException assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("DEPENDENCY_DELETE_POLICY", DependencyDeclaration.DependencyDeletePolicy.NOT_ALLOWED.name()) // @@ -338,7 +321,7 @@ public void testDependencyUpdatePolicyAllowAll() assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("DEPENDENCY_UPDATE_POLICY", DependencyDeclaration.DependencyUpdatePolicy.ALLOW_ALL.name()) // @@ -368,7 +351,7 @@ public void testDependencyUpdatePolicyAllowNone() assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, - new AddAppInstance.Request(this.testAApp.getAppId(), "", // + new AddAppInstance.Request(this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("DEPENDENCY_UPDATE_POLICY", DependencyDeclaration.DependencyUpdatePolicy.ALLOW_NONE.name()) // @@ -391,7 +374,7 @@ public void testDependencyUpdatePolicyAllowOnlyUnconfiguredProperties() assertEquals(0, this.appManagerTestBundle.sut.getInstantiatedApps().size()); this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, new AddAppInstance.Request( - this.testAApp.getAppId(), "", // + this.testAApp.getAppId(), "key", "", // JsonUtils.buildJsonObject() // .addProperty("DEPENDENCY_UPDATE_POLICY", DependencyDeclaration.DependencyUpdatePolicy.ALLOW_ONLY_UNCONFIGURED_PROPERTIES.name()) // diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerImplTest.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerImplTest.java index 7b89eb14e9b..59165c46c4b 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerImplTest.java +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerImplTest.java @@ -19,8 +19,6 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.app.evcs.KebaEvcs; import io.openems.edge.app.integratedsystem.FeneconHome; -import io.openems.edge.app.pvselfconsumption.GridOptimizedCharge; -import io.openems.edge.app.pvselfconsumption.SelfConsumptionOptimization; import io.openems.edge.app.timeofusetariff.AwattarHourly; import io.openems.edge.app.timeofusetariff.StromdaoCorrently; import io.openems.edge.common.host.Host; @@ -31,8 +29,6 @@ public class AppManagerImplTest { private AppManagerTestBundle appManagerTestBundle; private FeneconHome homeApp; - private GridOptimizedCharge gridOptimizedCharge; - private SelfConsumptionOptimization selfConsumptionOptimization; private KebaEvcs kebaEvcsApp; private AwattarHourly awattarApp; @@ -178,11 +174,31 @@ public void beforeEach() throws Exception { .addProperty("targetGridSetpoint", 0) // .build()) // .build()) // + .add("ctrlPrepareBatteryExtension0", JsonUtils.buildJsonObject() // + .addProperty("factoryId", "Controller.Ess.PrepareBatteryExtension") // + .addProperty("alias", "Batterie Erweiterung vorbereitung") // + .add("properties", JsonUtils.buildJsonObject() // + .addProperty("enabled", true) // + .addProperty("targetSoc", 30) // + .addProperty("enabled", true) // + .addProperty("ess_id", "ess0") // + .addProperty("isRunning", false) // + .addProperty("targetDate", "01.01.2000") // + .addProperty("targetTime", "08:00") // + .addProperty("targetTimeSpecified", false) // + .addProperty("targetTimeBuffer", 30) // + .addProperty("selfTermination", true) // + .addProperty("terminationBuffer", 120) // + .addProperty("conditionalTermination", true) // + .addProperty("endCondition", "CAPACITY_CHANGED") // + .build()) // + .build()) // .add("scheduler0", JsonUtils.buildJsonObject() // .addProperty("factoryId", "Scheduler.AllAlphabetically") // .add("properties", JsonUtils.buildJsonObject() // .addProperty("enabled", true) // .add("controllers.ids", JsonUtils.buildJsonArray() // + .add("ctrlPrepareBatteryExtension0") // .add("ctrlGridOptimizedCharge0") // .add("ctrlEssSurplusFeedToGrid0") // .add("ctrlBalancing0") // @@ -258,36 +274,35 @@ public void beforeEach() throws Exception { .addProperty("METER_ID", meterId) // .build()) // .build()) + .add(JsonUtils.buildJsonObject() // + .addProperty("appId", "App.Ess.PrepareBatteryExtension") // + .addProperty("alias", "") // + .addProperty("instanceId", UUID.randomUUID().toString()) // + .add("properties", JsonUtils.buildJsonObject() // + .addProperty("TARGET_SOC", 30) // + .build()) // + .build()) .build().toString()) // .build(); this.appManagerTestBundle = new AppManagerTestBundle(componentConfig, initialConfig, t -> { + return ImmutableList.of(// + this.homeApp = Apps.feneconHome(t), // + Apps.gridOptimizedCharge(t), // + Apps.selfConsumptionOptimization(t), // + Apps.prepareBatteryExtension(t), // - this.homeApp = new FeneconHome(t.componentManger, - AppManagerTestBundle.getComponentContext("App.FENECON.Home"), t.cm, t.componentUtil); - this.gridOptimizedCharge = new GridOptimizedCharge(t.componentManger, - AppManagerTestBundle.getComponentContext("App.PvSelfConsumption.GridOptimizedCharge"), t.cm, - t.componentUtil); - this.selfConsumptionOptimization = new SelfConsumptionOptimization(t.componentManger, - AppManagerTestBundle.getComponentContext("App.PvSelfConsumption.SelfConsumptionOptimization"), t.cm, - t.componentUtil); - - this.kebaEvcsApp = new KebaEvcs(t.componentManger, - AppManagerTestBundle.getComponentContext("App.Evcs.Keba"), t.cm, t.componentUtil); - this.awattarApp = new AwattarHourly(t.componentManger, - AppManagerTestBundle.getComponentContext("App.TimeVariablePrice.Awattar"), t.cm, t.componentUtil); - this.stromdao = new StromdaoCorrently(t.componentManger, - AppManagerTestBundle.getComponentContext("App.TimeVariablePrice.Stromdao"), t.cm, t.componentUtil); - - return ImmutableList.of(this.homeApp, this.gridOptimizedCharge, this.selfConsumptionOptimization, - this.kebaEvcsApp, this.awattarApp, this.stromdao); + this.kebaEvcsApp = Apps.kebaEvcs(t), // + this.awattarApp = Apps.awattarHourly(t), // + this.stromdao = Apps.stromdaoCorrently(t) // + ); }); } @Test public void testAppValidateWorker() throws OpenemsException, Exception { - assertEquals(this.appManagerTestBundle.sut.instantiatedApps.size(), 3); + assertEquals(this.appManagerTestBundle.sut.instantiatedApps.size(), 4); this.appManagerTestBundle.assertNoValidationErrors(); } diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerTestBundle.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerTestBundle.java index c055bdae62c..0b0dfb45e72 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerTestBundle.java +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppManagerTestBundle.java @@ -1,16 +1,23 @@ package io.openems.edge.core.appmanager; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.util.Dictionary; import java.util.Hashtable; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; +import org.osgi.framework.ServiceReference; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentConstants; import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.ComponentServiceObjects; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Modified; import com.google.common.collect.Lists; import com.google.gson.JsonArray; @@ -18,6 +25,8 @@ import com.google.gson.JsonPrimitive; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.exceptions.OpenemsException; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; import io.openems.common.utils.JsonUtils; import io.openems.common.utils.ReflectionUtils; import io.openems.edge.common.host.Host; @@ -25,11 +34,17 @@ import io.openems.edge.common.test.DummyComponentContext; import io.openems.edge.common.test.DummyComponentManager; import io.openems.edge.common.test.DummyConfigurationAdmin; +import io.openems.edge.common.user.User; +import io.openems.edge.core.appmanager.dependency.AppManagerAppHelper; import io.openems.edge.core.appmanager.dependency.AppManagerAppHelperImpl; import io.openems.edge.core.appmanager.dependency.ComponentAggregateTaskImpl; import io.openems.edge.core.appmanager.dependency.DependencyUtil; import io.openems.edge.core.appmanager.dependency.SchedulerAggregateTaskImpl; import io.openems.edge.core.appmanager.dependency.StaticIpAggregateTaskImpl; +import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; +import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance.Request; +import io.openems.edge.core.appmanager.jsonrpc.DeleteAppInstance; +import io.openems.edge.core.appmanager.jsonrpc.UpdateAppInstance; import io.openems.edge.core.appmanager.validator.CheckCardinality; import io.openems.edge.core.appmanager.validator.CheckRelayCount; import io.openems.edge.core.appmanager.validator.Checkable; @@ -44,6 +59,7 @@ public class AppManagerTestBundle { public final AppManagerImpl sut; public final AppManagerUtil appManagerUtil; + public final AppCenterBackendUtil appCenterBackendUtil; public final CheckablesBundle checkablesBundle; @@ -99,6 +115,7 @@ public AppManagerTestBundle(JsonObject initialComponentConfig, MyConfig initialA .setApps(JsonUtils.buildJsonArray() // .build() // .toString()) + .setKey("0000-0000-0000-0000") // .build(); } @@ -123,16 +140,79 @@ public AppManagerTestBundle(JsonObject initialComponentConfig, MyConfig initialA final var schedulerTask = new SchedulerAggregateTaskImpl(componentTask, this.componentUtil); final var staticIpTask = new StaticIpAggregateTaskImpl(this.componentUtil); - this.sut = new AppManagerImpl(); + this.sut = new AppManagerImpl() { + + @Activate + @Override + protected void activate(ComponentContext componentContext, Config config) { + super.activate(componentContext, config); + } + + @Modified + @Override + protected void modified(ComponentContext componentContext, Config config) throws OpenemsNamedException { + super.modified(componentContext, config); + } + + @Deactivate + @Override + protected void deactivate() { + super.deactivate(); + } + + @Override + public CompletableFuture handleAddAppInstanceRequest(User user, Request request, + boolean ignoreBackend) throws OpenemsNamedException { + final var response = super.handleAddAppInstanceRequest(user, request, ignoreBackend); + this.modifyWithCurrentConfig(); + return response; + } + + @Override + public CompletableFuture handleDeleteAppInstanceRequest(User user, + DeleteAppInstance.Request request) throws OpenemsNamedException { + final var response = super.handleDeleteAppInstanceRequest(user, request); + this.modifyWithCurrentConfig(); + return response; + } + + @Override + public CompletableFuture handleUpdateAppInstanceRequest(User user, + UpdateAppInstance.Request request) throws OpenemsNamedException { + final var response = super.handleUpdateAppInstanceRequest(user, request); + this.modifyWithCurrentConfig(); + return response; + } + + private final void modifyWithCurrentConfig() throws OpenemsNamedException { + final var config = MyConfig.create() // + .setApps(this.instantiatedApps.stream() // + .map(OpenemsAppInstance::toJsonObject) // + .collect(JsonUtils.toJsonArray()) // + .toString()) + .setKey("0000-0000-0000-0000") // + .build(); + DummyComponentContext context; + try { + context = DummyComponentContext.from(config); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new OpenemsException(e); + } + this.modified(context, config); + } + + }; this.componentManger.addComponent(this.sut); this.componentManger.setConfigurationAdmin(this.cm); this.appManagerUtil = new AppManagerUtilImpl(this.componentManger); + this.appCenterBackendUtil = new DummyAppCenterBackendUtil(); + ReflectionUtils.setAttribute(this.appManagerUtil.getClass(), this.appManagerUtil, "appManager", this.sut); this.checkablesBundle = new CheckablesBundle( new CheckCardinality(this.sut, this.appManagerUtil, getComponentContext(CheckCardinality.COMPONENT_NAME)), // - new CheckRelayCount(this.componentUtil, getComponentContext(CheckRelayCount.COMPONENT_NAME)) // + new CheckRelayCount(this.componentUtil, getComponentContext(CheckRelayCount.COMPONENT_NAME), null) // ); var dummyValidator = new DummyValidator(); @@ -142,6 +222,26 @@ public AppManagerTestBundle(JsonObject initialComponentConfig, MyConfig initialA var appManagerAppHelper = new AppManagerAppHelperImpl(this.componentManger, this.componentUtil, this.validator, componentTask, schedulerTask, staticIpTask); + final var csoAppManagerAppHelper = new ComponentServiceObjects() { + + @Override + public AppManagerAppHelper getService() { + return appManagerAppHelper; + } + + @Override + public void ungetService(AppManagerAppHelper service) { + // empty for test + } + + @Override + public ServiceReference getServiceReference() { + // not needed for test + return null; + } + + }; + // use this so the appManagerAppHelper does not has to be a OpenemsComponent and // the attribute can still be private ReflectionUtils.setAttribute(appManagerAppHelper.getClass(), appManagerAppHelper, "appManager", this.sut); @@ -153,11 +253,11 @@ public AppManagerTestBundle(JsonObject initialComponentConfig, MyConfig initialA new ComponentTest(this.sut) // .addReference("cm", this.cm) // .addReference("componentManager", this.componentManger) // - .addReference("appHelper", appManagerAppHelper) // + .addReference("csoAppManagerAppHelper", csoAppManagerAppHelper) // .addReference("validator", this.validator) // + .addReference("backendUtil", this.appCenterBackendUtil) // .addReference("availableApps", availableAppsSupplier.apply(this)) // .activate(initialAppManagerConfig); - } /** diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/Apps.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/Apps.java new file mode 100644 index 00000000000..982edfed532 --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/Apps.java @@ -0,0 +1,265 @@ +package io.openems.edge.core.appmanager; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; + +import io.openems.edge.app.TestADependencyToC; +import io.openems.edge.app.TestBDependencyToC; +import io.openems.edge.app.TestC; +import io.openems.edge.app.TestMultipleIds; +import io.openems.edge.app.api.ModbusTcpApiReadOnly; +import io.openems.edge.app.api.ModbusTcpApiReadWrite; +import io.openems.edge.app.api.RestJsonApiReadOnly; +import io.openems.edge.app.ess.PrepareBatteryExtension; +import io.openems.edge.app.evcs.HardyBarthEvcs; +import io.openems.edge.app.evcs.KebaEvcs; +import io.openems.edge.app.heat.HeatPump; +import io.openems.edge.app.integratedsystem.FeneconHome; +import io.openems.edge.app.meter.SocomecMeter; +import io.openems.edge.app.pvselfconsumption.GridOptimizedCharge; +import io.openems.edge.app.pvselfconsumption.SelfConsumptionOptimization; +import io.openems.edge.app.timeofusetariff.AwattarHourly; +import io.openems.edge.app.timeofusetariff.StromdaoCorrently; +import io.openems.edge.app.timeofusetariff.Tibber; +import io.openems.edge.common.component.ComponentManager; + +public class Apps { + + private Apps() { + super(); + } + + /** + * Helper method for easier creation of a list of the used {@link OpenemsApp + * OpenemsApps}. + * + * @param t the {@link AppManagerTestBundle} + * @param appFunctions the methods to create the {@link OpenemsApp OpenemsApps} + * @return the list of the {@link OpenemsApp OpenemsApps} + */ + @SafeVarargs + public static final List of(AppManagerTestBundle t, + Function... appFunctions) { + return Arrays.stream(appFunctions) // + .map(f -> f.apply(t)) // + .collect(Collectors.toUnmodifiableList()); + } + + // Integrated Systems + + /** + * Test method for creating a {@link FeneconHome}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final FeneconHome feneconHome(AppManagerTestBundle t) { + return app(t, FeneconHome::new, "App.FENECON.Home"); + } + + // Evcs + + /** + * Test method for creating a {@link KebaEvcs}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final KebaEvcs kebaEvcs(AppManagerTestBundle t) { + return app(t, KebaEvcs::new, "App.Evcs.Keba"); + } + + // TimeOfUseTariff + + /** + * Test method for creating a {@link AwattarHourly}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final AwattarHourly awattarHourly(AppManagerTestBundle t) { + return app(t, AwattarHourly::new, "App.TimeOfUseTariff.Awattar"); + } + + /** + * Test method for creating a {@link StromdaoCorrently}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final StromdaoCorrently stromdaoCorrently(AppManagerTestBundle t) { + return app(t, StromdaoCorrently::new, "App.TimeOfUseTariff.Stromdao"); + } + + /** + * Test method for creating a {@link Tibber}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final Tibber tibber(AppManagerTestBundle t) { + return app(t, Tibber::new, "App.TimeOfUseTariff.Tibber"); + } + + // Test + + /** + * Test method for creating a {@link TestADependencyToC}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final TestADependencyToC testADependencyToC(AppManagerTestBundle t) { + return app(t, TestADependencyToC::new, "App.Test.TestADependencyToC"); + } + + /** + * Test method for creating a {@link TestBDependencyToC}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final TestBDependencyToC testBDependencyToC(AppManagerTestBundle t) { + return app(t, TestBDependencyToC::new, "App.Test.TestBDependencyToC"); + } + + /** + * Test method for creating a {@link TestC}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final TestC testC(AppManagerTestBundle t) { + return app(t, TestC::new, "App.Test.TestC"); + } + + /** + * Test method for creating a {@link TestMultipleIds}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final TestMultipleIds testMultipleIds(AppManagerTestBundle t) { + return app(t, TestMultipleIds::new, "App.Test.TestMultipleIds"); + } + + // Api + + /** + * Test method for creating a {@link ModbusTcpApiReadOnly}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final ModbusTcpApiReadOnly modbusTcpApiReadOnly(AppManagerTestBundle t) { + return app(t, ModbusTcpApiReadOnly::new, "App.Api.ModbusTcp.ReadOnly"); + } + + /** + * Test method for creating a {@link ModbusTcpApiReadWrite}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final ModbusTcpApiReadWrite modbusTcpApiReadWrite(AppManagerTestBundle t) { + return app(t, ModbusTcpApiReadWrite::new, "App.Api.ModbusTcp.ReadWrite"); + } + + /** + * Test method for creating a {@link RestJsonApiReadOnly}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final RestJsonApiReadOnly restJsonApiReadOnly(AppManagerTestBundle t) { + return app(t, RestJsonApiReadOnly::new, "App.Api.RestJson.ReadOnly"); + } + + // Evcs + + /** + * Test method for creating a {@link RestJsonApiReadOnly}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final HardyBarthEvcs hardyBarthEvcs(AppManagerTestBundle t) { + return app(t, HardyBarthEvcs::new, "App.Evcs.HardyBarth"); + } + + // Heat + + /** + * Test method for creating a {@link HeatPump}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final HeatPump heatPump(AppManagerTestBundle t) { + return app(t, HeatPump::new, "App.Heat.HeatPump"); + } + + // PvSelfConsumption + + /** + * Test method for creating a {@link GridOptimizedCharge}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final GridOptimizedCharge gridOptimizedCharge(AppManagerTestBundle t) { + return app(t, GridOptimizedCharge::new, "App.PvSelfConsumption.GridOptimizedCharge"); + } + + /** + * Test method for creating a {@link SelfConsumptionOptimization}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final SelfConsumptionOptimization selfConsumptionOptimization(AppManagerTestBundle t) { + return app(t, SelfConsumptionOptimization::new, "App.PvSelfConsumption.SelfConsumptionOptimization"); + } + + // Meter + + /** + * Test method for creating a {@link SocomecMeter}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final SocomecMeter socomecMeter(AppManagerTestBundle t) { + return app(t, SocomecMeter::new, "App.Meter.Socomec"); + } + + // ess-controller + + /** + * Test method for creating a {@link PrepareBatteryExtension}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final PrepareBatteryExtension prepareBatteryExtension(AppManagerTestBundle t) { + return app(t, PrepareBatteryExtension::new, "App.Ess.PrepareBatteryExtension"); + } + + private static final T app(AppManagerTestBundle t, DefaultAppConstructor constructor, String appId) { + return constructor.create(t.componentManger, AppManagerTestBundle.getComponentContext(appId), t.cm, + t.componentUtil); + } + + private static interface DefaultAppConstructor { + + public A create(ComponentManager componentManager, ComponentContext componentContext, ConfigurationAdmin cm, + ComponentUtil componentUtil); + + } + +} diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyAppCenterBackendUtil.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyAppCenterBackendUtil.java new file mode 100644 index 00000000000..e1db227e675 --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyAppCenterBackendUtil.java @@ -0,0 +1,49 @@ +package io.openems.edge.core.appmanager; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +import com.google.common.collect.Lists; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.base.GenericJsonrpcResponseSuccess; +import io.openems.common.jsonrpc.base.JsonrpcResponseSuccess; +import io.openems.common.jsonrpc.response.AppCenterGetInstalledAppsResponse.Instance; +import io.openems.common.jsonrpc.response.AppCenterGetPossibleAppsResponse.Bundle; +import io.openems.edge.common.user.User; + +public class DummyAppCenterBackendUtil implements AppCenterBackendUtil { + + @Override + public boolean isKeyApplicable(User user, String key, String appId) { + return true; + } + + @Override + public void addInstallAppInstanceHistory(User user, String key, String appId, UUID instanceId) + throws OpenemsNamedException { + } + + @Override + public CompletableFuture addDeinstallAppInstanceHistory(User user, String appId, + UUID instanceId) throws OpenemsNamedException { + return CompletableFuture.completedFuture(new GenericJsonrpcResponseSuccess(UUID.randomUUID())); + } + + @Override + public boolean isConnected() { + return true; + } + + @Override + public List getPossibleApps(String key) { + return Lists.newArrayList(); + } + + @Override + public List getInstalledApps() throws OpenemsNamedException { + return Lists.newArrayList(); + } + +} diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/MyConfig.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/MyConfig.java index 196d4802883..cf953b19e99 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/appmanager/MyConfig.java +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/MyConfig.java @@ -1,12 +1,15 @@ package io.openems.edge.core.appmanager; +import java.util.Optional; + import io.openems.common.test.AbstractComponentConfig; @SuppressWarnings("all") public class MyConfig extends AbstractComponentConfig implements Config { - public static class Builder { - public String apps; + protected static class Builder { + private String apps; + private String key; private Builder() { } @@ -16,6 +19,11 @@ public Builder setApps(String apps) { return this; } + public Builder setKey(String key) { + this.key = key; + return this; + } + public MyConfig build() { return new MyConfig(this); } @@ -42,4 +50,9 @@ public String apps() { return this.builder.apps; } -} \ No newline at end of file + @Override + public String keyForFreeApps() { + return Optional.ofNullable(this.builder.key).orElse(""); + } + +} diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/ResolveDependenciesTest.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/ResolveDependenciesTest.java new file mode 100644 index 00000000000..b8cc3570f82 --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/ResolveDependenciesTest.java @@ -0,0 +1,64 @@ +package io.openems.edge.core.appmanager; + +import static org.junit.Assert.assertEquals; + +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import io.openems.common.session.Language; +import io.openems.common.session.Role; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.common.test.DummyUser; +import io.openems.edge.common.user.User; + +public class ResolveDependenciesTest { + + private final User user = new DummyUser("1", "password", Language.DEFAULT, Role.ADMIN); + + private AppManagerTestBundle testBundle; + + @Before + public void before() throws Exception { + this.testBundle = new AppManagerTestBundle(// + null, MyConfig.create() // + .setApps(JsonUtils.buildJsonArray() // + .add(JsonUtils.buildJsonObject() // + .addProperty("appId", "App.FENECON.Home") // + .addProperty("alias", "FENECON Home") // + .addProperty("instanceId", UUID.randomUUID().toString()) // + .add("properties", JsonUtils.buildJsonObject() // + .addProperty("SAFETY_COUNTRY", "GERMANY") // + .addProperty("MAX_FEED_IN_POWER", 9450) // + .addProperty("FEED_IN_SETTING", "LEADING_0_95") // + .addProperty("HAS_AC_METER", false) // + .addProperty("HAS_DC_PV1", false) // + .addProperty("HAS_DC_PV2", false) // + .addProperty("HAS_EMERGENCY_RESERVE", false) // + .build()) // + .add("dependencies", JsonUtils.buildJsonArray() // + // No dependencies they should be installed with the resolver + .build()) // + .build()) + .build() // + .toString()) + .build(), + t -> { + return Apps.of(t, // + Apps::feneconHome, // + Apps::gridOptimizedCharge, // + Apps::selfConsumptionOptimization, // + Apps::prepareBatteryExtension // + ); + }); + } + + @Test + public void testResolveDependencies() { + assertEquals(1, this.testBundle.sut.getInstantiatedApps().size()); + ResolveDependencies.resolveDependencies(this.user, this.testBundle.sut, this.testBundle.appManagerUtil); + assertEquals(4, this.testBundle.sut.getInstantiatedApps().size()); + } + +} diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/TestSettingComponentIds.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/TestSettingComponentIds.java new file mode 100644 index 00000000000..3115810f497 --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/TestSettingComponentIds.java @@ -0,0 +1,115 @@ +package io.openems.edge.core.appmanager; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Sets; + +import io.openems.common.session.Language; +import io.openems.common.session.Role; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.app.TestMultipleIds; +import io.openems.edge.common.test.DummyUser; +import io.openems.edge.common.user.User; +import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; +import io.openems.edge.core.appmanager.jsonrpc.UpdateAppInstance; + +public class TestSettingComponentIds { + + private final User user = new DummyUser("1", "password", Language.DEFAULT, Role.ADMIN); + + private AppManagerTestBundle appManagerTestBundle; + + private TestMultipleIds testMultipleIds; + + @Before + public void beforeEach() throws Exception { + this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { + return ImmutableList.of(// + this.testMultipleIds = Apps.testMultipleIds(t) // + ); + }); + } + + @Test + public void testSettingInitially() throws Exception { + final var installResponse = this.add(4); + + final var installProps = installResponse.instance.properties; + final var initId1 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_1.name()); + final var initId2 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_2.name()); + final var initId3 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_3.name()); + final var initId4 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_4.name()); + + assertEquals(4, Sets.newHashSet(initId1, initId2, initId3, initId4).size()); + } + + @Test + public void testSettingOnUpdate() throws Exception { + final var installResponse = this.add(2); + + final var installProps = installResponse.instance.properties; + final var initId1 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_1.name()); + final var initId2 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_2.name()); + assertEquals(2, Sets.newHashSet(initId1, initId2).size()); + assertEquals(3, installProps.size()); + + final var updateResponse = this.update(installResponse.instance.instanceId, 4); + final var updateProps = updateResponse.instance.properties; + final var updatedId1 = JsonUtils.getAsString(updateProps, TestMultipleIds.Property.ID_1.name()); + final var updatedId2 = JsonUtils.getAsString(updateProps, TestMultipleIds.Property.ID_2.name()); + final var initId3 = JsonUtils.getAsString(updateProps, TestMultipleIds.Property.ID_3.name()); + final var initId4 = JsonUtils.getAsString(updateProps, TestMultipleIds.Property.ID_4.name()); + + assertEquals(initId1, updatedId1); + assertEquals(initId2, updatedId2); + assertEquals(4, Sets.newHashSet(initId1, initId2, initId3, initId4).size()); + assertEquals(5, updateProps.size()); + } + + @Test + public void testRemoveIds() throws Exception { + final var installResponse = this.add(4); + + final var installProps = installResponse.instance.properties; + final var initId1 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_1.name()); + final var initId2 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_2.name()); + final var initId3 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_3.name()); + final var initId4 = JsonUtils.getAsString(installProps, TestMultipleIds.Property.ID_4.name()); + + assertEquals(4, Sets.newHashSet(initId1, initId2, initId3, initId4).size()); + + final var updateResponse = this.update(installResponse.instance.instanceId, 2); + final var updateProps = updateResponse.instance.properties; + final var updatedId1 = JsonUtils.getAsString(updateProps, TestMultipleIds.Property.ID_1.name()); + final var updatedId2 = JsonUtils.getAsString(updateProps, TestMultipleIds.Property.ID_2.name()); + + assertEquals(initId1, updatedId1); + assertEquals(initId2, updatedId2); + assertFalse(updateProps.has(TestMultipleIds.Property.ID_3.name())); + assertFalse(updateProps.has(TestMultipleIds.Property.ID_4.name())); + } + + private AddAppInstance.Response add(int setIds) throws Exception { + return this.appManagerTestBundle.sut.handleAddAppInstanceRequest(this.user, + new AddAppInstance.Request(this.testMultipleIds.getAppId(), "key", "alias", JsonUtils.buildJsonObject() // + .addProperty(TestMultipleIds.Property.SET_IDS.name(), setIds) // + .build())) + .get(); + } + + private UpdateAppInstance.Response update(UUID instanceId, int setIds) throws Exception { + return this.appManagerTestBundle.sut.handleUpdateAppInstanceRequest(this.user, + new UpdateAppInstance.Request(instanceId, "alias", JsonUtils.buildJsonObject() // + .addProperty(TestMultipleIds.Property.SET_IDS.name(), setIds) // + .build())) + .get(); + } + +} diff --git a/io.openems.edge.scheduler.fixedorder/test/io/openems/edge/scheduler/fixedorder/FixedOrderSchedulerImplTest.java b/io.openems.edge.scheduler.fixedorder/test/io/openems/edge/scheduler/fixedorder/FixedOrderSchedulerImplTest.java index ace2118cdce..3fe6abcd6d2 100644 --- a/io.openems.edge.scheduler.fixedorder/test/io/openems/edge/scheduler/fixedorder/FixedOrderSchedulerImplTest.java +++ b/io.openems.edge.scheduler.fixedorder/test/io/openems/edge/scheduler/fixedorder/FixedOrderSchedulerImplTest.java @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; import org.junit.Test; @@ -47,7 +46,7 @@ public void test() throws Exception { private static List getControllerIds(Scheduler scheduler) throws OpenemsNamedException { return scheduler.getControllers().stream() // - .collect(Collectors.toList()); + .toList(); } } From 19bfe241742e83fc24cab322f647cc15adc32d70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 05:38:53 +0200 Subject: [PATCH 20/23] Bump influxdb-client-* from 6.7.0 to 6.8.0 in /cnf (#2133) * Bump flux-dsl from 6.7.0 to 6.8.0 in /cnf Bumps [flux-dsl](https://github.com/influxdata/influxdb-client-java) from 6.7.0 to 6.8.0. - [Release notes](https://github.com/influxdata/influxdb-client-java/releases) - [Changelog](https://github.com/influxdata/influxdb-client-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/influxdata/influxdb-client-java/compare/v6.7.0...v6.8.0) --- updated-dependencies: - dependency-name: com.influxdb:flux-dsl dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump influxdb-client-java from 6.7.0 to 6.8.0 in /cnf Bumps [influxdb-client-java](https://github.com/influxdata/influxdb-client-java) from 6.7.0 to 6.8.0. - [Release notes](https://github.com/influxdata/influxdb-client-java/releases) - [Changelog](https://github.com/influxdata/influxdb-client-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/influxdata/influxdb-client-java/compare/v6.7.0...v6.8.0) --- updated-dependencies: - dependency-name: com.influxdb:influxdb-client-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump influxdb-client-utils from 6.7.0 to 6.8.0 in /cnf Bumps [influxdb-client-utils](https://github.com/influxdata/influxdb-client-java) from 6.7.0 to 6.8.0. - [Release notes](https://github.com/influxdata/influxdb-client-java/releases) - [Changelog](https://github.com/influxdata/influxdb-client-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/influxdata/influxdb-client-java/compare/v6.7.0...v6.8.0) --- updated-dependencies: - dependency-name: com.influxdb:influxdb-client-utils dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump influxdb-client-core from 6.7.0 to 6.8.0 in /cnf Bumps [influxdb-client-core](https://github.com/influxdata/influxdb-client-java) from 6.7.0 to 6.8.0. - [Release notes](https://github.com/influxdata/influxdb-client-java/releases) - [Changelog](https://github.com/influxdata/influxdb-client-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/influxdata/influxdb-client-java/compare/v6.7.0...v6.8.0) --- updated-dependencies: - dependency-name: com.influxdb:influxdb-client-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update bnd files --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Feilmeier --- cnf/pom.xml | 8 ++++---- io.openems.wrapper/bnd.bnd | 8 ++++---- io.openems.wrapper/influxdb-client-core.bnd | 4 ++-- io.openems.wrapper/influxdb-client-java.bnd | 4 ++-- io.openems.wrapper/influxdb-client-utils.bnd | 4 ++-- io.openems.wrapper/influxdb-flux-dsl.bnd | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index da48ae7da6a..a4d6b6e3cd2 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -275,22 +275,22 @@ com.influxdb influxdb-client-java - 6.7.0 + 6.8.0 com.influxdb influxdb-client-core - 6.7.0 + 6.8.0 com.influxdb influxdb-client-utils - 6.7.0 + 6.8.0 com.influxdb flux-dsl - 6.7.0 + 6.8.0 org.java-websocket diff --git a/io.openems.wrapper/bnd.bnd b/io.openems.wrapper/bnd.bnd index d9b5c084d6d..ad2f53be85e 100644 --- a/io.openems.wrapper/bnd.bnd +++ b/io.openems.wrapper/bnd.bnd @@ -4,10 +4,10 @@ Bundle-Description: This wraps external java libraries that do not have OSGi hea -sub: *.bnd -buildpath: \ com.github.rzymek:opczip;version='1.2.0',\ - com.influxdb:influxdb-client-core;version='6.7.0',\ - com.influxdb:influxdb-client-java;version='6.7.0',\ - com.influxdb:influxdb-client-utils;version='6.7.0',\ - com.influxdb:flux-dsl;version='6.7.0',\ + com.influxdb:influxdb-client-core;version='6.8.0',\ + com.influxdb:influxdb-client-java;version='6.8.0',\ + com.influxdb:influxdb-client-utils;version='6.8.0',\ + com.influxdb:flux-dsl;version='6.8.0',\ com.squareup.okhttp3:logging-interceptor;version='4.10.0',\ com.squareup.okhttp3:okhttp;version='4.10.0',\ com.squareup.retrofit2:retrofit;version='2.9.0',\ diff --git a/io.openems.wrapper/influxdb-client-core.bnd b/io.openems.wrapper/influxdb-client-core.bnd index 1461e916ae9..01f4e3e9934 100644 --- a/io.openems.wrapper/influxdb-client-core.bnd +++ b/io.openems.wrapper/influxdb-client-core.bnd @@ -2,10 +2,10 @@ Bundle-Name: influxdb-client-core Bundle-Description: The Java InfluxDB 2.0 Client Core Bundle-DocURL: https://github.com/influxdata/influxdb-client-java Bundle-License: https://opensource.org/licenses/MIT -Bundle-Version: 6.7.0 +Bundle-Version: 6.8.0 Include-Resource: \ - @influxdb-client-core-6.7.0.jar,\ + @influxdb-client-core-6.8.0.jar,\ Export-Package: \ com.influxdb,\ diff --git a/io.openems.wrapper/influxdb-client-java.bnd b/io.openems.wrapper/influxdb-client-java.bnd index 0bb104bd057..4c328436990 100644 --- a/io.openems.wrapper/influxdb-client-java.bnd +++ b/io.openems.wrapper/influxdb-client-java.bnd @@ -2,10 +2,10 @@ Bundle-Name: influxdb-client-java Bundle-Description: The Java InfluxDB 2.0 Client Java Bundle-DocURL: https://github.com/influxdata/influxdb-client-java Bundle-License: https://opensource.org/licenses/MIT -Bundle-Version: 6.7.0 +Bundle-Version: 6.8.0 Include-Resource: \ - @influxdb-client-java-6.7.0.jar,\ + @influxdb-client-java-6.8.0.jar,\ Export-Package: \ com.influxdb.client,\ diff --git a/io.openems.wrapper/influxdb-client-utils.bnd b/io.openems.wrapper/influxdb-client-utils.bnd index e5cdc3e002f..7105a971e9e 100644 --- a/io.openems.wrapper/influxdb-client-utils.bnd +++ b/io.openems.wrapper/influxdb-client-utils.bnd @@ -2,10 +2,10 @@ Bundle-Name: influxdb-client-utils Bundle-Description: The Java InfluxDB 2.0 Client Utils Bundle-DocURL: https://github.com/influxdata/influxdb-client-java Bundle-License: https://opensource.org/licenses/MIT -Bundle-Version: 6.7.0 +Bundle-Version: 6.8.0 Include-Resource: \ - @influxdb-client-utils-6.7.0.jar,\ + @influxdb-client-utils-6.8.0.jar,\ Export-Package: \ com.influxdb.utils,\ diff --git a/io.openems.wrapper/influxdb-flux-dsl.bnd b/io.openems.wrapper/influxdb-flux-dsl.bnd index ca3fc827500..f9843093939 100644 --- a/io.openems.wrapper/influxdb-flux-dsl.bnd +++ b/io.openems.wrapper/influxdb-flux-dsl.bnd @@ -2,10 +2,10 @@ Bundle-Name: influxdb-flux-dsl Bundle-Description: The Java InfluxDB 2.0 Flux DSL Bundle-DocURL: https://github.com/influxdata/influxdb-client-java Bundle-License: https://opensource.org/licenses/MIT -Bundle-Version: 6.7.0 +Bundle-Version: 6.8.0 Include-Resource: \ - @flux-dsl-6.7.0.jar,\ + @flux-dsl-6.8.0.jar,\ Export-Package: \ com.influxdb.query,\ From 4ae9e82ce15369259dea5cd1ee7cab401532c3f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 06:23:00 +0200 Subject: [PATCH 21/23] Bump kotlin-osgi-bundle from 1.8.10 to 1.8.20 in /cnf (#2128) * Bump kotlin-osgi-bundle from 1.8.10 to 1.8.20 in /cnf Bumps kotlin-osgi-bundle from 1.8.10 to 1.8.20. --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-osgi-bundle dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Update bndrun --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Feilmeier --- cnf/pom.xml | 2 +- io.openems.backend.application/BackendApp.bndrun | 2 +- io.openems.edge.application/EdgeApp.bndrun | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cnf/pom.xml b/cnf/pom.xml index a4d6b6e3cd2..07a32614217 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -300,7 +300,7 @@ org.jetbrains.kotlin kotlin-osgi-bundle - 1.8.10 + 1.8.20 org.jetbrains.kotlinx diff --git a/io.openems.backend.application/BackendApp.bndrun b/io.openems.backend.application/BackendApp.bndrun index f6fe613c2bd..08d271156c0 100644 --- a/io.openems.backend.application/BackendApp.bndrun +++ b/io.openems.backend.application/BackendApp.bndrun @@ -110,7 +110,7 @@ org.apache.felix.scr;version='[2.2.6,2.2.7)',\ org.apache.felix.webconsole;version='[4.7.2,4.7.3)',\ org.apache.felix.webconsole.plugins.ds;version='[2.2.0,2.2.1)',\ - org.jetbrains.kotlin.osgi-bundle;version='[1.8.10,1.8.11)',\ + org.jetbrains.kotlin.osgi-bundle;version='[1.8.20,1.8.21)',\ org.jsr-305;version='[3.0.2,3.0.3)',\ org.ops4j.pax.logging.pax-logging-api;version='[2.2.1,2.2.2)',\ org.ops4j.pax.logging.pax-logging-log4j2;version='[2.2.1,2.2.2)',\ diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index 8cf883fc0cd..4c92e9b1279 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -380,7 +380,7 @@ org.eclipse.jetty.io;version='[9.4.28,9.4.29)',\ org.eclipse.jetty.util;version='[9.4.28,9.4.29)',\ org.eclipse.paho.mqttv5.client;version='[1.2.5,1.2.6)',\ - org.jetbrains.kotlin.osgi-bundle;version='[1.8.10,1.8.11)',\ + org.jetbrains.kotlin.osgi-bundle;version='[1.8.20,1.8.21)',\ org.jsoup;version='[1.15.4,1.15.5)',\ org.jsr-305;version='[3.0.2,3.0.3)',\ org.openmuc.jmbus;version='[3.3.0,3.3.1)',\ From 1711e0644086f95fbf1fcc780facc8a816c69bf1 Mon Sep 17 00:00:00 2001 From: Stefan Feilmeier Date: Tue, 4 Apr 2023 06:58:37 +0200 Subject: [PATCH 22/23] Update gradle to 8.0.2 --- .gradle-wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gradle-wrapper/gradle-wrapper.properties b/.gradle-wrapper/gradle-wrapper.properties index fc10b601f7c..bdc9a83b1e6 100644 --- a/.gradle-wrapper/gradle-wrapper.properties +++ b/.gradle-wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2f82bebf6112b9e584e0871eb1cf76c887aaf935 Mon Sep 17 00:00:00 2001 From: Stefan Feilmeier Date: Tue, 4 Apr 2023 16:17:34 +0200 Subject: [PATCH 23/23] Push version to 2023.4.0 --- io.openems.common/src/io/openems/common/OpenemsConstants.java | 2 +- tools/prepare-next-snapshot.sh | 3 +-- tools/prepare-release.sh | 3 +-- ui/package-lock.json | 4 ++-- ui/package.json | 2 +- ui/src/app/user/user.component.html | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/io.openems.common/src/io/openems/common/OpenemsConstants.java b/io.openems.common/src/io/openems/common/OpenemsConstants.java index a2e63c529e8..08c68a57761 100644 --- a/io.openems.common/src/io/openems/common/OpenemsConstants.java +++ b/io.openems.common/src/io/openems/common/OpenemsConstants.java @@ -43,7 +43,7 @@ public class OpenemsConstants { /** * The additional version string. */ - public static final String VERSION_STRING = "SNAPSHOT"; + public static final String VERSION_STRING = ""; /** * The complete version as a SemanticVersion. diff --git a/tools/prepare-next-snapshot.sh b/tools/prepare-next-snapshot.sh index 113a0626ea9..771ff84bac2 100644 --- a/tools/prepare-next-snapshot.sh +++ b/tools/prepare-next-snapshot.sh @@ -36,8 +36,7 @@ echo "# Update $package_lock" sed --in-place "s/\(^ \"version\": \"\).*\(\".*$\)/\1$new_version\2/" $package_lock echo "# Update $user_component" -sed --in-place "s/\(\)/\1$new_version\2/" $user_component +sed --in-place "s/\(\).*\(<\/a>\)/\1$new_version \\($release_date\\)\2/" $user_component echo "# Finished" diff --git a/tools/prepare-release.sh b/tools/prepare-release.sh index 646a817f83d..32b912c8b36 100644 --- a/tools/prepare-release.sh +++ b/tools/prepare-release.sh @@ -35,8 +35,7 @@ echo "# Update $package_lock" sed --in-place "s/\(^ \"version\": \"\).*\(\".*$\)/\1$new_version\2/" $package_lock echo "# Update $user_component" -sed --in-place "s/\(\)/\1$new_version ($release_date)\2/" $user_component +sed --in-place "s/\(\).*\(<\/a>\)/\1$new_version \\($release_date\\)\2/" $user_component echo "# Finished" diff --git a/ui/package-lock.json b/ui/package-lock.json index c5945d3fe17..031869988ef 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "openems-ui", - "version": "2023.4.0-SNAPSHOT", + "version": "2023.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "openems-ui", - "version": "2023.4.0-SNAPSHOT", + "version": "2023.4.0", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "~15.1.2", diff --git a/ui/package.json b/ui/package.json index c1b5d782ed2..b503a48fbaf 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "openems-ui", - "version": "2023.4.0-SNAPSHOT", + "version": "2023.4.0", "license": "AGPL-3.0", "private": true, "dependencies": { diff --git a/ui/src/app/user/user.component.html b/ui/src/app/user/user.component.html index 8f4aa6426e7..bc333606f3d 100644 --- a/ui/src/app/user/user.component.html +++ b/ui/src/app/user/user.component.html @@ -105,7 +105,7 @@

      About.build

      {{chartTitle}}